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.

871 lines
27 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1998 - 1999
  3. Module Name:
  4. wmilib.c
  5. Abstract:
  6. WMI library utility functions for SCSI miniports
  7. CONSIDER adding the following functionality to the library:
  8. * Dynamic instance names
  9. * Different instance names for different guids
  10. Author:
  11. AlanWar
  12. Environment:
  13. kernel mode only
  14. Notes:
  15. Revision History:
  16. --*/
  17. #include "miniport.h"
  18. #include "scsi.h"
  19. #include "wmistr.h"
  20. #include "scsiwmi.h"
  21. typedef enum
  22. {
  23. ScsiProcessed, // Srb was processed and possibly completed
  24. ScsiNotCompleted, // Srb was process and NOT completed
  25. ScsiNotWmi, // Srb is not a WMI irp
  26. ScsiForward // Srb is wmi irp, but targeted at another device object
  27. } SYSCTL_SCSI_DISPOSITION, *PSYSCTL_SCSI_DISPOSITION;
  28. BOOLEAN
  29. ScsiWmipFindGuid(
  30. IN PSCSIWMIGUIDREGINFO GuidList,
  31. IN ULONG GuidCount,
  32. IN LPGUID Guid,
  33. OUT PULONG GuidIndex,
  34. OUT PULONG InstanceCount
  35. );
  36. BOOLEAN
  37. ScsiWmipFindGuid(
  38. IN PSCSIWMIGUIDREGINFO GuidList,
  39. IN ULONG GuidCount,
  40. IN LPGUID Guid,
  41. OUT PULONG GuidIndex,
  42. OUT PULONG InstanceCount
  43. )
  44. /*++
  45. Routine Description:
  46. This routine will search the list of guids registered and return
  47. the index for the one that was registered.
  48. Arguments:
  49. GuidList is the list of guids to search
  50. GuidCount is the count of guids in the list
  51. Guid is the guid being searched for
  52. *GuidIndex returns the index to the guid
  53. *InstanceCount returns the count of instances for the guid
  54. Return Value:
  55. TRUE if guid is found else FALSE
  56. --*/
  57. {
  58. ULONG i;
  59. for (i = 0; i < GuidCount; i++)
  60. {
  61. if (IsEqualGUID(Guid, GuidList[i].Guid))
  62. {
  63. *GuidIndex = i;
  64. *InstanceCount = GuidList[i].InstanceCount;
  65. return(TRUE);
  66. }
  67. }
  68. return(FALSE);
  69. }
  70. UCHAR ScsiWmipPostProcess(
  71. IN UCHAR MinorFunction,
  72. IN PUCHAR Buffer,
  73. IN ULONG BufferSize,
  74. IN ULONG BufferUsed,
  75. IN UCHAR Status,
  76. OUT PULONG ReturnSize
  77. )
  78. {
  79. ULONG retSize;
  80. ULONG bufferNeeded;
  81. switch(MinorFunction)
  82. {
  83. case IRP_MN_QUERY_ALL_DATA:
  84. {
  85. PWNODE_ALL_DATA wnode;
  86. PWNODE_TOO_SMALL wnodeTooSmall;
  87. ULONG bufferNeeded;
  88. ULONG instanceCount;
  89. POFFSETINSTANCEDATAANDLENGTH offsetInstanceDataAndLength;
  90. ULONG i;
  91. PULONG instanceLengthArray;
  92. ULONG dataBlockOffset;
  93. wnode = (PWNODE_ALL_DATA)Buffer;
  94. dataBlockOffset = wnode->DataBlockOffset;
  95. instanceCount = wnode->InstanceCount;
  96. bufferNeeded = dataBlockOffset + BufferUsed;
  97. if ((Status == SRB_STATUS_SUCCESS) &&
  98. (bufferNeeded > BufferSize))
  99. {
  100. Status = SRB_STATUS_DATA_OVERRUN;
  101. }
  102. if (Status != SRB_STATUS_SUCCESS)
  103. {
  104. if (Status == SRB_STATUS_DATA_OVERRUN)
  105. {
  106. wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
  107. wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
  108. wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
  109. wnodeTooSmall->SizeNeeded = bufferNeeded;
  110. retSize = sizeof(WNODE_TOO_SMALL);
  111. Status = SRB_STATUS_SUCCESS;
  112. } else {
  113. retSize = 0;
  114. }
  115. break;
  116. }
  117. instanceLengthArray = (PULONG)&wnode->OffsetInstanceDataAndLength[0];
  118. offsetInstanceDataAndLength = (POFFSETINSTANCEDATAANDLENGTH)instanceLengthArray;
  119. wnode->WnodeHeader.BufferSize = bufferNeeded;
  120. retSize = bufferNeeded;
  121. for (i = instanceCount; i != 0; i--)
  122. {
  123. offsetInstanceDataAndLength[i-1].LengthInstanceData = instanceLengthArray[i-1];
  124. }
  125. for (i = 0; i < instanceCount; i++)
  126. {
  127. offsetInstanceDataAndLength[i].OffsetInstanceData = dataBlockOffset;
  128. dataBlockOffset = (dataBlockOffset + offsetInstanceDataAndLength[i].LengthInstanceData + 7) & ~7;
  129. }
  130. break;
  131. }
  132. case IRP_MN_QUERY_SINGLE_INSTANCE:
  133. {
  134. PWNODE_SINGLE_INSTANCE wnode;
  135. PWNODE_TOO_SMALL wnodeTooSmall;
  136. ULONG bufferNeeded;
  137. wnode = (PWNODE_SINGLE_INSTANCE)Buffer;
  138. bufferNeeded = wnode->DataBlockOffset + BufferUsed;
  139. if (Status == SRB_STATUS_SUCCESS)
  140. {
  141. retSize = bufferNeeded;
  142. wnode->WnodeHeader.BufferSize = bufferNeeded;
  143. ASSERT(wnode->SizeDataBlock == BufferUsed);
  144. } else if (Status == SRB_STATUS_DATA_OVERRUN) {
  145. wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
  146. wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
  147. wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
  148. wnodeTooSmall->SizeNeeded = bufferNeeded;
  149. retSize = sizeof(WNODE_TOO_SMALL);
  150. Status = SRB_STATUS_SUCCESS;
  151. } else {
  152. retSize = 0;
  153. }
  154. break;
  155. }
  156. case IRP_MN_EXECUTE_METHOD:
  157. {
  158. PWNODE_METHOD_ITEM wnode;
  159. PWNODE_TOO_SMALL wnodeTooSmall;
  160. ULONG bufferNeeded;
  161. wnode = (PWNODE_METHOD_ITEM)Buffer;
  162. bufferNeeded = wnode->DataBlockOffset + BufferUsed;
  163. if (Status == SRB_STATUS_SUCCESS)
  164. {
  165. retSize = bufferNeeded;
  166. wnode->WnodeHeader.BufferSize = bufferNeeded;
  167. wnode->SizeDataBlock = BufferUsed;
  168. } else if (Status == SRB_STATUS_DATA_OVERRUN) {
  169. wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
  170. wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
  171. wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
  172. wnodeTooSmall->SizeNeeded = bufferNeeded;
  173. retSize = sizeof(WNODE_TOO_SMALL);
  174. Status = SRB_STATUS_SUCCESS;
  175. } else {
  176. retSize = 0;
  177. }
  178. break;
  179. }
  180. default:
  181. {
  182. //
  183. // All other requests don't return any data
  184. retSize = 0;
  185. break;
  186. }
  187. }
  188. *ReturnSize = retSize;
  189. return(Status);
  190. }
  191. VOID
  192. ScsiPortWmiPostProcess(
  193. IN PSCSIWMI_REQUEST_CONTEXT RequestContext,
  194. IN UCHAR Status,
  195. IN ULONG BufferUsed
  196. )
  197. {
  198. ASSERT(RequestContext != NULL);
  199. RequestContext->ReturnStatus = ScsiWmipPostProcess(
  200. RequestContext->MinorFunction,
  201. RequestContext->Buffer,
  202. RequestContext->BufferSize,
  203. BufferUsed,
  204. Status,
  205. &RequestContext->ReturnSize);
  206. }
  207. UCHAR
  208. ScsiWmipProcessRequest(
  209. IN PSCSI_WMILIB_CONTEXT WmiLibInfo,
  210. IN UCHAR MinorFunction,
  211. IN PVOID Context,
  212. IN PSCSIWMI_REQUEST_CONTEXT RequestContext,
  213. IN PVOID DataPath,
  214. IN ULONG BufferSize,
  215. IN PUCHAR Buffer,
  216. OUT PULONG ReturnSize,
  217. OUT PSYSCTL_SCSI_DISPOSITION IrpDisposition
  218. )
  219. {
  220. UCHAR status;
  221. ULONG retSize;
  222. ULONG guidIndex;
  223. ULONG instanceCount;
  224. ULONG instanceIndex;
  225. ASSERT(MinorFunction <= IRP_MN_EXECUTE_METHOD);
  226. *IrpDisposition = ScsiProcessed;
  227. if (MinorFunction != IRP_MN_REGINFO)
  228. {
  229. //
  230. // For all requests other than query registration info we are passed
  231. // a guid. Determine if the guid is one that is supported by the
  232. // device.
  233. ASSERT(WmiLibInfo->GuidList != NULL);
  234. if (ScsiWmipFindGuid(WmiLibInfo->GuidList,
  235. WmiLibInfo->GuidCount,
  236. (LPGUID)DataPath,
  237. &guidIndex,
  238. &instanceCount))
  239. {
  240. status = SRB_STATUS_SUCCESS;
  241. } else {
  242. status = SRB_STATUS_ERROR;
  243. }
  244. if ((status == SRB_STATUS_SUCCESS) &&
  245. ((MinorFunction == IRP_MN_QUERY_SINGLE_INSTANCE) ||
  246. (MinorFunction == IRP_MN_CHANGE_SINGLE_INSTANCE) ||
  247. (MinorFunction == IRP_MN_CHANGE_SINGLE_ITEM) ||
  248. (MinorFunction == IRP_MN_EXECUTE_METHOD)))
  249. {
  250. instanceIndex = ((PWNODE_SINGLE_INSTANCE)Buffer)->InstanceIndex;
  251. if ( (((PWNODE_HEADER)Buffer)->Flags) &
  252. WNODE_FLAG_STATIC_INSTANCE_NAMES)
  253. {
  254. if ( instanceIndex >= instanceCount )
  255. {
  256. status = SRB_STATUS_ERROR;
  257. }
  258. } else {
  259. status = SRB_STATUS_ERROR;
  260. }
  261. }
  262. //
  263. // If we couldn't find the guid or the instance name index is out
  264. // of range then return an error.
  265. if (status != SRB_STATUS_SUCCESS)
  266. {
  267. *ReturnSize = 0;
  268. *IrpDisposition = ScsiNotCompleted;
  269. return(status);
  270. }
  271. }
  272. switch(MinorFunction)
  273. {
  274. case IRP_MN_REGINFO:
  275. {
  276. ULONG guidCount;
  277. PSCSIWMIGUIDREGINFO guidList;
  278. PWMIREGINFOW wmiRegInfo;
  279. PWMIREGGUIDW wmiRegGuid;
  280. PWCHAR mofResourceName;
  281. PWCHAR stringPtr;
  282. ULONG mofResourceOffset;
  283. USHORT mofResourceSize;
  284. ULONG bufferNeeded;
  285. ULONG i;
  286. USHORT nameSize;
  287. ULONG nameOffset, nameFlags;
  288. USHORT mofResourceNameLen;
  289. //
  290. // Make sure that the required parts of the WMILIB_INFO structure
  291. // are filled in.
  292. ASSERT(WmiLibInfo->QueryWmiRegInfo != NULL);
  293. ASSERT(WmiLibInfo->QueryWmiDataBlock != NULL);
  294. status = WmiLibInfo->QueryWmiRegInfo(
  295. Context,
  296. RequestContext,
  297. &mofResourceName);
  298. if (status == SRB_STATUS_SUCCESS)
  299. {
  300. ASSERT(WmiLibInfo->GuidList != NULL);
  301. guidList = WmiLibInfo->GuidList;
  302. guidCount = WmiLibInfo->GuidCount;
  303. nameOffset = sizeof(WMIREGINFO) +
  304. guidCount * sizeof(WMIREGGUIDW);
  305. nameFlags = WMIREG_FLAG_INSTANCE_BASENAME;
  306. nameSize = sizeof(L"ScsiMiniPort");
  307. mofResourceOffset = nameOffset + nameSize + sizeof(USHORT);
  308. if (mofResourceName == NULL)
  309. {
  310. mofResourceSize = 0;
  311. } else {
  312. mofResourceNameLen = 0;
  313. while (mofResourceName[mofResourceNameLen] != 0)
  314. {
  315. mofResourceNameLen++;
  316. }
  317. mofResourceSize = mofResourceNameLen * sizeof(WCHAR);
  318. }
  319. bufferNeeded = mofResourceOffset + mofResourceSize + sizeof(USHORT);
  320. if (bufferNeeded <= BufferSize)
  321. {
  322. retSize = bufferNeeded;
  323. wmiRegInfo = (PWMIREGINFO)Buffer;
  324. wmiRegInfo->BufferSize = bufferNeeded;
  325. wmiRegInfo->NextWmiRegInfo = 0;
  326. wmiRegInfo->MofResourceName = mofResourceOffset;
  327. wmiRegInfo->RegistryPath = 0;
  328. wmiRegInfo->GuidCount = guidCount;
  329. for (i = 0; i < guidCount; i++)
  330. {
  331. wmiRegGuid = &wmiRegInfo->WmiRegGuid[i];
  332. wmiRegGuid->Guid = *guidList[i].Guid;
  333. wmiRegGuid->Flags = guidList[i].Flags | nameFlags;
  334. wmiRegGuid->InstanceInfo = nameOffset;
  335. wmiRegGuid->InstanceCount = guidList[i].InstanceCount;
  336. }
  337. stringPtr = (PWCHAR)((PUCHAR)Buffer + nameOffset);
  338. *stringPtr++ = nameSize;
  339. ScsiPortMoveMemory(stringPtr,
  340. L"ScsiMiniPort",
  341. nameSize);
  342. stringPtr = (PWCHAR)((PUCHAR)Buffer + mofResourceOffset);
  343. *stringPtr++ = mofResourceSize;
  344. ScsiPortMoveMemory(stringPtr,
  345. mofResourceName,
  346. mofResourceSize);
  347. } else {
  348. *((PULONG)Buffer) = bufferNeeded;
  349. retSize = sizeof(ULONG);
  350. }
  351. } else {
  352. // QueryWmiRegInfo failed
  353. retSize = 0;
  354. }
  355. *ReturnSize = retSize;
  356. *IrpDisposition = ScsiNotCompleted;
  357. return(status);
  358. }
  359. case IRP_MN_QUERY_ALL_DATA:
  360. {
  361. PWNODE_ALL_DATA wnode;
  362. ULONG bufferAvail;
  363. PULONG instanceLengthArray;
  364. PUCHAR dataBuffer;
  365. ULONG instanceLengthArraySize;
  366. ULONG dataBlockOffset;
  367. wnode = (PWNODE_ALL_DATA)Buffer;
  368. if (BufferSize < sizeof(WNODE_ALL_DATA))
  369. {
  370. //
  371. // The buffer should never be smaller than the size of
  372. // WNODE_ALL_DATA, however if it is then return with an
  373. // error requesting the minimum sized buffer.
  374. ASSERT(FALSE);
  375. status = SRB_STATUS_ERROR;
  376. *IrpDisposition = ScsiNotCompleted;
  377. break;
  378. }
  379. wnode->InstanceCount = instanceCount;
  380. wnode->WnodeHeader.Flags &= ~WNODE_FLAG_FIXED_INSTANCE_SIZE;
  381. instanceLengthArraySize = instanceCount * sizeof(OFFSETINSTANCEDATAANDLENGTH);
  382. dataBlockOffset = (FIELD_OFFSET(WNODE_ALL_DATA, OffsetInstanceDataAndLength) + instanceLengthArraySize + 7) & ~7;
  383. wnode->DataBlockOffset = dataBlockOffset;
  384. if (dataBlockOffset <= BufferSize)
  385. {
  386. instanceLengthArray = (PULONG)&wnode->OffsetInstanceDataAndLength[0];
  387. dataBuffer = Buffer + dataBlockOffset;
  388. bufferAvail = BufferSize - dataBlockOffset;
  389. } else {
  390. //
  391. // There is not enough room in the WNODE to complete
  392. // the query
  393. instanceLengthArray = NULL;
  394. dataBuffer = NULL;
  395. bufferAvail = 0;
  396. }
  397. status = WmiLibInfo->QueryWmiDataBlock(
  398. Context,
  399. RequestContext,
  400. guidIndex,
  401. 0,
  402. instanceCount,
  403. instanceLengthArray,
  404. bufferAvail,
  405. dataBuffer);
  406. break;
  407. }
  408. case IRP_MN_QUERY_SINGLE_INSTANCE:
  409. {
  410. PWNODE_SINGLE_INSTANCE wnode;
  411. ULONG dataBlockOffset;
  412. wnode = (PWNODE_SINGLE_INSTANCE)Buffer;
  413. dataBlockOffset = wnode->DataBlockOffset;
  414. status = WmiLibInfo->QueryWmiDataBlock(
  415. Context,
  416. RequestContext,
  417. guidIndex,
  418. instanceIndex,
  419. 1,
  420. &wnode->SizeDataBlock,
  421. BufferSize - dataBlockOffset,
  422. (PUCHAR)wnode + dataBlockOffset);
  423. break;
  424. }
  425. case IRP_MN_CHANGE_SINGLE_INSTANCE:
  426. {
  427. PWNODE_SINGLE_INSTANCE wnode;
  428. if (WmiLibInfo->SetWmiDataBlock != NULL)
  429. {
  430. wnode = (PWNODE_SINGLE_INSTANCE)Buffer;
  431. status = WmiLibInfo->SetWmiDataBlock(
  432. Context,
  433. RequestContext,
  434. guidIndex,
  435. instanceIndex,
  436. wnode->SizeDataBlock,
  437. (PUCHAR)wnode + wnode->DataBlockOffset);
  438. } else {
  439. //
  440. // If set callback is not filled in then it must be readonly
  441. status = SRB_STATUS_ERROR;
  442. *IrpDisposition = ScsiNotCompleted;
  443. }
  444. break;
  445. }
  446. case IRP_MN_CHANGE_SINGLE_ITEM:
  447. {
  448. PWNODE_SINGLE_ITEM wnode;
  449. if (WmiLibInfo->SetWmiDataItem != NULL)
  450. {
  451. wnode = (PWNODE_SINGLE_ITEM)Buffer;
  452. status = WmiLibInfo->SetWmiDataItem(
  453. Context,
  454. RequestContext,
  455. guidIndex,
  456. instanceIndex,
  457. wnode->ItemId,
  458. wnode->SizeDataItem,
  459. (PUCHAR)wnode + wnode->DataBlockOffset);
  460. } else {
  461. //
  462. // If set callback is not filled in then it must be readonly
  463. status = SRB_STATUS_ERROR;
  464. *IrpDisposition = ScsiNotCompleted;
  465. }
  466. break;
  467. }
  468. case IRP_MN_EXECUTE_METHOD:
  469. {
  470. PWNODE_METHOD_ITEM wnode;
  471. if (WmiLibInfo->ExecuteWmiMethod != NULL)
  472. {
  473. wnode = (PWNODE_METHOD_ITEM)Buffer;
  474. status = WmiLibInfo->ExecuteWmiMethod(
  475. Context,
  476. RequestContext,
  477. guidIndex,
  478. instanceIndex,
  479. wnode->MethodId,
  480. wnode->SizeDataBlock,
  481. BufferSize - wnode->DataBlockOffset,
  482. Buffer + wnode->DataBlockOffset);
  483. } else {
  484. //
  485. // If method callback is not filled in then it must be error
  486. status = SRB_STATUS_ERROR;
  487. *IrpDisposition = ScsiNotCompleted;
  488. }
  489. break;
  490. }
  491. case IRP_MN_ENABLE_EVENTS:
  492. {
  493. if (WmiLibInfo->WmiFunctionControl != NULL)
  494. {
  495. status = WmiLibInfo->WmiFunctionControl(
  496. Context,
  497. RequestContext,
  498. guidIndex,
  499. ScsiWmiEventControl,
  500. TRUE);
  501. } else {
  502. //
  503. // If callback is not filled in then just succeed
  504. status = SRB_STATUS_SUCCESS;
  505. *IrpDisposition = ScsiNotCompleted;
  506. }
  507. break;
  508. }
  509. case IRP_MN_DISABLE_EVENTS:
  510. {
  511. if (WmiLibInfo->WmiFunctionControl != NULL)
  512. {
  513. status = WmiLibInfo->WmiFunctionControl(
  514. Context,
  515. RequestContext,
  516. guidIndex,
  517. ScsiWmiEventControl,
  518. FALSE);
  519. } else {
  520. //
  521. // If callback is not filled in then just succeed
  522. status = SRB_STATUS_SUCCESS;
  523. *IrpDisposition = ScsiNotCompleted;
  524. }
  525. break;
  526. }
  527. case IRP_MN_ENABLE_COLLECTION:
  528. {
  529. if (WmiLibInfo->WmiFunctionControl != NULL)
  530. {
  531. status = WmiLibInfo->WmiFunctionControl(
  532. Context,
  533. RequestContext,
  534. guidIndex,
  535. ScsiWmiDataBlockControl,
  536. TRUE);
  537. } else {
  538. //
  539. // If callback is not filled in then just succeed
  540. status = SRB_STATUS_SUCCESS;
  541. *IrpDisposition = ScsiNotCompleted;
  542. }
  543. break;
  544. }
  545. case IRP_MN_DISABLE_COLLECTION:
  546. {
  547. if (WmiLibInfo->WmiFunctionControl != NULL)
  548. {
  549. status = WmiLibInfo->WmiFunctionControl(
  550. Context,
  551. RequestContext,
  552. guidIndex,
  553. ScsiWmiDataBlockControl,
  554. FALSE);
  555. } else {
  556. //
  557. // If callback is not filled in then just succeed
  558. status = SRB_STATUS_SUCCESS;
  559. *IrpDisposition = ScsiNotCompleted;
  560. }
  561. break;
  562. }
  563. default:
  564. {
  565. ASSERT(FALSE);
  566. status = SRB_STATUS_ERROR;
  567. *IrpDisposition = ScsiNotCompleted;
  568. break;
  569. }
  570. }
  571. return(status);
  572. }
  573. BOOLEAN
  574. ScsiPortWmiDispatchFunction(
  575. IN PSCSI_WMILIB_CONTEXT WmiLibInfo,
  576. IN UCHAR MinorFunction,
  577. IN PVOID Context,
  578. IN PSCSIWMI_REQUEST_CONTEXT RequestContext,
  579. IN PVOID DataPath,
  580. IN ULONG BufferSize,
  581. IN PVOID Buffer
  582. )
  583. /*++
  584. Routine Description:
  585. Dispatch helper routine for WMI srb requests. Based on the Minor
  586. function passed the WMI request is processed and this routine
  587. invokes the appropriate callback in the WMILIB structure.
  588. Arguments:
  589. WmiLibInfo has the SCSI WMILIB information control block associated
  590. with the adapter or logical unit
  591. DeviceContext is miniport defined context value passed on to the callbacks
  592. invoked by this api.
  593. RequestContext is a pointer to a context structure that maintains
  594. information about this WMI srb. This request context must remain
  595. valid throughout the entire processing of the srb, at least until
  596. ScsiPortWmiPostProcess returns with the final srb return status and
  597. buffer size. If the srb can pend then memory for this buffer should
  598. be allocated from the SRB extension. If not then the memory can be
  599. allocated from a stack frame that does not go out of scope, perhaps
  600. that of the caller to this api.
  601. DataPath is value passed in wmi request
  602. BufferSize is value passed in wmi request
  603. Buffer is value passed in wmi request
  604. Return Value:
  605. TRUE if request is pending else FALSE
  606. --*/
  607. {
  608. UCHAR status;
  609. SYSCTL_SCSI_DISPOSITION irpDisposition;
  610. ULONG retSize;
  611. ASSERT(RequestContext != NULL);
  612. //
  613. // First ensure that the irp is a WMI irp
  614. if (MinorFunction > IRP_MN_EXECUTE_METHOD)
  615. {
  616. //
  617. // This is not a WMI irp, setup error return
  618. status = SRB_STATUS_ERROR;
  619. RequestContext->ReturnSize = 0;
  620. RequestContext->ReturnStatus = status;
  621. } else {
  622. //
  623. // Let SCSIWMI library have a crack at the SRB
  624. RequestContext->MinorFunction = MinorFunction;
  625. RequestContext->Buffer = Buffer;
  626. RequestContext->BufferSize = BufferSize;
  627. RequestContext->ReturnSize = 0;
  628. status = ScsiWmipProcessRequest(WmiLibInfo,
  629. MinorFunction,
  630. Context,
  631. RequestContext,
  632. DataPath,
  633. BufferSize,
  634. Buffer,
  635. &retSize,
  636. &irpDisposition);
  637. if (irpDisposition == ScsiNotCompleted)
  638. {
  639. //
  640. // Some error occured while processing the SRB, for example
  641. // guid not found. Setup the returned error
  642. RequestContext->ReturnStatus = status;
  643. if (status != SRB_STATUS_SUCCESS)
  644. {
  645. retSize = 0;
  646. }
  647. RequestContext->ReturnSize = retSize;
  648. }
  649. }
  650. return(status == SRB_STATUS_PENDING);
  651. }
  652. VOID
  653. ScsiPortWmiFireLogicalUnitEvent(
  654. IN PVOID HwDeviceExtension,
  655. IN UCHAR PathId,
  656. IN UCHAR TargetId,
  657. IN UCHAR Lun,
  658. IN LPGUID Guid,
  659. IN ULONG InstanceIndex,
  660. IN ULONG EventDataSize,
  661. IN PVOID EventData
  662. )
  663. /*++
  664. Routine Description:
  665. This routine will fire a WMI event using the data buffer passed. This
  666. routine may be called at or below DPC level
  667. Arguments:
  668. HwDeviceExtension is the adapter device extension
  669. PathId identifies the SCSI bus if a logical unit is firing the event
  670. or is 0xff if the adapter is firing the event.
  671. TargetId identifies the target controller or device on the bus
  672. Lun identifies the logical unit number of the target device
  673. Guid is pointer to the GUID that represents the event
  674. InstanceIndex is the index of the instance of the event
  675. EventDataSize is the number of bytes of data that is being fired with
  676. with the event. This size specifies the size of the event data only
  677. and does NOT include the 0x40 bytes of preceeding padding.
  678. EventData is the data that is fired with the events. There must be exactly
  679. 0x40 bytes of padding preceeding the event data.
  680. Return Value:
  681. --*/
  682. {
  683. PWNODE_SINGLE_INSTANCE event;
  684. UCHAR status;
  685. ASSERT(EventData != NULL);
  686. event = (PWNODE_SINGLE_INSTANCE)EventData;
  687. event->WnodeHeader.Guid = *Guid;
  688. event->WnodeHeader.Flags = WNODE_FLAG_SINGLE_INSTANCE |
  689. WNODE_FLAG_EVENT_ITEM |
  690. WNODE_FLAG_STATIC_INSTANCE_NAMES;
  691. event->WnodeHeader.Linkage = 0;
  692. event->InstanceIndex = InstanceIndex;
  693. event->SizeDataBlock = EventDataSize;
  694. event->DataBlockOffset = 0x40;
  695. event->WnodeHeader.BufferSize = event->DataBlockOffset +
  696. event->SizeDataBlock;
  697. if (PathId != 0xff)
  698. {
  699. ScsiPortNotification(WMIEvent,
  700. HwDeviceExtension,
  701. event,
  702. PathId,
  703. TargetId,
  704. Lun);
  705. } else {
  706. ScsiPortNotification(WMIEvent,
  707. HwDeviceExtension,
  708. event,
  709. PathId);
  710. }
  711. }