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.

3155 lines
89 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. PULONG pData = (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. //
  1674. // Check the name with the one in the wnode. All we need to do is compare the
  1675. // number in the name.
  1676. //
  1677. ptmp2 = (PVOID)&Vc->InstanceName.Buffer[1];
  1678. if(RtlCompareMemory(ptmp1, ptmp2, 48) == 48)
  1679. {
  1680. //
  1681. // This is our baby. Slap a reference on it and get out.
  1682. //
  1683. *pVc = Vc;
  1684. InterlockedIncrement(&Vc->RefCount);
  1685. PS_UNLOCK_DPC(&Vc->Lock);
  1686. break;
  1687. }
  1688. }
  1689. PS_UNLOCK_DPC(&Vc->Lock);
  1690. }
  1691. PS_UNLOCK(&Adapter->Lock);
  1692. //
  1693. // If we didn't find the VC then return FAILURE.
  1694. //
  1695. if (!*pVc)
  1696. {
  1697. PsDbgOut(DBG_FAILURE, DBG_WMI,
  1698. ("[PsWmiFindInstanceName: Adapter %08X, Could not verify the instance name passed in\n"));
  1699. Status = STATUS_WMI_INSTANCE_NOT_FOUND;
  1700. }
  1701. }
  1702. }
  1703. else
  1704. {
  1705. //
  1706. // The name belongs to a miniport, check to see if it is for this one.
  1707. //
  1708. usTemp.Buffer = pInstanceName;
  1709. usTemp.Length = usTemp.MaximumLength = cbInstanceName;
  1710. if (!RtlEqualUnicodeString(&Adapter->WMIInstanceName, &usTemp, TRUE))
  1711. {
  1712. PsDbgOut(DBG_FAILURE, DBG_WMI,
  1713. ("[PsWmiFindInstanceName]: Adapter %08X, Invalid instance name \n", Adapter));
  1714. Status = STATUS_WMI_INSTANCE_NOT_FOUND;
  1715. }
  1716. }
  1717. }
  1718. return(Status);
  1719. }
  1720. NTSTATUS
  1721. PsQuerySetMiniport(PADAPTER Adapter,
  1722. PPS_WAN_LINK WanLink,
  1723. PGPC_CLIENT_VC Vc,
  1724. NDIS_OID Oid,
  1725. PVOID Data,
  1726. ULONG DataSize)
  1727. {
  1728. //
  1729. // Fail these no matter what
  1730. //
  1731. switch(Oid)
  1732. {
  1733. case OID_QOS_TC_SUPPORTED:
  1734. case OID_QOS_REMAINING_BANDWIDTH:
  1735. case OID_QOS_LATENCY:
  1736. case OID_QOS_FLOW_COUNT:
  1737. case OID_QOS_NON_BESTEFFORT_LIMIT:
  1738. case OID_QOS_SCHEDULING_PROFILES_SUPPORTED:
  1739. case OID_QOS_CURRENT_SCHEDULING_PROFILE:
  1740. case OID_QOS_DISABLE_DRR:
  1741. case OID_QOS_MAX_OUTSTANDING_SENDS:
  1742. case OID_QOS_TIMER_RESOLUTION:
  1743. return STATUS_WMI_NOT_SUPPORTED;
  1744. }
  1745. if(Vc)
  1746. {
  1747. switch(Oid)
  1748. {
  1749. case OID_QOS_STATISTICS_BUFFER:
  1750. NdisZeroMemory(&Vc->Stats, sizeof(PS_FLOW_STATS));
  1751. //
  1752. // Send the request down, so that the scheduling components
  1753. // can also reset their stats.
  1754. //
  1755. (*Vc->PsComponent->SetInformation)
  1756. (Vc->PsPipeContext,
  1757. Vc->PsFlowContext,
  1758. Oid,
  1759. DataSize,
  1760. Data);
  1761. return STATUS_SUCCESS;
  1762. default:
  1763. return STATUS_WMI_NOT_SUPPORTED;
  1764. }
  1765. }
  1766. //
  1767. // These work for Wan and LAN
  1768. //
  1769. switch(Oid) {
  1770. case OID_QOS_ENABLE_AVG_STATS:
  1771. if(DataSize != sizeof(ULONG)) {
  1772. return STATUS_BUFFER_TOO_SMALL;
  1773. }
  1774. gEnableAvgStats = *(PULONG)Data;
  1775. return STATUS_SUCCESS;
  1776. case OID_QOS_ENABLE_WINDOW_ADJUSTMENT:
  1777. if(DataSize != sizeof(ULONG)) {
  1778. return STATUS_BUFFER_TOO_SMALL;
  1779. }
  1780. gEnableWindowAdjustment = *(PULONG)Data;
  1781. return STATUS_SUCCESS;
  1782. #if DBG
  1783. case OID_QOS_LOG_THRESHOLD:
  1784. if(DataSize != sizeof(ULONG)) {
  1785. return STATUS_BUFFER_TOO_SMALL;
  1786. }
  1787. DbugTraceSetThreshold(*(PULONG)Data, Adapter, IndicateLogThreshold);
  1788. return STATUS_SUCCESS;
  1789. case OID_QOS_LOG_MASK:
  1790. if(DataSize != sizeof(ULONG)) {
  1791. return STATUS_BUFFER_TOO_SMALL;
  1792. }
  1793. LogTraceMask = *(PULONG)Data;
  1794. return STATUS_SUCCESS;
  1795. case OID_QOS_LOG_LEVEL:
  1796. if(DataSize != sizeof(ULONG)) {
  1797. return STATUS_BUFFER_TOO_SMALL;
  1798. }
  1799. LogTraceLevel = *(PULONG)Data;
  1800. return STATUS_SUCCESS;
  1801. #endif
  1802. }
  1803. if(WanLink)
  1804. {
  1805. switch(Oid)
  1806. {
  1807. case OID_QOS_STATISTICS_BUFFER:
  1808. NdisZeroMemory(&WanLink->Stats, sizeof(PS_ADAPTER_STATS));
  1809. //
  1810. // Send it to the scheduling components so that
  1811. // they can reset the per pipe stats
  1812. //
  1813. (*WanLink->PsComponent->SetInformation)
  1814. (WanLink->PsPipeContext,
  1815. NULL,
  1816. Oid,
  1817. DataSize,
  1818. Data);
  1819. return STATUS_SUCCESS;
  1820. case OID_QOS_FLOW_MODE:
  1821. if(DataSize != sizeof(ULONG)) {
  1822. return STATUS_BUFFER_TOO_SMALL;
  1823. }
  1824. if(*(PULONG)Data == ADAPTER_FLOW_MODE_DIFFSERV ||
  1825. *(PULONG)Data == ADAPTER_FLOW_MODE_STANDARD )
  1826. {
  1827. InterlockedExchange((PLONG)&WanLink->AdapterMode, *(PULONG)Data);
  1828. return STATUS_SUCCESS;
  1829. }
  1830. else
  1831. {
  1832. return STATUS_INVALID_PARAMETER;
  1833. }
  1834. case OID_QOS_HIERARCHY_CLASS:
  1835. (*WanLink->PsComponent->SetInformation)
  1836. (WanLink->PsPipeContext,
  1837. NULL,
  1838. Oid,
  1839. DataSize,
  1840. Data);
  1841. return STATUS_SUCCESS;
  1842. }
  1843. }
  1844. if(Adapter->MediaType != NdisMediumWan)
  1845. {
  1846. switch(Oid)
  1847. {
  1848. case OID_QOS_STATISTICS_BUFFER:
  1849. NdisZeroMemory(&Adapter->Stats, sizeof(PS_ADAPTER_STATS));
  1850. //
  1851. // Send it to the scheduling components so that
  1852. // they can reset the per pipe stats
  1853. //
  1854. (*Adapter->PsComponent->SetInformation)
  1855. (Adapter->PsPipeContext,
  1856. NULL,
  1857. Oid,
  1858. DataSize,
  1859. Data);
  1860. return STATUS_SUCCESS;
  1861. case OID_QOS_FLOW_MODE:
  1862. if(DataSize != sizeof(ULONG)) {
  1863. return STATUS_BUFFER_TOO_SMALL;
  1864. }
  1865. if(*(PULONG)Data == ADAPTER_FLOW_MODE_DIFFSERV ||
  1866. *(PULONG)Data == ADAPTER_FLOW_MODE_STANDARD )
  1867. {
  1868. InterlockedExchange((PLONG)&Adapter->AdapterMode, *(PULONG)Data);
  1869. return STATUS_SUCCESS;
  1870. }
  1871. else
  1872. {
  1873. return STATUS_INVALID_PARAMETER;
  1874. }
  1875. case OID_QOS_HIERARCHY_CLASS:
  1876. (*Adapter->PsComponent->SetInformation)
  1877. (Adapter->PsPipeContext,
  1878. NULL,
  1879. Oid,
  1880. DataSize,
  1881. Data);
  1882. return STATUS_SUCCESS;
  1883. case OID_QOS_BESTEFFORT_BANDWIDTH:
  1884. if(DataSize != sizeof(ULONG))
  1885. {
  1886. return STATUS_BUFFER_TOO_SMALL;
  1887. }
  1888. else
  1889. {
  1890. return ModifyBestEffortBandwidth(Adapter, *(PULONG)Data);
  1891. }
  1892. }
  1893. }
  1894. return STATUS_WMI_NOT_SUPPORTED;
  1895. }
  1896. NTSTATUS
  1897. PsWmiHandleSingleInstance(ULONG MinorFunction,
  1898. PWNODE_SINGLE_INSTANCE wnode,
  1899. PNDIS_GUID pNdisGuid,
  1900. ULONG BufferSize,
  1901. PULONG pReturnSize)
  1902. {
  1903. PPS_WAN_LINK WanLink;
  1904. PGPC_CLIENT_VC Vc;
  1905. USHORT cbInstanceName;
  1906. PWSTR pInstanceName;
  1907. PLIST_ENTRY NextAdapter;
  1908. PADAPTER Adapter;
  1909. NTSTATUS Status = STATUS_WMI_INSTANCE_NOT_FOUND;
  1910. //
  1911. // Send this to all the adapter instances.
  1912. //
  1913. *pReturnSize = 0;
  1914. //
  1915. // First, we need to check if this is the window size adjustment guid..
  1916. //
  1917. if( pNdisGuid->Oid == OID_QOS_ENABLE_WINDOW_ADJUSTMENT)
  1918. {
  1919. if( MinorFunction == IRP_MN_CHANGE_SINGLE_INSTANCE)
  1920. {
  1921. PUCHAR pGuidData;
  1922. ULONG GuidDataSize;
  1923. pGuidData = (PUCHAR)wnode + wnode->DataBlockOffset;
  1924. GuidDataSize = wnode->SizeDataBlock;
  1925. //
  1926. // Attempt to set the miniport with the information.
  1927. //
  1928. Status = PsQuerySetMiniport(NULL,
  1929. NULL,
  1930. NULL,
  1931. pNdisGuid->Oid,
  1932. pGuidData,
  1933. GuidDataSize);
  1934. return Status;
  1935. }
  1936. else if( MinorFunction == IRP_MN_QUERY_SINGLE_INSTANCE )
  1937. {
  1938. ULONG BytesNeeded;
  1939. ULONG wnodeSize;
  1940. //
  1941. // Determine the buffer size needed for the GUID data.
  1942. //
  1943. Status = PsQueryGuidDataSize(NULL,
  1944. NULL,
  1945. NULL,
  1946. pNdisGuid->Oid,
  1947. &BytesNeeded);
  1948. if (!NT_SUCCESS(Status))
  1949. {
  1950. return Status;
  1951. }
  1952. //
  1953. // Determine the size of the wnode.
  1954. //
  1955. wnodeSize = wnode->DataBlockOffset + BytesNeeded;
  1956. if (BufferSize < wnodeSize)
  1957. {
  1958. WMI_BUFFER_TOO_SMALL(BufferSize, wnode, wnodeSize, &Status, pReturnSize);
  1959. return Status;
  1960. }
  1961. //
  1962. // Initialize the wnode.
  1963. //
  1964. KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
  1965. wnode->WnodeHeader.BufferSize = wnodeSize;
  1966. wnode->SizeDataBlock = BytesNeeded;
  1967. //
  1968. // Validate the guid and get the data for it.
  1969. //
  1970. Status = PsQueryGuidData(NULL,
  1971. NULL,
  1972. NULL,
  1973. pNdisGuid->Oid,
  1974. (PUCHAR)wnode + wnode->DataBlockOffset,
  1975. BytesNeeded);
  1976. if (!NT_SUCCESS(Status))
  1977. {
  1978. return Status;
  1979. }
  1980. else
  1981. {
  1982. *pReturnSize = wnodeSize;
  1983. }
  1984. }
  1985. }
  1986. //
  1987. // If we are here, then it is a "per adapter" guid/oid
  1988. //
  1989. PS_LOCK(&AdapterListLock);
  1990. NextAdapter = AdapterList.Flink;
  1991. while(NextAdapter != &AdapterList)
  1992. {
  1993. Adapter = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage);
  1994. PS_LOCK_DPC(&Adapter->Lock);
  1995. if(Adapter->PsMpState != AdapterStateRunning)
  1996. {
  1997. PS_UNLOCK_DPC(&Adapter->Lock);
  1998. NextAdapter = NextAdapter->Flink;
  1999. continue;
  2000. }
  2001. REFADD(&Adapter->RefCount, 'WMIQ');
  2002. PS_UNLOCK_DPC(&Adapter->Lock);
  2003. PS_UNLOCK(&AdapterListLock);
  2004. //
  2005. // We first see if this instance name is meaningful for this adapter.
  2006. //
  2007. cbInstanceName = *(PUSHORT)((PUCHAR)wnode + wnode->OffsetInstanceName);
  2008. pInstanceName = (PWSTR)((PUCHAR)wnode + wnode->OffsetInstanceName + sizeof(USHORT));
  2009. //
  2010. // This routine will determine if the wnode's instance name is a miniport or VC.
  2011. // If it's a VC then it will find which one.
  2012. //
  2013. Vc = 0;
  2014. WanLink = 0;
  2015. Status = PsWmiFindInstanceName(&WanLink, &Vc, Adapter, pInstanceName, cbInstanceName);
  2016. if(!NT_SUCCESS(Status))
  2017. {
  2018. PS_LOCK(&AdapterListLock);
  2019. NextAdapter = NextAdapter->Flink;
  2020. REFDEL(&Adapter->RefCount, TRUE, 'WMIQ');
  2021. continue;
  2022. }
  2023. else
  2024. {
  2025. //
  2026. // Found the adapter or the Vc or the WanLink. If this fails from this point, we can just return.
  2027. //
  2028. switch(MinorFunction)
  2029. {
  2030. case IRP_MN_QUERY_SINGLE_INSTANCE:
  2031. {
  2032. ULONG BytesNeeded;
  2033. ULONG wnodeSize;
  2034. //
  2035. // Determine the buffer size needed for the GUID data.
  2036. //
  2037. Status = PsQueryGuidDataSize(Adapter,
  2038. WanLink,
  2039. Vc,
  2040. pNdisGuid->Oid,
  2041. &BytesNeeded);
  2042. if (!NT_SUCCESS(Status))
  2043. {
  2044. PsDbgOut(DBG_FAILURE, DBG_WMI,
  2045. ("[PsWmiQuerySingleInstance]: Adpater %08X, Unable to determine OID data size for OID %0x\n",
  2046. Adapter, pNdisGuid->Oid));
  2047. break;
  2048. }
  2049. //
  2050. // Determine the size of the wnode.
  2051. //
  2052. wnodeSize = wnode->DataBlockOffset + BytesNeeded;
  2053. if (BufferSize < wnodeSize)
  2054. {
  2055. WMI_BUFFER_TOO_SMALL(BufferSize, wnode, wnodeSize, &Status, pReturnSize);
  2056. break;
  2057. }
  2058. //
  2059. // Initialize the wnode.
  2060. //
  2061. KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
  2062. wnode->WnodeHeader.BufferSize = wnodeSize;
  2063. wnode->SizeDataBlock = BytesNeeded;
  2064. //
  2065. // Validate the guid and get the data for it.
  2066. //
  2067. Status = PsQueryGuidData(Adapter,
  2068. WanLink,
  2069. Vc,
  2070. pNdisGuid->Oid,
  2071. (PUCHAR)wnode + wnode->DataBlockOffset,
  2072. BytesNeeded);
  2073. if (!NT_SUCCESS(Status))
  2074. {
  2075. PsDbgOut(DBG_FAILURE, DBG_WMI,
  2076. ("PsWmiQuerySingleInstance: Adapter %08X, Failed to get the OID data for OID %08X.\n",
  2077. Adapter, pNdisGuid->Oid));
  2078. }
  2079. else
  2080. {
  2081. *pReturnSize = wnodeSize;
  2082. }
  2083. break;
  2084. }
  2085. case IRP_MN_CHANGE_SINGLE_INSTANCE:
  2086. {
  2087. PUCHAR pGuidData;
  2088. ULONG GuidDataSize;
  2089. pGuidData = (PUCHAR)wnode + wnode->DataBlockOffset;
  2090. GuidDataSize = wnode->SizeDataBlock;
  2091. //
  2092. // Attempt to set the miniport with the information.
  2093. //
  2094. Status = PsQuerySetMiniport(Adapter,
  2095. WanLink,
  2096. Vc,
  2097. pNdisGuid->Oid,
  2098. pGuidData,
  2099. GuidDataSize);
  2100. break;
  2101. }
  2102. default:
  2103. PsAssert(0);
  2104. }
  2105. //
  2106. // If this was a VC then we need to dereference it.
  2107. //
  2108. if (NULL != WanLink)
  2109. {
  2110. REFDEL(&WanLink->RefCount, FALSE, 'WMII');
  2111. }
  2112. if (NULL != Vc)
  2113. {
  2114. DerefClVc(Vc);
  2115. }
  2116. REFDEL(&Adapter->RefCount, FALSE, 'WMIQ');
  2117. return Status;
  2118. }
  2119. }
  2120. PS_UNLOCK(&AdapterListLock);
  2121. return Status;
  2122. }
  2123. NTSTATUS
  2124. WMIDispatch(
  2125. IN PDEVICE_OBJECT pdo,
  2126. IN PIRP pirp
  2127. )
  2128. /*++
  2129. Routine Description:
  2130. Arguments:
  2131. Return Value:
  2132. --*/
  2133. {
  2134. PIO_STACK_LOCATION pirpSp = IoGetCurrentIrpStackLocation(pirp);
  2135. ULONG_PTR ProviderId = pirpSp->Parameters.WMI.ProviderId;
  2136. PVOID DataPath = pirpSp->Parameters.WMI.DataPath;
  2137. ULONG BufferSize = pirpSp->Parameters.WMI.BufferSize;
  2138. PVOID Buffer = pirpSp->Parameters.WMI.Buffer;
  2139. NTSTATUS Status;
  2140. ULONG ReturnSize = 0;
  2141. KIRQL OldIrql;
  2142. ULONG MinorFunction;
  2143. PsDbgOut(DBG_TRACE, DBG_WMI,
  2144. ("[WMIDispatch]: Device Object %08X, IRP Device Object %08X, "
  2145. "Minor function %d \n", pdo, pirpSp->Parameters.WMI.ProviderId,
  2146. pirpSp->MinorFunction));
  2147. #if DBG
  2148. OldIrql = KeGetCurrentIrql();
  2149. #endif
  2150. //
  2151. // Fail the irp if we don't find an adapter. We also fail the irp if the provider ID is not
  2152. // us.
  2153. //
  2154. // If the ProviderID is not us, then ideally we need to pass it down the irp stack.
  2155. //
  2156. // (By calling IoSkipCurrentIrpStackLocation(pirp) &
  2157. // IocallDriver(Adapter->NextDeviceObject, pirp);
  2158. //
  2159. // In this case, we are not attached to anything, so we can just fail the request.
  2160. //
  2161. if((pirpSp->Parameters.WMI.ProviderId != (ULONG_PTR)pdo)) {
  2162. PsDbgOut(DBG_FAILURE, DBG_WMI,
  2163. ("[WMIDispatch]: Could not find the adapter for pdo 0x%x \n", pdo));
  2164. pirp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  2165. pirp->IoStatus.Information = 0;
  2166. IoCompleteRequest(pirp, IO_NO_INCREMENT);
  2167. return STATUS_INVALID_DEVICE_REQUEST;
  2168. }
  2169. MinorFunction = pirpSp->MinorFunction;
  2170. switch (pirpSp->MinorFunction)
  2171. {
  2172. case IRP_MN_REGINFO:
  2173. Status = PsWmiRegister((ULONG_PTR)DataPath,
  2174. Buffer,
  2175. BufferSize,
  2176. &ReturnSize);
  2177. break;
  2178. case IRP_MN_QUERY_ALL_DATA:
  2179. Status = PsWmiQueryAllData((LPGUID)DataPath,
  2180. (PWNODE_ALL_DATA)Buffer,
  2181. BufferSize,
  2182. &ReturnSize);
  2183. break;
  2184. case IRP_MN_CHANGE_SINGLE_INSTANCE:
  2185. {
  2186. PWNODE_SINGLE_INSTANCE wnode = (PWNODE_SINGLE_INSTANCE) Buffer;
  2187. PPS_WAN_LINK WanLink;
  2188. PGPC_CLIENT_VC Vc;
  2189. USHORT cbInstanceName;
  2190. PWSTR pInstanceName;
  2191. PNDIS_GUID pNdisGuid;
  2192. PUCHAR pGuidData;
  2193. ULONG GuidDataSize;
  2194. //
  2195. // See if the GUID is ours
  2196. //
  2197. Status = PsWmiGetGuid(&pNdisGuid, &wnode->WnodeHeader.Guid, 0);
  2198. if(!NT_SUCCESS(Status))
  2199. {
  2200. PsDbgOut(DBG_FAILURE, DBG_WMI, ("[WmiDispatch]: Invalid GUID \n"));
  2201. Status = STATUS_INVALID_PARAMETER;
  2202. break;
  2203. }
  2204. //
  2205. // Is this guid settable?
  2206. //
  2207. if (PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_NOT_SETTABLE))
  2208. {
  2209. PsDbgOut(DBG_FAILURE, DBG_WMI, ("[WmiDispatch]: Guid is not settable!\n"));
  2210. Status = STATUS_WMI_NOT_SUPPORTED;
  2211. break;
  2212. }
  2213. //
  2214. // Get a pointer to the GUID data and size.
  2215. //
  2216. GuidDataSize = wnode->SizeDataBlock;
  2217. pGuidData = (PUCHAR)wnode + wnode->DataBlockOffset;
  2218. if (GuidDataSize == 0)
  2219. {
  2220. PsDbgOut(DBG_FAILURE, DBG_WMI,
  2221. ("[PsWmiHandleSingleInstance]: Guid has not data to set!\n"));
  2222. Status = STATUS_INVALID_PARAMETER;
  2223. break;
  2224. }
  2225. //
  2226. // Make sure it's not a stauts indication.
  2227. //
  2228. if (!PS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_TO_OID))
  2229. {
  2230. PsDbgOut(DBG_FAILURE, DBG_WMI,
  2231. ("[PsWmiHandleSingleInstance]: Guid does not translate to an OID\n"));
  2232. Status = STATUS_INVALID_DEVICE_REQUEST;
  2233. break;
  2234. }
  2235. Status = PsWmiHandleSingleInstance(IRP_MN_CHANGE_SINGLE_INSTANCE, wnode, pNdisGuid, BufferSize, &ReturnSize);
  2236. break;
  2237. }
  2238. case IRP_MN_QUERY_SINGLE_INSTANCE:
  2239. {
  2240. PWNODE_SINGLE_INSTANCE wnode = (PWNODE_SINGLE_INSTANCE) Buffer;
  2241. PNDIS_GUID pNdisGuid;
  2242. //
  2243. // See if the GUID is ours
  2244. //
  2245. Status = PsWmiGetGuid(&pNdisGuid, &wnode->WnodeHeader.Guid, 0);
  2246. if(!NT_SUCCESS(Status))
  2247. {
  2248. PsDbgOut(DBG_FAILURE, DBG_WMI, ("[WmiDispatch]: Invalid GUID \n"));
  2249. Status = STATUS_INVALID_PARAMETER;
  2250. }
  2251. else
  2252. {
  2253. Status = PsWmiHandleSingleInstance(IRP_MN_QUERY_SINGLE_INSTANCE, wnode, pNdisGuid, BufferSize, &ReturnSize);
  2254. }
  2255. break;
  2256. }
  2257. case IRP_MN_ENABLE_EVENTS:
  2258. Status = PsWmiEnableEvents((LPGUID)DataPath);
  2259. break;
  2260. case IRP_MN_DISABLE_EVENTS:
  2261. Status = PsWmiDisableEvents((LPGUID)DataPath);
  2262. break;
  2263. case IRP_MN_ENABLE_COLLECTION:
  2264. case IRP_MN_DISABLE_COLLECTION:
  2265. case IRP_MN_CHANGE_SINGLE_ITEM:
  2266. Status = STATUS_NOT_SUPPORTED;
  2267. PsDbgOut(DBG_TRACE, DBG_WMI,
  2268. ("[WMIDispatch]: Unsupported minor function (0x%x) \n",
  2269. pirpSp->MinorFunction));
  2270. break;
  2271. default:
  2272. PsDbgOut(DBG_FAILURE, DBG_WMI,
  2273. ("[WMIDispatch]: Invalid minor function (0x%x) \n",
  2274. pirpSp->MinorFunction));
  2275. Status = STATUS_INVALID_DEVICE_REQUEST;
  2276. break;
  2277. }
  2278. PsAssert(KeGetCurrentIrql() == OldIrql);
  2279. pirp->IoStatus.Status = Status;
  2280. PsAssert(ReturnSize <= BufferSize);
  2281. pirp->IoStatus.Information = NT_SUCCESS(Status) ? ReturnSize : 0;
  2282. IoCompleteRequest(pirp, IO_NO_INCREMENT);
  2283. //
  2284. // Allow IFC_UP notifications.
  2285. //
  2286. if(MinorFunction == IRP_MN_REGINFO)
  2287. {
  2288. //
  2289. // Need to walk all the adapters and send notifications.
  2290. //
  2291. PLIST_ENTRY NextAdapter;
  2292. PADAPTER Adapter;
  2293. PS_LOCK(&AdapterListLock);
  2294. WMIInitialized = TRUE;
  2295. NextAdapter = AdapterList.Flink;
  2296. while(NextAdapter != &AdapterList)
  2297. {
  2298. Adapter = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage);
  2299. PS_LOCK_DPC(&Adapter->Lock);
  2300. if(Adapter->PsMpState == AdapterStateRunning && !Adapter->IfcNotification)
  2301. {
  2302. Adapter->IfcNotification = TRUE;
  2303. REFADD(&Adapter->RefCount, 'WMIN');
  2304. PS_UNLOCK_DPC(&Adapter->Lock);
  2305. PS_UNLOCK(&AdapterListLock);
  2306. TcIndicateInterfaceChange(Adapter, 0, NDIS_STATUS_INTERFACE_UP);
  2307. PS_LOCK(&AdapterListLock);
  2308. NextAdapter = NextAdapter->Flink;
  2309. REFDEL(&Adapter->RefCount, TRUE, 'WMIN');
  2310. }
  2311. else
  2312. {
  2313. //
  2314. // This adapter is not yet ready. The interface will be indicated
  2315. // in the mpinitialize handler, when the adapter gets ready.
  2316. //
  2317. PS_UNLOCK_DPC(&Adapter->Lock);
  2318. NextAdapter = NextAdapter->Flink;
  2319. }
  2320. }
  2321. PS_UNLOCK(&AdapterListLock);
  2322. }
  2323. PsDbgOut(DBG_TRACE, DBG_WMI, ("[WMIDispatch] : completing with Status %X \n", Status));
  2324. return(Status);
  2325. }
  2326. NTSTATUS
  2327. GenerateInstanceName(
  2328. IN PNDIS_STRING Prefix,
  2329. IN PADAPTER Adapter,
  2330. IN PLARGE_INTEGER Index,
  2331. IN PNDIS_STRING pInstanceName)
  2332. {
  2333. #define CONVERT_MASK 0x000000000000000F
  2334. NTSTATUS Status = STATUS_SUCCESS;
  2335. USHORT cbSize;
  2336. PUNICODE_STRING uBaseInstanceName = (PUNICODE_STRING)&Adapter->WMIInstanceName;
  2337. UINT Value;
  2338. 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'};
  2339. WCHAR tmpBuffer[18] = {0};
  2340. UINT c;
  2341. ULONGLONG tmpIndex;
  2342. KIRQL OldIrql;
  2343. do
  2344. {
  2345. //
  2346. // Is there already a name associated with this VC?
  2347. //
  2348. //
  2349. // The instance name will be of the format:
  2350. // <Prefix>: [YYYYYYYYYYYYYYYY] Base Name
  2351. //
  2352. cbSize = INSTANCE_ID_SIZE + Prefix->Length;
  2353. if (NULL != uBaseInstanceName)
  2354. {
  2355. cbSize += uBaseInstanceName->Length;
  2356. }
  2357. //
  2358. // Initialize a temporary UNICODE_STRING to build the name.
  2359. //
  2360. NdisZeroMemory(pInstanceName->Buffer, cbSize);
  2361. pInstanceName->Length = 0;
  2362. pInstanceName->MaximumLength = cbSize;
  2363. //
  2364. // Add the prefix
  2365. //
  2366. RtlCopyUnicodeString(pInstanceName, Prefix);
  2367. //
  2368. // Add the separator.
  2369. //
  2370. RtlAppendUnicodeToString(pInstanceName, L" [");
  2371. //
  2372. // Add the VC index.
  2373. //
  2374. //tmpIndex = (ULONGLONG)(Index->HighPart << 32) | (ULONGLONG)Index->LowPart;
  2375. tmpIndex = Index->QuadPart;
  2376. for (c = 16; c > 0; c--)
  2377. {
  2378. //
  2379. // Get the nibble to convert.
  2380. //
  2381. Value = (UINT)(tmpIndex & CONVERT_MASK);
  2382. tmpBuffer[c - 1] = wcLookUp[Value];
  2383. //
  2384. // Shift the tmpIndex by a nibble.
  2385. //
  2386. tmpIndex >>= 4;
  2387. }
  2388. RtlAppendUnicodeToString(pInstanceName, tmpBuffer);
  2389. //
  2390. // Add closing bracket.
  2391. //
  2392. RtlAppendUnicodeToString(pInstanceName, L"]");
  2393. if (NULL != uBaseInstanceName)
  2394. {
  2395. RtlAppendUnicodeToString(pInstanceName, L" ");
  2396. //
  2397. // Append the base instance name passed into us to the end.
  2398. //
  2399. RtlAppendUnicodeToString(pInstanceName, uBaseInstanceName->Buffer);
  2400. }
  2401. } while (FALSE);
  2402. return(Status);
  2403. }