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.

2892 lines
90 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. ndiswmi.c
  5. Abstract:
  6. This module contains the routines necessary to process IRPs sent under the
  7. IRP_MJ_SYSTEM_CONTROL major code.
  8. Author:
  9. Kyle Brandon (KyleB)
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include <precomp.h>
  15. #pragma hdrstop
  16. #define MODULE_NUMBER MODULE_WMI
  17. #define MOF_RESOURCE_NAME L"NdisMofResource"
  18. NTSTATUS
  19. ndisWmiFindInstanceName(
  20. IN PNDIS_CO_VC_PTR_BLOCK *ppVcBlock,
  21. IN PNDIS_MINIPORT_BLOCK Miniport,
  22. IN PWSTR pInstanceName,
  23. IN USHORT cbInstanceName
  24. )
  25. {
  26. NTSTATUS Status = STATUS_SUCCESS;
  27. PNDIS_OPEN_BLOCK pOpen;
  28. PLIST_ENTRY Link;
  29. PNDIS_CO_VC_PTR_BLOCK pVcBlock = NULL;
  30. UINT cListCount;
  31. PLIST_ENTRY pListHead;
  32. UNICODE_STRING usTemp;
  33. *ppVcBlock = NULL;
  34. usTemp.Buffer = pInstanceName;
  35. usTemp.Length = usTemp.MaximumLength = cbInstanceName;
  36. //
  37. // See if this is a VC instance ?
  38. //
  39. if (pInstanceName[VC_ID_INDEX] == VC_IDENTIFIER)
  40. {
  41. //
  42. // The request is for some VC. Go through the Miniport's list of WMI enabled VCs.
  43. //
  44. Link = Miniport->WmiEnabledVcs.Flink;
  45. while (Link != &Miniport->WmiEnabledVcs)
  46. {
  47. //
  48. // Get a pointer to the VC.
  49. //
  50. pVcBlock = CONTAINING_RECORD(Link, NDIS_CO_VC_PTR_BLOCK, WmiLink);
  51. //
  52. // Check the name with the one in the wnode.
  53. //
  54. if (RtlEqualUnicodeString(&pVcBlock->VcInstanceName, &usTemp, TRUE))
  55. {
  56. //
  57. // This is our baby. Slap a reference on it and get out.
  58. //
  59. if (!ndisReferenceVcPtr(pVcBlock))
  60. {
  61. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  62. ("ndisWmiFindInstanceName: Unable to reference the VC\n"));
  63. //
  64. // VC is closing, can't query this one.
  65. //
  66. Status = NDIS_STATUS_FAILURE;
  67. }
  68. break;
  69. }
  70. //
  71. // Initialize this so that we know when we've found the VC in the outer loop.
  72. //
  73. pVcBlock = NULL;
  74. Link = Link->Flink;
  75. }
  76. //
  77. // If we didn't find the VC then return FAILURE.
  78. //
  79. if (Link == &Miniport->WmiEnabledVcs)
  80. {
  81. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  82. ("ndisWmiFindInstanceName: Could not verify the instance name passed in\n"));
  83. Status = STATUS_WMI_INSTANCE_NOT_FOUND;
  84. }
  85. //
  86. // If we found the VC then save it before leaving.
  87. //
  88. if (NT_SUCCESS(Status))
  89. {
  90. *ppVcBlock = pVcBlock;
  91. }
  92. }
  93. else
  94. {
  95. //
  96. // The name belongs to a miniport, check to see if it is for this one.
  97. //
  98. if (!RtlEqualUnicodeString(Miniport->pAdapterInstanceName, &usTemp, TRUE))
  99. {
  100. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  101. ("ndisWmiFindInstanceName: Invalid instance name\n"));
  102. Status = STATUS_WMI_INSTANCE_NOT_FOUND;
  103. }
  104. }
  105. return(Status);
  106. }
  107. BOOLEAN
  108. ndisWmiGuidIsAdapterSpecific(
  109. IN LPGUID guid
  110. )
  111. {
  112. BOOLEAN fAdapterOnly = FALSE;
  113. if (NdisEqualMemory(guid, (PVOID)&GUID_NDIS_ENUMERATE_ADAPTER, sizeof(GUID)) ||
  114. NdisEqualMemory(guid, (PVOID)&GUID_POWER_DEVICE_ENABLE, sizeof(GUID)) ||
  115. NdisEqualMemory(guid, (PVOID)&GUID_POWER_DEVICE_WAKE_ENABLE, sizeof(GUID)) ||
  116. NdisEqualMemory(guid, (PVOID)&GUID_NDIS_WAKE_ON_MAGIC_PACKET_ONLY, sizeof(GUID)))
  117. {
  118. fAdapterOnly = TRUE;
  119. }
  120. return(fAdapterOnly);
  121. }
  122. NDIS_STATUS
  123. ndisQuerySetMiniport(
  124. IN PNDIS_MINIPORT_BLOCK Miniport,
  125. IN PNDIS_CO_VC_PTR_BLOCK pVcBlock,
  126. IN BOOLEAN fSet,
  127. IN PNDIS_REQUEST pRequest,
  128. IN PLARGE_INTEGER pTime OPTIONAL
  129. )
  130. /*++
  131. Routine Description:
  132. Arguments:
  133. Return Value:
  134. --*/
  135. {
  136. BOOLEAN fQuery = !fSet;
  137. UINT Count;
  138. NDIS_STATUS NdisStatus;
  139. PNDIS_COREQ_RESERVED CoReqRsvd;
  140. PnPReferencePackage();
  141. #define MAX_WAIT_COUNT 5000
  142. #define WAIT_TIME 1000
  143. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_DEVICE_FAILED | fMINIPORT_PM_HALTED))
  144. {
  145. PnPDereferencePackage();
  146. return (fQuery ? NDIS_STATUS_FAILURE : NDIS_STATUS_SUCCESS);
  147. }
  148. //
  149. // Initialize the co-request reserved information.
  150. //
  151. CoReqRsvd = PNDIS_COREQ_RESERVED_FROM_REQUEST(pRequest);
  152. PNDIS_RESERVED_FROM_PNDIS_REQUEST(pRequest)->Open = NULL;
  153. //
  154. // preserve the mandatory setting on request
  155. //
  156. PNDIS_RESERVED_FROM_PNDIS_REQUEST(pRequest)->Flags &= REQST_MANDATORY;
  157. PNDIS_RESERVED_FROM_PNDIS_REQUEST(pRequest)->Flags |= REQST_SIGNAL_EVENT;
  158. INITIALIZE_EVENT(&CoReqRsvd->Event);
  159. //
  160. // If the miniport is being reset, then wait for the reset to complete before going any further.
  161. // Make sure we do not wait indefinitely either
  162. //
  163. for (Count = 0; Count < MAX_WAIT_COUNT; Count ++)
  164. {
  165. if (!MINIPORT_TEST_FLAG(Miniport, (fMINIPORT_RESET_IN_PROGRESS | fMINIPORT_RESET_REQUESTED)))
  166. {
  167. break;
  168. }
  169. NdisMSleep(WAIT_TIME); // 1 msec
  170. }
  171. if (Count == MAX_WAIT_COUNT)
  172. {
  173. PnPDereferencePackage();
  174. return(NDIS_STATUS_RESET_IN_PROGRESS);
  175. }
  176. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO))
  177. {
  178. NDIS_HANDLE MiniportVcContext = NULL;
  179. do
  180. {
  181. if (NULL != pVcBlock)
  182. {
  183. if (!ndisReferenceVcPtr(pVcBlock))
  184. {
  185. NdisStatus = NDIS_STATUS_CLOSING;
  186. break;
  187. }
  188. else
  189. {
  190. MiniportVcContext = pVcBlock->MiniportContext;
  191. }
  192. }
  193. NdisStatus = Miniport->DriverHandle->MiniportCharacteristics.CoRequestHandler(
  194. Miniport->MiniportAdapterContext,
  195. MiniportVcContext,
  196. pRequest);
  197. if (NDIS_STATUS_PENDING == NdisStatus)
  198. {
  199. WAIT_FOR_OBJECT(&CoReqRsvd->Event, pTime);
  200. //
  201. // Get the status that the miniport returned.
  202. //
  203. NdisStatus = CoReqRsvd->Status;
  204. }
  205. if (NULL != pVcBlock)
  206. {
  207. ndisDereferenceVcPtr(pVcBlock);
  208. }
  209. } while (FALSE);
  210. }
  211. else
  212. {
  213. if ((fSet && (Miniport->DriverHandle->MiniportCharacteristics.SetInformationHandler != NULL)) ||
  214. (fQuery && (Miniport->DriverHandle->MiniportCharacteristics.QueryInformationHandler != NULL)))
  215. {
  216. BOOLEAN LocalLock;
  217. KIRQL OldIrql;
  218. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  219. ndisMQueueRequest(Miniport, pRequest);
  220. LOCK_MINIPORT(Miniport, LocalLock);
  221. if (LocalLock || MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  222. {
  223. ndisMDoRequests(Miniport);
  224. }
  225. else
  226. {
  227. //
  228. // Queue the miniport request and wait for it to complete.
  229. //
  230. NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemRequest, NULL);
  231. }
  232. UNLOCK_MINIPORT(Miniport, LocalLock);
  233. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  234. if (NT_SUCCESS(WAIT_FOR_OBJECT(&CoReqRsvd->Event, pTime)))
  235. {
  236. //
  237. // Get the status that the miniport returned.
  238. //
  239. NdisStatus = CoReqRsvd->Status;
  240. }
  241. else
  242. {
  243. NdisStatus = -1; // Special error-code to return time-out
  244. }
  245. }
  246. else
  247. {
  248. //
  249. // If there isn't a proper handler then this is not a valid request.
  250. //
  251. NdisStatus = STATUS_INVALID_PARAMETER;
  252. }
  253. }
  254. PnPDereferencePackage();
  255. return(NdisStatus);
  256. }
  257. NDIS_STATUS
  258. ndisQueryCustomGuids(
  259. IN PNDIS_MINIPORT_BLOCK Miniport,
  260. IN PNDIS_REQUEST Request,
  261. OUT PNDIS_GUID * ppGuidToOid,
  262. OUT PUSHORT pcGuidToOid
  263. )
  264. /*++
  265. Routine Description:
  266. Arguments:
  267. Return Value:
  268. --*/
  269. {
  270. USHORT BytesNeeded;
  271. NDIS_STATUS Status;
  272. USHORT c, cCustomGuids = 0;
  273. PNDIS_GUID pGuidToOid = NULL;
  274. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  275. ("==>ndisQueryCustomGuids\n"));
  276. *ppGuidToOid = NULL;
  277. *pcGuidToOid = 0;
  278. do
  279. {
  280. //
  281. // Determine the size needed for the custom GUID to OID map.
  282. //
  283. #if (OID_GEN_CO_SUPPORTED_GUIDS != OID_GEN_SUPPORTED_GUIDS)
  284. #error (OID_GEN_CO_SUPPORTED_GUIDS == OID_GEN_SUPPORTED_GUIDS)
  285. #endif
  286. INIT_INTERNAL_REQUEST(Request, OID_GEN_SUPPORTED_GUIDS, NdisRequestQueryInformation, NULL, 0);
  287. Status = ndisQuerySetMiniport(Miniport, NULL, FALSE, Request, NULL);
  288. BytesNeeded = (USHORT)Request->DATA.QUERY_INFORMATION.BytesNeeded;
  289. //
  290. // If the miniport has custom GUIDs then make sure it returned a valid
  291. // length for the BytesNeeded.
  292. //
  293. if (((NDIS_STATUS_INVALID_LENGTH == Status) ||
  294. (NDIS_STATUS_BUFFER_TOO_SHORT == Status)) && (0 != BytesNeeded))
  295. {
  296. //
  297. // Bytes needed should contain the amount of space needed.
  298. //
  299. cCustomGuids = (BytesNeeded / sizeof(NDIS_GUID));
  300. }
  301. //
  302. // If there are no custom GUIDs to support then get out.
  303. //
  304. if (cCustomGuids == 0)
  305. {
  306. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  307. ("ndisQueryCustomGuids: Miniport does not support custom GUIDS\n"));
  308. Status = NDIS_STATUS_NOT_SUPPORTED;
  309. break;
  310. }
  311. //
  312. // Allocate a buffer to hold the GUID to OID mapping
  313. // for the custom GUIDs.
  314. //
  315. pGuidToOid = ALLOC_FROM_POOL(BytesNeeded, NDIS_TAG_WMI_GUID_TO_OID);
  316. if (NULL == pGuidToOid)
  317. {
  318. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  319. ("ndisQueryCustomGuids: Unable to allocate memory for the GUID to OID map\n"));
  320. Status = NDIS_STATUS_RESOURCES;
  321. break;
  322. }
  323. //
  324. // Query the list of GUIDs
  325. //
  326. if (0 != cCustomGuids)
  327. {
  328. //
  329. // Store the buffer with the request.
  330. //
  331. Request->DATA.QUERY_INFORMATION.InformationBuffer = pGuidToOid;
  332. Request->DATA.QUERY_INFORMATION.InformationBufferLength = BytesNeeded;
  333. //
  334. // Query for the list of custom GUIDs and OIDs.
  335. //
  336. Status = ndisQuerySetMiniport(Miniport, NULL, FALSE, Request, NULL);
  337. if (NDIS_STATUS_SUCCESS != Status)
  338. {
  339. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  340. ("ndisQueryCustomGuids: Unable to get the list of supported Co GUIDs\n"));
  341. break;
  342. }
  343. //
  344. // Go through this list and mark the guids as co.
  345. //
  346. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO))
  347. {
  348. for (c = 0; c < cCustomGuids; c++)
  349. {
  350. NDIS_GUID_SET_FLAG(&pGuidToOid[c], fNDIS_GUID_CO_NDIS);
  351. }
  352. }
  353. }
  354. } while (FALSE);
  355. if (NDIS_STATUS_SUCCESS == Status)
  356. {
  357. *ppGuidToOid = pGuidToOid;
  358. *pcGuidToOid = cCustomGuids;
  359. }
  360. else
  361. {
  362. if (NULL != pGuidToOid)
  363. {
  364. FREE_POOL(pGuidToOid);
  365. }
  366. }
  367. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  368. ("<==ndisQueryCustomGuids\n"));
  369. return(Status);
  370. }
  371. USHORT
  372. ndisWmiMapOids(
  373. IN OUT PNDIS_GUID pDst,
  374. IN IN USHORT cDst,
  375. IN PNDIS_OID pOidList,
  376. IN USHORT cOidList,
  377. IN PNDIS_GUID ndisSupportedList,
  378. IN ULONG cSupportedList
  379. )
  380. /*++
  381. Routine Description:
  382. Arguments:
  383. Return Value:
  384. --*/
  385. {
  386. USHORT c1, c2, ctmp = cDst;
  387. for (c1 = 0; c1 < cSupportedList; c1++)
  388. {
  389. for (c2 = 0; c2 < cOidList; c2++)
  390. {
  391. if (ndisSupportedList[c1].Oid == pOidList[c2])
  392. {
  393. if (NULL != pDst)
  394. {
  395. //
  396. // Copy the guid into the destination buffer.
  397. //
  398. NdisMoveMemory(&pDst[ctmp], &ndisSupportedList[c1], sizeof(NDIS_GUID));
  399. }
  400. ctmp++;
  401. break;
  402. }
  403. }
  404. }
  405. return ctmp;
  406. }
  407. NDIS_STATUS
  408. ndisQuerySupportedGuidToOidList(
  409. IN PNDIS_MINIPORT_BLOCK Miniport
  410. )
  411. /*++
  412. Routine Description:
  413. This routine will query the miniport and determine the mapping of
  414. supported GUIDs and their corresponding OIDs. This will include any
  415. custom OIDs that the driver supports.
  416. Arguments:
  417. Return Value:
  418. --*/
  419. {
  420. ULONG BytesNeeded;
  421. NDIS_STATUS NdisStatus;
  422. USHORT cOidList = 0;
  423. PNDIS_OID pOidList = NULL;
  424. USHORT cCustomGuids = 0;
  425. PNDIS_GUID pCustomGuids = NULL;
  426. USHORT cGuidToOidMap = 0;
  427. PNDIS_GUID pGuidToOidMap = NULL;
  428. USHORT c1, c2;
  429. NDIS_REQUEST Request;
  430. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  431. ("==>ndisQuerySupportedGuidToOidList\n"));
  432. do
  433. {
  434. #if (OID_GEN_SUPPORTED_LIST != OID_GEN_CO_SUPPORTED_LIST)
  435. #error (OID_GEN_SUPPORTED_LIST != OID_GEN_CO_SUPPORTED_LIST)
  436. #endif
  437. //
  438. // Determine the amount of buffer space needed for the supported list.
  439. //
  440. INIT_INTERNAL_REQUEST(&Request, OID_GEN_SUPPORTED_LIST, NdisRequestQueryInformation, NULL, 0);
  441. NdisStatus = ndisQuerySetMiniport(Miniport, NULL, FALSE, &Request, NULL);
  442. BytesNeeded = Request.DATA.QUERY_INFORMATION.BytesNeeded;
  443. //
  444. // The driver should have returned invalid length and the
  445. // length needed in BytesNeeded.
  446. //
  447. if (((NDIS_STATUS_INVALID_LENGTH != NdisStatus) && (NDIS_STATUS_BUFFER_TOO_SHORT != NdisStatus)) ||
  448. (0 == BytesNeeded))
  449. {
  450. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  451. ("ndisQuerySupportedGuidToOidList: Failed to get the size of the supported OID list.\n"));
  452. NdisStatus = NDIS_STATUS_FAILURE;
  453. break;
  454. }
  455. //
  456. // Determine the number of Oids supported.
  457. //
  458. cOidList = (USHORT)(BytesNeeded/sizeof(NDIS_OID));
  459. //
  460. // Allocate a buffer to hold the supported list of OIDs.
  461. //
  462. pOidList = ALLOC_FROM_POOL(BytesNeeded, NDIS_TAG_WMI_OID_SUPPORTED_LIST);
  463. if (NULL == pOidList)
  464. {
  465. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  466. ("ndisQuerySupportedGuidToOidList: Failed to allocate memory for the OID list.\n"));
  467. NdisStatus = NDIS_STATUS_RESOURCES;
  468. break;
  469. }
  470. Request.DATA.QUERY_INFORMATION.InformationBuffer = pOidList;
  471. Request.DATA.QUERY_INFORMATION.InformationBufferLength = BytesNeeded;
  472. //
  473. // Now query the supported list of OIDs into the buffer.
  474. //
  475. NdisStatus = ndisQuerySetMiniport(Miniport, NULL, FALSE, &Request, NULL);
  476. if (NDIS_STATUS_SUCCESS != NdisStatus)
  477. {
  478. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  479. ("ndisQuerySupportedGuidToOidList: Failed to read in the supported OID list.\n"));
  480. break;
  481. }
  482. //
  483. // Determine the number of [Co]NDIS OIDs that NDIS will handle on behalf of the miniport
  484. //
  485. cGuidToOidMap = ndisWmiMapOids(NULL,
  486. cGuidToOidMap,
  487. pOidList,
  488. cOidList,
  489. ndisSupportedGuids,
  490. sizeof(ndisSupportedGuids)/sizeof(NDIS_GUID));
  491. cGuidToOidMap = ndisWmiMapOids(NULL,
  492. cGuidToOidMap,
  493. pOidList,
  494. cOidList,
  495. ndisCoSupportedGuids,
  496. sizeof(ndisCoSupportedGuids)/sizeof(NDIS_GUID));
  497. //
  498. // Determine the number of media specific OIDs that NDIS will handle on
  499. // behalf of the miniport
  500. //
  501. cGuidToOidMap = ndisWmiMapOids(NULL,
  502. cGuidToOidMap,
  503. pOidList,
  504. cOidList,
  505. ndisMediaSupportedGuids,
  506. sizeof(ndisMediaSupportedGuids)/sizeof(NDIS_GUID));
  507. //
  508. // Determine the number of custom GUIDs supported.
  509. //
  510. NdisStatus = ndisQueryCustomGuids(Miniport, &Request, &pCustomGuids, &cCustomGuids);
  511. if (NDIS_STATUS_SUCCESS == NdisStatus)
  512. {
  513. cGuidToOidMap += cCustomGuids;
  514. }
  515. //
  516. // Add to the guid count the number of status indications we are
  517. // registering.
  518. //
  519. cGuidToOidMap += (sizeof(ndisStatusSupportedGuids) / sizeof(NDIS_GUID));
  520. //
  521. // Add the number of GUIDs that ndis will handle.
  522. // Add any guids that are not supported with an OID. These will be handled
  523. // entirely by ndis.
  524. //
  525. for (c1 = 0; c1 < sizeof(ndisSupportedGuids) / sizeof(NDIS_GUID); c1++)
  526. {
  527. if (NDIS_GUID_TEST_FLAG(&ndisSupportedGuids[c1], fNDIS_GUID_NDIS_ONLY))
  528. {
  529. //
  530. // Check to see if the miniport is CoNDIS
  531. //
  532. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO) ||
  533. !NDIS_GUID_TEST_FLAG(&ndisSupportedGuids[c1], fNDIS_GUID_CO_NDIS))
  534. {
  535. cGuidToOidMap++;
  536. }
  537. }
  538. }
  539. //
  540. // Allocate space for the GUID to OID map.
  541. //
  542. pGuidToOidMap = ALLOC_FROM_POOL(cGuidToOidMap * sizeof(NDIS_GUID), NDIS_TAG_WMI_GUID_TO_OID);
  543. if (NULL == pGuidToOidMap)
  544. {
  545. NdisStatus = NDIS_STATUS_RESOURCES;
  546. break;
  547. }
  548. NdisZeroMemory(pGuidToOidMap, cGuidToOidMap * sizeof(NDIS_GUID));
  549. //
  550. // Add the GUIDs that NDIS will handle
  551. //
  552. for (c1 = 0, c2 = 0;
  553. c1 < sizeof(ndisSupportedGuids) / sizeof(NDIS_GUID);
  554. c1++)
  555. {
  556. if (NDIS_GUID_TEST_FLAG(&ndisSupportedGuids[c1], fNDIS_GUID_NDIS_ONLY))
  557. {
  558. //
  559. // Check to see if the miniport is CoNDIS
  560. //
  561. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO) ||
  562. !NDIS_GUID_TEST_FLAG(&ndisSupportedGuids[c1], fNDIS_GUID_CO_NDIS))
  563. {
  564. NdisMoveMemory(&pGuidToOidMap[c2], &ndisSupportedGuids[c1], sizeof(NDIS_GUID));
  565. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO))
  566. {
  567. //
  568. // we need to mark this for the enumerate guids.
  569. //
  570. pGuidToOidMap[c2].Flags |= fNDIS_GUID_CO_NDIS;
  571. }
  572. c2++;
  573. }
  574. }
  575. }
  576. //
  577. // Save the current number of GUIDs in the map in c1
  578. //
  579. c1 = c2;
  580. //
  581. // Find the PNDIS_GUIDs that are appropriate for the miniport.
  582. //
  583. c1 = ndisWmiMapOids(pGuidToOidMap,
  584. c1,
  585. pOidList,
  586. cOidList,
  587. ndisSupportedGuids,
  588. sizeof(ndisSupportedGuids)/sizeof(NDIS_GUID));
  589. c1 = ndisWmiMapOids(pGuidToOidMap,
  590. c1,
  591. pOidList,
  592. cOidList,
  593. ndisCoSupportedGuids,
  594. sizeof(ndisCoSupportedGuids)/sizeof(NDIS_GUID));
  595. //
  596. // Check for media specific OIDs that ndis can support.
  597. //
  598. c1 = ndisWmiMapOids(pGuidToOidMap,
  599. c1,
  600. pOidList,
  601. cOidList,
  602. ndisMediaSupportedGuids,
  603. sizeof(ndisMediaSupportedGuids)/sizeof(NDIS_GUID));
  604. //
  605. // Add the status indications to the map of supported guids.
  606. //
  607. NdisMoveMemory(&pGuidToOidMap[c1], ndisStatusSupportedGuids, sizeof(ndisStatusSupportedGuids));
  608. c1 += (sizeof(ndisStatusSupportedGuids) / sizeof(NDIS_GUID));
  609. //
  610. // Save the GUID to OID mapping with the miniport.
  611. //
  612. Miniport->pNdisGuidMap = pGuidToOidMap;
  613. Miniport->cNdisGuidMap = cGuidToOidMap;
  614. //
  615. // Now copy over the custom GUID information if any.
  616. //
  617. if (NULL != pCustomGuids)
  618. {
  619. NdisMoveMemory(&pGuidToOidMap[c1],
  620. pCustomGuids,
  621. cCustomGuids * sizeof(NDIS_GUID));
  622. Miniport->pCustomGuidMap = &pGuidToOidMap[c1];
  623. Miniport->cCustomGuidMap = cCustomGuids;
  624. }
  625. else
  626. {
  627. //
  628. // Make sure these are initialized if they are not supported.
  629. //
  630. Miniport->pCustomGuidMap = NULL;
  631. Miniport->cCustomGuidMap = 0;
  632. }
  633. //
  634. // We've succeeded.
  635. //
  636. NdisStatus = NDIS_STATUS_SUCCESS;
  637. } while (FALSE);
  638. //
  639. // Free up the buffer that contains the custom GUIDs.
  640. //
  641. if (NULL != pCustomGuids)
  642. {
  643. FREE_POOL(pCustomGuids);
  644. }
  645. //
  646. // Free up the list of supported driver OIDs.
  647. //
  648. if (NULL != pOidList)
  649. {
  650. FREE_POOL(pOidList);
  651. }
  652. //
  653. // If there was an error and we allocated the GUID to OID map then
  654. // free it up also.
  655. //
  656. if (NDIS_STATUS_SUCCESS != NdisStatus)
  657. {
  658. if (NULL != pGuidToOidMap)
  659. {
  660. FREE_POOL(pGuidToOidMap);
  661. }
  662. }
  663. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  664. ("<==ndisQuerySupportedGuidToOidList\n"));
  665. return(NdisStatus);
  666. }
  667. NTSTATUS
  668. ndisWmiRegister(
  669. IN PNDIS_MINIPORT_BLOCK Miniport,
  670. IN ULONG_PTR RegistrationType,
  671. IN PWMIREGINFO wmiRegInfo,
  672. IN ULONG wmiRegInfoSize,
  673. IN PULONG pReturnSize
  674. )
  675. /*++
  676. Routine Description:
  677. Arguments:
  678. Return Value:
  679. --*/
  680. {
  681. PWMIREGINFO pwri;
  682. ULONG CustomSizeNeeded = 0;
  683. ULONG CustomBufferSize;
  684. ULONG CommonSizeNeeded;
  685. ULONG cCommonGuids;
  686. PUNICODE_STRING pMiniportRegistryPath;
  687. PNDIS_GUID pndisguid;
  688. PWMIREGGUID pwrg;
  689. PUCHAR ptmp;
  690. NTSTATUS Status;
  691. UINT c;
  692. NDIS_STATUS NdisStatus;
  693. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  694. ("==>ndisWmiRegister\n"));
  695. //
  696. // Initialize the return size.
  697. //
  698. *pReturnSize = 0;
  699. do
  700. {
  701. //
  702. // Is this a register request?
  703. //
  704. if (WMIREGISTER == RegistrationType)
  705. {
  706. //
  707. // Get the supported list of OIDs
  708. //
  709. if (Miniport->pNdisGuidMap == NULL)
  710. {
  711. NdisStatus = ndisQuerySupportedGuidToOidList(Miniport);
  712. if (NDIS_STATUS_SUCCESS != NdisStatus)
  713. {
  714. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  715. ("ndisWmiRegister: Unable to get the supported GUID to OID map\n"));
  716. Status = STATUS_UNSUCCESSFUL;
  717. break;
  718. }
  719. }
  720. //
  721. // Determine the amount of space needed for the Custom GUIDs
  722. //
  723. if (Miniport->cCustomGuidMap != 0)
  724. {
  725. //
  726. // Get a pointer to the registry path of the driver.
  727. //
  728. pMiniportRegistryPath = &Miniport->DriverHandle->NdisDriverInfo->ServiceRegPath;
  729. CustomSizeNeeded = sizeof(WMIREGINFO) +
  730. (Miniport->cCustomGuidMap * sizeof(WMIREGGUID)) +
  731. (sizeof(MOF_RESOURCE_NAME) - sizeof(WCHAR) + sizeof(USHORT)) +
  732. (pMiniportRegistryPath->Length + sizeof(USHORT));
  733. }
  734. //
  735. // Determine how much memory we need to allocate.
  736. //
  737. cCommonGuids = Miniport->cNdisGuidMap - Miniport->cCustomGuidMap;
  738. CommonSizeNeeded = sizeof(WMIREGINFO) + (cCommonGuids * sizeof(WMIREGGUID));
  739. CustomBufferSize = CustomSizeNeeded;
  740. CustomSizeNeeded = (CustomSizeNeeded + (sizeof(PVOID) - 1)) & ~(sizeof(PVOID) - 1);
  741. //
  742. // CustomBufferSize represents the number of bytes required to store the
  743. // custom WMI registration info. CustomSizeNeeded is this value rounded
  744. // up so that the adjacent WMI registration info is properly aligned.
  745. //
  746. //
  747. // We need to give this above information back to WMI.
  748. //
  749. if (wmiRegInfoSize < (CustomSizeNeeded + CommonSizeNeeded))
  750. {
  751. ASSERT(wmiRegInfoSize >= 4);
  752. *((PULONG)wmiRegInfo) = (CustomSizeNeeded + CommonSizeNeeded);
  753. *pReturnSize = sizeof(ULONG);
  754. Status = STATUS_BUFFER_TOO_SMALL;
  755. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  756. ("ndisWmiRegister: Insufficient buffer space for WMI registration information.\n"));
  757. break;
  758. }
  759. //
  760. // Get a pointer to the buffer passed in.
  761. //
  762. pwri = wmiRegInfo;
  763. *pReturnSize = CustomSizeNeeded + CommonSizeNeeded;
  764. NdisZeroMemory(pwri, CustomSizeNeeded + CommonSizeNeeded);
  765. //
  766. // do we need to initialize a WMIREGINFO struct for custom GUIDs?
  767. //
  768. if (0 != CustomSizeNeeded)
  769. {
  770. //
  771. // Initialize the WMIREGINFO struct for the miniport's
  772. // custom GUIDs.
  773. //
  774. pwri->BufferSize = CustomBufferSize;
  775. pwri->NextWmiRegInfo = CustomSizeNeeded;
  776. pwri->GuidCount = Miniport->cCustomGuidMap;
  777. for (c = 0, pndisguid = Miniport->pCustomGuidMap, pwrg = pwri->WmiRegGuid;
  778. (c < Miniport->cCustomGuidMap);
  779. c++, pndisguid++, pwrg++)
  780. {
  781. CopyMemory(&pwrg->Guid, &pndisguid->Guid, sizeof(GUID));
  782. }
  783. //
  784. // Fill in the registry path.
  785. //
  786. ptmp = (PUCHAR)pwrg;
  787. pwri->RegistryPath = (ULONG)((ULONG_PTR)ptmp - (ULONG_PTR)pwri);
  788. *((PUSHORT)ptmp) = pMiniportRegistryPath->Length;
  789. ptmp += sizeof(USHORT);
  790. CopyMemory(ptmp, pMiniportRegistryPath->Buffer, pMiniportRegistryPath->Length);
  791. //
  792. // Get a pointer to the destination for the MOF name.
  793. //
  794. ptmp += pMiniportRegistryPath->Length;
  795. //
  796. // Save the offset to the mof resource.
  797. //
  798. pwri->MofResourceName = (ULONG)((ULONG_PTR)ptmp - (ULONG_PTR)pwri);
  799. *((PUSHORT)ptmp) = sizeof(MOF_RESOURCE_NAME) - sizeof(WCHAR);
  800. ptmp += sizeof(USHORT);
  801. //
  802. // Copy the mof name into the wri buffer.
  803. //
  804. CopyMemory(ptmp, MOF_RESOURCE_NAME, sizeof(MOF_RESOURCE_NAME) - sizeof(WCHAR));
  805. //
  806. // Go on to the next WMIREGINFO struct for the common GUIDs.
  807. //
  808. pwri = (PWMIREGINFO)((PCHAR)pwri + pwri->NextWmiRegInfo);
  809. }
  810. //
  811. // Initialize the pwri struct for the common Oids.
  812. //
  813. pwri->BufferSize = CommonSizeNeeded;
  814. pwri->NextWmiRegInfo = 0;
  815. pwri->GuidCount = cCommonGuids;
  816. //
  817. // Go through the GUIDs that we support.
  818. //
  819. for (c = 0, pndisguid = Miniport->pNdisGuidMap, pwrg = pwri->WmiRegGuid;
  820. (c < cCommonGuids);
  821. c++, pndisguid++, pwrg++)
  822. {
  823. if (NdisEqualMemory(&pndisguid->Guid, (PVOID)&GUID_POWER_DEVICE_ENABLE, sizeof(GUID)) ||
  824. NdisEqualMemory(&pndisguid->Guid, (PVOID)&GUID_POWER_DEVICE_WAKE_ENABLE, sizeof(GUID)) ||
  825. NdisEqualMemory(&pndisguid->Guid, (PVOID)&GUID_NDIS_WAKE_ON_MAGIC_PACKET_ONLY, sizeof(GUID)))
  826. {
  827. {
  828. (ULONG_PTR)pwrg->InstanceInfo = (ULONG_PTR)(Miniport->PhysicalDeviceObject);
  829. pwrg->Flags = WMIREG_FLAG_INSTANCE_PDO;
  830. pwrg->InstanceCount = 1;
  831. }
  832. }
  833. CopyMemory(&pwrg->Guid, &pndisguid->Guid, sizeof(GUID));
  834. }
  835. pwri->RegistryPath = 0;
  836. pwri->MofResourceName = 0;
  837. Status = STATUS_SUCCESS;
  838. }
  839. else
  840. {
  841. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  842. ("ndisWmiRegister: Unsupported registration type\n"));
  843. Status = STATUS_INVALID_PARAMETER;
  844. break;
  845. }
  846. } while (FALSE);
  847. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  848. ("<==ndisWmiRegister\n"));
  849. return(Status);
  850. }
  851. NTSTATUS
  852. ndisWmiGetGuid(
  853. OUT PNDIS_GUID *ppNdisGuid,
  854. IN PNDIS_MINIPORT_BLOCK Miniport,
  855. IN LPGUID guid,
  856. IN NDIS_STATUS status
  857. )
  858. /*++
  859. Routine Description:
  860. Arguments:
  861. Return Value:
  862. --*/
  863. {
  864. UINT c;
  865. PNDIS_GUID pNdisGuid;
  866. NDIS_STATUS RetStatus = NDIS_STATUS_FAILURE;
  867. //
  868. // Search the custom GUIDs
  869. //
  870. if (NULL != Miniport->pNdisGuidMap)
  871. {
  872. for (c = 0, pNdisGuid = Miniport->pNdisGuidMap;
  873. (c < Miniport->cNdisGuidMap);
  874. c++, pNdisGuid++)
  875. {
  876. //
  877. // Make sure that we have a supported GUID and the GUID maps
  878. // to an OID.
  879. //
  880. if (NULL != guid)
  881. {
  882. //
  883. // We are to look for a guid to oid mapping.
  884. //
  885. if (NdisEqualMemory(&pNdisGuid->Guid, guid, sizeof(GUID)))
  886. {
  887. //
  888. // We found the GUID, save the OID that we will need to
  889. // send to the miniport.
  890. //
  891. RetStatus = NDIS_STATUS_SUCCESS;
  892. *ppNdisGuid = pNdisGuid;
  893. break;
  894. }
  895. }
  896. else
  897. {
  898. //
  899. // We need to find the guid for the status indication
  900. //
  901. if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_TO_STATUS) &&
  902. (pNdisGuid->Status == status))
  903. {
  904. RetStatus = NDIS_STATUS_SUCCESS;
  905. *ppNdisGuid = pNdisGuid;
  906. break;
  907. }
  908. }
  909. }
  910. }
  911. return(RetStatus);
  912. }
  913. NTSTATUS
  914. ndisQueryGuidDataSize(
  915. OUT PULONG pBytesNeeded,
  916. IN PNDIS_MINIPORT_BLOCK Miniport,
  917. IN PNDIS_CO_VC_PTR_BLOCK pVcBlock OPTIONAL,
  918. IN LPGUID guid
  919. )
  920. /*++
  921. Routine Description:
  922. This routine will determine the amount of buffer space needed for
  923. the GUID's data.
  924. Arguments:
  925. pBytesNeeded - Pointer to storage for the size needed.
  926. Miniport - Pointer to the miniport block.
  927. guid - GUID to query.
  928. Return Value:
  929. --*/
  930. {
  931. NTSTATUS NtStatus;
  932. NDIS_STATUS Status;
  933. PNDIS_GUID pNdisGuid;
  934. NDIS_REQUEST Request;
  935. ULONG GuidDataSize;
  936. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  937. ("==>ndisQueryGuidDataSize\n"));
  938. do
  939. {
  940. //
  941. // Make sure that we support the guid that was passed, and find
  942. // the corresponding OID.
  943. //
  944. NtStatus = ndisWmiGetGuid(&pNdisGuid, Miniport, guid, 0);
  945. if (!NT_SUCCESS(NtStatus))
  946. {
  947. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  948. ("ndisQueryGuidDataSize: Unsupported GUID\n"));
  949. NtStatus = STATUS_INVALID_PARAMETER;
  950. break;
  951. }
  952. //
  953. // Check for an ndis only guid
  954. //
  955. if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_NDIS_ONLY))
  956. {
  957. NtStatus = STATUS_SUCCESS;
  958. //
  959. // The following GUIDs all return the same data.
  960. //
  961. if (NdisEqualMemory(&pNdisGuid->Guid, (PVOID)&GUID_NDIS_ENUMERATE_ADAPTER, sizeof(GUID)))
  962. {
  963. //
  964. // Length of string and the string data.
  965. //
  966. *pBytesNeeded = Miniport->MiniportName.Length + sizeof(USHORT);
  967. }
  968. else if (NdisEqualMemory(&pNdisGuid->Guid, (PVOID)&GUID_POWER_DEVICE_ENABLE, sizeof(GUID)))
  969. {
  970. *pBytesNeeded = sizeof(BOOLEAN);
  971. }
  972. else if (NdisEqualMemory(&pNdisGuid->Guid, (PVOID)&GUID_POWER_DEVICE_WAKE_ENABLE, sizeof(GUID)))
  973. {
  974. *pBytesNeeded = sizeof(BOOLEAN);
  975. }
  976. else if (NdisEqualMemory(&pNdisGuid->Guid, (PVOID)&GUID_NDIS_WAKE_ON_MAGIC_PACKET_ONLY, sizeof(GUID)))
  977. {
  978. *pBytesNeeded = sizeof(BOOLEAN);
  979. }
  980. else if ((NULL != pVcBlock) && NdisEqualMemory(&pNdisGuid->Guid, (PVOID)&GUID_NDIS_ENUMERATE_VC, sizeof(GUID)))
  981. {
  982. //
  983. // There is not data for this VC. It's simply used to enumerate VCs on a miniport.
  984. //
  985. *pBytesNeeded = 0;
  986. }
  987. else
  988. {
  989. //
  990. // Unknown guid is being queried...
  991. //
  992. NtStatus = STATUS_INVALID_PARAMETER;
  993. }
  994. break;
  995. }
  996. //
  997. // Is this a GUID to OID mapping?
  998. //
  999. if (!NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_TO_OID))
  1000. {
  1001. NtStatus = STATUS_INVALID_DEVICE_REQUEST;
  1002. break;
  1003. }
  1004. //
  1005. // Do we need to query the OID for the size of the data?
  1006. //
  1007. if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_ARRAY) ||
  1008. NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_UNICODE_STRING) ||
  1009. NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_ANSI_STRING) ||
  1010. (pNdisGuid->Size == (ULONG)-1))
  1011. {
  1012. //
  1013. // Query the miniport for the current size of the variable length block.
  1014. //
  1015. INIT_INTERNAL_REQUEST(&Request, pNdisGuid->Oid, NdisRequestQueryStatistics, NULL, 0);
  1016. Status = ndisQuerySetMiniport(Miniport,
  1017. pVcBlock,
  1018. FALSE,
  1019. &Request,
  1020. NULL);
  1021. //
  1022. // Make sure that the miniport failed the above request with
  1023. // the correct error code and that the BytesNeeded is valid.
  1024. //
  1025. if ((NDIS_STATUS_INVALID_LENGTH != Status) &&
  1026. (NDIS_STATUS_BUFFER_TOO_SHORT != Status) &&
  1027. (NDIS_STATUS_SUCCESS != Status))
  1028. {
  1029. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1030. ("ndisQueryGuidDataSize: Failed to query driver OID: 0x%x\n", Status));
  1031. MAP_NDIS_STATUS_TO_NT_STATUS(Status, &NtStatus);
  1032. break;
  1033. }
  1034. GuidDataSize = Request.DATA.QUERY_INFORMATION.BytesNeeded;
  1035. if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_ANSI_STRING))
  1036. {
  1037. //
  1038. // The size returned is the number of ansi characters. Convert this
  1039. // to the unicode string size needed
  1040. //
  1041. GuidDataSize = GuidDataSize * sizeof(WCHAR);
  1042. GuidDataSize += sizeof(USHORT);
  1043. }
  1044. else if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_UNICODE_STRING))
  1045. {
  1046. //
  1047. // string data has a USHORT for the size.
  1048. //
  1049. GuidDataSize += sizeof(USHORT);
  1050. }
  1051. else if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_ARRAY))
  1052. {
  1053. //
  1054. // The data is going to have a ULONG of size information at the
  1055. // start of the buffer.
  1056. //
  1057. GuidDataSize += sizeof(ULONG);
  1058. }
  1059. }
  1060. else
  1061. {
  1062. GuidDataSize = pNdisGuid->Size;
  1063. }
  1064. //
  1065. // Return the bytes needed.
  1066. //
  1067. *pBytesNeeded = GuidDataSize;
  1068. NtStatus = STATUS_SUCCESS;
  1069. } while (FALSE);
  1070. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  1071. ("<==ndisQueryGuidDataSize\n"));
  1072. return(NtStatus);
  1073. }
  1074. NTSTATUS
  1075. ndisQueryGuidData(
  1076. IN PUCHAR Buffer,
  1077. IN ULONG BufferLength,
  1078. IN PNDIS_MINIPORT_BLOCK Miniport,
  1079. IN PNDIS_CO_VC_PTR_BLOCK pVcBlock,
  1080. IN LPGUID guid,
  1081. IN PIRP Irp
  1082. )
  1083. /*++
  1084. Routine Description:
  1085. Arguments:
  1086. Return Value:
  1087. --*/
  1088. {
  1089. NTSTATUS NtStatus;
  1090. NDIS_STATUS Status;
  1091. PNDIS_GUID pNdisGuid;
  1092. NDIS_REQUEST Request;
  1093. ANSI_STRING strAnsi = {0};
  1094. UNICODE_STRING strUnicode = {0};
  1095. ULONG QuerySize;
  1096. PUCHAR QueryBuffer;
  1097. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  1098. ("==>ndisQueryGuidData\n"));
  1099. do
  1100. {
  1101. //
  1102. // If the buffer length is equal to 0 then there is no data to query.
  1103. //
  1104. if (0 == BufferLength)
  1105. {
  1106. NtStatus = STATUS_SUCCESS;
  1107. break;
  1108. }
  1109. ZeroMemory(Buffer, BufferLength);
  1110. //
  1111. // Make sure that we support the guid that was passed, and find
  1112. // the corresponding OID.
  1113. //
  1114. NtStatus = ndisWmiGetGuid(&pNdisGuid, Miniport, guid, 0);
  1115. if (!NT_SUCCESS(NtStatus))
  1116. {
  1117. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1118. ("ndisQueryGuidData: Unsupported GUID\n"));
  1119. NtStatus = STATUS_INVALID_PARAMETER;
  1120. break;
  1121. }
  1122. if (!ndisWmiCheckAccess(pNdisGuid,
  1123. fNDIS_GUID_ALLOW_READ,
  1124. SE_LOAD_DRIVER_PRIVILEGE,
  1125. Irp))
  1126. {
  1127. NtStatus = STATUS_PRIVILEGE_NOT_HELD;
  1128. break;
  1129. }
  1130. //
  1131. // Is this an NDIS supported GUID?
  1132. //
  1133. if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_NDIS_ONLY))
  1134. {
  1135. NtStatus = STATUS_SUCCESS;
  1136. //
  1137. // The following GUIDs all return the same data.
  1138. //
  1139. if (NdisEqualMemory(&pNdisGuid->Guid, (PVOID)&GUID_NDIS_ENUMERATE_ADAPTER, sizeof(GUID)))
  1140. {
  1141. *(PUSHORT)Buffer = Miniport->MiniportName.Length;
  1142. NdisMoveMemory(Buffer + sizeof(USHORT),
  1143. Miniport->MiniportName.Buffer,
  1144. Miniport->MiniportName.Length);
  1145. }
  1146. else if (NdisEqualMemory(&pNdisGuid->Guid, (PVOID)&GUID_POWER_DEVICE_ENABLE, sizeof(GUID)))
  1147. {
  1148. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_PM_SUPPORTED) &&
  1149. (!MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_NO_HALT_ON_SUSPEND)))
  1150. {
  1151. *((PBOOLEAN)Buffer) = MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_DEVICE_POWER_ENABLE);
  1152. }
  1153. else
  1154. {
  1155. NtStatus = STATUS_INVALID_DEVICE_REQUEST;
  1156. }
  1157. }
  1158. else if (NdisEqualMemory(&pNdisGuid->Guid, (PVOID)&GUID_POWER_DEVICE_WAKE_ENABLE, sizeof(GUID)))
  1159. {
  1160. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_PM_SUPPORTED) &&
  1161. (Miniport->DeviceCaps.SystemWake > PowerSystemWorking))
  1162. {
  1163. *((PBOOLEAN)Buffer) = MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_DEVICE_POWER_WAKE_ENABLE);
  1164. }
  1165. else
  1166. {
  1167. NtStatus = STATUS_INVALID_DEVICE_REQUEST;
  1168. }
  1169. }
  1170. else if (NdisEqualMemory(&pNdisGuid->Guid, (PVOID)&GUID_NDIS_WAKE_ON_MAGIC_PACKET_ONLY, sizeof(GUID)))
  1171. {
  1172. //
  1173. // let the user see this only if we can do wake on magic packet
  1174. //
  1175. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_PM_SUPPORTED) &&
  1176. (Miniport->DeviceCaps.SystemWake > PowerSystemWorking) &&
  1177. (Miniport->PMCapabilities.WakeUpCapabilities.MinMagicPacketWakeUp != NdisDeviceStateUnspecified) &&
  1178. !(Miniport->PnPCapabilities & NDIS_DEVICE_DISABLE_WAKE_ON_MAGIC_PACKET))
  1179. {
  1180. *((PBOOLEAN)Buffer) = (Miniport->PnPCapabilities & NDIS_DEVICE_DISABLE_WAKE_ON_PATTERN_MATCH) ?
  1181. TRUE:
  1182. FALSE;
  1183. }
  1184. else
  1185. {
  1186. NtStatus = STATUS_INVALID_DEVICE_REQUEST;
  1187. }
  1188. }
  1189. else if ((NULL != pVcBlock) && NdisEqualMemory(&pNdisGuid->Guid, (PVOID)&GUID_NDIS_ENUMERATE_VC, sizeof(GUID)))
  1190. {
  1191. //
  1192. // There is no data for this VC.
  1193. //
  1194. break;
  1195. }
  1196. else
  1197. {
  1198. //
  1199. // Unknown guid is being queried...
  1200. //
  1201. NtStatus = STATUS_INVALID_PARAMETER;
  1202. }
  1203. break;
  1204. }
  1205. //
  1206. // Is this a GUID to OID mapping?
  1207. //
  1208. if (!NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_TO_OID))
  1209. {
  1210. NtStatus = STATUS_INVALID_DEVICE_REQUEST;
  1211. break;
  1212. }
  1213. //
  1214. // Determine the query size. This will depend upon the type of
  1215. // data.
  1216. //
  1217. if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_ARRAY))
  1218. {
  1219. //
  1220. // The query size is at least the BufferLength minus the ULONG
  1221. // used for the count. The query buffer will start after the
  1222. // ULONG of count informaiton in the buffer.
  1223. //
  1224. QuerySize = BufferLength - sizeof(ULONG);
  1225. QueryBuffer = Buffer + sizeof(ULONG);
  1226. }
  1227. else if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_ANSI_STRING) ||
  1228. NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_UNICODE_STRING))
  1229. {
  1230. //
  1231. // The query size is at least the BufferLength minus the ULONG
  1232. // used for the count. The query buffer will start after the
  1233. // ULONG of count informaiton in the buffer.
  1234. //
  1235. QuerySize = BufferLength - sizeof(USHORT);
  1236. QueryBuffer = Buffer + sizeof(USHORT);
  1237. //
  1238. // Is this a query for an ANSI string?
  1239. //
  1240. if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_ANSI_STRING))
  1241. {
  1242. //
  1243. // The BufferLength is the number of WCHARS not counting a terminating
  1244. // NULL.
  1245. //
  1246. QuerySize = (QuerySize / sizeof(WCHAR)) + 1;
  1247. }
  1248. }
  1249. else
  1250. {
  1251. QuerySize = BufferLength;
  1252. QueryBuffer = Buffer;
  1253. }
  1254. //
  1255. // Query the driver for the actual data.
  1256. //
  1257. INIT_INTERNAL_REQUEST(&Request, pNdisGuid->Oid, NdisRequestQueryStatistics, QueryBuffer, QuerySize);
  1258. Status = ndisQuerySetMiniport(Miniport,
  1259. pVcBlock,
  1260. FALSE,
  1261. &Request,
  1262. NULL);
  1263. if (NDIS_STATUS_SUCCESS != Status)
  1264. {
  1265. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1266. ("ndisQueryGuidData: Failed to query the value for driver OID: 0x%x\n", Status));
  1267. MAP_NDIS_STATUS_TO_NT_STATUS(Status, &NtStatus);
  1268. break;
  1269. }
  1270. //
  1271. // If this is an array or string we need to fill in the
  1272. // count/number.
  1273. //
  1274. NtStatus = STATUS_SUCCESS;
  1275. if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_ARRAY))
  1276. {
  1277. //
  1278. // Determine the number of elements.
  1279. //
  1280. *(PULONG)Buffer = QuerySize / pNdisGuid->Size;
  1281. }
  1282. else if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_UNICODE_STRING))
  1283. {
  1284. //
  1285. // The BytesNeeded contains the number of bytes in the string.
  1286. //
  1287. *(PUSHORT)Buffer = (USHORT)QuerySize;
  1288. }
  1289. else if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_ANSI_STRING))
  1290. {
  1291. //
  1292. // The buffer contains the ASCII string, build an
  1293. // ANSI string from this.
  1294. //
  1295. RtlInitAnsiString(&strAnsi, QueryBuffer);
  1296. //
  1297. // Convert the ansi string to unicode.
  1298. //
  1299. NtStatus = RtlAnsiStringToUnicodeString(&strUnicode, &strAnsi, TRUE);
  1300. ASSERT(NT_SUCCESS(NtStatus));
  1301. if (NT_SUCCESS(NtStatus))
  1302. {
  1303. //
  1304. // Save the length with the string.
  1305. //
  1306. *(PUSHORT)Buffer = strUnicode.Length;
  1307. //
  1308. // Copy the string to the wnode buffer.
  1309. //
  1310. NdisMoveMemory(QueryBuffer, strUnicode.Buffer, strUnicode.Length);
  1311. //
  1312. // Free the buffer allocated for the unicode string.
  1313. //
  1314. RtlFreeUnicodeString(&strUnicode);
  1315. }
  1316. }
  1317. } while (FALSE);
  1318. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  1319. ("<==ndisQueryGuidData\n"));
  1320. return(NtStatus);
  1321. }
  1322. NTSTATUS
  1323. ndisWmiQueryAllData(
  1324. IN PNDIS_MINIPORT_BLOCK Miniport,
  1325. IN LPGUID guid,
  1326. IN PWNODE_ALL_DATA wnode,
  1327. IN ULONG BufferSize,
  1328. OUT PULONG pReturnSize,
  1329. IN PIRP Irp
  1330. )
  1331. /*++
  1332. Routine Description:
  1333. Arguments:
  1334. Return Value:
  1335. --*/
  1336. {
  1337. NTSTATUS NtStatus;
  1338. ULONG wnodeSize = ALIGN_8_TYPE(WNODE_ALL_DATA);
  1339. ULONG InstanceNameOffsetsSize, InstanceNameSize;
  1340. ULONG wnodeTotalSize;
  1341. ULONG BytesNeeded;
  1342. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  1343. ("==>ndisWmiQueryAllData\n"));
  1344. do
  1345. {
  1346. *pReturnSize = 0;
  1347. if (BufferSize < sizeof(WNODE_TOO_SMALL))
  1348. {
  1349. WMI_BUFFER_TOO_SMALL(BufferSize, wnode, sizeof(WNODE_TOO_SMALL), &NtStatus, pReturnSize);
  1350. break;
  1351. }
  1352. //
  1353. // If the guid is only relavent to the adapter then answer it here.
  1354. // Is this GUID meant for "adapters" only, i.e. not vc's.
  1355. //
  1356. if (ndisWmiGuidIsAdapterSpecific(guid) ||
  1357. !MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO))
  1358. {
  1359. ULONG dataSize;
  1360. PUCHAR pucTmp;
  1361. //
  1362. // Determine the buffer size needed for the GUID data.
  1363. //
  1364. NtStatus = ndisQueryGuidDataSize(&BytesNeeded, Miniport, NULL, guid);
  1365. if (!NT_SUCCESS(NtStatus))
  1366. {
  1367. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1368. ("ndisWmiQueryAllData: Unable to determine GUID data size\n"));
  1369. break;
  1370. }
  1371. //
  1372. // Determine the size of the WNODE that is needed.
  1373. //
  1374. dataSize = ALIGN_UP(BytesNeeded, ULONG);
  1375. InstanceNameOffsetsSize = sizeof(ULONG);
  1376. InstanceNameSize = sizeof(USHORT) + Miniport->pAdapterInstanceName->Length; // comes at the end, no need to pad
  1377. wnodeTotalSize = wnodeSize + dataSize + InstanceNameOffsetsSize + InstanceNameSize;
  1378. if (BufferSize < wnodeTotalSize)
  1379. {
  1380. WMI_BUFFER_TOO_SMALL(BufferSize, wnode, wnodeTotalSize, &NtStatus, pReturnSize);
  1381. break;
  1382. }
  1383. //
  1384. // Initialize the wnode.
  1385. //
  1386. KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
  1387. wnode->WnodeHeader.Flags |= WNODE_FLAG_FIXED_INSTANCE_SIZE;
  1388. wnode->WnodeHeader.BufferSize = wnodeTotalSize;
  1389. wnode->InstanceCount = 1;
  1390. wnode->DataBlockOffset = wnodeSize;
  1391. wnode->OffsetInstanceNameOffsets = wnodeSize + dataSize;
  1392. wnode->FixedInstanceSize = BytesNeeded;
  1393. //
  1394. // Fill in the data block.
  1395. //
  1396. NtStatus = ndisQueryGuidData((PUCHAR)wnode + wnodeSize,
  1397. BytesNeeded,
  1398. Miniport,
  1399. NULL,
  1400. guid,
  1401. Irp);
  1402. if (!NT_SUCCESS(NtStatus))
  1403. {
  1404. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1405. ("ndisWmiQueryAllData: Failed to get the GUID data.\n"));
  1406. break;
  1407. }
  1408. *(PULONG)((PUCHAR)wnode + wnode->OffsetInstanceNameOffsets) = wnodeSize + dataSize + InstanceNameOffsetsSize;
  1409. //
  1410. // Get the pointer to where we store the instance name.
  1411. //
  1412. pucTmp = (PUCHAR)((PUCHAR)wnode + wnodeSize + dataSize + InstanceNameOffsetsSize);
  1413. *((PUSHORT)pucTmp) = Miniport->pAdapterInstanceName->Length;
  1414. NdisMoveMemory(pucTmp + sizeof(USHORT),
  1415. Miniport->pAdapterInstanceName->Buffer,
  1416. Miniport->pAdapterInstanceName->Length);
  1417. NtStatus = STATUS_SUCCESS;
  1418. *pReturnSize = wnode->WnodeHeader.BufferSize;
  1419. }
  1420. else
  1421. {
  1422. ULONG cRoughInstanceCount = Miniport->VcCount + 1;
  1423. UINT cInstanceCount = 0;
  1424. PUCHAR pBuffer;
  1425. ULONG OffsetToInstanceNames;
  1426. PLIST_ENTRY Link;
  1427. PNDIS_CO_VC_PTR_BLOCK pVcBlock = NULL;
  1428. POFFSETINSTANCEDATAANDLENGTH poidl;
  1429. PULONG pInstanceNameOffsets;
  1430. ULONG OffsetToInstanceInfo;
  1431. BOOLEAN OutOfSpace = FALSE;
  1432. //
  1433. // Initialize common wnode information.
  1434. //
  1435. KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
  1436. //
  1437. // Setup the OFFSETINSTANCEDATAANDLENGTH array.
  1438. //
  1439. poidl = wnode->OffsetInstanceDataAndLength;
  1440. wnode->OffsetInstanceNameOffsets = wnodeSize + ALIGN_UP((sizeof(OFFSETINSTANCEDATAANDLENGTH) * cRoughInstanceCount), ULONG);
  1441. //
  1442. // Get a pointer to the array of offsets to the instance names.
  1443. //
  1444. pInstanceNameOffsets = (PULONG)((PUCHAR)wnode + wnode->OffsetInstanceNameOffsets);
  1445. //
  1446. // Get the offset from the wnode where will will start copying the instance
  1447. // data into.
  1448. //
  1449. OffsetToInstanceInfo = ALIGN_8_LENGTH(wnode->OffsetInstanceNameOffsets + sizeof(ULONG) * cRoughInstanceCount);
  1450. //
  1451. // Get a pointer to start placing the data.
  1452. //
  1453. pBuffer = (PUCHAR)wnode + OffsetToInstanceInfo;
  1454. //
  1455. // Check to make sure we have at least this much buffer space in the wnode.
  1456. //
  1457. wnodeTotalSize = OffsetToInstanceInfo;
  1458. //
  1459. // Start with the miniport.
  1460. //
  1461. NtStatus = ndisQueryGuidDataSize(&BytesNeeded, Miniport, NULL, guid);
  1462. if (NT_SUCCESS(NtStatus))
  1463. {
  1464. //
  1465. // Make sure we have enough buffer space for the instance name and
  1466. // the data. If not we still continue since we need to find the total
  1467. // size
  1468. //
  1469. wnodeTotalSize += ALIGN_8_LENGTH(Miniport->pAdapterInstanceName->Length + sizeof(USHORT)) +
  1470. ALIGN_8_LENGTH(BytesNeeded);
  1471. if (BufferSize >= wnodeTotalSize)
  1472. {
  1473. ///
  1474. //
  1475. // The instance info contains the instance name followed by the
  1476. // data for the item.
  1477. //
  1478. ///
  1479. //
  1480. // Add the offset to the instance name to the table.
  1481. //
  1482. pInstanceNameOffsets[cInstanceCount] = OffsetToInstanceInfo;
  1483. //
  1484. // Copy the instance name into the wnode buffer.
  1485. //
  1486. *((PUSHORT)pBuffer) = Miniport->pAdapterInstanceName->Length;
  1487. NdisMoveMemory(pBuffer + sizeof(USHORT),
  1488. Miniport->pAdapterInstanceName->Buffer,
  1489. Miniport->pAdapterInstanceName->Length);
  1490. //
  1491. // Keep track of true instance counts.
  1492. //
  1493. OffsetToInstanceInfo += ALIGN_8_LENGTH(sizeof(USHORT) + Miniport->pAdapterInstanceName->Length);
  1494. pBuffer = (PUCHAR)wnode + OffsetToInstanceInfo;
  1495. //
  1496. // Query the data for the miniport.
  1497. //
  1498. NtStatus = ndisQueryGuidData(pBuffer, BytesNeeded, Miniport, NULL, guid, Irp);
  1499. if (!NT_SUCCESS(NtStatus))
  1500. {
  1501. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1502. ("ndisWmiQueryAllData: Failed to get the GUID data.\n"));
  1503. break;
  1504. }
  1505. //
  1506. // Save the length of the data item for this instance.
  1507. //
  1508. poidl[cInstanceCount].OffsetInstanceData = OffsetToInstanceInfo;
  1509. poidl[cInstanceCount].LengthInstanceData = BytesNeeded;
  1510. //
  1511. // Keep track of true instance counts.
  1512. //
  1513. OffsetToInstanceInfo += ALIGN_8_LENGTH(BytesNeeded);
  1514. pBuffer = (PUCHAR)wnode + OffsetToInstanceInfo;
  1515. }
  1516. //
  1517. // Increment the current instance count.
  1518. //
  1519. cInstanceCount++;
  1520. }
  1521. else
  1522. {
  1523. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1524. ("ndisWmiQueryAllData: Unable to determine GUID data size\n"));
  1525. break;
  1526. }
  1527. //
  1528. // Only the miniport?
  1529. //
  1530. if (cInstanceCount == cRoughInstanceCount)
  1531. {
  1532. if (BufferSize >= wnodeTotalSize)
  1533. {
  1534. wnode->WnodeHeader.BufferSize = wnodeTotalSize;
  1535. wnode->InstanceCount = cInstanceCount;
  1536. *pReturnSize = wnode->WnodeHeader.BufferSize;
  1537. NtStatus = STATUS_SUCCESS;
  1538. }
  1539. else
  1540. {
  1541. WMI_BUFFER_TOO_SMALL(BufferSize, wnode, wnodeTotalSize, &NtStatus, pReturnSize);
  1542. }
  1543. break;
  1544. }
  1545. //
  1546. // First search the inactive vc list.
  1547. //
  1548. Link = Miniport->WmiEnabledVcs.Flink;
  1549. while (Link != &Miniport->WmiEnabledVcs)
  1550. {
  1551. //
  1552. // We only have room for so many VCs.
  1553. //
  1554. if (cInstanceCount >= cRoughInstanceCount)
  1555. {
  1556. break;
  1557. }
  1558. //
  1559. // Get a pointer to the VC.
  1560. //
  1561. pVcBlock = CONTAINING_RECORD(Link, NDIS_CO_VC_PTR_BLOCK, WmiLink);
  1562. if (!ndisReferenceVcPtr(pVcBlock))
  1563. {
  1564. Link = Link->Flink;
  1565. //
  1566. // This VC is cleaning up.
  1567. //
  1568. continue;
  1569. }
  1570. //
  1571. // If there is an instance name associated with the VC then we need to query it.
  1572. //
  1573. if (NULL != pVcBlock->VcInstanceName.Buffer)
  1574. {
  1575. //
  1576. // Start with the miniport.
  1577. //
  1578. NtStatus = ndisQueryGuidDataSize(&BytesNeeded,
  1579. Miniport,
  1580. pVcBlock,
  1581. guid);
  1582. if (NT_SUCCESS(NtStatus))
  1583. {
  1584. //
  1585. // Make sure we have enough buffer space for the instance name and
  1586. // the data.
  1587. //
  1588. wnodeTotalSize += ALIGN_8_LENGTH(pVcBlock->VcInstanceName.Length + sizeof(USHORT)) +
  1589. ALIGN_8_LENGTH(BytesNeeded);
  1590. if (BufferSize < wnodeTotalSize)
  1591. {
  1592. WMI_BUFFER_TOO_SMALL(BufferSize, wnode, wnodeTotalSize, &NtStatus, pReturnSize);
  1593. OutOfSpace = TRUE;
  1594. ndisDereferenceVcPtr(pVcBlock);
  1595. Link = Link->Flink;
  1596. continue;
  1597. }
  1598. //
  1599. // The instance info contains the instance name followed by the
  1600. // data for the item.
  1601. //
  1602. //
  1603. // Add the offset to the instance name to the table.
  1604. //
  1605. pInstanceNameOffsets[cInstanceCount] = OffsetToInstanceInfo;
  1606. //
  1607. // Copy the instance name into the wnode buffer.
  1608. //
  1609. *((PUSHORT)pBuffer) = pVcBlock->VcInstanceName.Length;
  1610. NdisMoveMemory(pBuffer + sizeof(USHORT),
  1611. pVcBlock->VcInstanceName.Buffer,
  1612. pVcBlock->VcInstanceName.Length);
  1613. //
  1614. // Keep track of true instance counts.
  1615. //
  1616. OffsetToInstanceInfo += ALIGN_8_LENGTH(sizeof(USHORT) + pVcBlock->VcInstanceName.Length);
  1617. pBuffer = (PUCHAR)wnode + OffsetToInstanceInfo;
  1618. //
  1619. // Query the data for the miniport.
  1620. //
  1621. NtStatus = ndisQueryGuidData(pBuffer,
  1622. BytesNeeded,
  1623. Miniport,
  1624. pVcBlock,
  1625. guid,
  1626. Irp);
  1627. if (!NT_SUCCESS(NtStatus))
  1628. {
  1629. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1630. ("ndisWmiQueryAllData: Failed to query GUID data\n"));
  1631. ndisDereferenceVcPtr(pVcBlock);
  1632. break;
  1633. }
  1634. //
  1635. // Save the length of the data item for this instance.
  1636. //
  1637. poidl[cInstanceCount].OffsetInstanceData = OffsetToInstanceInfo;
  1638. poidl[cInstanceCount].LengthInstanceData = BytesNeeded;
  1639. //
  1640. // Keep track of true instance counts.
  1641. //
  1642. OffsetToInstanceInfo += ALIGN_8_LENGTH(BytesNeeded);
  1643. pBuffer = (PUCHAR)wnode + OffsetToInstanceInfo;
  1644. //
  1645. // Increment the current instance count.
  1646. //
  1647. cInstanceCount++;
  1648. }
  1649. }
  1650. ndisDereferenceVcPtr(pVcBlock);
  1651. Link = Link->Flink;
  1652. }
  1653. if (!OutOfSpace)
  1654. {
  1655. wnode->WnodeHeader.BufferSize = wnodeTotalSize;
  1656. wnode->InstanceCount = cInstanceCount;
  1657. //
  1658. // Set the status to success.
  1659. //
  1660. NtStatus = STATUS_SUCCESS;
  1661. *pReturnSize = wnode->WnodeHeader.BufferSize;
  1662. }
  1663. }
  1664. } while (FALSE);
  1665. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  1666. ("<==ndisWmiQueryAllData\n"));
  1667. return(NtStatus);
  1668. }
  1669. NTSTATUS
  1670. ndisWmiQuerySingleInstance(
  1671. IN PNDIS_MINIPORT_BLOCK Miniport,
  1672. IN PWNODE_SINGLE_INSTANCE wnode,
  1673. IN ULONG BufferSize,
  1674. OUT PULONG pReturnSize,
  1675. IN PIRP Irp
  1676. )
  1677. /*++
  1678. Routine Description:
  1679. Arguments:
  1680. Return Value:
  1681. --*/
  1682. {
  1683. NTSTATUS NtStatus;
  1684. ULONG BytesNeeded;
  1685. ULONG wnodeSize;
  1686. USHORT cbInstanceName;
  1687. PWSTR pInstanceName;
  1688. PNDIS_CO_VC_PTR_BLOCK pVcBlock = NULL;
  1689. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  1690. ("==>ndisWmiQuerySingleInstance\n"));
  1691. do
  1692. {
  1693. *pReturnSize = 0;
  1694. if (wnode->WnodeHeader.Flags & WNODE_FLAG_STATIC_INSTANCE_NAMES)
  1695. {
  1696. //
  1697. // This is a static instance name
  1698. //
  1699. pVcBlock = NULL;
  1700. }
  1701. else
  1702. {
  1703. //
  1704. // Determine if this is for a VC or a miniport...
  1705. //
  1706. cbInstanceName = *(PUSHORT)((PUCHAR)wnode + wnode->OffsetInstanceName);
  1707. pInstanceName = (PWSTR)((PUCHAR)wnode + wnode->OffsetInstanceName + sizeof(USHORT));
  1708. //
  1709. // This routine will determine if the wnode's instance name is a miniport or VC.
  1710. // If it's a VC then it will find which one.
  1711. //
  1712. NtStatus = ndisWmiFindInstanceName(&pVcBlock, Miniport, pInstanceName, cbInstanceName);
  1713. if (!NT_SUCCESS(NtStatus))
  1714. {
  1715. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1716. ("ndisWmiQuerySingleInstance: Unable to find the instance name\n"));
  1717. pVcBlock = NULL;
  1718. break;
  1719. }
  1720. }
  1721. //
  1722. // Determine the buffer size needed for the GUID data.
  1723. //
  1724. NtStatus = ndisQueryGuidDataSize(&BytesNeeded,
  1725. Miniport,
  1726. pVcBlock,
  1727. &wnode->WnodeHeader.Guid);
  1728. if (!NT_SUCCESS(NtStatus))
  1729. {
  1730. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1731. ("ndisWmiQuerySingleInstance: Unable to determine GUID data size\n"));
  1732. break;
  1733. }
  1734. //
  1735. // Determine the size of the wnode.
  1736. //
  1737. wnodeSize = wnode->DataBlockOffset + BytesNeeded;
  1738. if (BufferSize < wnodeSize)
  1739. {
  1740. WMI_BUFFER_TOO_SMALL(BufferSize, wnode, wnodeSize, &NtStatus, pReturnSize);
  1741. break;
  1742. }
  1743. //
  1744. // Initialize the wnode.
  1745. //
  1746. KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
  1747. wnode->WnodeHeader.BufferSize = wnodeSize;
  1748. wnode->SizeDataBlock = BytesNeeded;
  1749. //
  1750. // Validate the guid and get the data for it.
  1751. //
  1752. NtStatus = ndisQueryGuidData((PUCHAR)wnode + wnode->DataBlockOffset,
  1753. BytesNeeded,
  1754. Miniport,
  1755. pVcBlock,
  1756. &wnode->WnodeHeader.Guid,
  1757. Irp);
  1758. if (!NT_SUCCESS(NtStatus))
  1759. {
  1760. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1761. ("ndisWmiQuerySingleInstance: Failed to get the GUID data.\n"));
  1762. break;
  1763. }
  1764. *pReturnSize = wnodeSize;
  1765. NtStatus = STATUS_SUCCESS;
  1766. } while (FALSE);
  1767. //
  1768. // If this was a VC then we need to dereference it.
  1769. //
  1770. if (NULL != pVcBlock)
  1771. {
  1772. ndisDereferenceVcPtr(pVcBlock);
  1773. }
  1774. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  1775. ("<==ndisWmiQuerySingleInstance\n"));
  1776. return(NtStatus);
  1777. }
  1778. NTSTATUS
  1779. ndisWmiChangeSingleInstance(
  1780. IN PNDIS_MINIPORT_BLOCK Miniport,
  1781. IN PWNODE_SINGLE_INSTANCE wnode,
  1782. IN ULONG BufferSize,
  1783. OUT PULONG pReturnSize,
  1784. IN PIRP Irp
  1785. )
  1786. /*++
  1787. Routine Description:
  1788. Arguments:
  1789. Return Value:
  1790. --*/
  1791. {
  1792. NTSTATUS NtStatus;
  1793. NDIS_STATUS Status;
  1794. PNDIS_GUID pNdisGuid;
  1795. PUCHAR pGuidData;
  1796. ULONG GuidDataSize;
  1797. NDIS_REQUEST Request;
  1798. USHORT cbInstanceName;
  1799. PWSTR pInstanceName;
  1800. PNDIS_CO_VC_PTR_BLOCK pVcBlock = NULL;
  1801. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  1802. ("==>ndisWmiChangeSingleInstance\n"));
  1803. do
  1804. {
  1805. if (wnode->WnodeHeader.Flags & WNODE_FLAG_STATIC_INSTANCE_NAMES)
  1806. {
  1807. //
  1808. // This is a static instance name
  1809. //
  1810. pVcBlock = NULL;
  1811. }
  1812. else
  1813. {
  1814. //
  1815. // Determine if this is for a VC or a miniport...
  1816. //
  1817. cbInstanceName = *(PUSHORT)((PUCHAR)wnode + wnode->OffsetInstanceName);
  1818. pInstanceName = (PWSTR)((PUCHAR)wnode + wnode->OffsetInstanceName + sizeof(USHORT));
  1819. //
  1820. // This routine will determine if the wnode's instance name is a miniport or VC.
  1821. // If it's a VC then it will find which one.
  1822. //
  1823. NtStatus = ndisWmiFindInstanceName(&pVcBlock, Miniport, pInstanceName, cbInstanceName);
  1824. if (!NT_SUCCESS(NtStatus))
  1825. {
  1826. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1827. ("ndisWmiChangeSingleInstance: Unable to find the instance name\n"));
  1828. pVcBlock = NULL;
  1829. break;
  1830. }
  1831. }
  1832. //
  1833. // Make sure that we support the guid that was passed, and find
  1834. // the corresponding OID.
  1835. //
  1836. NtStatus = ndisWmiGetGuid(&pNdisGuid,
  1837. Miniport,
  1838. &wnode->WnodeHeader.Guid,
  1839. 0);
  1840. if (!NT_SUCCESS(NtStatus))
  1841. {
  1842. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1843. ("ndisWmiChangeSingleInstance: Unsupported GUID\n"));
  1844. NtStatus = STATUS_INVALID_PARAMETER;
  1845. break;
  1846. }
  1847. if (!ndisWmiCheckAccess(pNdisGuid,
  1848. fNDIS_GUID_ALLOW_WRITE,
  1849. SE_LOAD_DRIVER_PRIVILEGE,
  1850. Irp))
  1851. {
  1852. NtStatus = STATUS_PRIVILEGE_NOT_HELD;
  1853. break;
  1854. }
  1855. //
  1856. // Is this guid settable?
  1857. //
  1858. if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_NOT_SETTABLE))
  1859. {
  1860. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1861. ("ndisWmiChangeSingleInstance: Guid is not settable!\n"));
  1862. NtStatus = STATUS_NOT_SUPPORTED;
  1863. break;
  1864. }
  1865. //
  1866. // Get a pointer to the GUID data and size.
  1867. //
  1868. GuidDataSize = wnode->SizeDataBlock;
  1869. pGuidData = (PUCHAR)wnode + wnode->DataBlockOffset;
  1870. if (GuidDataSize == 0)
  1871. {
  1872. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1873. ("ndisWmiChangeSingleInstance: Guid has not data to set!\n"));
  1874. NtStatus = STATUS_INVALID_PARAMETER;
  1875. break;
  1876. }
  1877. //
  1878. // Is this an internal ndis guid?
  1879. //
  1880. if ((NULL == pVcBlock) && NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_NDIS_ONLY))
  1881. {
  1882. PBOOLEAN pBoolean = (PBOOLEAN)pGuidData;
  1883. NtStatus = STATUS_SUCCESS;
  1884. //
  1885. // for PM set guids, we should update registry for future boots
  1886. //
  1887. //
  1888. if (NdisEqualMemory(&pNdisGuid->Guid, (PVOID)&GUID_POWER_DEVICE_ENABLE, sizeof(GUID)))
  1889. {
  1890. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_PM_SUPPORTED) &&
  1891. (!MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_NO_HALT_ON_SUSPEND)))
  1892. {
  1893. if (*pBoolean)
  1894. {
  1895. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_DEVICE_POWER_ENABLE);
  1896. //
  1897. // enabling power management also enables wake on link change
  1898. // assuming the adapter supports it
  1899. //
  1900. if ((Miniport->PMCapabilities.WakeUpCapabilities.MinLinkChangeWakeUp != NdisDeviceStateUnspecified) &&
  1901. (Miniport->MediaDisconnectTimeOut != (USHORT)(-1)))
  1902. {
  1903. Miniport->WakeUpEnable |= NDIS_PNP_WAKE_UP_LINK_CHANGE;
  1904. }
  1905. Miniport->PnPCapabilities &= ~NDIS_DEVICE_DISABLE_PM;
  1906. }
  1907. else
  1908. {
  1909. //
  1910. // disabling power management also disables wake on link and magic packet
  1911. //
  1912. Miniport->WakeUpEnable &= ~NDIS_PNP_WAKE_UP_LINK_CHANGE;
  1913. MINIPORT_PNP_CLEAR_FLAG(Miniport, fMINIPORT_DEVICE_POWER_ENABLE);
  1914. Miniport->PnPCapabilities |= (NDIS_DEVICE_DISABLE_PM |
  1915. NDIS_DEVICE_DISABLE_WAKE_UP);
  1916. }
  1917. }
  1918. else
  1919. {
  1920. NtStatus = STATUS_INVALID_DEVICE_REQUEST;
  1921. }
  1922. }
  1923. else if (NdisEqualMemory(&pNdisGuid->Guid, (PVOID)&GUID_POWER_DEVICE_WAKE_ENABLE, sizeof(GUID)))
  1924. {
  1925. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_PM_SUPPORTED) &&
  1926. (Miniport->DeviceCaps.SystemWake > PowerSystemWorking))
  1927. {
  1928. if (*pBoolean)
  1929. {
  1930. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_DEVICE_POWER_WAKE_ENABLE);
  1931. Miniport->PnPCapabilities &= ~NDIS_DEVICE_DISABLE_WAKE_UP;
  1932. //
  1933. // enableing Wake on Lan enables wake on Magic Packet method
  1934. // assuming the miniport supports it and it is not disabled in the registry
  1935. //
  1936. if ((Miniport->PMCapabilities.WakeUpCapabilities.MinMagicPacketWakeUp != NdisDeviceStateUnspecified) &&
  1937. !(Miniport->PnPCapabilities & NDIS_DEVICE_DISABLE_WAKE_ON_MAGIC_PACKET))
  1938. {
  1939. Miniport->WakeUpEnable |= NDIS_PNP_WAKE_UP_MAGIC_PACKET;
  1940. }
  1941. }
  1942. else
  1943. {
  1944. MINIPORT_PNP_CLEAR_FLAG(Miniport, fMINIPORT_DEVICE_POWER_WAKE_ENABLE);
  1945. //
  1946. // disabling Wake On Lan also disables wake on Magic Packet method
  1947. //
  1948. Miniport->WakeUpEnable &= ~NDIS_PNP_WAKE_UP_MAGIC_PACKET;
  1949. Miniport->PnPCapabilities |= NDIS_DEVICE_DISABLE_WAKE_UP;
  1950. }
  1951. }
  1952. else
  1953. {
  1954. NtStatus = STATUS_INVALID_DEVICE_REQUEST;
  1955. }
  1956. }
  1957. else if (NdisEqualMemory(&pNdisGuid->Guid, (PVOID)&GUID_NDIS_WAKE_ON_MAGIC_PACKET_ONLY, sizeof(GUID)))
  1958. {
  1959. //
  1960. // let the user set this only if we can do wake on magic packet
  1961. //
  1962. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_PM_SUPPORTED) &&
  1963. (Miniport->DeviceCaps.SystemWake > PowerSystemWorking) &&
  1964. (Miniport->PMCapabilities.WakeUpCapabilities.MinMagicPacketWakeUp != NdisDeviceStateUnspecified) &&
  1965. !(Miniport->PnPCapabilities & NDIS_DEVICE_DISABLE_WAKE_ON_MAGIC_PACKET))
  1966. {
  1967. if (*pBoolean)
  1968. {
  1969. //
  1970. // user does -not- want to wake on pattern match
  1971. //
  1972. Miniport->PnPCapabilities |= NDIS_DEVICE_DISABLE_WAKE_ON_PATTERN_MATCH;
  1973. }
  1974. else
  1975. {
  1976. Miniport->PnPCapabilities &= ~NDIS_DEVICE_DISABLE_WAKE_ON_PATTERN_MATCH;
  1977. }
  1978. }
  1979. else
  1980. {
  1981. NtStatus = STATUS_INVALID_DEVICE_REQUEST;
  1982. }
  1983. }
  1984. else
  1985. {
  1986. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1987. ("ndisWmiChangeSingleInstance: Invalid NDIS internal GUID!\n"));
  1988. NtStatus = STATUS_INVALID_DEVICE_REQUEST;
  1989. }
  1990. if (NT_SUCCESS(NtStatus))
  1991. {
  1992. if (MINIPORT_PNP_TEST_FLAGS(Miniport, fMINIPORT_DEVICE_POWER_ENABLE |
  1993. fMINIPORT_DEVICE_POWER_WAKE_ENABLE))
  1994. {
  1995. //
  1996. // power management and wol has been enabled by the user
  1997. // check to see what we should tell protocols about the new
  1998. // WOL capabilities of the device
  1999. // NOTE: set NDIS_DEVICE_WAKE_UP_ENABLE only if pattern match is enabled
  2000. //
  2001. if (Miniport->PnPCapabilities & NDIS_DEVICE_DISABLE_WAKE_ON_PATTERN_MATCH)
  2002. Miniport->PMCapabilities.Flags &= ~(NDIS_DEVICE_WAKE_UP_ENABLE |
  2003. NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE);
  2004. else
  2005. //
  2006. // user did not disable wake on pattern match, for protocol's purpose
  2007. // wol is enabled
  2008. //
  2009. Miniport->PMCapabilities.Flags |= NDIS_DEVICE_WAKE_UP_ENABLE |
  2010. NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE;
  2011. if (Miniport->PnPCapabilities & NDIS_DEVICE_DISABLE_WAKE_ON_MAGIC_PACKET)
  2012. Miniport->PMCapabilities.Flags &= ~NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE;
  2013. else
  2014. //
  2015. // user did not disable wake on magic packet, do -not- set the NDIS_DEVICE_WAKE_UP_ENABLE
  2016. // bit becasue wake on pattern match may not be enabled
  2017. //
  2018. Miniport->PMCapabilities.Flags |= NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE;
  2019. }
  2020. else
  2021. Miniport->PMCapabilities.Flags &= ~(NDIS_DEVICE_WAKE_UP_ENABLE |
  2022. NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE |
  2023. NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE);
  2024. ndisWritePnPCapabilities(Miniport, Miniport->PnPCapabilities);
  2025. ndisPnPNotifyAllTransports(Miniport,
  2026. NetEventPnPCapabilities,
  2027. &Miniport->PMCapabilities.Flags,
  2028. sizeof(ULONG));
  2029. }
  2030. break;
  2031. }
  2032. //
  2033. // Make sure it's not a stauts indication.
  2034. //
  2035. if (!NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_TO_OID))
  2036. {
  2037. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  2038. ("ndisWmiChangeSingleInstance: Guid does not translate to an OID\n"));
  2039. NtStatus = STATUS_INVALID_DEVICE_REQUEST;
  2040. break;
  2041. }
  2042. //
  2043. // Attempt to set the miniport with the information.
  2044. //
  2045. INIT_INTERNAL_REQUEST(&Request, pNdisGuid->Oid, NdisRequestSetInformation, pGuidData, GuidDataSize);
  2046. Status = ndisQuerySetMiniport(Miniport,
  2047. pVcBlock,
  2048. TRUE,
  2049. &Request,
  2050. NULL);
  2051. if (NDIS_STATUS_SUCCESS != Status)
  2052. {
  2053. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  2054. ("ndisWmiChangeSingleInstance: Failed to set the new information on the miniport\n"));
  2055. MAP_NDIS_STATUS_TO_NT_STATUS(Status, &NtStatus);
  2056. break;
  2057. }
  2058. NtStatus = STATUS_SUCCESS;
  2059. } while (FALSE);
  2060. //
  2061. // If this was a VC then we need to dereference it.
  2062. //
  2063. if (NULL != pVcBlock)
  2064. {
  2065. ndisDereferenceVcPtr(pVcBlock);
  2066. }
  2067. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2068. ("<==ndisWmiChangeSingleInstance\n"));
  2069. return(NtStatus);
  2070. }
  2071. NTSTATUS
  2072. ndisWmiChangeSingleItem(
  2073. IN PNDIS_MINIPORT_BLOCK Miniport,
  2074. IN PWNODE_SINGLE_ITEM wnode,
  2075. IN ULONG BufferSize,
  2076. OUT PULONG pReturnSize,
  2077. IN PIRP Irp
  2078. )
  2079. /*++
  2080. Routine Description:
  2081. Arguments:
  2082. Return Value:
  2083. --*/
  2084. {
  2085. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2086. ("==>ndisWmiChangeSingleItem\n"));
  2087. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2088. ("<==ndisWmiChangeSingleItem: Not Supported\n"));
  2089. return(STATUS_NOT_SUPPORTED);
  2090. }
  2091. NTSTATUS
  2092. FASTCALL
  2093. ndisWmiEnableEvents(
  2094. IN PNDIS_MINIPORT_BLOCK Miniport,
  2095. IN LPGUID Guid
  2096. )
  2097. /*++
  2098. Routine Description:
  2099. Arguments:
  2100. Return Value:
  2101. --*/
  2102. {
  2103. NDIS_STATUS Status;
  2104. PNDIS_GUID pNdisGuid = NULL;
  2105. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2106. ("==>ndisWmiEnableEvents\n"));
  2107. do
  2108. {
  2109. //
  2110. // Get a pointer to the Guid/Status to enable.
  2111. //
  2112. Status = ndisWmiGetGuid(&pNdisGuid, Miniport, Guid, 0);
  2113. if (NdisEqualMemory(Guid, (PVOID)&GUID_NDIS_NOTIFY_BIND, sizeof(GUID)) ||
  2114. NdisEqualMemory(Guid, (PVOID)&GUID_NDIS_NOTIFY_UNBIND, sizeof(GUID)) ||
  2115. NdisEqualMemory(Guid, (PVOID)&GUID_NDIS_NOTIFY_DEVICE_POWER_ON, sizeof(GUID)) ||
  2116. NdisEqualMemory(Guid, (PVOID)&GUID_NDIS_NOTIFY_DEVICE_POWER_OFF, sizeof(GUID)) ||
  2117. NdisEqualMemory(Guid, (PVOID)&GUID_NDIS_NOTIFY_ADAPTER_ARRIVAL, sizeof(GUID)) ||
  2118. NdisEqualMemory(Guid, (PVOID)&GUID_NDIS_NOTIFY_ADAPTER_REMOVAL, sizeof(GUID)))
  2119. {
  2120. if (pNdisGuid)
  2121. {
  2122. NDIS_GUID_SET_FLAG(pNdisGuid, fNDIS_GUID_EVENT_ENABLED);
  2123. }
  2124. Status = STATUS_SUCCESS;
  2125. break;
  2126. }
  2127. if (!NT_SUCCESS(Status))
  2128. {
  2129. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  2130. ("ndisWmiEnableEvents: Cannot find the guid to enable an event\n"));
  2131. Status = STATUS_INVALID_PARAMETER;
  2132. break;
  2133. }
  2134. //
  2135. // Is this GUID an event indication?
  2136. //
  2137. if (!NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_TO_STATUS))
  2138. {
  2139. Status = STATUS_INVALID_DEVICE_REQUEST;
  2140. break;
  2141. }
  2142. //
  2143. // Mark the guid as enabled
  2144. //
  2145. NDIS_GUID_SET_FLAG(pNdisGuid, fNDIS_GUID_EVENT_ENABLED);
  2146. Status = STATUS_SUCCESS;
  2147. } while (FALSE);
  2148. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2149. ("<==ndisWmiEnableEvents\n"));
  2150. return(Status);
  2151. }
  2152. NTSTATUS
  2153. FASTCALL
  2154. ndisWmiDisableEvents(
  2155. IN PNDIS_MINIPORT_BLOCK Miniport,
  2156. IN LPGUID Guid
  2157. )
  2158. /*++
  2159. Routine Description:
  2160. Arguments:
  2161. Return Value:
  2162. --*/
  2163. {
  2164. NDIS_STATUS Status;
  2165. PNDIS_GUID pNdisGuid;
  2166. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2167. ("==>ndisWmiDisableEvents\n"));
  2168. do
  2169. {
  2170. //
  2171. // Get a pointer to the Guid/Status to enable.
  2172. //
  2173. Status = ndisWmiGetGuid(&pNdisGuid, Miniport, Guid, 0);
  2174. if (!NT_SUCCESS(Status))
  2175. {
  2176. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  2177. ("ndisWmiDisableEvents: Cannot find the guid to enable an event\n"));
  2178. Status = STATUS_INVALID_PARAMETER;
  2179. break;
  2180. }
  2181. //
  2182. // Is this GUID an event indication?
  2183. //
  2184. if (!NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_TO_STATUS))
  2185. {
  2186. Status = STATUS_INVALID_DEVICE_REQUEST;
  2187. break;
  2188. }
  2189. //
  2190. // Mark the guid as enabled
  2191. //
  2192. NDIS_GUID_CLEAR_FLAG(pNdisGuid, fNDIS_GUID_EVENT_ENABLED);
  2193. Status = STATUS_SUCCESS;
  2194. } while (FALSE);
  2195. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2196. ("<==ndisWmiDisableEvents\n"));
  2197. return(Status);
  2198. }
  2199. NTSTATUS
  2200. ndisWMIDispatch(
  2201. IN PDEVICE_OBJECT DeviceObject,
  2202. IN PIRP pirp
  2203. )
  2204. /*++
  2205. Routine Description:
  2206. Arguments:
  2207. Return Value:
  2208. --*/
  2209. {
  2210. PIO_STACK_LOCATION pirpSp = IoGetCurrentIrpStackLocation(pirp);
  2211. PVOID DataPath = pirpSp->Parameters.WMI.DataPath;
  2212. ULONG BufferSize = pirpSp->Parameters.WMI.BufferSize;
  2213. PVOID Buffer = pirpSp->Parameters.WMI.Buffer;
  2214. NTSTATUS Status;
  2215. ULONG ReturnSize = 0;
  2216. PNDIS_MINIPORT_BLOCK Miniport;
  2217. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2218. ("==>ndisWMIDispatch\n"));
  2219. //
  2220. // Get a pointer to miniport block
  2221. //
  2222. Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)DeviceObject->DeviceExtension + 1);
  2223. try
  2224. {
  2225. if (Miniport->Signature != (PVOID)MINIPORT_DEVICE_MAGIC_VALUE)
  2226. {
  2227. //
  2228. // This is not a miniport. Likely a device created by the driver. Try dispatching to it.
  2229. //
  2230. return(ndisDummyIrpHandler(DeviceObject, pirp));
  2231. }
  2232. }
  2233. except(EXCEPTION_EXECUTE_HANDLER)
  2234. {
  2235. return(STATUS_ACCESS_VIOLATION);
  2236. }
  2237. //
  2238. // If the provider ID is not us then pass it down the stack.
  2239. //
  2240. if (pirpSp->Parameters.WMI.ProviderId != (ULONG_PTR)DeviceObject)
  2241. {
  2242. IoSkipCurrentIrpStackLocation(pirp);
  2243. Status = IoCallDriver(Miniport->NextDeviceObject, pirp);
  2244. return(Status);
  2245. }
  2246. switch (pirpSp->MinorFunction)
  2247. {
  2248. case IRP_MN_REGINFO:
  2249. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2250. ("ndisWMIDispatch: IRP_MN_REGINFO\n"));
  2251. Status = ndisWmiRegister(Miniport,
  2252. (ULONG_PTR)DataPath,
  2253. Buffer,
  2254. BufferSize,
  2255. &ReturnSize);
  2256. break;
  2257. case IRP_MN_QUERY_ALL_DATA:
  2258. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2259. ("ndisWMIDispatch: IRP_MN_QUERY_ALL_DATA\n"));
  2260. Status = ndisWmiQueryAllData(Miniport,
  2261. (LPGUID)DataPath,
  2262. (PWNODE_ALL_DATA)Buffer,
  2263. BufferSize,
  2264. &ReturnSize,
  2265. pirp);
  2266. break;
  2267. case IRP_MN_QUERY_SINGLE_INSTANCE:
  2268. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2269. ("ndisWMIDispatch: IRP_MN_QUERY_SINGLE_INSTANCE\n"));
  2270. Status = ndisWmiQuerySingleInstance(Miniport,
  2271. Buffer,
  2272. BufferSize,
  2273. &ReturnSize,
  2274. pirp);
  2275. break;
  2276. case IRP_MN_CHANGE_SINGLE_INSTANCE:
  2277. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2278. ("ndisWMIDispatch: IRP_MN_CHANGE_SINGLE_INSTANCE\n"));
  2279. Status = ndisWmiChangeSingleInstance(Miniport,
  2280. Buffer,
  2281. BufferSize,
  2282. &ReturnSize,
  2283. pirp);
  2284. break;
  2285. case IRP_MN_CHANGE_SINGLE_ITEM:
  2286. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2287. ("ndisWMIDispatch: IRP_MN_CHANGE_SINGLE_ITEM\n"));
  2288. Status = ndisWmiChangeSingleItem(Miniport,
  2289. Buffer,
  2290. BufferSize,
  2291. &ReturnSize,
  2292. pirp);
  2293. break;
  2294. case IRP_MN_ENABLE_EVENTS:
  2295. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2296. ("ndisWMIDispatch: IRP_MN_ENABLE_EVENTS\n"));
  2297. Status = ndisWmiEnableEvents(Miniport, (LPGUID)DataPath);
  2298. break;
  2299. case IRP_MN_DISABLE_EVENTS:
  2300. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2301. ("ndisWMIDispatch: IRP_MN_DISABLE_EVENTS\n"));
  2302. Status = ndisWmiDisableEvents(Miniport, (LPGUID)DataPath);
  2303. break;
  2304. case IRP_MN_ENABLE_COLLECTION:
  2305. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2306. ("ndisWMIDispatch: IRP_MN_ENABLE_COLLECTION\n"));
  2307. Status = STATUS_NOT_SUPPORTED;
  2308. break;
  2309. case IRP_MN_DISABLE_COLLECTION:
  2310. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2311. ("ndisWMIDispatch: IRP_MN_DISABLE_COLLECTION\n"));
  2312. Status = STATUS_NOT_SUPPORTED;
  2313. break;
  2314. default:
  2315. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2316. ("ndisWMIDispatch: Invalid minor function (0x%x)\n", pirpSp->MinorFunction));
  2317. Status = STATUS_INVALID_DEVICE_REQUEST;
  2318. break;
  2319. }
  2320. pirp->IoStatus.Status = Status;
  2321. ASSERT(ReturnSize <= BufferSize);
  2322. if (Status == STATUS_BUFFER_TOO_SMALL)
  2323. {
  2324. pirp->IoStatus.Information = ReturnSize;
  2325. }
  2326. else
  2327. {
  2328. pirp->IoStatus.Information = NT_SUCCESS(Status) ? ReturnSize : 0;
  2329. }
  2330. IoCompleteRequest(pirp, IO_NO_INCREMENT);
  2331. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_INFO,
  2332. ("<==ndisWMIDispatch\n"));
  2333. return(Status);
  2334. }
  2335. VOID
  2336. ndisSetupWmiNode(
  2337. IN PNDIS_MINIPORT_BLOCK Miniport,
  2338. IN PUNICODE_STRING InstanceName,
  2339. IN ULONG DataBlockSize,
  2340. IN PVOID pGuid,
  2341. IN OUT PWNODE_SINGLE_INSTANCE * pwnode
  2342. )
  2343. {
  2344. /*
  2345. sets up a wmi node
  2346. the caller will fill in the data block after the call returns
  2347. */
  2348. PWNODE_SINGLE_INSTANCE wnode;
  2349. ULONG wnodeSize;
  2350. ULONG wnodeInstanceNameSize;
  2351. NTSTATUS Status;
  2352. PUCHAR ptmp;
  2353. //
  2354. // Determine the amount of wnode information we need.
  2355. //
  2356. wnodeSize = ALIGN_8_TYPE(WNODE_SINGLE_INSTANCE);
  2357. wnodeInstanceNameSize = ALIGN_8_LENGTH(InstanceName->Length + sizeof(USHORT));
  2358. wnode = ALLOC_FROM_POOL(wnodeSize + wnodeInstanceNameSize + DataBlockSize,
  2359. NDIS_TAG_WMI_EVENT_ITEM);
  2360. if (NULL != wnode)
  2361. {
  2362. NdisZeroMemory(wnode, wnodeSize + wnodeInstanceNameSize + DataBlockSize);
  2363. wnode->WnodeHeader.BufferSize = wnodeSize + DataBlockSize + wnodeInstanceNameSize;
  2364. wnode->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(Miniport->DeviceObject);
  2365. wnode->WnodeHeader.Version = 1;
  2366. KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
  2367. RtlCopyMemory(&wnode->WnodeHeader.Guid, pGuid, sizeof(GUID));
  2368. wnode->WnodeHeader.Flags = WNODE_FLAG_EVENT_ITEM | WNODE_FLAG_SINGLE_INSTANCE;
  2369. wnode->OffsetInstanceName = wnodeSize;
  2370. wnode->DataBlockOffset = wnodeSize + wnodeInstanceNameSize;
  2371. wnode->SizeDataBlock = DataBlockSize;
  2372. //
  2373. // Get a pointer to the start of the instance name.
  2374. //
  2375. ptmp = (PUCHAR)wnode + wnodeSize;
  2376. //
  2377. // Copy in the instance name.
  2378. //
  2379. *((PUSHORT)ptmp) = InstanceName->Length;
  2380. RtlCopyMemory(ptmp + sizeof(USHORT),
  2381. InstanceName->Buffer,
  2382. InstanceName->Length);
  2383. }
  2384. *pwnode = wnode;
  2385. }
  2386. BOOLEAN
  2387. ndisWmiCheckAccess(
  2388. IN PNDIS_GUID pNdisGuid,
  2389. IN ULONG DesiredAccess,
  2390. IN LONG RequiredPrivilege,
  2391. IN PIRP Irp
  2392. )
  2393. {
  2394. LUID Privilege;
  2395. BOOLEAN AccessAllowed = FALSE;
  2396. //
  2397. // SE_LOAD_DRIVER_PRIVILEGE
  2398. //
  2399. if ((DesiredAccess & fNDIS_GUID_ALLOW_READ) == fNDIS_GUID_ALLOW_READ)
  2400. {
  2401. if (pNdisGuid->Flags & fNDIS_GUID_ALLOW_READ)
  2402. {
  2403. AccessAllowed = TRUE;
  2404. }
  2405. else
  2406. {
  2407. Privilege = RtlConvertLongToLuid(RequiredPrivilege);
  2408. AccessAllowed = SeSinglePrivilegeCheck(Privilege, Irp->RequestorMode);
  2409. }
  2410. }
  2411. else if ((DesiredAccess & fNDIS_GUID_ALLOW_WRITE) == fNDIS_GUID_ALLOW_WRITE)
  2412. {
  2413. if (pNdisGuid->Flags & fNDIS_GUID_ALLOW_WRITE)
  2414. {
  2415. AccessAllowed = TRUE;
  2416. }
  2417. else
  2418. {
  2419. Privilege = RtlConvertLongToLuid(RequiredPrivilege);
  2420. AccessAllowed = SeSinglePrivilegeCheck(Privilege, Irp->RequestorMode);
  2421. }
  2422. }
  2423. else
  2424. {
  2425. #if DBG
  2426. DbgPrint("ndisWmiCheckAccess: DesiredAccess can only be READ or WRITE.\n");
  2427. #endif
  2428. ASSERT(FALSE);
  2429. }
  2430. return AccessAllowed;
  2431. }