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.

1431 lines
39 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft, Inc
  3. Module Name:
  4. wmi.c
  5. Abstract:
  6. This is the common source code for WMI debugging support within a NT
  7. SCSI miniport. This code implements the WMI specific functionality that
  8. needed and is independent of the miniport that includes it. To include
  9. the wmi debugging code in a miniport, the miniport must do the following:
  10. 1. Create a file (say wmi.c) that includes any headers needed by the
  11. the miniport and #define PHWDEVEXT to the name for its hardware device
  12. extension. One of the headers needs to #define WMI_TEST_CODE to include
  13. wmi debug code in the build.
  14. 2. Include the following before the hardware device extension structure:
  15. #ifdef WMI_TEST_CODE
  16. #define MAX_STRING 255
  17. typedef struct
  18. {
  19. BOOLEAN boolean;
  20. UCHAR uchar;
  21. USHORT ushort;
  22. ULONG ulong;
  23. ULONGLONG ulonglong;
  24. CHAR achar;
  25. SHORT ashort;
  26. LONG along;
  27. LONGLONG longlong;
  28. WCHAR datetime[25];
  29. USHORT stringlen;
  30. WCHAR string[MAX_STRING];
  31. } EC1, *PEC1;
  32. typedef struct
  33. {
  34. BOOLEAN boolean[8];
  35. UCHAR uchar[8];
  36. USHORT ushort[4];
  37. ULONG ulong[2];
  38. ULONGLONG ulonglong;
  39. CHAR achar[8];
  40. SHORT ashort[4];
  41. LONG along[2];
  42. LONGLONG longlong;
  43. WCHAR datetime[25];
  44. USHORT stringlen;
  45. WCHAR string[MAX_STRING];
  46. } EC2, *PEC2;
  47. #define WMI_EVENT_BUFFER_SIZE (sizeof(EC2) + 0x40)
  48. #endif
  49. 3. Include the following within the hardware device extension structure:
  50. #ifdef WMI_TEST_CODE
  51. SCSI_WMILIB_CONTEXT WmiLibContext;
  52. ULONG Ec1Count;
  53. ULONG Ec1Length[4];
  54. ULONG Ec1ActualLength[4];
  55. EC1 Ec1[4];
  56. ULONG Ec2Count;
  57. ULONG Ec2Length[4];
  58. ULONG Ec2ActualLength[4];
  59. EC2 Ec2[4];
  60. UCHAR EventBuffer[WMI_EVENT_BUFFER_SIZE];
  61. #endif
  62. 4. Include the following in the HwDetect routine
  63. #ifdef WMI_TEST_CODE
  64. //
  65. // Enable and initialize WMI
  66. ConfigInfo->WmiDataProvider = TRUE;
  67. WmiInitialize(CardPtr);
  68. #endif
  69. 5. Dispatch wmi srbs to WmiSrb().
  70. Environment:
  71. kernel mode only
  72. Notes:
  73. Revision History:
  74. --*/
  75. #ifdef WMI_TEST_CODE
  76. BOOLEAN WmiSampSetEc1(
  77. PHWDEVEXT CardPtr,
  78. PUCHAR Buffer,
  79. ULONG Length,
  80. ULONG Index
  81. );
  82. BOOLEAN WmiSampSetEc2(
  83. PHWDEVEXT CardPtr,
  84. PUCHAR Buffer,
  85. ULONG Length,
  86. ULONG Index
  87. );
  88. #define WmiSampDateTime L"19940525133015.000000-300"
  89. #define Wmi_MofResourceName L"MofResource"
  90. #define WmiSampleClass1 0
  91. #define WmiSampleClass2 1
  92. #define WmiSampleClass3 2
  93. #define WmiSampleClass4 3
  94. #define WmiSampleClass5 4
  95. #define WmiSampleClass6 5
  96. #define WmiSampleClass7 6
  97. #define WmiGetSetData 7
  98. #define WmiFireEvent 8
  99. #define WmiEventClass1 9
  100. #define WmiEventClass2 10
  101. #define WmiEventClass3 11
  102. #define WmiEventClass4 12
  103. #define WmiEventClass5 13
  104. #define WmiEventClass6 14
  105. #define WmiEventClass7 15
  106. GUID WmiSampleClass1Guid = { 0x15d851f1, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  107. GUID WmiSampleClass2Guid = { 0x15d851f2, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  108. GUID WmiSampleClass3Guid = { 0x15d851f3, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  109. GUID WmiSampleClass4Guid = { 0x15d851f4, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  110. GUID WmiSampleClass5Guid = { 0x15d851f5, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  111. GUID WmiSampleClass6Guid = { 0x15d851f6, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  112. GUID WmiSampleClass7Guid = { 0x15d851f7, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  113. GUID WmiGetSetDataGuid = { 0x15d851f8, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  114. GUID WmiFireEventGuid = { 0x15d851f9, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  115. GUID WmiEventClass1Guid = { 0x15d851e1, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  116. GUID WmiEventClass2Guid = { 0x15d851e2, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  117. GUID WmiEventClass3Guid = { 0x15d851e3, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  118. GUID WmiEventClass4Guid = { 0x15d851e4, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  119. GUID WmiEventClass5Guid = { 0x15d851e5, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  120. GUID WmiEventClass6Guid = { 0x15d851e6, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  121. GUID WmiEventClass7Guid = { 0x15d851e7, 0x6539, 0x11d1, 0xa5, 0x29, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 };
  122. SCSIWMIGUIDREGINFO GuidList[] =
  123. {
  124. {
  125. &WmiSampleClass1Guid,
  126. 1,
  127. 0
  128. },
  129. {
  130. &WmiSampleClass2Guid,
  131. 1,
  132. 0
  133. },
  134. {
  135. &WmiSampleClass3Guid,
  136. 1,
  137. 0
  138. },
  139. {
  140. &WmiSampleClass4Guid,
  141. 1,
  142. 0
  143. },
  144. {
  145. &WmiSampleClass5Guid,
  146. 1,
  147. 0
  148. },
  149. {
  150. &WmiSampleClass6Guid,
  151. 1,
  152. 0
  153. },
  154. {
  155. &WmiSampleClass7Guid,
  156. 1,
  157. 0
  158. },
  159. {
  160. &WmiGetSetDataGuid,
  161. 1,
  162. 0
  163. },
  164. {
  165. &WmiFireEventGuid,
  166. 1,
  167. 0
  168. },
  169. {
  170. &WmiEventClass1Guid,
  171. 1,
  172. WMIREG_FLAG_EVENT_ONLY_GUID
  173. },
  174. {
  175. &WmiEventClass2Guid,
  176. 1,
  177. WMIREG_FLAG_EVENT_ONLY_GUID
  178. },
  179. {
  180. &WmiEventClass3Guid,
  181. 1,
  182. WMIREG_FLAG_EVENT_ONLY_GUID
  183. },
  184. {
  185. &WmiEventClass4Guid,
  186. 1,
  187. WMIREG_FLAG_EVENT_ONLY_GUID
  188. },
  189. {
  190. &WmiEventClass5Guid,
  191. 1,
  192. WMIREG_FLAG_EVENT_ONLY_GUID
  193. },
  194. {
  195. &WmiEventClass6Guid,
  196. 1,
  197. WMIREG_FLAG_EVENT_ONLY_GUID
  198. },
  199. {
  200. &WmiEventClass7Guid,
  201. 1,
  202. WMIREG_FLAG_EVENT_ONLY_GUID
  203. },
  204. };
  205. #define WmiGuidCount (sizeof(GuidList) / sizeof(SCSIWMIGUIDREGINFO))
  206. UCHAR
  207. QueryWmiDataBlock(
  208. IN PVOID Context,
  209. IN PVOID DispatchContext,
  210. IN ULONG GuidIndex,
  211. IN ULONG InstanceIndex,
  212. IN ULONG InstanceCount,
  213. IN OUT PULONG InstanceLengthArray,
  214. IN ULONG OutBufferSize,
  215. OUT PUCHAR Buffer
  216. );
  217. UCHAR
  218. QueryWmiRegInfo(
  219. IN PVOID Context,
  220. IN PSCSIWMI_REQUEST_CONTEXT DispatchContext,
  221. OUT PWCHAR *MofResourceName
  222. );
  223. UCHAR
  224. WmiFunctionControl (
  225. IN PVOID Context,
  226. IN PSCSIWMI_REQUEST_CONTEXT DispatchContext,
  227. IN ULONG GuidIndex,
  228. IN SCSIWMI_ENABLE_DISABLE_CONTROL Function,
  229. IN BOOLEAN Enable
  230. );
  231. UCHAR
  232. WmiExecuteMethod (
  233. IN PVOID Context,
  234. IN PSCSIWMI_REQUEST_CONTEXT DispatchContext,
  235. IN ULONG GuidIndex,
  236. IN ULONG InstanceIndex,
  237. IN ULONG MethodId,
  238. IN ULONG InBufferSize,
  239. IN ULONG OutBufferSize,
  240. IN OUT PUCHAR Buffer
  241. );
  242. UCHAR
  243. WmiSetDataItem (
  244. IN PVOID Context,
  245. IN PSCSIWMI_REQUEST_CONTEXT DispatchContext,
  246. IN ULONG GuidIndex,
  247. IN ULONG InstanceIndex,
  248. IN ULONG DataItemId,
  249. IN ULONG BufferSize,
  250. IN PUCHAR Buffer
  251. );
  252. UCHAR
  253. WmiSetDataBlock (
  254. IN PVOID Context,
  255. IN PSCSIWMI_REQUEST_CONTEXT DispatchContext,
  256. IN ULONG GuidIndex,
  257. IN ULONG InstanceIndex,
  258. IN ULONG BufferSize,
  259. IN PUCHAR Buffer
  260. );
  261. void WmiInitialize(
  262. IN PHWDEVEXT CardPtr
  263. )
  264. {
  265. PSCSI_WMILIB_CONTEXT WmiLibContext;
  266. UCHAR Ec[sizeof(EC2) + 11*sizeof(WCHAR)];
  267. PEC1 Ec1;
  268. PEC2 Ec2;
  269. ULONG i;
  270. WmiLibContext = &CardPtr->WmiLibContext;
  271. WmiLibContext->GuidList = GuidList;
  272. WmiLibContext->GuidCount = WmiGuidCount;
  273. WmiLibContext->QueryWmiRegInfo = QueryWmiRegInfo;
  274. WmiLibContext->QueryWmiDataBlock = QueryWmiDataBlock;
  275. WmiLibContext->WmiFunctionControl = WmiFunctionControl;
  276. WmiLibContext->SetWmiDataBlock = WmiSetDataBlock;
  277. WmiLibContext->SetWmiDataItem = WmiSetDataItem;
  278. WmiLibContext->ExecuteWmiMethod = WmiExecuteMethod;
  279. CardPtr->Ec1Count = 3;
  280. CardPtr->Ec2Count = 3;
  281. for (i = 0; i < 4; i++)
  282. {
  283. Ec1 = (PEC1)Ec;
  284. memset(Ec1, i, sizeof(EC1));
  285. ScsiPortMoveMemory(Ec1->string, L"EC1-0", 5*sizeof(WCHAR));
  286. Ec1->stringlen = 10;
  287. Ec1->string[4] += (USHORT)i;
  288. ScsiPortMoveMemory(Ec1->datetime, WmiSampDateTime, 25*sizeof(WCHAR));
  289. WmiSampSetEc1(CardPtr,
  290. (PUCHAR)Ec1,
  291. FIELD_OFFSET(EC1, string) + 10,
  292. i);
  293. Ec2 = (PEC2)Ec;
  294. memset(Ec2, i, sizeof(EC2));
  295. ScsiPortMoveMemory(Ec2->string, L"EC2-0", 5*sizeof(WCHAR));
  296. Ec2->stringlen = 10;
  297. Ec2->string[4] += (USHORT)i;
  298. ScsiPortMoveMemory(Ec2->datetime, WmiSampDateTime, 25*sizeof(WCHAR));
  299. WmiSampSetEc2(CardPtr,
  300. (PUCHAR)Ec2,
  301. FIELD_OFFSET(EC2, string) + 10,
  302. i);
  303. }
  304. }
  305. BOOLEAN
  306. WmiSrb(
  307. IN PHWDEVEXT CardPtr,
  308. IN OUT PSCSI_WMI_REQUEST_BLOCK Srb
  309. )
  310. /*++
  311. Routine Description:
  312. Process an SRB_FUNCTION_WMI request packet.
  313. This routine is called from the SCSI port driver synchronized with the
  314. kernel via StartIo. On completion of WMI processing, the SCSI
  315. port driver is notified that the adapter can take another request, if
  316. any are available.
  317. Arguments:
  318. HwCardPtr - HBA miniport driver's adapter data storage.
  319. Srb - IO request packet.
  320. Return Value:
  321. Value to return to Aha154xStartIo caller. Always TRUE.
  322. --*/
  323. {
  324. UCHAR status;
  325. SCSIWMI_REQUEST_CONTEXT dc;
  326. PSCSIWMI_REQUEST_CONTEXT dispatchContext = &dc;
  327. ULONG retSize;
  328. BOOLEAN pending;
  329. //
  330. // Validate our assumptions.
  331. //
  332. ASSERT(Srb->Function == SRB_FUNCTION_WMI);
  333. ASSERT(Srb->Length == sizeof(SCSI_WMI_REQUEST_BLOCK));
  334. ASSERT(Srb->DataTransferLength >= sizeof(ULONG));
  335. ASSERT(Srb->DataBuffer);
  336. //
  337. // Only support wmi for the adapter and not disks
  338. if (!(Srb->WMIFlags & SRB_WMI_FLAGS_ADAPTER_REQUEST)) {
  339. Srb->DataTransferLength = 0;
  340. Srb->SrbStatus = SRB_STATUS_SUCCESS;
  341. return SRB_STATUS_SUCCESS;
  342. }
  343. //
  344. // Process the incoming WMI request.
  345. //
  346. dispatchContext->UserContext = Srb;
  347. DebugPrint((1, "ScsiPortWmiDispatchFunction(%x,\n%x,\n%x,\n%x,\n%x,\n%x,\n%x)\n",
  348. &CardPtr->WmiLibContext,
  349. Srb->WMISubFunction,
  350. CardPtr,
  351. dispatchContext,
  352. Srb->DataPath,
  353. Srb->DataTransferLength,
  354. Srb->DataBuffer));
  355. pending = ScsiPortWmiDispatchFunction(&CardPtr->WmiLibContext,
  356. Srb->WMISubFunction,
  357. CardPtr,
  358. dispatchContext,
  359. Srb->DataPath,
  360. Srb->DataTransferLength,
  361. Srb->DataBuffer);
  362. ASSERT(pending == FALSE);
  363. // We can do this since we assume it is done synchronously
  364. retSize = ScsiPortWmiGetReturnSize(dispatchContext);
  365. status = ScsiPortWmiGetReturnStatus(dispatchContext);
  366. DebugPrint((1,"WmiSrb %x completed %d, retsize 0x%x\n", Srb, status, retSize));
  367. Srb->DataTransferLength = retSize;
  368. //
  369. // Adapter ready for next request.
  370. //
  371. Srb->SrbStatus = status;
  372. return TRUE;
  373. }
  374. ULONG WmiSampGetEc1(
  375. PHWDEVEXT CardPtr,
  376. PUCHAR Buffer,
  377. ULONG Index
  378. )
  379. {
  380. ScsiPortMoveMemory(Buffer,
  381. &CardPtr->Ec1[Index],
  382. CardPtr->Ec1Length[Index]);
  383. return(CardPtr->Ec1Length[Index]);
  384. }
  385. ULONG WmiSampGetActualEc1(
  386. PHWDEVEXT CardPtr,
  387. PUCHAR Buffer,
  388. ULONG Index
  389. )
  390. {
  391. ScsiPortMoveMemory(Buffer,
  392. &CardPtr->Ec1[Index],
  393. CardPtr->Ec1ActualLength[Index]);
  394. return(CardPtr->Ec1ActualLength[Index]);
  395. }
  396. BOOLEAN WmiSampSetEc1(
  397. PHWDEVEXT CardPtr,
  398. PUCHAR Buffer,
  399. ULONG Length,
  400. ULONG Index
  401. )
  402. {
  403. PEC1 New;
  404. ULONG NewLength;
  405. NewLength = (Length + 7) & ~7;
  406. if (NewLength > sizeof(EC1))
  407. {
  408. return(FALSE);
  409. }
  410. CardPtr->Ec1Length[Index] = NewLength;
  411. CardPtr->Ec1ActualLength[Index] = Length;
  412. ScsiPortMoveMemory(&CardPtr->Ec1[Index],
  413. Buffer,
  414. Length);
  415. return(TRUE);
  416. }
  417. ULONG WmiSampGetEc2(
  418. PHWDEVEXT CardPtr,
  419. PUCHAR Buffer,
  420. ULONG Index
  421. )
  422. {
  423. ScsiPortMoveMemory(Buffer,
  424. &CardPtr->Ec2[Index],
  425. CardPtr->Ec2Length[Index]);
  426. return(CardPtr->Ec2Length[Index]);
  427. }
  428. ULONG WmiSampGetActualEc2(
  429. PHWDEVEXT CardPtr,
  430. PUCHAR Buffer,
  431. ULONG Index
  432. )
  433. {
  434. ScsiPortMoveMemory(Buffer,
  435. &CardPtr->Ec2[Index],
  436. CardPtr->Ec2ActualLength[Index]);
  437. return(CardPtr->Ec2ActualLength[Index]);
  438. }
  439. BOOLEAN WmiSampSetEc2(
  440. PHWDEVEXT CardPtr,
  441. PUCHAR Buffer,
  442. ULONG Length,
  443. ULONG Index
  444. )
  445. {
  446. PEC2 New;
  447. ULONG NewLength;
  448. NewLength = (Length + 7) & ~7;
  449. if (NewLength > sizeof(EC2))
  450. {
  451. return(FALSE);
  452. }
  453. CardPtr->Ec2Length[Index] = NewLength;
  454. CardPtr->Ec2ActualLength[Index] = Length;
  455. ScsiPortMoveMemory(&CardPtr->Ec2[Index],
  456. Buffer,
  457. Length);
  458. return(TRUE);
  459. }
  460. BOOLEAN
  461. QueryWmiDataBlock(
  462. IN PVOID Context,
  463. IN PSCSIWMI_REQUEST_CONTEXT DispatchContext,
  464. IN ULONG GuidIndex,
  465. IN ULONG InstanceIndex,
  466. IN ULONG InstanceCount,
  467. IN OUT PULONG InstanceLengthArray,
  468. IN ULONG BufferAvail,
  469. OUT PUCHAR Buffer
  470. )
  471. {
  472. PHWDEVEXT CardPtr = (PHWDEVEXT)Context;
  473. UCHAR status;
  474. ULONG i;
  475. ULONG sizeNeeded;
  476. ULONG sizeUsed;
  477. ULONG vlSize;
  478. //
  479. // Only ever registers 1 instance per guid
  480. ASSERT((InstanceIndex == 0) &&
  481. (InstanceCount == 1));
  482. DebugPrint((1, "QueryWmiDataBlock (%x,\n%x,\n%x,\n%x,\n%x,\n%x,\n%x,\n%x,\n",
  483. Context,
  484. DispatchContext,
  485. GuidIndex,
  486. InstanceIndex,
  487. InstanceCount,
  488. InstanceLengthArray,
  489. BufferAvail,
  490. Buffer));
  491. switch(GuidIndex)
  492. {
  493. case WmiSampleClass1:
  494. case WmiSampleClass2:
  495. case WmiEventClass1:
  496. case WmiEventClass2:
  497. {
  498. // plain EC1
  499. sizeNeeded = CardPtr->Ec1Length[0];
  500. if (BufferAvail < sizeNeeded)
  501. {
  502. status = SRB_STATUS_DATA_OVERRUN;
  503. } else {
  504. *InstanceLengthArray = sizeNeeded;
  505. WmiSampGetEc1(CardPtr, Buffer, 0);
  506. status = SRB_STATUS_SUCCESS;
  507. }
  508. break;
  509. }
  510. case WmiSampleClass3:
  511. case WmiEventClass3:
  512. {
  513. // fixed array of EC1
  514. sizeNeeded = 0;
  515. for (i = 0; i < 4; i++)
  516. {
  517. //
  518. // Embedded classes must be naturally aligned, but we
  519. // maintain naturally aligned lengths not acttual lengths
  520. sizeNeeded += CardPtr->Ec1Length[i];
  521. }
  522. if (BufferAvail < sizeNeeded)
  523. {
  524. status = SRB_STATUS_DATA_OVERRUN;
  525. } else {
  526. *InstanceLengthArray = sizeNeeded;
  527. for (i = 0; i < 4; i++)
  528. {
  529. sizeUsed = WmiSampGetEc1(CardPtr, Buffer, i);
  530. Buffer += sizeUsed;
  531. }
  532. status = SRB_STATUS_SUCCESS;
  533. }
  534. break;
  535. }
  536. case WmiSampleClass4:
  537. case WmiEventClass4:
  538. {
  539. // variable array of EC1
  540. sizeNeeded = (sizeof(ULONG) + 7) & ~7;
  541. vlSize = CardPtr->Ec1Count;
  542. ASSERT(vlSize <= 4);
  543. for (i = 0; i < vlSize; i++)
  544. {
  545. sizeNeeded += CardPtr->Ec1Length[i];
  546. }
  547. if (BufferAvail < sizeNeeded)
  548. {
  549. status = SRB_STATUS_DATA_OVERRUN;
  550. } else {
  551. *InstanceLengthArray = sizeNeeded;
  552. *((PULONG)Buffer) = vlSize;
  553. Buffer += (sizeof(ULONG) + 7) & ~7;
  554. for (i = 0; i < vlSize; i++)
  555. {
  556. sizeUsed = WmiSampGetEc1(CardPtr, Buffer, i);
  557. Buffer += sizeUsed;
  558. }
  559. status = SRB_STATUS_SUCCESS;
  560. }
  561. break;
  562. }
  563. case WmiSampleClass5:
  564. case WmiEventClass5:
  565. {
  566. // plain EC2
  567. sizeNeeded = CardPtr->Ec2Length[0];
  568. if (BufferAvail < sizeNeeded)
  569. {
  570. status = SRB_STATUS_DATA_OVERRUN;
  571. } else {
  572. *InstanceLengthArray = sizeNeeded;
  573. WmiSampGetEc2(CardPtr, Buffer, 0);
  574. status = SRB_STATUS_SUCCESS;
  575. }
  576. break;
  577. }
  578. case WmiSampleClass6:
  579. case WmiEventClass6:
  580. {
  581. // fixed array EC2
  582. sizeNeeded = 0;
  583. for (i = 0; i < 4; i++)
  584. {
  585. sizeNeeded += CardPtr->Ec2Length[i];
  586. }
  587. if (BufferAvail < sizeNeeded)
  588. {
  589. status = SRB_STATUS_DATA_OVERRUN;
  590. } else {
  591. *InstanceLengthArray = sizeNeeded;
  592. for (i = 0; i < 4; i++)
  593. {
  594. sizeUsed = WmiSampGetEc2(CardPtr, Buffer, i);
  595. Buffer += sizeUsed;
  596. }
  597. status = SRB_STATUS_SUCCESS;
  598. }
  599. break;
  600. }
  601. case WmiSampleClass7:
  602. case WmiEventClass7:
  603. {
  604. // VL array EC2
  605. sizeNeeded = (sizeof(ULONG) + 7) & ~7;
  606. vlSize = CardPtr->Ec2Count;
  607. for (i = 0; i < vlSize; i++)
  608. {
  609. sizeNeeded += CardPtr->Ec2Length[i];
  610. }
  611. if (BufferAvail < sizeNeeded)
  612. {
  613. status = SRB_STATUS_DATA_OVERRUN;
  614. } else {
  615. *InstanceLengthArray = sizeNeeded;
  616. *((PULONG)Buffer) = vlSize;
  617. Buffer += (sizeof(ULONG)+7) & ~7;
  618. for (i = 0; i < vlSize; i++)
  619. {
  620. sizeUsed = WmiSampGetEc2(CardPtr, Buffer, i);
  621. Buffer += sizeUsed;
  622. }
  623. status = SRB_STATUS_SUCCESS;
  624. }
  625. break;
  626. }
  627. case WmiFireEvent:
  628. case WmiGetSetData:
  629. {
  630. // return no data
  631. sizeNeeded = sizeof(USHORT);
  632. if (BufferAvail < sizeNeeded)
  633. {
  634. status = SRB_STATUS_DATA_OVERRUN;
  635. } else {
  636. *InstanceLengthArray = sizeNeeded;
  637. status = SRB_STATUS_SUCCESS;
  638. }
  639. break;
  640. }
  641. default:
  642. {
  643. status = SRB_STATUS_ERROR;
  644. break;
  645. }
  646. }
  647. ScsiPortWmiPostProcess(
  648. DispatchContext,
  649. status,
  650. sizeNeeded);
  651. return FALSE;
  652. }
  653. UCHAR
  654. QueryWmiRegInfo(
  655. IN PVOID Context,
  656. IN PSCSIWMI_REQUEST_CONTEXT DispatchContext,
  657. OUT PWCHAR *MofResourceName
  658. )
  659. {
  660. *MofResourceName = Wmi_MofResourceName;
  661. return SRB_STATUS_SUCCESS;
  662. }
  663. UCHAR WmiSampSetEc1Worker(
  664. PHWDEVEXT CardPtr,
  665. ULONG BufferSize,
  666. ULONG Index,
  667. PUCHAR Buffer,
  668. PULONG BufferUsed
  669. )
  670. {
  671. ULONG blockLen;
  672. UCHAR status;
  673. PEC1 Ec1;
  674. Ec1 = (PEC1)Buffer;
  675. if (BufferSize >= FIELD_OFFSET(EC1, string))
  676. {
  677. blockLen = FIELD_OFFSET(EC1, string) + Ec1->stringlen;
  678. if (blockLen <= BufferSize)
  679. {
  680. if (! WmiSampSetEc1(CardPtr,
  681. Buffer,
  682. blockLen,
  683. Index))
  684. {
  685. return(SRB_STATUS_ERROR);
  686. }
  687. *BufferUsed = (blockLen+7) & ~7;
  688. status = SRB_STATUS_SUCCESS;
  689. } else {
  690. DebugPrint((1,"Set EC1 buffer too small\n"));
  691. status = SRB_STATUS_ERROR;
  692. }
  693. } else {
  694. DebugPrint((1,"Set EC1 buffer size wrong %d\n", BufferSize));
  695. status = SRB_STATUS_ERROR;
  696. }
  697. return(status);
  698. }
  699. UCHAR WmiSampSetEc2Worker(
  700. PHWDEVEXT CardPtr,
  701. ULONG BufferSize,
  702. ULONG Index,
  703. PUCHAR Buffer,
  704. PULONG BufferUsed
  705. )
  706. {
  707. ULONG blockLen;
  708. UCHAR status;
  709. PUSHORT wPtr;
  710. PEC2 Ec2;
  711. Ec2 = (PEC2)Buffer;
  712. if (BufferSize >= FIELD_OFFSET(EC2, string))
  713. {
  714. blockLen = FIELD_OFFSET(EC2, string) + Ec2->stringlen;
  715. if (blockLen <= BufferSize)
  716. {
  717. if (! WmiSampSetEc2(CardPtr,
  718. Buffer,
  719. blockLen,
  720. Index))
  721. {
  722. return(SRB_STATUS_ERROR);
  723. }
  724. *BufferUsed = (blockLen+7) & ~7;
  725. status = SRB_STATUS_SUCCESS;
  726. } else {
  727. DebugPrint((1,"Set EC2 buffer too small\n"));
  728. status = SRB_STATUS_ERROR;
  729. }
  730. } else {
  731. DebugPrint((1,"Set EC2 buffer size wrong %d\n", BufferSize));
  732. status = SRB_STATUS_ERROR;
  733. }
  734. return(status);
  735. }
  736. BOOLEAN
  737. WmiSetDataBlock (
  738. IN PVOID Context,
  739. IN PSCSIWMI_REQUEST_CONTEXT DispatchContext,
  740. IN ULONG GuidIndex,
  741. IN ULONG InstanceIndex,
  742. IN ULONG BufferSize,
  743. IN PUCHAR Buffer
  744. )
  745. {
  746. PHWDEVEXT CardPtr = (PHWDEVEXT)Context;
  747. UCHAR status;
  748. ULONG bufferUsed;
  749. ULONG i;
  750. ULONG vlSize;
  751. DebugPrint((1, "WmiSetDataBlock(%x,\n%x,\n%x,\n%x,\n%x,\n%x)\n",
  752. Context,
  753. DispatchContext,
  754. GuidIndex,
  755. InstanceIndex,
  756. BufferSize,
  757. Buffer));
  758. switch(GuidIndex)
  759. {
  760. case WmiSampleClass1:
  761. case WmiSampleClass2:
  762. {
  763. // plain EC1
  764. status = WmiSampSetEc1Worker(CardPtr,
  765. BufferSize,
  766. 0,
  767. Buffer,
  768. &bufferUsed);
  769. break;
  770. }
  771. case WmiSampleClass3:
  772. {
  773. // fixed array of EC1
  774. for (i = 0, status = SRB_STATUS_SUCCESS;
  775. (i < 4) && (status == SRB_STATUS_SUCCESS); i++)
  776. {
  777. status = WmiSampSetEc1Worker(CardPtr,
  778. BufferSize,
  779. i,
  780. Buffer,
  781. &bufferUsed);
  782. Buffer += bufferUsed;
  783. BufferSize -= bufferUsed;
  784. }
  785. break;
  786. }
  787. case WmiSampleClass4:
  788. {
  789. // variable array of EC1
  790. if (BufferSize >= ((sizeof(ULONG) +7) & ~7))
  791. {
  792. vlSize = *((PULONG)Buffer);
  793. Buffer += ((sizeof(ULONG) +7) & ~7);
  794. if ((vlSize >= 1) && (vlSize <= 4))
  795. {
  796. for (i = 0, status = SRB_STATUS_SUCCESS;
  797. (i < vlSize) && (status == SRB_STATUS_SUCCESS); i++)
  798. {
  799. status = WmiSampSetEc1Worker(CardPtr,
  800. BufferSize,
  801. i,
  802. Buffer,
  803. &bufferUsed);
  804. Buffer += bufferUsed;
  805. BufferSize -= bufferUsed;
  806. }
  807. if (status == SRB_STATUS_SUCCESS)
  808. {
  809. CardPtr->Ec1Count = vlSize;
  810. }
  811. } else {
  812. DebugPrint((1,"SetEc1 only up to [4] allowed, not %d\n",
  813. vlSize));
  814. status = SRB_STATUS_ERROR;
  815. }
  816. } else {
  817. DebugPrint((1,"SetEc1 size too small\n"));
  818. status = SRB_STATUS_ERROR;
  819. }
  820. break;
  821. }
  822. case WmiSampleClass5:
  823. {
  824. // plain EC2
  825. status = WmiSampSetEc2Worker(CardPtr,
  826. BufferSize,
  827. 0,
  828. Buffer,
  829. &bufferUsed);
  830. break;
  831. }
  832. case WmiSampleClass6:
  833. {
  834. // fixed array EC2
  835. for (i = 0, status = SRB_STATUS_SUCCESS;
  836. (i < 4) && (status == SRB_STATUS_SUCCESS); i++)
  837. {
  838. status = WmiSampSetEc2Worker(CardPtr,
  839. BufferSize,
  840. i,
  841. Buffer,
  842. &bufferUsed);
  843. Buffer += bufferUsed;
  844. BufferSize -= bufferUsed;
  845. }
  846. break;
  847. }
  848. case WmiSampleClass7:
  849. {
  850. // VL array EC2
  851. if (BufferSize >= sizeof(ULONG))
  852. {
  853. vlSize = *((PULONG)Buffer);
  854. Buffer += (sizeof(ULONG) +7) & ~7;
  855. if ((vlSize >= 1) && (vlSize <= 4))
  856. {
  857. for (i = 0, status = SRB_STATUS_SUCCESS;
  858. (i < vlSize) && (status == SRB_STATUS_SUCCESS); i++)
  859. {
  860. status = WmiSampSetEc2Worker(CardPtr,
  861. BufferSize,
  862. i,
  863. Buffer,
  864. &bufferUsed);
  865. Buffer += bufferUsed;
  866. BufferSize -= bufferUsed;
  867. }
  868. if (status == SRB_STATUS_SUCCESS)
  869. {
  870. CardPtr->Ec1Count = vlSize;
  871. }
  872. } else {
  873. DebugPrint((1,"SetEc2 only up to [4] allowed, not %d\n",
  874. vlSize));
  875. status = SRB_STATUS_ERROR;
  876. }
  877. } else {
  878. DebugPrint((1,"SetEc2 size too small\n"));
  879. status = SRB_STATUS_ERROR;
  880. }
  881. break;
  882. }
  883. default:
  884. {
  885. status = SRB_STATUS_ERROR;
  886. break;
  887. }
  888. }
  889. ScsiPortWmiPostProcess(
  890. DispatchContext,
  891. status,
  892. 0);
  893. return(FALSE);
  894. }
  895. BOOLEAN
  896. WmiSetDataItem (
  897. IN PVOID Context,
  898. IN PSCSIWMI_REQUEST_CONTEXT DispatchContext,
  899. IN ULONG GuidIndex,
  900. IN ULONG InstanceIndex,
  901. IN ULONG DataItemId,
  902. IN ULONG BufferSize,
  903. IN PUCHAR Buffer
  904. )
  905. {
  906. UCHAR status;
  907. DebugPrint((1, "WmiSetDataItem(%x,\n%x,\n%x,\n%x,\n%x,\n%x,\n%x)\n",
  908. Context,
  909. DispatchContext,
  910. GuidIndex,
  911. InstanceIndex,
  912. DataItemId,
  913. BufferSize,
  914. Buffer));
  915. switch(GuidIndex)
  916. {
  917. case WmiSampleClass1:
  918. case WmiSampleClass2:
  919. case WmiSampleClass3:
  920. case WmiSampleClass4:
  921. case WmiSampleClass5:
  922. case WmiSampleClass6:
  923. case WmiSampleClass7:
  924. {
  925. status = SRB_STATUS_ERROR;
  926. break;
  927. }
  928. default:
  929. {
  930. status = SRB_STATUS_ERROR;
  931. break;
  932. }
  933. }
  934. ScsiPortWmiPostProcess(
  935. DispatchContext,
  936. status,
  937. 0);
  938. return(FALSE);
  939. }
  940. UCHAR WmiSampFireEvent(
  941. PHWDEVEXT CardPtr,
  942. ULONG WnodeType, // 0 - AllData, 1 - Single Instance
  943. ULONG DataType, // 1 - 7 is guid id
  944. ULONG BlockIndex // 0 - 3 is block index containing data
  945. )
  946. {
  947. PWNODE_HEADER Wnode;
  948. PWNODE_EVENT_REFERENCE WnodeER;
  949. ULONG dataSize;
  950. LPGUID Guid;
  951. UCHAR status;
  952. ULONG sizeNeeded;
  953. if (BlockIndex > 3)
  954. {
  955. return(SRB_STATUS_ERROR);
  956. }
  957. switch(DataType)
  958. {
  959. case 1:
  960. {
  961. // EC1
  962. dataSize = CardPtr->Ec1Length[BlockIndex];
  963. Guid = &WmiEventClass1Guid;
  964. break;
  965. }
  966. case 2:
  967. {
  968. // EC1 (embedded)
  969. dataSize = CardPtr->Ec1Length[BlockIndex];
  970. Guid = &WmiEventClass2Guid;
  971. break;
  972. }
  973. case 5:
  974. {
  975. // EC2 (embedded)
  976. dataSize = CardPtr->Ec2Length[BlockIndex];
  977. Guid = &WmiEventClass5Guid;
  978. break;
  979. }
  980. default:
  981. {
  982. return(SRB_STATUS_ERROR);
  983. }
  984. }
  985. Wnode = (PWNODE_HEADER)CardPtr->EventBuffer;
  986. sizeNeeded = sizeof(WNODE_EVENT_REFERENCE);
  987. if (sizeNeeded > WMI_EVENT_BUFFER_SIZE)
  988. {
  989. ASSERT(FALSE);
  990. return(SRB_STATUS_ERROR);
  991. }
  992. Wnode->Flags = WNODE_FLAG_EVENT_ITEM |
  993. WNODE_FLAG_EVENT_REFERENCE |
  994. WNODE_FLAG_STATIC_INSTANCE_NAMES;
  995. WnodeER = (PWNODE_EVENT_REFERENCE)Wnode;
  996. WnodeER->TargetGuid = *Guid;
  997. WnodeER->TargetDataBlockSize = dataSize + sizeof(WNODE_SINGLE_INSTANCE);
  998. WnodeER->TargetInstanceIndex = 0;
  999. Wnode->Guid = *Guid;
  1000. Wnode->BufferSize = sizeNeeded;
  1001. ScsiPortNotification(WMIEvent,
  1002. CardPtr,
  1003. Wnode,
  1004. 0xff);
  1005. return(SRB_STATUS_SUCCESS);
  1006. }
  1007. BOOLEAN
  1008. WmiExecuteMethod (
  1009. IN PVOID Context,
  1010. IN PSCSIWMI_REQUEST_CONTEXT DispatchContext,
  1011. IN ULONG GuidIndex,
  1012. IN ULONG InstanceIndex,
  1013. IN ULONG MethodId,
  1014. IN ULONG InBufferSize,
  1015. IN ULONG BufferAvail,
  1016. IN OUT PUCHAR Buffer
  1017. )
  1018. {
  1019. PHWDEVEXT CardPtr = (PHWDEVEXT)Context;
  1020. ULONG sizeNeeded = 0;
  1021. UCHAR status;
  1022. PSCSI_REQUEST_BLOCK srb = (PSCSI_REQUEST_BLOCK)(DispatchContext->UserContext);
  1023. ULONG bufferUsed;
  1024. ULONG blockIndex;
  1025. ULONG UlongPadSize = (sizeof(ULONG) + 7) & ~7;
  1026. DebugPrint((1, "WmiExecuteMethod(%x,\n%x,\n%x,\n%x,\n%x,\n%x,\n%x,\n%x)\n",
  1027. Context,
  1028. DispatchContext,
  1029. GuidIndex,
  1030. InstanceIndex,
  1031. MethodId,
  1032. InBufferSize,
  1033. BufferAvail,
  1034. Buffer));
  1035. if (GuidIndex == WmiGetSetData)
  1036. {
  1037. switch(MethodId)
  1038. {
  1039. case 1:
  1040. case 7:
  1041. {
  1042. // SetEc1
  1043. if (InBufferSize < UlongPadSize)
  1044. {
  1045. status = SRB_STATUS_ERROR;
  1046. sizeNeeded = 0;
  1047. break;
  1048. } else {
  1049. blockIndex = *((PULONG)Buffer);
  1050. if (blockIndex > 3)
  1051. {
  1052. status = SRB_STATUS_ERROR;
  1053. break;
  1054. }
  1055. Buffer += UlongPadSize;
  1056. InBufferSize -= UlongPadSize;
  1057. }
  1058. status = WmiSampSetEc1Worker(CardPtr,
  1059. InBufferSize,
  1060. blockIndex,
  1061. Buffer,
  1062. &bufferUsed);
  1063. sizeNeeded = 0;
  1064. break;
  1065. }
  1066. case 2:
  1067. case 8:
  1068. {
  1069. // SetEc2
  1070. if (InBufferSize < UlongPadSize)
  1071. {
  1072. status = SRB_STATUS_ERROR;
  1073. sizeNeeded = 0;
  1074. break;
  1075. } else {
  1076. blockIndex = *((PULONG)Buffer);
  1077. if (blockIndex > 3)
  1078. {
  1079. status = SRB_STATUS_ERROR;
  1080. break;
  1081. }
  1082. Buffer += UlongPadSize;
  1083. InBufferSize -= UlongPadSize;
  1084. }
  1085. status = WmiSampSetEc2Worker(CardPtr,
  1086. InBufferSize,
  1087. blockIndex,
  1088. Buffer,
  1089. &bufferUsed);
  1090. sizeNeeded = 0;
  1091. break;
  1092. }
  1093. case 3:
  1094. case 9:
  1095. {
  1096. // GetEc1
  1097. if (InBufferSize != sizeof(ULONG))
  1098. {
  1099. status = SRB_STATUS_ERROR;
  1100. sizeNeeded = 0;
  1101. break;
  1102. } else {
  1103. blockIndex = *((PULONG)Buffer);
  1104. if (blockIndex > 3)
  1105. {
  1106. status = SRB_STATUS_ERROR;
  1107. break;
  1108. }
  1109. }
  1110. sizeNeeded = CardPtr->Ec1ActualLength[blockIndex];
  1111. if (BufferAvail < sizeNeeded)
  1112. {
  1113. status = SRB_STATUS_DATA_OVERRUN;
  1114. } else {
  1115. WmiSampGetActualEc1(CardPtr, Buffer, blockIndex);
  1116. status = SRB_STATUS_SUCCESS;
  1117. }
  1118. break;
  1119. }
  1120. case 4:
  1121. case 10:
  1122. {
  1123. // GetEc2
  1124. if (InBufferSize != sizeof(ULONG))
  1125. {
  1126. status = SRB_STATUS_ERROR;
  1127. sizeNeeded = 0;
  1128. break;
  1129. } else {
  1130. blockIndex = *((PULONG)Buffer);
  1131. if (blockIndex > 3)
  1132. {
  1133. status = SRB_STATUS_ERROR;
  1134. break;
  1135. }
  1136. }
  1137. sizeNeeded = CardPtr->Ec2ActualLength[blockIndex];
  1138. if (BufferAvail < sizeNeeded)
  1139. {
  1140. status = SRB_STATUS_DATA_OVERRUN;
  1141. } else {
  1142. WmiSampGetActualEc2(CardPtr, Buffer, blockIndex);
  1143. status = SRB_STATUS_SUCCESS;
  1144. }
  1145. break;
  1146. }
  1147. case 13:
  1148. {
  1149. ScsiPortNotification(WMIReregister,
  1150. CardPtr,
  1151. 0xff);
  1152. status = SRB_STATUS_SUCCESS;
  1153. sizeNeeded = 0;
  1154. break;
  1155. }
  1156. case 5:
  1157. case 11:
  1158. case 6:
  1159. case 12:
  1160. default:
  1161. {
  1162. status = SRB_STATUS_ERROR;
  1163. }
  1164. }
  1165. } else if (GuidIndex == WmiFireEvent) {
  1166. if (MethodId == 1)
  1167. {
  1168. if (InBufferSize == 3*sizeof(ULONG))
  1169. {
  1170. ULONG wnodeType;
  1171. ULONG dataType;
  1172. ULONG blockIndex;
  1173. wnodeType = *(PULONG)Buffer;
  1174. Buffer += sizeof(ULONG);
  1175. dataType = *(PULONG)Buffer;
  1176. Buffer += sizeof(ULONG);
  1177. blockIndex = *(PULONG)Buffer;
  1178. Buffer += sizeof(ULONG);
  1179. status = WmiSampFireEvent(CardPtr,
  1180. wnodeType,
  1181. dataType,
  1182. blockIndex);
  1183. sizeNeeded = 0;
  1184. } else {
  1185. status = SRB_STATUS_ERROR;
  1186. }
  1187. } else {
  1188. status = SRB_STATUS_ERROR;
  1189. }
  1190. } else {
  1191. status = SRB_STATUS_ERROR;
  1192. }
  1193. ScsiPortWmiPostProcess(
  1194. DispatchContext,
  1195. status,
  1196. sizeNeeded);
  1197. return(FALSE);
  1198. }
  1199. BOOLEAN
  1200. WmiFunctionControl (
  1201. IN PVOID Context,
  1202. IN PSCSIWMI_REQUEST_CONTEXT DispatchContext,
  1203. IN ULONG GuidIndex,
  1204. IN SCSIWMI_ENABLE_DISABLE_CONTROL Function,
  1205. IN BOOLEAN Enable
  1206. )
  1207. {
  1208. UCHAR status = SRB_STATUS_SUCCESS;
  1209. //
  1210. // TODO: Verify that expensive guids are being enbled and inexpensive ones
  1211. // are not, same with events
  1212. DebugPrint((1, "WmiFunctionControl(%x,\n%x,\n%x,\n%x,\n%x)\n\n",
  1213. Context,
  1214. DispatchContext,
  1215. GuidIndex,
  1216. Function,
  1217. Enable));
  1218. ScsiPortWmiPostProcess(
  1219. DispatchContext,
  1220. status,
  1221. 0);
  1222. return(FALSE);
  1223. }
  1224. #endif