Leaked source code of windows server 2003
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.

3135 lines
92 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. wmi.c
  5. Abstract:
  6. Psched's WMI support.
  7. Author:
  8. Rajesh Sundaram (rajeshsu) 01-Aug-1998.
  9. Environment:
  10. Kernel Mode
  11. Revision History:
  12. --*/
  13. #include "psched.h"
  14. #pragma hdrstop
  15. //
  16. // Forward declaration for using in #pragma.
  17. //
  18. NTSTATUS
  19. PsQueryGuidDataSize(
  20. PADAPTER Adapter,
  21. PPS_WAN_LINK WanLink,
  22. PGPC_CLIENT_VC Vc,
  23. NDIS_OID Oid,
  24. PULONG BytesNeeded);
  25. #pragma alloc_text(PAGE, PsQueryGuidDataSize)
  26. #define ALIGN(x) (((x) + 7) & ~7)
  27. NDIS_STRING DefaultProfile = NDIS_STRING_CONST("Default Profile");
  28. #define fPS_GUID_TO_OID 0x00000001 // Normal GUID to OID mapping
  29. #define fPS_GUID_TO_STATUS 0x00000002 // GUID to status mapping
  30. #define fPS_GUID_ANSI_STRING 0x00000004 // ANSI string
  31. #define fPS_GUID_UNICODE_STRING 0x00000008 // Unicode String
  32. #define fPS_GUID_ARRAY 0x00000010 // Array
  33. #define fPS_GUID_EVENT_ENABLED 0x00000020 // Event is enabled
  34. #define fPS_GUID_NOT_SETTABLE 0x00000040 // GUID is read only
  35. #define fPS_GUID_EVENT_PERMANENT 0x00000080
  36. #define PS_GUID_SET_FLAG(m, f) ((m)->Flags |= (f))
  37. #define PS_GUID_CLEAR_FLAG(m, f) ((m)->Flags &= ~(f))
  38. #define PS_GUID_TEST_FLAG(m, f) (((m)->Flags & (f)) != 0)
  39. #define MOF_RESOURCE_NAME L"PschedMofResource"
  40. #if DBG
  41. #define NUMBER_QOS_GUIDS 30
  42. #else
  43. #define NUMBER_QOS_GUIDS 24
  44. #endif
  45. NDIS_GUID gPschedSupportedGuids[NUMBER_QOS_GUIDS] =
  46. {
  47. #if DBG
  48. //
  49. // GUID_QOS_LOG_LEVEL
  50. //
  51. {{0x9dd7f3aeL,0xf2a8,0x11d2,0xbe,0x1b,0x00,0xa0,0xc9,0x9e,0xe6,0x3b},
  52. OID_QOS_LOG_LEVEL,
  53. 4,
  54. fPS_GUID_TO_OID
  55. },
  56. //
  57. // GUID_QOS_LOG_MASK
  58. //
  59. {{0x9e696320L,0xf2a8,0x11d2,0xbe,0x1b,0x00,0xa0,0xc9,0x9e,0xe6,0x3b},
  60. OID_QOS_LOG_MASK,
  61. 4,
  62. fPS_GUID_TO_OID
  63. },
  64. //
  65. // GUID_QOS_STATUS_LOG_THRESHOLD
  66. //
  67. {{0x357b74d2L,0x6134,0x11d1,0xab,0x5b,0x00,0xa0,0xc9,0x24,0x88,0x37},
  68. QOS_STATUS_LOG_THRESHOLD,
  69. 4,
  70. fPS_GUID_TO_STATUS
  71. },
  72. //
  73. // GUID_QOS_LOG_BUFFER_SIZE
  74. //
  75. {{0x357b74d3L,0x6134,0x11d1,0xab,0x5b,0x00,0xa0,0xc9,0x24,0x88,0x37},
  76. OID_QOS_LOG_BUFFER_SIZE,
  77. 4,
  78. fPS_GUID_TO_OID
  79. },
  80. //
  81. // GUID_QOS_LOG_THRESHOLD
  82. //
  83. {{0x357b74d0L,0x6134,0x11d1,0xab,0x5b,0x00,0xa0,0xc9,0x24,0x88,0x37},
  84. OID_QOS_LOG_THRESHOLD,
  85. 4,
  86. fPS_GUID_TO_OID
  87. },
  88. //
  89. // GUID_QOS_LOG_DATA
  90. //
  91. {{0x357b74d1L,0x6134,0x11d1,0xab,0x5b,0x00,0xa0,0xc9,0x24,0x88,0x37},
  92. OID_QOS_LOG_DATA,
  93. (ULONG)-1,
  94. fPS_GUID_TO_OID
  95. },
  96. #endif
  97. //
  98. // GUID_QOS_TC_SUPPORTED
  99. //
  100. {{0xe40056dcL,0x40c8,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x59,0x15},
  101. OID_QOS_TC_SUPPORTED,
  102. -1,
  103. fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE
  104. },
  105. //
  106. // GUID_QOS_REMAINING_BANDWIDTH
  107. //
  108. {{0xc4c51720L,0x40ec,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15},
  109. OID_QOS_REMAINING_BANDWIDTH,
  110. 4,
  111. fPS_GUID_TO_OID | fPS_GUID_TO_STATUS | fPS_GUID_NOT_SETTABLE
  112. },
  113. //
  114. // GUID_QOS_BESTEFFORT_BANDWIDTH
  115. //
  116. {{0xed885290L,0x40ec,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15},
  117. OID_QOS_BESTEFFORT_BANDWIDTH,
  118. 4,
  119. fPS_GUID_TO_OID
  120. },
  121. //
  122. // GUID_QOS_HIERARCHY_CLASS
  123. //
  124. {{0xf2cc20c0,0x70c7,0x11d1,0xab,0x5c,0x0,0xa0,0xc9,0x24,0x88,0x37},
  125. OID_QOS_HIERARCHY_CLASS,
  126. 4,
  127. fPS_GUID_TO_OID
  128. },
  129. //
  130. // GUID_QOS_LATENCY
  131. //
  132. {{0xfc408ef0L,0x40ec,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15},
  133. OID_QOS_LATENCY,
  134. 4,
  135. fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE
  136. },
  137. //
  138. // GUID_QOS_FLOW_COUNT
  139. //
  140. {{0x1147f880L,0x40ed,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15},
  141. OID_QOS_FLOW_COUNT,
  142. 4,
  143. fPS_GUID_TO_OID | fPS_GUID_TO_STATUS | fPS_GUID_NOT_SETTABLE
  144. },
  145. //
  146. // GUID_QOS_NON_BESTEFFORT_LIMIT
  147. //
  148. {{0x185c44e0L,0x40ed,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15},
  149. OID_QOS_NON_BESTEFFORT_LIMIT,
  150. 4,
  151. fPS_GUID_TO_OID
  152. },
  153. //
  154. // GUID_QOS_SCHEDULING_PROFILES_SUPPORTED
  155. //
  156. {{0x1ff890f0L,0x40ed,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15},
  157. OID_QOS_SCHEDULING_PROFILES_SUPPORTED,
  158. 8,
  159. fPS_GUID_TO_OID
  160. },
  161. //
  162. // GUID_QOS_CURRENT_SCHEDULING_PROFILE
  163. //
  164. {{0x2966ed30L,0x40ed,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15},
  165. OID_QOS_CURRENT_SCHEDULING_PROFILE,
  166. -1,
  167. fPS_GUID_TO_OID | fPS_GUID_UNICODE_STRING | fPS_GUID_NOT_SETTABLE
  168. },
  169. //
  170. // GUID_QOS_MAX_OUTSTANDING_SENDS
  171. //
  172. {{0x161ffa86L,0x6120,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15},
  173. OID_QOS_MAX_OUTSTANDING_SENDS,
  174. 4,
  175. fPS_GUID_TO_OID
  176. },
  177. //
  178. // GUID_QOS_DISABLE_DRR
  179. //
  180. {{0x1fa6dc7aL,0x6120,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15},
  181. OID_QOS_DISABLE_DRR,
  182. 4,
  183. fPS_GUID_TO_OID
  184. },
  185. //
  186. // GUID_QOS_STATISTICS_BUFFER
  187. //
  188. {{0xbb2c0980L,0xe900,0x11d1,0xb0,0x7e,0x00,0x80,0xc7,0x13,0x82,0xbf},
  189. OID_QOS_STATISTICS_BUFFER,
  190. -1,
  191. fPS_GUID_TO_OID
  192. },
  193. //
  194. // GUID_QOS_TC_INTERFACE_UP_INDICATION
  195. //
  196. {{0x0ca13af0L,0x46c4,0x11d1,0x78,0xac,0x00,0x80,0x5f,0x68,0x35,0x1e},
  197. NDIS_STATUS_INTERFACE_UP,
  198. 8,
  199. fPS_GUID_TO_STATUS | fPS_GUID_EVENT_ENABLED | fPS_GUID_EVENT_PERMANENT
  200. },
  201. //
  202. // GUID_QOS_TC_INTERFACE_DOWN_INDICATION
  203. //
  204. {{0xaf5315e4L,0xce61,0x11d1,0x7c,0x8a,0x00,0xc0,0x4f,0xc9,0xb5,0x7c},
  205. NDIS_STATUS_INTERFACE_DOWN,
  206. 8,
  207. fPS_GUID_TO_STATUS | fPS_GUID_EVENT_ENABLED | fPS_GUID_EVENT_PERMANENT
  208. },
  209. //
  210. // GUID_QOS_TC_INTERFACE_CHANGE_INDICATION
  211. //
  212. {{0xda76a254L,0xce61,0x11d1,0x7c,0x8a,0x00,0xc0,0x4f,0xc9,0xb5,0x7c},
  213. NDIS_STATUS_INTERFACE_CHANGE,
  214. 8,
  215. fPS_GUID_TO_STATUS | fPS_GUID_EVENT_ENABLED | fPS_GUID_EVENT_PERMANENT
  216. },
  217. //
  218. // GUID_QOS_FLOW_MODE
  219. //
  220. {{0x5c82290aL,0x515a,0x11d2,0x8e,0x58,0x00,0xc0,0x4f,0xc9,0xbf,0xcb},
  221. OID_QOS_FLOW_MODE,
  222. 4,
  223. fPS_GUID_TO_OID
  224. },
  225. //
  226. // GUID_QOS_ISSLOW_FLOW
  227. //
  228. {{0xabf273a4,0xee07,0x11d2,0xbe,0x1b,0x00,0xa0,0xc9,0x9e,0xe6,0x3b},
  229. OID_QOS_ISSLOW_FLOW,
  230. 4,
  231. fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE
  232. },
  233. //
  234. // GUID_QOS_TIMER_RESOLUTION
  235. //
  236. {{0xba10cc88,0xf13e,0x11d2,0xbe,0x1b,0x00,0xa0,0xc9,0x9e,0xe6,0x3b},
  237. OID_QOS_TIMER_RESOLUTION,
  238. 4,
  239. fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE
  240. },
  241. //
  242. // GUID_QOS_FLOW_IP_CONFORMING
  243. //
  244. {{0x07f99a8b, 0xfcd2, 0x11d2, 0xbe, 0x1e, 0x00, 0xa0, 0xc9, 0x9e, 0xe6, 0x3b},
  245. OID_QOS_FLOW_IP_CONFORMING,
  246. 4,
  247. fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE
  248. },
  249. //
  250. // GUID_QOS_FLOW_IP_NONCONFORMING
  251. //
  252. {{0x087a5987, 0xfcd2, 0x11d2, 0xbe, 0x1e, 0x00, 0xa0, 0xc9, 0x9e, 0xe6, 0x3b},
  253. OID_QOS_FLOW_IP_NONCONFORMING,
  254. 4,
  255. fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE
  256. },
  257. //
  258. // GUID_QOS_FLOW_8021P_CONFORMING
  259. //
  260. {{0x08c1e013, 0xfcd2, 0x11d2, 0xbe, 0x1e, 0x00, 0xa0, 0xc9, 0x9e, 0xe6, 0x3b},
  261. OID_QOS_FLOW_8021P_CONFORMING,
  262. 4,
  263. fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE
  264. },
  265. //
  266. // GUID_QOS_FLOW_8021P_NONCONFORMING
  267. //
  268. {{0x09023f91, 0xfcd2, 0x11d2, 0xbe, 0x1e, 0x00, 0xa0, 0xc9, 0x9e, 0xe6, 0x3b},
  269. OID_QOS_FLOW_8021P_NONCONFORMING,
  270. 4,
  271. fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE
  272. },
  273. //
  274. // GUID_QOS_ENABLE_AVG_STATS
  275. //
  276. {{0xbafb6d11, 0x27c4, 0x4801, 0xa4, 0x6f, 0xef, 0x80, 0x80, 0xc1, 0x88, 0xc8},
  277. OID_QOS_ENABLE_AVG_STATS,
  278. 4,
  279. fPS_GUID_TO_OID
  280. },
  281. //
  282. // GUID_QOS_ENABLE_WINDOW_ADJUSTMENT
  283. //
  284. {{0xaa966725, 0xd3e9, 0x4c55, 0xb3, 0x35, 0x2a, 0x0, 0x27, 0x9a, 0x1e, 0x64},
  285. OID_QOS_ENABLE_WINDOW_ADJUSTMENT,
  286. 4,
  287. fPS_GUID_TO_OID
  288. }
  289. };
  290. NTSTATUS
  291. PsWmiGetGuid(
  292. OUT PNDIS_GUID *ppNdisGuid,
  293. IN LPGUID guid,
  294. IN NDIS_OID Oid
  295. )
  296. /*++
  297. Routine Description:
  298. Arguments:
  299. Return Value:
  300. --*/
  301. {
  302. UINT c;
  303. PNDIS_GUID pNdisGuid;
  304. NDIS_STATUS RetStatus = STATUS_UNSUCCESSFUL;
  305. //
  306. // Search the custom GUIDs
  307. //
  308. for (c = 0, pNdisGuid = gPschedSupportedGuids;
  309. (c < NUMBER_QOS_GUIDS);
  310. c++, pNdisGuid++)
  311. {
  312. //
  313. // Make sure that we have a supported GUID and the GUID maps
  314. // to an OID.
  315. //
  316. if (NULL != guid)
  317. {
  318. //
  319. // We are to look for a guid to oid mapping.
  320. //
  321. if (NdisEqualMemory(&pNdisGuid->Guid, guid, sizeof(GUID)))
  322. {
  323. //
  324. // We found the GUID, save the OID that we will need to
  325. // send to the miniport.
  326. //
  327. RetStatus = STATUS_SUCCESS;
  328. *ppNdisGuid = pNdisGuid;
  329. break;
  330. }
  331. }
  332. else
  333. {
  334. //
  335. // We need to find the quid for the status indication
  336. //
  337. if (PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_TO_STATUS) &&
  338. (pNdisGuid->Oid == Oid))
  339. {
  340. RetStatus = STATUS_SUCCESS;
  341. *ppNdisGuid = pNdisGuid;
  342. break;
  343. }
  344. }
  345. }
  346. return(RetStatus);
  347. }
  348. NTSTATUS
  349. PsWmiRegister(
  350. IN ULONG_PTR RegistrationType,
  351. IN PWMIREGINFO wmiRegInfo,
  352. IN ULONG wmiRegInfoSize,
  353. IN PULONG pReturnSize
  354. )
  355. /*++
  356. Routine Description:
  357. Arguments:
  358. Return Value:
  359. --*/
  360. {
  361. PWMIREGINFO pwri;
  362. ULONG SizeNeeded = 0;
  363. PNDIS_GUID pguid;
  364. PWMIREGGUID pwrg;
  365. PUCHAR ptmp;
  366. NTSTATUS Status;
  367. UINT c;
  368. //
  369. // Initialize the return size.
  370. //
  371. *pReturnSize = 0;
  372. //
  373. // Is this a register request?
  374. //
  375. if (WMIREGISTER == RegistrationType)
  376. {
  377. //
  378. // Determine the amount of space needed for the GUIDs, the MOF and the
  379. // registry path
  380. //
  381. SizeNeeded = sizeof(WMIREGINFO) +
  382. (NUMBER_QOS_GUIDS * sizeof(WMIREGGUID)) +
  383. //(sizeof(MOF_RESOURCE_NAME) - sizeof(WCHAR) + sizeof(USHORT)) +
  384. (PsMpName.Length + sizeof(USHORT));
  385. //
  386. // We need to give this above information back to WMI.
  387. //
  388. if (wmiRegInfoSize < SizeNeeded)
  389. {
  390. PsAssert(wmiRegInfoSize >= 4);
  391. *((PULONG)wmiRegInfo) = SizeNeeded ;
  392. *pReturnSize = sizeof(ULONG);
  393. Status = STATUS_SUCCESS;
  394. PsDbgOut(DBG_TRACE, DBG_WMI,
  395. ("[PsWmiRegister]: Insufficient buffer space for WMI registration information.\n"));
  396. return Status;
  397. }
  398. //
  399. // Get a pointer to the buffer passed in.
  400. //
  401. pwri = wmiRegInfo;
  402. *pReturnSize = SizeNeeded;
  403. NdisZeroMemory(pwri, SizeNeeded);
  404. pwri->BufferSize = SizeNeeded;
  405. //
  406. // Copy the GUIDs
  407. //
  408. pwri->GuidCount = NUMBER_QOS_GUIDS;
  409. for(c = 0, pwrg = pwri->WmiRegGuid, pguid = gPschedSupportedGuids;
  410. c < NUMBER_QOS_GUIDS;
  411. c++, pguid++, pwrg++)
  412. {
  413. RtlCopyMemory(&pwrg->Guid, &pguid->Guid, sizeof(GUID));
  414. }
  415. //
  416. // Fill in the registry path
  417. //
  418. ptmp = (PUCHAR)pwrg;
  419. pwri->RegistryPath = (ULONG)((ULONG_PTR)ptmp - (ULONG_PTR)pwri);
  420. *((PUSHORT)ptmp) = PsMpName.Length;
  421. ptmp += sizeof(USHORT);
  422. RtlCopyMemory(ptmp, PsMpName.Buffer, PsMpName.Length);
  423. /*
  424. //
  425. // Get a pointer to the destination for the MOF name.
  426. //
  427. ptmp += PsMpName.Length;
  428. //
  429. // Save the offset to the mof resource.
  430. //
  431. /*
  432. pwri->MofResourceName = (ULONG)((ULONG_PTR)ptmp - (ULONG_PTR)pwri);
  433. *((PUSHORT)ptmp) = sizeof(MOF_RESOURCE_NAME) - sizeof(WCHAR);
  434. ptmp += sizeof(USHORT);
  435. //
  436. // Copy the mof name into the wri buffer.
  437. //
  438. RtlCopyMemory(ptmp, MOF_RESOURCE_NAME, sizeof(MOF_RESOURCE_NAME) - sizeof(WCHAR));
  439. */
  440. Status = STATUS_SUCCESS;
  441. }
  442. else
  443. {
  444. PsDbgOut(DBG_FAILURE, DBG_WMI,
  445. ("[PsWmiRegister]: Unsupported registration type\n"));
  446. Status = STATUS_INVALID_PARAMETER;
  447. }
  448. return(Status);
  449. }
  450. NTSTATUS
  451. PsTcNotify(IN PADAPTER Adapter,
  452. IN PPS_WAN_LINK WanLink,
  453. IN NDIS_OID Oid,
  454. IN PVOID StatusBuffer,
  455. IN ULONG StatusBufferSize)
  456. {
  457. KIRQL OldIrql;
  458. NTSTATUS NtStatus = STATUS_SUCCESS;
  459. do
  460. {
  461. PWCHAR pInstanceName;
  462. USHORT cbInstanceName;
  463. PWNODE_SINGLE_INSTANCE wnode;
  464. ULONG wnodeSize;
  465. ULONG DataBlockSize = 0;
  466. ULONG InstanceNameSize = 0;
  467. ULONG BufSize;
  468. PUCHAR ptmp;
  469. PNDIS_GUID pNdisGuid;
  470. REFADD(&Adapter->RefCount, 'WMIN');
  471. if(Adapter->MediaType == NdisMediumWan) {
  472. if(!WanLink) {
  473. REFDEL(&Adapter->RefCount, FALSE, 'WMIN');
  474. return STATUS_UNSUCCESSFUL;
  475. }
  476. PS_LOCK(&WanLink->Lock);
  477. if(WanLink->State != WanStateOpen) {
  478. PS_UNLOCK(&WanLink->Lock);
  479. REFDEL(&Adapter->RefCount, FALSE, 'WMIN');
  480. return STATUS_UNSUCCESSFUL;
  481. }
  482. else {
  483. REFADD(&WanLink->RefCount, 'WMIN');
  484. PS_UNLOCK(&WanLink->Lock);
  485. }
  486. pInstanceName = WanLink->InstanceName.Buffer;
  487. cbInstanceName = WanLink->InstanceName.Length;
  488. }
  489. else {
  490. //
  491. // Get nice pointers to the instance names.
  492. //
  493. pInstanceName = Adapter->WMIInstanceName.Buffer;
  494. cbInstanceName = Adapter->WMIInstanceName.Length;
  495. }
  496. //
  497. // If there is no instance name then we can't indicate an event.
  498. //
  499. if (NULL == pInstanceName)
  500. {
  501. NtStatus = STATUS_UNSUCCESSFUL;
  502. break;
  503. }
  504. //
  505. // Check to see if the status is enabled for WMI event indication.
  506. //
  507. NtStatus = PsWmiGetGuid(&pNdisGuid, NULL, Oid);
  508. if ((!NT_SUCCESS(NtStatus)) ||
  509. !PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_EVENT_ENABLED))
  510. {
  511. NtStatus = STATUS_UNSUCCESSFUL;
  512. break;
  513. }
  514. //
  515. // Determine the amount of wnode information we need.
  516. //
  517. wnodeSize = ALIGN(sizeof(WNODE_SINGLE_INSTANCE));
  518. //
  519. // If the data item is an array then we need to add in the number of
  520. // elements.
  521. //
  522. if (PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_ARRAY))
  523. {
  524. DataBlockSize = StatusBufferSize + sizeof(ULONG);
  525. }
  526. else
  527. {
  528. DataBlockSize = StatusBufferSize;
  529. }
  530. //
  531. // We have a guid registered and active.
  532. //
  533. //
  534. // The data has to start at a word boundary, so need to align everything before it (the wnode and the
  535. // instance name)
  536. //
  537. InstanceNameSize = ALIGN(cbInstanceName + sizeof(USHORT));
  538. BufSize = wnodeSize + InstanceNameSize + DataBlockSize;
  539. wnode = ExAllocatePoolWithTag(NonPagedPool, BufSize, WMITag);
  540. if (NULL == wnode)
  541. {
  542. NtStatus = STATUS_UNSUCCESSFUL;
  543. break;
  544. }
  545. NdisZeroMemory(wnode, BufSize);
  546. wnode->WnodeHeader.BufferSize = BufSize;
  547. wnode->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(PsDeviceObject);
  548. wnode->WnodeHeader.Version = 1;
  549. KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
  550. RtlCopyMemory(&wnode->WnodeHeader.Guid, &pNdisGuid->Guid, sizeof(GUID));
  551. wnode->WnodeHeader.Flags = WNODE_FLAG_EVENT_ITEM |
  552. WNODE_FLAG_SINGLE_INSTANCE;
  553. wnode->OffsetInstanceName = wnodeSize;
  554. wnode->DataBlockOffset = wnodeSize + InstanceNameSize;
  555. wnode->SizeDataBlock = DataBlockSize;
  556. //
  557. // Get a pointer to the start of the data block.
  558. //
  559. ptmp = (PUCHAR)wnode + wnodeSize;
  560. //
  561. // Copy in the instance name. wnodesize is already aligned to 8 byte boundary, so the instance
  562. // name will begin at a 8 byte boundary.
  563. //
  564. *((PUSHORT)ptmp) = cbInstanceName;
  565. NdisMoveMemory(ptmp + sizeof(USHORT), pInstanceName, cbInstanceName);
  566. //
  567. // Increment ptmp to the start of the data block.
  568. //
  569. ptmp = (PUCHAR)wnode + wnode->DataBlockOffset;
  570. //
  571. // Copy in the data.
  572. //
  573. if (PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_ARRAY))
  574. {
  575. //
  576. // If the status is an array but there is no data then complete it with no
  577. // data and a 0 length
  578. //
  579. if ((NULL == StatusBuffer) || (0 == StatusBufferSize))
  580. {
  581. *((PULONG)ptmp) = 0;
  582. }
  583. else
  584. {
  585. //
  586. // Save the number of elements in the first ULONG.
  587. //
  588. *((PULONG)ptmp) = StatusBufferSize / pNdisGuid->Size;
  589. //
  590. // Copy the data after the number of elements.
  591. //
  592. NdisMoveMemory(ptmp + sizeof(ULONG), StatusBuffer, StatusBufferSize);
  593. }
  594. }
  595. else
  596. {
  597. PsAssert(StatusBuffer != NULL);
  598. //
  599. // Do we indicate any data up?
  600. //
  601. if (0 != DataBlockSize)
  602. {
  603. //
  604. // Copy the data into the buffer.
  605. //
  606. NdisMoveMemory(ptmp, StatusBuffer, DataBlockSize);
  607. }
  608. }
  609. //
  610. // Indicate the event to WMI. WMI will take care of freeing
  611. // the WMI struct back to pool.
  612. //
  613. NtStatus = IoWMIWriteEvent(wnode);
  614. if (!NT_SUCCESS(NtStatus))
  615. {
  616. PsDbgOut(DBG_FAILURE, DBG_WMI,
  617. ("[PsTcNotify]: Adapter %08X, Unable to indicate the WMI event.\n", Adapter));
  618. ExFreePool(wnode);
  619. }
  620. } while (FALSE);
  621. REFDEL(&Adapter->RefCount, FALSE, 'WMIN');
  622. if(WanLink) {
  623. REFDEL(&WanLink->RefCount, FALSE, 'WMIN');
  624. }
  625. return NtStatus;
  626. }
  627. NTSTATUS
  628. FASTCALL
  629. PsWmiEnableEvents(
  630. IN LPGUID Guid
  631. )
  632. /*++
  633. Routine Description:
  634. Arguments:
  635. Return Value:
  636. --*/
  637. {
  638. NTSTATUS Status;
  639. PNDIS_GUID pNdisGuid;
  640. do
  641. {
  642. //
  643. // Get a pointer to the Guid/Status to enable.
  644. //
  645. Status = PsWmiGetGuid(&pNdisGuid, Guid, 0);
  646. if (!NT_SUCCESS(Status))
  647. {
  648. PsDbgOut(DBG_FAILURE, DBG_WMI,
  649. ("[PsWmiEnableEvents]: Cannot find the guid to enable an event\n"));
  650. Status = STATUS_INVALID_PARAMETER;
  651. break;
  652. }
  653. //
  654. // Is this GUID an event indication?
  655. //
  656. if (!PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_TO_STATUS))
  657. {
  658. PsDbgOut(DBG_FAILURE, DBG_WMI,
  659. ("[PsWmiEnableEvents]: Guid is not an event request \n"));
  660. Status = STATUS_INVALID_DEVICE_REQUEST;
  661. break;
  662. }
  663. //
  664. // Mark the guid as enabled
  665. //
  666. PS_GUID_SET_FLAG(pNdisGuid, fPS_GUID_EVENT_ENABLED);
  667. Status = STATUS_SUCCESS;
  668. } while (FALSE);
  669. return(Status);
  670. }
  671. NTSTATUS
  672. FASTCALL
  673. PsWmiDisableEvents(
  674. IN LPGUID Guid
  675. )
  676. /*++
  677. Routine Description:
  678. Arguments:
  679. Return Value:
  680. --*/
  681. {
  682. NTSTATUS Status;
  683. PNDIS_GUID pNdisGuid;
  684. do
  685. {
  686. //
  687. // Get a pointer to the Guid/Status to enable.
  688. //
  689. Status = PsWmiGetGuid(&pNdisGuid, Guid, 0);
  690. if (!NT_SUCCESS(Status))
  691. {
  692. PsDbgOut(DBG_FAILURE, DBG_WMI,
  693. ("[PsWmiDisableEvents]: Cannot find the guid to disable an event\n"));
  694. Status = STATUS_INVALID_PARAMETER;
  695. break;
  696. }
  697. //
  698. // Is this GUID an event indication?
  699. //
  700. if (!PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_TO_STATUS))
  701. {
  702. PsDbgOut(DBG_FAILURE, DBG_WMI,
  703. ("[PsWmiDisableEvents]: Guid is not an event request \n"));
  704. Status = STATUS_INVALID_DEVICE_REQUEST;
  705. break;
  706. }
  707. if(!PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_EVENT_PERMANENT)) {
  708. //
  709. // Mark the guid as disabled
  710. //
  711. PS_GUID_CLEAR_FLAG(pNdisGuid, fPS_GUID_EVENT_ENABLED);
  712. }
  713. Status = STATUS_SUCCESS;
  714. } while (FALSE);
  715. return(Status);
  716. }
  717. #define WMI_BUFFER_TOO_SMALL(_BufferSize, _Wnode, _WnodeSize, _pStatus, _pRSize) \
  718. { \
  719. if ((_BufferSize) < sizeof(WNODE_TOO_SMALL)) \
  720. { \
  721. *(_pStatus) = STATUS_BUFFER_TOO_SMALL; \
  722. } \
  723. else \
  724. { \
  725. (_Wnode)->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL); \
  726. (_Wnode)->WnodeHeader.Flags |= WNODE_FLAG_TOO_SMALL; \
  727. ((PWNODE_TOO_SMALL)(_Wnode))->SizeNeeded = (_WnodeSize); \
  728. *(_pRSize) = sizeof(WNODE_TOO_SMALL); \
  729. *(_pStatus) = STATUS_SUCCESS; \
  730. } \
  731. }
  732. NTSTATUS
  733. PsQueryGuidDataSize(
  734. PADAPTER Adapter,
  735. PPS_WAN_LINK WanLink,
  736. PGPC_CLIENT_VC Vc,
  737. NDIS_OID Oid,
  738. PULONG BytesNeeded)
  739. {
  740. ULONG Len;
  741. ULONG BytesWritten;
  742. NDIS_STATUS Status;
  743. PAGED_CODE();
  744. if(Vc)
  745. {
  746. switch(Oid)
  747. {
  748. case OID_QOS_STATISTICS_BUFFER:
  749. // If the query comes for a VC, then we return per flow stats
  750. // else we return per adapter stats. The query is also sent through
  751. // the scheduling components, so that they can fill in the per flow
  752. // or per query stats.
  753. //
  754. Len = 0;
  755. BytesWritten = 0;
  756. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  757. *BytesNeeded = 0;
  758. (*Vc->PsComponent->QueryInformation)
  759. (Vc->PsPipeContext,
  760. Vc->PsFlowContext,
  761. Oid,
  762. Len,
  763. NULL,
  764. &BytesWritten,
  765. BytesNeeded,
  766. &Status);
  767. *BytesNeeded += sizeof(PS_FLOW_STATS) + FIELD_OFFSET(PS_COMPONENT_STATS, Stats);
  768. return STATUS_SUCCESS;
  769. case OID_QOS_ISSLOW_FLOW:
  770. case OID_QOS_FLOW_IP_CONFORMING:
  771. case OID_QOS_FLOW_IP_NONCONFORMING:
  772. case OID_QOS_FLOW_8021P_CONFORMING:
  773. case OID_QOS_FLOW_8021P_NONCONFORMING:
  774. *BytesNeeded = sizeof(ULONG);
  775. return STATUS_SUCCESS;
  776. default:
  777. return STATUS_WMI_NOT_SUPPORTED;
  778. }
  779. }
  780. //
  781. // The following OIDs are similar for both WAN and Adapters
  782. //
  783. switch(Oid)
  784. {
  785. //
  786. // (12636): The following will be enabled when we do admission control over WAN.
  787. // case OID_QOS_REMAINING_BANDWIDTH:
  788. // case OID_QOS_NON_BESTEFFORT_LIMIT:
  789. //
  790. case OID_QOS_BESTEFFORT_BANDWIDTH:
  791. case OID_QOS_LATENCY:
  792. case OID_QOS_FLOW_COUNT:
  793. case OID_QOS_FLOW_MODE:
  794. case OID_QOS_MAX_OUTSTANDING_SENDS:
  795. case OID_QOS_DISABLE_DRR:
  796. case OID_QOS_TIMER_RESOLUTION:
  797. case OID_QOS_ENABLE_AVG_STATS:
  798. case OID_QOS_ENABLE_WINDOW_ADJUSTMENT:
  799. #if DBG
  800. case OID_QOS_LOG_BUFFER_SIZE:
  801. case OID_QOS_LOG_THRESHOLD:
  802. case OID_QOS_LOG_LEVEL:
  803. case OID_QOS_LOG_MASK:
  804. #endif
  805. *BytesNeeded = sizeof(ULONG);
  806. return STATUS_SUCCESS;
  807. #if DBG
  808. case OID_QOS_LOG_DATA:
  809. *BytesNeeded = SchedtGetBytesUnread();
  810. return STATUS_SUCCESS;
  811. #endif
  812. case OID_QOS_CURRENT_SCHEDULING_PROFILE:
  813. if(!Adapter->ProfileName.Buffer) {
  814. *BytesNeeded = sizeof(DefaultProfile);
  815. }
  816. else {
  817. *BytesNeeded = Adapter->ProfileName.Length;
  818. }
  819. return STATUS_SUCCESS;
  820. }
  821. //
  822. // OIDs that are WAN link specific
  823. //
  824. if(WanLink)
  825. {
  826. switch(Oid)
  827. {
  828. case OID_QOS_HIERARCHY_CLASS:
  829. {
  830. Len = 0;
  831. BytesWritten = 0;
  832. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  833. *BytesNeeded = 0;
  834. (*WanLink->PsComponent->QueryInformation)
  835. (WanLink->PsPipeContext,
  836. 0,
  837. Oid,
  838. Len,
  839. NULL,
  840. &BytesWritten,
  841. BytesNeeded,
  842. &Status);
  843. return STATUS_SUCCESS;
  844. }
  845. case OID_QOS_STATISTICS_BUFFER:
  846. {
  847. Len = 0;
  848. BytesWritten = 0;
  849. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  850. *BytesNeeded = 0;
  851. (*WanLink->PsComponent->QueryInformation)
  852. (WanLink->PsPipeContext,
  853. NULL,
  854. Oid,
  855. Len,
  856. NULL,
  857. &BytesWritten,
  858. BytesNeeded,
  859. &Status);
  860. *BytesNeeded += sizeof(PS_ADAPTER_STATS) + FIELD_OFFSET(PS_COMPONENT_STATS, Stats);
  861. return STATUS_SUCCESS;
  862. }
  863. case OID_QOS_TC_SUPPORTED:
  864. *BytesNeeded = 0;
  865. CollectWanNetworkAddresses(Adapter, WanLink, BytesNeeded, NULL);
  866. return STATUS_SUCCESS;
  867. default:
  868. return STATUS_WMI_NOT_SUPPORTED;
  869. }
  870. }
  871. if(Adapter->MediaType != NdisMediumWan)
  872. {
  873. switch(Oid)
  874. {
  875. case OID_QOS_TC_SUPPORTED:
  876. *BytesNeeded = 0;
  877. CollectNetworkAddresses(Adapter, BytesNeeded, NULL);
  878. return STATUS_SUCCESS;
  879. //
  880. // (12636): Take the next 2 case statements away when we turn on admission control over WAN links.
  881. //
  882. case OID_QOS_REMAINING_BANDWIDTH:
  883. case OID_QOS_NON_BESTEFFORT_LIMIT:
  884. *BytesNeeded = sizeof(ULONG);
  885. return STATUS_SUCCESS;
  886. case OID_QOS_HIERARCHY_CLASS:
  887. {
  888. Len = 0;
  889. BytesWritten = 0;
  890. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  891. *BytesNeeded = 0;
  892. (*Adapter->PsComponent->QueryInformation)
  893. (Adapter->PsPipeContext,
  894. 0,
  895. Oid,
  896. Len,
  897. NULL,
  898. &BytesWritten,
  899. BytesNeeded,
  900. &Status);
  901. return STATUS_SUCCESS;
  902. }
  903. case OID_QOS_STATISTICS_BUFFER:
  904. {
  905. Len = 0;
  906. BytesWritten = 0;
  907. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  908. *BytesNeeded = 0;
  909. (*Adapter->PsComponent->QueryInformation)
  910. (Adapter->PsPipeContext,
  911. NULL,
  912. Oid,
  913. Len,
  914. NULL,
  915. &BytesWritten,
  916. BytesNeeded,
  917. &Status);
  918. *BytesNeeded += sizeof(PS_ADAPTER_STATS) + FIELD_OFFSET(PS_COMPONENT_STATS, Stats);
  919. return STATUS_SUCCESS;
  920. }
  921. default:
  922. return STATUS_WMI_NOT_SUPPORTED;
  923. }
  924. }
  925. return STATUS_WMI_NOT_SUPPORTED;
  926. }
  927. NTSTATUS
  928. PsQueryGuidData(
  929. PADAPTER Adapter,
  930. PPS_WAN_LINK WanLink,
  931. PGPC_CLIENT_VC Vc,
  932. NDIS_OID Oid,
  933. PVOID Buffer,
  934. ULONG BufferSize)
  935. {
  936. UNALIGNED PULONG pData = (UNALIGNED PULONG) Buffer;
  937. ULONG Len;
  938. ULONG BytesNeeded;
  939. ULONG BytesWritten;
  940. PUCHAR Data;
  941. NDIS_STATUS Status;
  942. PPS_COMPONENT_STATS Cstats;
  943. PsAssert(((ULONGLONG)pData % sizeof(PULONG)) == 0);
  944. if(Vc)
  945. {
  946. switch(Oid)
  947. {
  948. case OID_QOS_FLOW_IP_CONFORMING:
  949. *pData = (((PCF_INFO_QOS)(Vc->CfInfoQoS))->ToSValue) >> 2;
  950. return STATUS_SUCCESS;
  951. case OID_QOS_FLOW_IP_NONCONFORMING:
  952. *pData = (Vc->IPPrecedenceNonConforming >> 2);
  953. return STATUS_SUCCESS;
  954. case OID_QOS_FLOW_8021P_CONFORMING:
  955. *pData = Vc->UserPriorityConforming;
  956. return STATUS_SUCCESS;
  957. case OID_QOS_FLOW_8021P_NONCONFORMING:
  958. *pData = Vc->UserPriorityNonConforming;
  959. return STATUS_SUCCESS;
  960. case OID_QOS_ISSLOW_FLOW:
  961. *pData = (Vc->Flags & GPC_ISSLOW_FLOW)?TRUE:FALSE;
  962. return STATUS_SUCCESS;
  963. case OID_QOS_STATISTICS_BUFFER:
  964. // If the query comes for a VC, then we return per flow stats
  965. // else we return per adapter stats. The query is also sent through
  966. // the scheduling components, so that they can fill in the per flow
  967. // or per query stats.
  968. //
  969. Len = BufferSize;
  970. BytesNeeded = 0;
  971. BytesWritten;
  972. BytesWritten = sizeof(PS_FLOW_STATS) + FIELD_OFFSET(PS_COMPONENT_STATS, Stats);
  973. Cstats = (PPS_COMPONENT_STATS) Buffer;
  974. Cstats->Type = PS_COMPONENT_FLOW;
  975. Cstats->Length = sizeof(PS_FLOW_STATS);
  976. NdisMoveMemory(&Cstats->Stats,
  977. &Vc->Stats,
  978. sizeof(PS_FLOW_STATS));
  979. Status = NDIS_STATUS_SUCCESS;
  980. Data = (PVOID)( (PUCHAR) Buffer + BytesWritten);
  981. (*Vc->PsComponent->QueryInformation)
  982. (Vc->PsPipeContext,
  983. Vc->PsFlowContext,
  984. Oid,
  985. Len,
  986. Data,
  987. &BytesWritten,
  988. &BytesNeeded,
  989. &Status);
  990. return Status;
  991. default:
  992. return STATUS_WMI_NOT_SUPPORTED;
  993. }
  994. }
  995. //
  996. // The Following OIDs are similar for both WAN and Adapters
  997. //
  998. switch(Oid)
  999. {
  1000. case OID_QOS_CURRENT_SCHEDULING_PROFILE:
  1001. if(!Adapter->ProfileName.Buffer)
  1002. {
  1003. NdisMoveMemory(Buffer,
  1004. &DefaultProfile,
  1005. sizeof(DefaultProfile));
  1006. }
  1007. else {
  1008. NdisMoveMemory(Buffer,
  1009. &Adapter->ProfileName.Buffer,
  1010. Adapter->ProfileName.Length);
  1011. }
  1012. return STATUS_SUCCESS;
  1013. case OID_QOS_DISABLE_DRR:
  1014. *pData = (Adapter->PipeFlags & PS_DISABLE_DRR)?1:0;
  1015. return STATUS_SUCCESS;
  1016. case OID_QOS_MAX_OUTSTANDING_SENDS:
  1017. *pData = Adapter->MaxOutstandingSends;
  1018. return STATUS_SUCCESS;
  1019. case OID_QOS_BESTEFFORT_BANDWIDTH:
  1020. PS_LOCK(&Adapter->Lock);
  1021. *pData = Adapter->BestEffortLimit;
  1022. PS_UNLOCK(&Adapter->Lock);
  1023. return STATUS_SUCCESS;
  1024. case OID_QOS_TIMER_RESOLUTION:
  1025. *pData = gTimerResolutionActualTime/10;
  1026. return STATUS_SUCCESS;
  1027. case OID_QOS_LATENCY:
  1028. //
  1029. // Don't have a valid measure of latency right now.
  1030. //
  1031. *pData = -1;
  1032. return STATUS_SUCCESS;
  1033. case OID_QOS_ENABLE_AVG_STATS:
  1034. *pData = gEnableAvgStats;
  1035. return STATUS_SUCCESS;
  1036. case OID_QOS_ENABLE_WINDOW_ADJUSTMENT:
  1037. *pData = gEnableWindowAdjustment;
  1038. return STATUS_SUCCESS;
  1039. #if DBG
  1040. case OID_QOS_LOG_BUFFER_SIZE:
  1041. *pData = SchedtGetBufferSize();
  1042. return STATUS_SUCCESS;
  1043. // The following is temporary until the status reporting works...
  1044. // for a query on log threshold we return the current size of the
  1045. // log rather than the threshold value... this is just an easy
  1046. // way to allow the app to poll the log size without defining a
  1047. // new GUID that would be temporary anyway.
  1048. case OID_QOS_LOG_THRESHOLD:
  1049. *pData = SchedtGetBytesUnread();
  1050. return STATUS_SUCCESS;
  1051. case OID_QOS_LOG_MASK:
  1052. *pData = LogTraceMask;
  1053. return STATUS_SUCCESS;
  1054. case OID_QOS_LOG_LEVEL:
  1055. *pData = LogTraceLevel;
  1056. return STATUS_SUCCESS;
  1057. case OID_QOS_LOG_DATA:
  1058. {
  1059. ULONG BytesRead;
  1060. DbugReadTraceBuffer(Buffer, BufferSize, &BytesRead);
  1061. return STATUS_SUCCESS;
  1062. }
  1063. #endif
  1064. }
  1065. if(WanLink)
  1066. {
  1067. switch(Oid)
  1068. {
  1069. case OID_QOS_FLOW_MODE:
  1070. {
  1071. *pData = WanLink->AdapterMode;
  1072. return STATUS_SUCCESS;
  1073. }
  1074. //
  1075. // (12636): This has to be uncommented when we do admission control over WAN links.
  1076. //
  1077. #if 0
  1078. case OID_QOS_REMAINING_BANDWIDTH:
  1079. PS_LOCK(&WanLink->Lock);
  1080. *pData = WanLink->RemainingBandWidth;
  1081. PS_UNLOCK(&WanLink->Lock);
  1082. return STATUS_SUCCESS;
  1083. case OID_QOS_NON_BESTEFFORT_LIMIT:
  1084. PS_LOCK(&WanLink->Lock);
  1085. *pData = WanLink->NonBestEffortLimit;
  1086. PS_UNLOCK(&WanLink->Lock);
  1087. return STATUS_SUCCESS;
  1088. #endif
  1089. case OID_QOS_HIERARCHY_CLASS:
  1090. {
  1091. BytesWritten = 0;
  1092. BytesNeeded = 0;
  1093. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  1094. (*WanLink->PsComponent->QueryInformation)
  1095. (WanLink->PsPipeContext,
  1096. NULL,
  1097. Oid,
  1098. BufferSize,
  1099. Buffer,
  1100. &BytesWritten,
  1101. &BufferSize,
  1102. &Status);
  1103. return STATUS_SUCCESS;
  1104. }
  1105. case OID_QOS_STATISTICS_BUFFER:
  1106. // If the query comes for a VC, then we return per flow stats
  1107. // else we return per adapter stats. The query is also sent through
  1108. // the scheduling components, so that they can fill in the per flow
  1109. // or per query stats.
  1110. //
  1111. Len = BufferSize;
  1112. BytesNeeded = 0;
  1113. BytesWritten;
  1114. BytesWritten = sizeof(PS_ADAPTER_STATS) + FIELD_OFFSET(PS_COMPONENT_STATS, Stats);
  1115. Cstats = (PPS_COMPONENT_STATS) Buffer;
  1116. Cstats->Type = PS_COMPONENT_ADAPTER;
  1117. Cstats->Length = sizeof(PS_ADAPTER_STATS);
  1118. NdisMoveMemory(&Cstats->Stats,
  1119. &WanLink->Stats,
  1120. sizeof(PS_ADAPTER_STATS));
  1121. Status = NDIS_STATUS_SUCCESS;
  1122. Data = (PVOID)( (PUCHAR) Buffer + BytesWritten);
  1123. (*WanLink->PsComponent->QueryInformation)
  1124. (WanLink->PsPipeContext,
  1125. NULL,
  1126. Oid,
  1127. Len,
  1128. Data,
  1129. &BytesWritten,
  1130. &BytesNeeded,
  1131. &Status);
  1132. return Status;
  1133. case OID_QOS_TC_SUPPORTED:
  1134. CollectWanNetworkAddresses(Adapter, WanLink, &BufferSize, Buffer);
  1135. return STATUS_SUCCESS;
  1136. case OID_QOS_FLOW_COUNT:
  1137. PS_LOCK(&WanLink->Lock);
  1138. *pData = WanLink->FlowsInstalled;
  1139. PS_UNLOCK(&WanLink->Lock);
  1140. PsAssert((LONG)*pData >= 0);
  1141. return STATUS_SUCCESS;
  1142. default:
  1143. return STATUS_WMI_NOT_SUPPORTED;
  1144. }
  1145. }
  1146. if(Adapter->MediaType != NdisMediumWan)
  1147. {
  1148. switch(Oid)
  1149. {
  1150. case OID_QOS_FLOW_MODE:
  1151. {
  1152. *pData = Adapter->AdapterMode;
  1153. return STATUS_SUCCESS;
  1154. }
  1155. case OID_QOS_HIERARCHY_CLASS:
  1156. {
  1157. BytesWritten = 0;
  1158. BytesNeeded = 0;
  1159. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  1160. (*Adapter->PsComponent->QueryInformation)
  1161. (Adapter->PsPipeContext,
  1162. NULL,
  1163. Oid,
  1164. BufferSize,
  1165. Buffer,
  1166. &BytesWritten,
  1167. &BufferSize,
  1168. &Status);
  1169. return STATUS_SUCCESS;
  1170. }
  1171. case OID_QOS_STATISTICS_BUFFER:
  1172. // If the query comes for a VC, then we return per flow stats
  1173. // else we return per adapter stats. The query is also sent through
  1174. // the scheduling components, so that they can fill in the per flow
  1175. // or per query stats.
  1176. //
  1177. Len = BufferSize;
  1178. BytesNeeded = 0;
  1179. BytesWritten;
  1180. BytesWritten = sizeof(PS_ADAPTER_STATS) + FIELD_OFFSET(PS_COMPONENT_STATS, Stats);
  1181. Cstats = (PPS_COMPONENT_STATS) Buffer;
  1182. Cstats->Type = PS_COMPONENT_ADAPTER;
  1183. Cstats->Length = sizeof(PS_ADAPTER_STATS);
  1184. NdisMoveMemory(&Cstats->Stats,
  1185. &Adapter->Stats,
  1186. sizeof(PS_ADAPTER_STATS));
  1187. Status = NDIS_STATUS_SUCCESS;
  1188. Data = (PVOID)( (PUCHAR) Buffer + BytesWritten);
  1189. (*Adapter->PsComponent->QueryInformation)
  1190. (Adapter->PsPipeContext,
  1191. NULL,
  1192. Oid,
  1193. Len,
  1194. Data,
  1195. &BytesWritten,
  1196. &BytesNeeded,
  1197. &Status);
  1198. return Status;
  1199. case OID_QOS_TC_SUPPORTED:
  1200. CollectNetworkAddresses(Adapter, &BufferSize, Buffer);
  1201. return STATUS_SUCCESS;
  1202. case OID_QOS_REMAINING_BANDWIDTH:
  1203. PS_LOCK(&Adapter->Lock);
  1204. *pData = Adapter->RemainingBandWidth;
  1205. PS_UNLOCK(&Adapter->Lock);
  1206. return STATUS_SUCCESS;
  1207. case OID_QOS_FLOW_COUNT:
  1208. PS_LOCK(&Adapter->Lock);
  1209. *pData = Adapter->FlowsInstalled;
  1210. PS_UNLOCK(&Adapter->Lock);
  1211. PsAssert((LONG)*pData >= 0);
  1212. return STATUS_SUCCESS;
  1213. case OID_QOS_NON_BESTEFFORT_LIMIT:
  1214. PS_LOCK(&Adapter->Lock);
  1215. *pData = Adapter->NonBestEffortLimit;
  1216. PS_UNLOCK(&Adapter->Lock);
  1217. return STATUS_SUCCESS;
  1218. default:
  1219. return STATUS_WMI_NOT_SUPPORTED;
  1220. }
  1221. }
  1222. return STATUS_WMI_NOT_SUPPORTED;
  1223. }
  1224. NTSTATUS
  1225. PsWmiQueryAllData(
  1226. IN LPGUID guid,
  1227. IN PWNODE_ALL_DATA wnode,
  1228. IN ULONG BufferSize,
  1229. OUT PULONG pReturnSize
  1230. )
  1231. /*++
  1232. Routine Description:
  1233. Arguments:
  1234. Return Value:
  1235. --*/
  1236. {
  1237. NTSTATUS NtStatus;
  1238. NDIS_STATUS Status;
  1239. ULONG wnodeSize = ALIGN(sizeof(WNODE_ALL_DATA));
  1240. ULONG wnodeTotalSize;
  1241. PNDIS_GUID pNdisGuid;
  1242. ULONG BytesNeeded;
  1243. UINT cRoughInstanceCount;
  1244. UINT cInstanceCount = 0;
  1245. PUCHAR pBuffer;
  1246. ULONG OffsetToInstanceNames;
  1247. PLIST_ENTRY Link;
  1248. PPS_WAN_LINK WanLink = NULL;
  1249. POFFSETINSTANCEDATAANDLENGTH poidl;
  1250. PULONG pInstanceNameOffsets;
  1251. ULONG OffsetToInstanceInfo;
  1252. BOOLEAN OutOfSpace = FALSE;
  1253. PADAPTER Adapter;
  1254. PLIST_ENTRY NextAdapter;
  1255. ULONG InstanceNameSize;
  1256. do
  1257. {
  1258. *pReturnSize = 0;
  1259. if (BufferSize < sizeof(WNODE_TOO_SMALL))
  1260. {
  1261. //
  1262. // Too small even to hold a WNODE_TOO_SMALL !
  1263. //
  1264. NtStatus = STATUS_BUFFER_TOO_SMALL;
  1265. break;
  1266. }
  1267. //
  1268. // We can maintain a global count when adapters and wanlinks go up and down rather
  1269. // than counting it here. However, QueryAllData is not a very frequently used operation to
  1270. // justify this extra code.
  1271. //
  1272. cRoughInstanceCount = 0;
  1273. PS_LOCK(&AdapterListLock);
  1274. NextAdapter = AdapterList.Flink;
  1275. while(NextAdapter != &AdapterList)
  1276. {
  1277. Adapter = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage);
  1278. NextAdapter = NextAdapter->Flink;
  1279. if(Adapter->MediaType == NdisMediumWan)
  1280. {
  1281. PS_LOCK_DPC(&Adapter->Lock);
  1282. cRoughInstanceCount += Adapter->WanLinkCount;
  1283. PS_UNLOCK_DPC(&Adapter->Lock);
  1284. }
  1285. else
  1286. {
  1287. cRoughInstanceCount += 1;
  1288. }
  1289. }
  1290. PS_UNLOCK(&AdapterListLock);
  1291. //
  1292. // Get the OID and see if we support it.
  1293. //
  1294. NtStatus = PsWmiGetGuid(&pNdisGuid, guid, 0);
  1295. if(!NT_SUCCESS(NtStatus))
  1296. {
  1297. PsDbgOut(DBG_FAILURE, DBG_WMI,
  1298. ("[PsWmiQueryAllData]: Unsupported guid \n"));
  1299. break;
  1300. }
  1301. //
  1302. // Initialize common wnode information.
  1303. //
  1304. KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
  1305. //
  1306. // Setup the OFFSETINSTANCEDATAANDLENGTH array.
  1307. //
  1308. poidl = wnode->OffsetInstanceDataAndLength;
  1309. wnode->OffsetInstanceNameOffsets = wnodeSize + (sizeof(OFFSETINSTANCEDATAANDLENGTH) * cRoughInstanceCount);
  1310. //
  1311. // Get a pointer to the array of offsets to the instance names.
  1312. //
  1313. pInstanceNameOffsets = (PULONG)((PUCHAR)wnode + wnode->OffsetInstanceNameOffsets);
  1314. //
  1315. // Get the offset from the wnode where will will start copying the instance
  1316. // data into.
  1317. //
  1318. OffsetToInstanceInfo = ALIGN(wnode->OffsetInstanceNameOffsets + (sizeof(ULONG) * cRoughInstanceCount));
  1319. //
  1320. // Get a pointer to start placing the data.
  1321. //
  1322. pBuffer = (PUCHAR)wnode + OffsetToInstanceInfo;
  1323. //
  1324. // Check to make sure we have at least this much buffer space in the wnode.
  1325. //
  1326. wnodeTotalSize = OffsetToInstanceInfo;
  1327. PS_LOCK(&AdapterListLock);
  1328. NextAdapter = AdapterList.Flink;
  1329. while(NextAdapter != &AdapterList)
  1330. {
  1331. Adapter = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage);
  1332. PS_LOCK_DPC(&Adapter->Lock);
  1333. if(Adapter->PsMpState != AdapterStateRunning)
  1334. {
  1335. PS_UNLOCK_DPC(&Adapter->Lock);
  1336. NextAdapter = NextAdapter->Flink;
  1337. continue;
  1338. }
  1339. REFADD(&Adapter->RefCount, 'WMIQ');
  1340. PS_UNLOCK_DPC(&Adapter->Lock);
  1341. PS_UNLOCK(&AdapterListLock);
  1342. if(Adapter->MediaType != NdisMediumWan)
  1343. {
  1344. NtStatus = PsQueryGuidDataSize(Adapter, NULL, NULL, pNdisGuid->Oid, &BytesNeeded);
  1345. if(NT_SUCCESS(NtStatus))
  1346. {
  1347. // Make sure we have enough buffer space for the instance name and
  1348. // the data. If not we still continue since we need to find the total
  1349. // size
  1350. InstanceNameSize = ALIGN(Adapter->WMIInstanceName.Length + sizeof(WCHAR));
  1351. wnodeTotalSize += InstanceNameSize + ALIGN(BytesNeeded);
  1352. if (BufferSize < wnodeTotalSize)
  1353. {
  1354. WMI_BUFFER_TOO_SMALL(BufferSize, wnode, wnodeTotalSize, &NtStatus, pReturnSize);
  1355. OutOfSpace = TRUE;
  1356. PS_LOCK(&AdapterListLock);
  1357. NextAdapter = NextAdapter->Flink;
  1358. REFDEL(&Adapter->RefCount, TRUE, 'WMIQ');
  1359. continue;
  1360. }
  1361. //
  1362. // We only have room for so many Instances.
  1363. //
  1364. if(cInstanceCount >= cRoughInstanceCount)
  1365. {
  1366. PsDbgOut(DBG_FAILURE, DBG_WMI,
  1367. ("[PsWmiQueryAllData]: Adapter %08X, Received more wanlinks (%d) than we counted "
  1368. "initially (%d)\n", Adapter, cInstanceCount, cRoughInstanceCount));
  1369. PS_LOCK(&AdapterListLock);
  1370. REFDEL(&Adapter->RefCount, TRUE, 'WMIQ');
  1371. break;
  1372. }
  1373. //
  1374. // Add the offset to the instance name to the table.
  1375. //
  1376. pInstanceNameOffsets[cInstanceCount] = OffsetToInstanceInfo;
  1377. //
  1378. // Copy the instance name into the wnode buffer.
  1379. //
  1380. *((PUSHORT)pBuffer) = Adapter->WMIInstanceName.Length;
  1381. NdisMoveMemory(pBuffer + sizeof(USHORT),
  1382. Adapter->WMIInstanceName.Buffer,
  1383. Adapter->WMIInstanceName.Length);
  1384. //
  1385. // Keep track of true instance counts.
  1386. //
  1387. OffsetToInstanceInfo += InstanceNameSize;
  1388. pBuffer = (PUCHAR)wnode + OffsetToInstanceInfo;
  1389. //
  1390. // Query the data
  1391. //
  1392. NtStatus = PsQueryGuidData(Adapter, NULL, NULL, pNdisGuid->Oid, pBuffer, BytesNeeded);
  1393. if(!NT_SUCCESS(NtStatus))
  1394. {
  1395. PsDbgOut(DBG_FAILURE, DBG_WMI,
  1396. ("[PsWmiQueryAllData]: Adapter %08X, Failed to query OID %08X \n", Adapter,
  1397. pNdisGuid->Oid));
  1398. PS_LOCK(&AdapterListLock);
  1399. REFDEL(&Adapter->RefCount, TRUE, 'WMIQ');
  1400. break;
  1401. }
  1402. //
  1403. // Save the length of the data item for this instance.
  1404. //
  1405. poidl[cInstanceCount].OffsetInstanceData = OffsetToInstanceInfo;
  1406. poidl[cInstanceCount].LengthInstanceData = BytesNeeded;
  1407. //
  1408. // Keep track of true instance count.
  1409. //
  1410. OffsetToInstanceInfo += ALIGN(BytesNeeded);
  1411. pBuffer = (PUCHAR)wnode + OffsetToInstanceInfo;
  1412. cInstanceCount ++;
  1413. }
  1414. }
  1415. else
  1416. {
  1417. //
  1418. // Search the Wan Links
  1419. //
  1420. PS_LOCK(&Adapter->Lock);
  1421. Link = Adapter->WanLinkList.Flink;
  1422. for(Link = Adapter->WanLinkList.Flink;
  1423. Link != &Adapter->WanLinkList;
  1424. )
  1425. {
  1426. //
  1427. // We only have room for so many Instances.
  1428. //
  1429. if(cInstanceCount >= cRoughInstanceCount)
  1430. {
  1431. PsDbgOut(DBG_FAILURE, DBG_WMI,
  1432. ("[PsWmiQueryAllData]: Adapter %08X, Received more wanlinks (%d) than we counted "
  1433. "initially (%d)\n", Adapter, cInstanceCount, cRoughInstanceCount));
  1434. break;
  1435. }
  1436. //
  1437. // Get a pointer to the WanLink.
  1438. //
  1439. WanLink = CONTAINING_RECORD(Link, PS_WAN_LINK, Linkage);
  1440. PS_LOCK_DPC(&WanLink->Lock);
  1441. //
  1442. // Check to see if the WanLink is cleaning up.
  1443. //
  1444. if(WanLink->State != WanStateOpen) {
  1445. PS_UNLOCK_DPC(&WanLink->Lock);
  1446. PsDbgOut(DBG_FAILURE, DBG_WMI,
  1447. ("[PsWmiQueryAllData]: Adapter %08X, WanLink %08X: Link not ready \n", Adapter, WanLink));
  1448. Link = Link->Flink;
  1449. continue;
  1450. }
  1451. REFADD(&WanLink->RefCount, 'WMIQ');
  1452. PS_UNLOCK_DPC(&WanLink->Lock);
  1453. PS_UNLOCK(&Adapter->Lock);
  1454. //
  1455. // If there is an instance name associated with the VC then we need to query it.
  1456. //
  1457. PsAssert(WanLink->InstanceName.Buffer);
  1458. NtStatus = PsQueryGuidDataSize(Adapter, WanLink, NULL, pNdisGuid->Oid, &BytesNeeded);
  1459. if(NT_SUCCESS(NtStatus))
  1460. {
  1461. //
  1462. // Make sure we have enough buffer space for the instance name and
  1463. // the data.
  1464. //
  1465. InstanceNameSize = ALIGN(WanLink->InstanceName.Length + sizeof(USHORT));
  1466. wnodeTotalSize += InstanceNameSize + ALIGN(BytesNeeded);
  1467. if (BufferSize < wnodeTotalSize)
  1468. {
  1469. WMI_BUFFER_TOO_SMALL(BufferSize, wnode,
  1470. wnodeTotalSize,
  1471. &NtStatus, pReturnSize);
  1472. OutOfSpace = TRUE;
  1473. PS_LOCK(&Adapter->Lock);
  1474. Link = Link->Flink;
  1475. REFDEL(&WanLink->RefCount, TRUE, 'WMIQ');
  1476. continue;
  1477. }
  1478. //
  1479. // The instance info contains the instance name followed by the
  1480. // data for the item.
  1481. //
  1482. //
  1483. // Add the offset to the instance name to the table.
  1484. //
  1485. pInstanceNameOffsets[cInstanceCount] = OffsetToInstanceInfo;
  1486. //
  1487. // Copy the instance name into the wnode buffer.
  1488. //
  1489. *((PUSHORT)pBuffer) = WanLink->InstanceName.Length;
  1490. NdisMoveMemory(pBuffer + sizeof(USHORT),
  1491. WanLink->InstanceName.Buffer,
  1492. WanLink->InstanceName.Length);
  1493. //
  1494. // Keep track of true instance counts.
  1495. //
  1496. OffsetToInstanceInfo += InstanceNameSize;
  1497. pBuffer = (PUCHAR)wnode + OffsetToInstanceInfo;
  1498. //
  1499. //
  1500. //
  1501. NtStatus = PsQueryGuidData(Adapter, WanLink, NULL, pNdisGuid->Oid, pBuffer, BytesNeeded);
  1502. if (!NT_SUCCESS(NtStatus))
  1503. {
  1504. PsDbgOut(DBG_FAILURE, DBG_WMI,
  1505. ("[PsWmiQueryAllData]: Adapter %08X, Failed to query GUID data\n", Adapter));
  1506. PS_LOCK(&Adapter->Lock);
  1507. REFDEL(&WanLink->RefCount, TRUE, 'WMIQ');
  1508. break;
  1509. }
  1510. //
  1511. // Save the length of the data item for this instance.
  1512. //
  1513. poidl[cInstanceCount].OffsetInstanceData = OffsetToInstanceInfo;
  1514. poidl[cInstanceCount].LengthInstanceData = BytesNeeded;
  1515. //
  1516. // Keep track of true instance counts.
  1517. //
  1518. OffsetToInstanceInfo += ALIGN(BytesNeeded);
  1519. pBuffer = (PUCHAR)wnode + OffsetToInstanceInfo;
  1520. //
  1521. // Increment the current instance count.
  1522. //
  1523. cInstanceCount++;
  1524. }
  1525. PS_LOCK(&Adapter->Lock);
  1526. Link = Link->Flink;
  1527. REFDEL(&WanLink->RefCount, TRUE, 'WMIQ');
  1528. }
  1529. PS_UNLOCK(&Adapter->Lock);
  1530. }
  1531. PS_LOCK(&AdapterListLock);
  1532. NextAdapter = NextAdapter->Flink;
  1533. REFDEL(&Adapter->RefCount, TRUE, 'WMIQ');
  1534. }
  1535. PS_UNLOCK(&AdapterListLock);
  1536. if (!OutOfSpace)
  1537. {
  1538. wnode->WnodeHeader.BufferSize = wnodeTotalSize;
  1539. wnode->InstanceCount = cInstanceCount;
  1540. //
  1541. // Set the status to success.
  1542. //
  1543. NtStatus = STATUS_SUCCESS;
  1544. *pReturnSize = wnode->WnodeHeader.BufferSize;
  1545. }
  1546. } while (FALSE);
  1547. return(NtStatus);
  1548. }
  1549. NTSTATUS
  1550. PsWmiFindInstanceName(
  1551. IN PPS_WAN_LINK *pWanLink,
  1552. IN PGPC_CLIENT_VC *pVc,
  1553. IN PADAPTER Adapter,
  1554. IN PWSTR pInstanceName,
  1555. IN USHORT cbInstanceName
  1556. )
  1557. {
  1558. NTSTATUS Status = STATUS_SUCCESS;
  1559. PVOID ptmp1;
  1560. PVOID ptmp2;
  1561. PLIST_ENTRY Link;
  1562. UINT cListCount;
  1563. PLIST_ENTRY pListHead;
  1564. PPS_WAN_LINK WanLink;
  1565. PGPC_CLIENT_VC Vc;
  1566. NDIS_STRING usTemp;
  1567. *pWanLink = NULL;
  1568. *pVc = NULL;
  1569. if ( NdisEqualMemory(pInstanceName,
  1570. WanPrefix.Buffer,
  1571. WanPrefix.Length))
  1572. {
  1573. //
  1574. // The name belongs to a miniport, check to see if it is for this one.
  1575. //
  1576. usTemp.Buffer = (PWCHAR)((PCHAR)pInstanceName + WanPrefix.Length + INSTANCE_ID_SIZE);
  1577. usTemp.Length = usTemp.MaximumLength = cbInstanceName - WanPrefix.Length - INSTANCE_ID_SIZE;
  1578. //
  1579. // Get a ULONGLONG pointer to the wnode's instance name.
  1580. //
  1581. ptmp1 = (PVOID)&pInstanceName[1];
  1582. //
  1583. // No point in searching wanlinks on the non wan adapters.
  1584. //
  1585. if(Adapter->MediaType == NdisMediumWan && RtlEqualUnicodeString(&Adapter->WMIInstanceName, &usTemp, TRUE))
  1586. {
  1587. //
  1588. // The request is for some WAN Link. Go through the Miniport's list of WMI enabled VCs.
  1589. //
  1590. PS_LOCK(&Adapter->Lock);
  1591. for(Link = Adapter->WanLinkList.Flink;
  1592. Link != &Adapter->WanLinkList;
  1593. Link = Link->Flink)
  1594. {
  1595. //
  1596. // Get a pointer to the VC.
  1597. //
  1598. WanLink = CONTAINING_RECORD(Link, PS_WAN_LINK, Linkage);
  1599. PS_LOCK_DPC(&WanLink->Lock);
  1600. if(WanLink->State == WanStateOpen)
  1601. {
  1602. //
  1603. // Check the name with the one in the wnode.
  1604. //
  1605. ptmp2 = (PVOID)&WanLink->InstanceName.Buffer[1];
  1606. if (RtlCompareMemory( ptmp1, ptmp2, 48) == 48)
  1607. {
  1608. //
  1609. // This is our baby. Slap a reference on it and get out.
  1610. //
  1611. *pWanLink = WanLink;
  1612. REFADD(&WanLink->RefCount, 'WMII');
  1613. PS_UNLOCK_DPC(&WanLink->Lock);
  1614. break;
  1615. }
  1616. }
  1617. PS_UNLOCK_DPC(&WanLink->Lock);
  1618. }
  1619. PS_UNLOCK(&Adapter->Lock);
  1620. //
  1621. // If we didn't find the WanLink then return FAILURE.
  1622. //
  1623. if (!*pWanLink)
  1624. {
  1625. PsDbgOut(DBG_FAILURE, DBG_WMI,
  1626. ("[PsWmiFindInstanceName: Adapter %08X, Could not verify the instance name passed in\n"));
  1627. Status = STATUS_WMI_INSTANCE_NOT_FOUND;
  1628. }
  1629. }
  1630. else
  1631. {
  1632. Status = STATUS_WMI_INSTANCE_NOT_FOUND;
  1633. }
  1634. }
  1635. else {
  1636. if ( NdisEqualMemory(pInstanceName,
  1637. VcPrefix.Buffer,
  1638. VcPrefix.Length))
  1639. {
  1640. //
  1641. // The name belongs to a miniport, check to see if it is for this one.
  1642. //
  1643. usTemp.Buffer = (PWCHAR)((PCHAR)pInstanceName + VcPrefix.Length + INSTANCE_ID_SIZE);
  1644. usTemp.Length = usTemp.MaximumLength = cbInstanceName - VcPrefix.Length - INSTANCE_ID_SIZE;
  1645. //
  1646. // Make sure that the VC is searched on the correct adapter. Otherwise, we could land up
  1647. // searching all the VCs on all the adapters.
  1648. //
  1649. if (!RtlEqualUnicodeString(&Adapter->WMIInstanceName, &usTemp, TRUE))
  1650. {
  1651. Status = STATUS_WMI_INSTANCE_NOT_FOUND;
  1652. }
  1653. else
  1654. {
  1655. //
  1656. // Get a ULONGLONG pointer to the wnode's instance name.
  1657. //
  1658. ptmp1 = (PVOID)&pInstanceName[1];
  1659. //
  1660. // The request is for some Vc. Go through the Miniport's list of WMI enabled VCs.
  1661. //
  1662. PS_LOCK(&Adapter->Lock);
  1663. for(Link = Adapter->GpcClientVcList.Flink;
  1664. Link != &Adapter->GpcClientVcList;
  1665. Link = Link->Flink)
  1666. {
  1667. //
  1668. // Get a pointer to the VC.
  1669. //
  1670. Vc = CONTAINING_RECORD(Link, GPC_CLIENT_VC, Linkage);
  1671. PS_LOCK_DPC(&Vc->Lock);
  1672. if( (Vc->ClVcState == CL_CALL_COMPLETE) ||
  1673. (Vc->ClVcState == CL_INTERNAL_CALL_COMPLETE) ||
  1674. (Vc->ClVcState == CL_MODIFY_PENDING) )
  1675. {
  1676. //
  1677. // Check the name with the one in the wnode. All we need to do is compare the
  1678. // number in the name.
  1679. //
  1680. ptmp2 = (PVOID)&Vc->InstanceName.Buffer[1];
  1681. if(RtlCompareMemory(ptmp1, ptmp2, 48) == 48)
  1682. {
  1683. //
  1684. // This is our baby. Slap a reference on it and get out.
  1685. //
  1686. *pVc = Vc;
  1687. InterlockedIncrement(&Vc->RefCount);
  1688. PS_UNLOCK_DPC(&Vc->Lock);
  1689. break;
  1690. }
  1691. }
  1692. PS_UNLOCK_DPC(&Vc->Lock);
  1693. }
  1694. PS_UNLOCK(&Adapter->Lock);
  1695. //
  1696. // If we didn't find the VC then return FAILURE.
  1697. //
  1698. if (!*pVc)
  1699. {
  1700. PsDbgOut(DBG_FAILURE, DBG_WMI,
  1701. ("[PsWmiFindInstanceName: Adapter %08X, Could not verify the instance name passed in\n"));
  1702. Status = STATUS_WMI_INSTANCE_NOT_FOUND;
  1703. }
  1704. }
  1705. }
  1706. else
  1707. {
  1708. //
  1709. // The name belongs to a miniport, check to see if it is for this one.
  1710. //
  1711. usTemp.Buffer = pInstanceName;
  1712. usTemp.Length = usTemp.MaximumLength = cbInstanceName;
  1713. if (!RtlEqualUnicodeString(&Adapter->WMIInstanceName, &usTemp, TRUE))
  1714. {
  1715. PsDbgOut(DBG_FAILURE, DBG_WMI,
  1716. ("[PsWmiFindInstanceName]: Adapter %08X, Invalid instance name \n", Adapter));
  1717. Status = STATUS_WMI_INSTANCE_NOT_FOUND;
  1718. }
  1719. }
  1720. }
  1721. return(Status);
  1722. }
  1723. NTSTATUS
  1724. PsQuerySetMiniport(PADAPTER Adapter,
  1725. PPS_WAN_LINK WanLink,
  1726. PGPC_CLIENT_VC Vc,
  1727. NDIS_OID Oid,
  1728. PVOID Data,
  1729. ULONG DataSize)
  1730. {
  1731. //
  1732. // Fail these no matter what
  1733. //
  1734. switch(Oid)
  1735. {
  1736. case OID_QOS_TC_SUPPORTED:
  1737. case OID_QOS_REMAINING_BANDWIDTH:
  1738. case OID_QOS_LATENCY:
  1739. case OID_QOS_FLOW_COUNT:
  1740. case OID_QOS_NON_BESTEFFORT_LIMIT:
  1741. case OID_QOS_SCHEDULING_PROFILES_SUPPORTED:
  1742. case OID_QOS_CURRENT_SCHEDULING_PROFILE:
  1743. case OID_QOS_DISABLE_DRR:
  1744. case OID_QOS_MAX_OUTSTANDING_SENDS:
  1745. case OID_QOS_TIMER_RESOLUTION:
  1746. return STATUS_WMI_NOT_SUPPORTED;
  1747. }
  1748. if(Vc)
  1749. {
  1750. switch(Oid)
  1751. {
  1752. case OID_QOS_STATISTICS_BUFFER:
  1753. NdisZeroMemory(&Vc->Stats, sizeof(PS_FLOW_STATS));
  1754. //
  1755. // Send the request down, so that the scheduling components
  1756. // can also reset their stats.
  1757. //
  1758. (*Vc->PsComponent->SetInformation)
  1759. (Vc->PsPipeContext,
  1760. Vc->PsFlowContext,
  1761. Oid,
  1762. DataSize,
  1763. Data);
  1764. return STATUS_SUCCESS;
  1765. default:
  1766. return STATUS_WMI_NOT_SUPPORTED;
  1767. }
  1768. }
  1769. //
  1770. // These work for Wan and LAN
  1771. //
  1772. switch(Oid) {
  1773. case OID_QOS_ENABLE_AVG_STATS:
  1774. if(DataSize != sizeof(ULONG)) {
  1775. return STATUS_BUFFER_TOO_SMALL;
  1776. }
  1777. gEnableAvgStats = *(UNALIGNED PULONG)Data;
  1778. return STATUS_SUCCESS;
  1779. case OID_QOS_ENABLE_WINDOW_ADJUSTMENT:
  1780. if(DataSize != sizeof(ULONG)) {
  1781. return STATUS_BUFFER_TOO_SMALL;
  1782. }
  1783. gEnableWindowAdjustment = *(UNALIGNED PULONG)Data;
  1784. return STATUS_SUCCESS;
  1785. #if DBG
  1786. case OID_QOS_LOG_THRESHOLD:
  1787. if(DataSize != sizeof(ULONG)) {
  1788. return STATUS_BUFFER_TOO_SMALL;
  1789. }
  1790. DbugTraceSetThreshold(*(PULONG)Data, Adapter, IndicateLogThreshold);
  1791. return STATUS_SUCCESS;
  1792. case OID_QOS_LOG_MASK:
  1793. if(DataSize != sizeof(ULONG)) {
  1794. return STATUS_BUFFER_TOO_SMALL;
  1795. }
  1796. LogTraceMask = *(PULONG)Data;
  1797. return STATUS_SUCCESS;
  1798. case OID_QOS_LOG_LEVEL:
  1799. if(DataSize != sizeof(ULONG)) {
  1800. return STATUS_BUFFER_TOO_SMALL;
  1801. }
  1802. LogTraceLevel = *(PULONG)Data;
  1803. return STATUS_SUCCESS;
  1804. #endif
  1805. }
  1806. if(WanLink)
  1807. {
  1808. switch(Oid)
  1809. {
  1810. case OID_QOS_STATISTICS_BUFFER:
  1811. NdisZeroMemory(&WanLink->Stats, sizeof(PS_ADAPTER_STATS));
  1812. //
  1813. // Send it to the scheduling components so that
  1814. // they can reset the per pipe stats
  1815. //
  1816. (*WanLink->PsComponent->SetInformation)
  1817. (WanLink->PsPipeContext,
  1818. NULL,
  1819. Oid,
  1820. DataSize,
  1821. Data);
  1822. return STATUS_SUCCESS;
  1823. case OID_QOS_FLOW_MODE:
  1824. if(DataSize != sizeof(ULONG)) {
  1825. return STATUS_BUFFER_TOO_SMALL;
  1826. } else {
  1827. return STATUS_INVALID_PARAMETER;
  1828. }
  1829. case OID_QOS_HIERARCHY_CLASS:
  1830. (*WanLink->PsComponent->SetInformation)
  1831. (WanLink->PsPipeContext,
  1832. NULL,
  1833. Oid,
  1834. DataSize,
  1835. Data);
  1836. return STATUS_SUCCESS;
  1837. }
  1838. }
  1839. if(Adapter->MediaType != NdisMediumWan)
  1840. {
  1841. switch(Oid)
  1842. {
  1843. case OID_QOS_STATISTICS_BUFFER:
  1844. NdisZeroMemory(&Adapter->Stats, sizeof(PS_ADAPTER_STATS));
  1845. //
  1846. // Send it to the scheduling components so that
  1847. // they can reset the per pipe stats
  1848. //
  1849. (*Adapter->PsComponent->SetInformation)
  1850. (Adapter->PsPipeContext,
  1851. NULL,
  1852. Oid,
  1853. DataSize,
  1854. Data);
  1855. return STATUS_SUCCESS;
  1856. case OID_QOS_FLOW_MODE:
  1857. if(DataSize != sizeof(ULONG)) {
  1858. return STATUS_BUFFER_TOO_SMALL;
  1859. } else {
  1860. return STATUS_INVALID_PARAMETER;
  1861. }
  1862. case OID_QOS_HIERARCHY_CLASS:
  1863. (*Adapter->PsComponent->SetInformation)
  1864. (Adapter->PsPipeContext,
  1865. NULL,
  1866. Oid,
  1867. DataSize,
  1868. Data);
  1869. return STATUS_SUCCESS;
  1870. case OID_QOS_BESTEFFORT_BANDWIDTH:
  1871. if(DataSize != sizeof(ULONG))
  1872. {
  1873. return STATUS_BUFFER_TOO_SMALL;
  1874. }
  1875. else
  1876. {
  1877. return ModifyBestEffortBandwidth(Adapter, *(UNALIGNED PULONG)Data);
  1878. }
  1879. }
  1880. }
  1881. return STATUS_WMI_NOT_SUPPORTED;
  1882. }
  1883. NTSTATUS
  1884. PsWmiHandleSingleInstance(ULONG MinorFunction,
  1885. PWNODE_SINGLE_INSTANCE wnode,
  1886. PNDIS_GUID pNdisGuid,
  1887. ULONG BufferSize,
  1888. PULONG pReturnSize)
  1889. {
  1890. PPS_WAN_LINK WanLink;
  1891. PGPC_CLIENT_VC Vc;
  1892. USHORT cbInstanceName;
  1893. PWSTR pInstanceName;
  1894. PLIST_ENTRY NextAdapter;
  1895. PADAPTER Adapter;
  1896. NTSTATUS Status = STATUS_WMI_INSTANCE_NOT_FOUND;
  1897. //
  1898. // Send this to all the adapter instances.
  1899. //
  1900. *pReturnSize = 0;
  1901. //
  1902. // First, we need to check if this is the window size adjustment guid..
  1903. //
  1904. if( pNdisGuid->Oid == OID_QOS_ENABLE_WINDOW_ADJUSTMENT)
  1905. {
  1906. if( MinorFunction == IRP_MN_CHANGE_SINGLE_INSTANCE)
  1907. {
  1908. PUCHAR pGuidData;
  1909. ULONG GuidDataSize;
  1910. pGuidData = (PUCHAR)wnode + wnode->DataBlockOffset;
  1911. GuidDataSize = wnode->SizeDataBlock;
  1912. //
  1913. // Attempt to set the miniport with the information.
  1914. //
  1915. Status = PsQuerySetMiniport(NULL,
  1916. NULL,
  1917. NULL,
  1918. pNdisGuid->Oid,
  1919. pGuidData,
  1920. GuidDataSize);
  1921. return Status;
  1922. }
  1923. else if( MinorFunction == IRP_MN_QUERY_SINGLE_INSTANCE )
  1924. {
  1925. ULONG BytesNeeded;
  1926. ULONG wnodeSize;
  1927. //
  1928. // Determine the buffer size needed for the GUID data.
  1929. //
  1930. Status = PsQueryGuidDataSize(NULL,
  1931. NULL,
  1932. NULL,
  1933. pNdisGuid->Oid,
  1934. &BytesNeeded);
  1935. if (!NT_SUCCESS(Status))
  1936. {
  1937. return Status;
  1938. }
  1939. //
  1940. // Determine the size of the wnode.
  1941. //
  1942. wnodeSize = wnode->DataBlockOffset + BytesNeeded;
  1943. if (BufferSize < wnodeSize)
  1944. {
  1945. WMI_BUFFER_TOO_SMALL(BufferSize, wnode, wnodeSize, &Status, pReturnSize);
  1946. return Status;
  1947. }
  1948. //
  1949. // Initialize the wnode.
  1950. //
  1951. KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
  1952. wnode->WnodeHeader.BufferSize = wnodeSize;
  1953. wnode->SizeDataBlock = BytesNeeded;
  1954. //
  1955. // Validate the guid and get the data for it.
  1956. //
  1957. Status = PsQueryGuidData(NULL,
  1958. NULL,
  1959. NULL,
  1960. pNdisGuid->Oid,
  1961. (PUCHAR)wnode + wnode->DataBlockOffset,
  1962. BytesNeeded);
  1963. if (!NT_SUCCESS(Status))
  1964. {
  1965. return Status;
  1966. }
  1967. else
  1968. {
  1969. *pReturnSize = wnodeSize;
  1970. }
  1971. }
  1972. }
  1973. //
  1974. // If we are here, then it is a "per adapter" guid/oid
  1975. //
  1976. PS_LOCK(&AdapterListLock);
  1977. NextAdapter = AdapterList.Flink;
  1978. while(NextAdapter != &AdapterList)
  1979. {
  1980. Adapter = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage);
  1981. PS_LOCK_DPC(&Adapter->Lock);
  1982. if(Adapter->PsMpState != AdapterStateRunning)
  1983. {
  1984. PS_UNLOCK_DPC(&Adapter->Lock);
  1985. NextAdapter = NextAdapter->Flink;
  1986. continue;
  1987. }
  1988. REFADD(&Adapter->RefCount, 'WMIQ');
  1989. PS_UNLOCK_DPC(&Adapter->Lock);
  1990. PS_UNLOCK(&AdapterListLock);
  1991. //
  1992. // We first see if this instance name is meaningful for this adapter.
  1993. //
  1994. cbInstanceName = *(PUSHORT)((PUCHAR)wnode + wnode->OffsetInstanceName);
  1995. pInstanceName = (PWSTR)((PUCHAR)wnode + wnode->OffsetInstanceName + sizeof(USHORT));
  1996. //
  1997. // This routine will determine if the wnode's instance name is a miniport or VC.
  1998. // If it's a VC then it will find which one.
  1999. //
  2000. Vc = 0;
  2001. WanLink = 0;
  2002. Status = PsWmiFindInstanceName(&WanLink, &Vc, Adapter, pInstanceName, cbInstanceName);
  2003. if(!NT_SUCCESS(Status))
  2004. {
  2005. PS_LOCK(&AdapterListLock);
  2006. NextAdapter = NextAdapter->Flink;
  2007. REFDEL(&Adapter->RefCount, TRUE, 'WMIQ');
  2008. continue;
  2009. }
  2010. else
  2011. {
  2012. //
  2013. // Found the adapter or the Vc or the WanLink. If this fails from this point, we can just return.
  2014. //
  2015. switch(MinorFunction)
  2016. {
  2017. case IRP_MN_QUERY_SINGLE_INSTANCE:
  2018. {
  2019. ULONG BytesNeeded;
  2020. ULONG wnodeSize;
  2021. //
  2022. // Determine the buffer size needed for the GUID data.
  2023. //
  2024. Status = PsQueryGuidDataSize(Adapter,
  2025. WanLink,
  2026. Vc,
  2027. pNdisGuid->Oid,
  2028. &BytesNeeded);
  2029. if (!NT_SUCCESS(Status))
  2030. {
  2031. PsDbgOut(DBG_FAILURE, DBG_WMI,
  2032. ("[PsWmiQuerySingleInstance]: Adpater %08X, Unable to determine OID data size for OID %0x\n",
  2033. Adapter, pNdisGuid->Oid));
  2034. break;
  2035. }
  2036. //
  2037. // Determine the size of the wnode.
  2038. //
  2039. wnodeSize = wnode->DataBlockOffset + BytesNeeded;
  2040. if (BufferSize < wnodeSize)
  2041. {
  2042. WMI_BUFFER_TOO_SMALL(BufferSize, wnode, wnodeSize, &Status, pReturnSize);
  2043. break;
  2044. }
  2045. //
  2046. // Initialize the wnode.
  2047. //
  2048. KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
  2049. wnode->WnodeHeader.BufferSize = wnodeSize;
  2050. wnode->SizeDataBlock = BytesNeeded;
  2051. //
  2052. // Validate the guid and get the data for it.
  2053. //
  2054. Status = PsQueryGuidData(Adapter,
  2055. WanLink,
  2056. Vc,
  2057. pNdisGuid->Oid,
  2058. (PUCHAR)wnode + wnode->DataBlockOffset,
  2059. BytesNeeded);
  2060. if (!NT_SUCCESS(Status))
  2061. {
  2062. PsDbgOut(DBG_FAILURE, DBG_WMI,
  2063. ("PsWmiQuerySingleInstance: Adapter %08X, Failed to get the OID data for OID %08X.\n",
  2064. Adapter, pNdisGuid->Oid));
  2065. }
  2066. else
  2067. {
  2068. *pReturnSize = wnodeSize;
  2069. }
  2070. break;
  2071. }
  2072. case IRP_MN_CHANGE_SINGLE_INSTANCE:
  2073. {
  2074. PUCHAR pGuidData;
  2075. ULONG GuidDataSize;
  2076. pGuidData = (PUCHAR)wnode + wnode->DataBlockOffset;
  2077. GuidDataSize = wnode->SizeDataBlock;
  2078. //
  2079. // Attempt to set the miniport with the information.
  2080. //
  2081. Status = PsQuerySetMiniport(Adapter,
  2082. WanLink,
  2083. Vc,
  2084. pNdisGuid->Oid,
  2085. pGuidData,
  2086. GuidDataSize);
  2087. break;
  2088. }
  2089. default:
  2090. PsAssert(0);
  2091. }
  2092. //
  2093. // If this was a VC then we need to dereference it.
  2094. //
  2095. if (NULL != WanLink)
  2096. {
  2097. REFDEL(&WanLink->RefCount, FALSE, 'WMII');
  2098. }
  2099. if (NULL != Vc)
  2100. {
  2101. DerefClVc(Vc);
  2102. }
  2103. REFDEL(&Adapter->RefCount, FALSE, 'WMIQ');
  2104. return Status;
  2105. }
  2106. }
  2107. PS_UNLOCK(&AdapterListLock);
  2108. return Status;
  2109. }
  2110. NTSTATUS
  2111. WMIDispatch(
  2112. IN PDEVICE_OBJECT pdo,
  2113. IN PIRP pirp
  2114. )
  2115. /*++
  2116. Routine Description:
  2117. Arguments:
  2118. Return Value:
  2119. --*/
  2120. {
  2121. PIO_STACK_LOCATION pirpSp = IoGetCurrentIrpStackLocation(pirp);
  2122. ULONG_PTR ProviderId = pirpSp->Parameters.WMI.ProviderId;
  2123. PVOID DataPath = pirpSp->Parameters.WMI.DataPath;
  2124. ULONG BufferSize = pirpSp->Parameters.WMI.BufferSize;
  2125. PVOID Buffer = pirpSp->Parameters.WMI.Buffer;
  2126. NTSTATUS Status;
  2127. ULONG ReturnSize = 0;
  2128. KIRQL OldIrql;
  2129. ULONG MinorFunction;
  2130. PsDbgOut(DBG_TRACE, DBG_WMI,
  2131. ("[WMIDispatch]: Device Object %08X, IRP Device Object %08X, "
  2132. "Minor function %d \n", pdo, pirpSp->Parameters.WMI.ProviderId,
  2133. pirpSp->MinorFunction));
  2134. #if DBG
  2135. OldIrql = KeGetCurrentIrql();
  2136. #endif
  2137. //
  2138. // Fail the irp if we don't find an adapter. We also fail the irp if the provider ID is not
  2139. // us.
  2140. //
  2141. // If the ProviderID is not us, then ideally we need to pass it down the irp stack.
  2142. //
  2143. // (By calling IoSkipCurrentIrpStackLocation(pirp) &
  2144. // IocallDriver(Adapter->NextDeviceObject, pirp);
  2145. //
  2146. // In this case, we are not attached to anything, so we can just fail the request.
  2147. //
  2148. if((pirpSp->Parameters.WMI.ProviderId != (ULONG_PTR)pdo)) {
  2149. PsDbgOut(DBG_FAILURE, DBG_WMI,
  2150. ("[WMIDispatch]: Could not find the adapter for pdo 0x%x \n", pdo));
  2151. pirp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  2152. pirp->IoStatus.Information = 0;
  2153. IoCompleteRequest(pirp, IO_NO_INCREMENT);
  2154. return STATUS_INVALID_DEVICE_REQUEST;
  2155. }
  2156. MinorFunction = pirpSp->MinorFunction;
  2157. switch (pirpSp->MinorFunction)
  2158. {
  2159. case IRP_MN_REGINFO:
  2160. Status = PsWmiRegister((ULONG_PTR)DataPath,
  2161. Buffer,
  2162. BufferSize,
  2163. &ReturnSize);
  2164. break;
  2165. case IRP_MN_QUERY_ALL_DATA:
  2166. Status = PsWmiQueryAllData((LPGUID)DataPath,
  2167. (PWNODE_ALL_DATA)Buffer,
  2168. BufferSize,
  2169. &ReturnSize);
  2170. break;
  2171. case IRP_MN_CHANGE_SINGLE_INSTANCE:
  2172. {
  2173. PWNODE_SINGLE_INSTANCE wnode = (PWNODE_SINGLE_INSTANCE) Buffer;
  2174. PPS_WAN_LINK WanLink;
  2175. PGPC_CLIENT_VC Vc;
  2176. USHORT cbInstanceName;
  2177. PWSTR pInstanceName;
  2178. PNDIS_GUID pNdisGuid;
  2179. PUCHAR pGuidData;
  2180. ULONG GuidDataSize;
  2181. //
  2182. // See if the GUID is ours
  2183. //
  2184. Status = PsWmiGetGuid(&pNdisGuid, &wnode->WnodeHeader.Guid, 0);
  2185. if(!NT_SUCCESS(Status))
  2186. {
  2187. PsDbgOut(DBG_FAILURE, DBG_WMI, ("[WmiDispatch]: Invalid GUID \n"));
  2188. Status = STATUS_INVALID_PARAMETER;
  2189. break;
  2190. }
  2191. //
  2192. // Is this guid settable?
  2193. //
  2194. if (PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_NOT_SETTABLE))
  2195. {
  2196. PsDbgOut(DBG_FAILURE, DBG_WMI, ("[WmiDispatch]: Guid is not settable!\n"));
  2197. Status = STATUS_WMI_NOT_SUPPORTED;
  2198. break;
  2199. }
  2200. //
  2201. // Get a pointer to the GUID data and size.
  2202. //
  2203. GuidDataSize = wnode->SizeDataBlock;
  2204. pGuidData = (PUCHAR)wnode + wnode->DataBlockOffset;
  2205. if (GuidDataSize == 0)
  2206. {
  2207. PsDbgOut(DBG_FAILURE, DBG_WMI,
  2208. ("[PsWmiHandleSingleInstance]: Guid has not data to set!\n"));
  2209. Status = STATUS_INVALID_PARAMETER;
  2210. break;
  2211. }
  2212. //
  2213. // Make sure it's not a stauts indication.
  2214. //
  2215. if (!PS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_TO_OID))
  2216. {
  2217. PsDbgOut(DBG_FAILURE, DBG_WMI,
  2218. ("[PsWmiHandleSingleInstance]: Guid does not translate to an OID\n"));
  2219. Status = STATUS_INVALID_DEVICE_REQUEST;
  2220. break;
  2221. }
  2222. Status = PsWmiHandleSingleInstance(IRP_MN_CHANGE_SINGLE_INSTANCE, wnode, pNdisGuid, BufferSize, &ReturnSize);
  2223. break;
  2224. }
  2225. case IRP_MN_QUERY_SINGLE_INSTANCE:
  2226. {
  2227. PWNODE_SINGLE_INSTANCE wnode = (PWNODE_SINGLE_INSTANCE) Buffer;
  2228. PNDIS_GUID pNdisGuid;
  2229. //
  2230. // See if the GUID is ours
  2231. //
  2232. Status = PsWmiGetGuid(&pNdisGuid, &wnode->WnodeHeader.Guid, 0);
  2233. if(!NT_SUCCESS(Status))
  2234. {
  2235. PsDbgOut(DBG_FAILURE, DBG_WMI, ("[WmiDispatch]: Invalid GUID \n"));
  2236. Status = STATUS_INVALID_PARAMETER;
  2237. }
  2238. else
  2239. {
  2240. Status = PsWmiHandleSingleInstance(IRP_MN_QUERY_SINGLE_INSTANCE, wnode, pNdisGuid, BufferSize, &ReturnSize);
  2241. }
  2242. break;
  2243. }
  2244. case IRP_MN_ENABLE_EVENTS:
  2245. Status = PsWmiEnableEvents((LPGUID)DataPath);
  2246. break;
  2247. case IRP_MN_DISABLE_EVENTS:
  2248. Status = PsWmiDisableEvents((LPGUID)DataPath);
  2249. break;
  2250. case IRP_MN_ENABLE_COLLECTION:
  2251. case IRP_MN_DISABLE_COLLECTION:
  2252. case IRP_MN_CHANGE_SINGLE_ITEM:
  2253. Status = STATUS_NOT_SUPPORTED;
  2254. PsDbgOut(DBG_TRACE, DBG_WMI,
  2255. ("[WMIDispatch]: Unsupported minor function (0x%x) \n",
  2256. pirpSp->MinorFunction));
  2257. break;
  2258. default:
  2259. PsDbgOut(DBG_FAILURE, DBG_WMI,
  2260. ("[WMIDispatch]: Invalid minor function (0x%x) \n",
  2261. pirpSp->MinorFunction));
  2262. Status = STATUS_INVALID_DEVICE_REQUEST;
  2263. break;
  2264. }
  2265. PsAssert(KeGetCurrentIrql() == OldIrql);
  2266. pirp->IoStatus.Status = Status;
  2267. PsAssert(ReturnSize <= BufferSize);
  2268. pirp->IoStatus.Information = NT_SUCCESS(Status) ? ReturnSize : 0;
  2269. IoCompleteRequest(pirp, IO_NO_INCREMENT);
  2270. //
  2271. // Allow IFC_UP notifications.
  2272. //
  2273. if(MinorFunction == IRP_MN_REGINFO)
  2274. {
  2275. //
  2276. // Need to walk all the adapters and send notifications.
  2277. //
  2278. PLIST_ENTRY NextAdapter;
  2279. PADAPTER Adapter;
  2280. PS_LOCK(&AdapterListLock);
  2281. WMIInitialized = TRUE;
  2282. NextAdapter = AdapterList.Flink;
  2283. while(NextAdapter != &AdapterList)
  2284. {
  2285. Adapter = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage);
  2286. PS_LOCK_DPC(&Adapter->Lock);
  2287. if(Adapter->PsMpState == AdapterStateRunning && !Adapter->IfcNotification)
  2288. {
  2289. Adapter->IfcNotification = TRUE;
  2290. REFADD(&Adapter->RefCount, 'WMIN');
  2291. PS_UNLOCK_DPC(&Adapter->Lock);
  2292. PS_UNLOCK(&AdapterListLock);
  2293. TcIndicateInterfaceChange(Adapter, 0, NDIS_STATUS_INTERFACE_UP);
  2294. PS_LOCK(&AdapterListLock);
  2295. NextAdapter = NextAdapter->Flink;
  2296. REFDEL(&Adapter->RefCount, TRUE, 'WMIN');
  2297. }
  2298. else
  2299. {
  2300. //
  2301. // This adapter is not yet ready. The interface will be indicated
  2302. // in the mpinitialize handler, when the adapter gets ready.
  2303. //
  2304. PS_UNLOCK_DPC(&Adapter->Lock);
  2305. NextAdapter = NextAdapter->Flink;
  2306. }
  2307. }
  2308. PS_UNLOCK(&AdapterListLock);
  2309. }
  2310. PsDbgOut(DBG_TRACE, DBG_WMI, ("[WMIDispatch] : completing with Status %X \n", Status));
  2311. return(Status);
  2312. }
  2313. NTSTATUS
  2314. GenerateInstanceName(
  2315. IN PNDIS_STRING Prefix,
  2316. IN PADAPTER Adapter,
  2317. IN PLARGE_INTEGER Index,
  2318. IN PNDIS_STRING pInstanceName)
  2319. {
  2320. #define CONVERT_MASK 0x000000000000000F
  2321. NTSTATUS Status = STATUS_SUCCESS;
  2322. USHORT cbSize;
  2323. PUNICODE_STRING uBaseInstanceName = (PUNICODE_STRING)&Adapter->WMIInstanceName;
  2324. UINT Value;
  2325. WCHAR wcLookUp[] = {L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F'};
  2326. WCHAR tmpBuffer[18] = {0};
  2327. UINT c;
  2328. ULONGLONG tmpIndex;
  2329. KIRQL OldIrql;
  2330. do
  2331. {
  2332. //
  2333. // Is there already a name associated with this VC?
  2334. //
  2335. //
  2336. // The instance name will be of the format:
  2337. // <Prefix>: [YYYYYYYYYYYYYYYY] Base Name
  2338. //
  2339. cbSize = INSTANCE_ID_SIZE + Prefix->Length;
  2340. if (NULL != uBaseInstanceName)
  2341. {
  2342. cbSize += uBaseInstanceName->Length;
  2343. }
  2344. //
  2345. // Initialize a temporary UNICODE_STRING to build the name.
  2346. //
  2347. NdisZeroMemory(pInstanceName->Buffer, cbSize);
  2348. pInstanceName->Length = 0;
  2349. pInstanceName->MaximumLength = cbSize;
  2350. //
  2351. // Add the prefix
  2352. //
  2353. RtlCopyUnicodeString(pInstanceName, Prefix);
  2354. //
  2355. // Add the separator.
  2356. //
  2357. RtlAppendUnicodeToString(pInstanceName, L" [");
  2358. //
  2359. // Add the VC index.
  2360. //
  2361. //tmpIndex = (ULONGLONG)(Index->HighPart << 32) | (ULONGLONG)Index->LowPart;
  2362. tmpIndex = Index->QuadPart;
  2363. for (c = 16; c > 0; c--)
  2364. {
  2365. //
  2366. // Get the nibble to convert.
  2367. //
  2368. Value = (UINT)(tmpIndex & CONVERT_MASK);
  2369. tmpBuffer[c - 1] = wcLookUp[Value];
  2370. //
  2371. // Shift the tmpIndex by a nibble.
  2372. //
  2373. tmpIndex >>= 4;
  2374. }
  2375. RtlAppendUnicodeToString(pInstanceName, tmpBuffer);
  2376. //
  2377. // Add closing bracket.
  2378. //
  2379. RtlAppendUnicodeToString(pInstanceName, L"]");
  2380. if (NULL != uBaseInstanceName)
  2381. {
  2382. RtlAppendUnicodeToString(pInstanceName, L" ");
  2383. //
  2384. // Append the base instance name passed into us to the end.
  2385. //
  2386. RtlAppendUnicodeToString(pInstanceName, uBaseInstanceName->Buffer);
  2387. }
  2388. } while (FALSE);
  2389. return(Status);
  2390. }