Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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