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.

653 lines
17 KiB

  1. #include "pch.h"
  2. #include "hpwmi.h"
  3. //
  4. // When SoftPCI creates a SHPC devnode, it needs to do the following:
  5. //
  6. // 1) Call SoftPCI_SetEventContext to set the event callback context.
  7. // 2) Call SoftPCI_RegisterHotplugEvents to register for event callbacks.
  8. //
  9. // Potentially we should get the WMI instance name for the device by calling
  10. // SoftPCI_AllocWmiInstanceName once when the devnode is created instead
  11. // of every time we do something WMI related.
  12. //
  13. BOOL
  14. SoftPCI_AllocWmiInstanceName(
  15. OUT PWCHAR WmiInstanceName,
  16. IN PWCHAR DeviceId
  17. )
  18. {
  19. ULONG numChar;
  20. numChar = WmiDevInstToInstanceNameW(WmiInstanceName,
  21. MAX_PATH,
  22. DeviceId,
  23. 0
  24. );
  25. if (numChar > MAX_PATH) {
  26. return FALSE;
  27. } else {
  28. return TRUE;
  29. }
  30. }
  31. BOOL
  32. SoftPCI_AllocWnodeSI(
  33. IN PPCI_DN Pdn,
  34. IN LPGUID Guid,
  35. IN PVOID Buffer,
  36. IN ULONG BufferSize,
  37. OUT PWNODE_SINGLE_INSTANCE *WnodeForBuffer
  38. )
  39. {
  40. PWNODE_HEADER Wnode;
  41. PWNODE_SINGLE_INSTANCE WnodeSI;
  42. ULONG sizeNeeded;
  43. PUCHAR WnodeDataPtr;
  44. SOFTPCI_ASSERT(Buffer != NULL);
  45. SOFTPCI_ASSERT(BufferSize != 0);
  46. if ((Buffer == NULL) ||
  47. (BufferSize == 0)) {
  48. return FALSE;
  49. }
  50. sizeNeeded = FIELD_OFFSET(WNODE_SINGLE_INSTANCE, VariableData) +
  51. BufferSize;
  52. Wnode = (PWNODE_HEADER)malloc(sizeNeeded);
  53. if (!Wnode) {
  54. return FALSE;
  55. }
  56. Wnode->Flags = WNODE_FLAG_SINGLE_INSTANCE | WNODE_FLAG_PDO_INSTANCE_NAMES;
  57. Wnode->BufferSize = sizeNeeded;
  58. Wnode->Guid = *Guid;
  59. WnodeSI = (PWNODE_SINGLE_INSTANCE)Wnode;
  60. WnodeSI->DataBlockOffset = FIELD_OFFSET(WNODE_SINGLE_INSTANCE, VariableData);
  61. WnodeSI->InstanceIndex = 0;
  62. WnodeSI->SizeDataBlock = BufferSize;
  63. WnodeDataPtr = (PUCHAR)Wnode + WnodeSI->DataBlockOffset;
  64. RtlCopyMemory(WnodeDataPtr, Buffer, BufferSize);
  65. *WnodeForBuffer = WnodeSI;
  66. return TRUE;
  67. }
  68. BOOL
  69. SoftPCI_SetEventContext(
  70. IN PPCI_DN ControllerDevnode
  71. )
  72. {
  73. WMIHANDLE methodHandle = NULL;
  74. ULONG status;
  75. BOOL returnVal;
  76. if (!(ControllerDevnode->WmiId[0])) {
  77. return FALSE;
  78. }
  79. status = WmiOpenBlock((LPGUID)&GUID_HPS_EVENT_CONTEXT,
  80. WMIGUID_SET,
  81. &methodHandle
  82. );
  83. if (status != ERROR_SUCCESS) {
  84. returnVal = FALSE;
  85. goto cleanup;
  86. }
  87. status = WmiSetSingleInstanceW(methodHandle,
  88. ControllerDevnode->WmiId,
  89. 1,
  90. sizeof(PCI_DN),
  91. ControllerDevnode
  92. );
  93. if (status != ERROR_SUCCESS) {
  94. returnVal = FALSE;
  95. goto cleanup;
  96. }
  97. returnVal = TRUE;
  98. cleanup:
  99. if (methodHandle) {
  100. WmiCloseBlock(methodHandle);
  101. }
  102. return returnVal;
  103. }
  104. BOOL
  105. SoftPCI_GetHotplugData(
  106. IN PPCI_DN ControllerDevnode,
  107. IN PHPS_HWINIT_DESCRIPTOR HpData
  108. )
  109. {
  110. WMIHANDLE methodHandle = NULL;
  111. PWNODE_SINGLE_INSTANCE wnodeSI = NULL;
  112. ULONG status;
  113. ULONG size;
  114. BOOL returnVal = FALSE;
  115. if (!(ControllerDevnode->WmiId[0])) {
  116. return FALSE;
  117. }
  118. status = WmiOpenBlock((LPGUID)&GUID_HPS_INIT_DATA,
  119. WMIGUID_QUERY,
  120. &methodHandle
  121. );
  122. if (status != ERROR_SUCCESS) {
  123. goto cleanup;
  124. }
  125. size = sizeof(WNODE_TOO_SMALL);
  126. wnodeSI = malloc(size);
  127. if (wnodeSI == NULL) {
  128. goto cleanup;
  129. }
  130. status = WmiQuerySingleInstanceW(methodHandle,
  131. ControllerDevnode->WmiId,
  132. &size,
  133. wnodeSI);
  134. if (status == ERROR_INSUFFICIENT_BUFFER)
  135. {
  136. free(wnodeSI);
  137. wnodeSI = malloc(size);
  138. if (wnodeSI == NULL) {
  139. goto cleanup;
  140. }
  141. status = WmiQuerySingleInstanceW(methodHandle,
  142. ControllerDevnode->WmiId,
  143. &size,
  144. wnodeSI);
  145. }
  146. if (status == ERROR_SUCCESS) {
  147. returnVal = TRUE;
  148. if (wnodeSI->SizeDataBlock) {
  149. RtlCopyMemory(HpData,(PUCHAR)wnodeSI+wnodeSI->DataBlockOffset,wnodeSI->SizeDataBlock);
  150. }
  151. }
  152. cleanup:
  153. if (methodHandle) {
  154. WmiCloseBlock(methodHandle);
  155. }
  156. if (wnodeSI) {
  157. free(wnodeSI);
  158. }
  159. return returnVal;
  160. }
  161. BOOL
  162. SoftPCI_ExecuteHotplugSlotMethod(
  163. IN PPCI_DN ControllerDevnode,
  164. IN UCHAR SlotNum,
  165. IN HPS_SLOT_EVENT_TYPE EventType
  166. )
  167. {
  168. HPS_SLOT_EVENT slotEvent;
  169. WMIHANDLE methodHandle = NULL;
  170. ULONG status;
  171. ULONG outSize;
  172. BOOL returnVal;
  173. if (!(ControllerDevnode->WmiId[0])) {
  174. return FALSE;
  175. }
  176. status = WmiOpenBlock((LPGUID)&GUID_HPS_SLOT_METHOD,
  177. WMIGUID_EXECUTE,
  178. &methodHandle
  179. );
  180. if (status != ERROR_SUCCESS) {
  181. returnVal = FALSE;
  182. goto cleanup;
  183. }
  184. slotEvent.SlotNum = SlotNum;
  185. slotEvent.EventType = EventType;
  186. outSize = 0;
  187. status = WmiExecuteMethodW(methodHandle,
  188. ControllerDevnode->WmiId,
  189. SlotMethod,
  190. sizeof(HPS_SLOT_EVENT),
  191. &slotEvent,
  192. &outSize,
  193. NULL
  194. );
  195. if (status != ERROR_SUCCESS) {
  196. returnVal = FALSE;
  197. goto cleanup;
  198. }
  199. returnVal = TRUE;
  200. cleanup:
  201. if (methodHandle) {
  202. WmiCloseBlock(methodHandle);
  203. }
  204. return returnVal;
  205. }
  206. BOOL
  207. SoftPCI_AddHotplugDevice(
  208. IN PPCI_DN ControllerDevnode,
  209. IN PSOFTPCI_DEVICE Device
  210. )
  211. {
  212. WMIHANDLE methodHandle = NULL;
  213. ULONG status = ERROR_INVALID_DATA;
  214. ULONG outSize;
  215. BOOL returnVal;
  216. if (!(ControllerDevnode->WmiId[0])) {
  217. SoftPCI_Debug(SoftPciHotPlug, L"GetHotplugDevice - No WMI id!\n");
  218. returnVal= FALSE;
  219. goto cleanup;
  220. }
  221. status = WmiOpenBlock((LPGUID)&GUID_HPS_SLOT_METHOD,
  222. WMIGUID_EXECUTE,
  223. &methodHandle
  224. );
  225. if (status != ERROR_SUCCESS) {
  226. returnVal = FALSE;
  227. goto cleanup;
  228. }
  229. outSize = 0;
  230. status = WmiExecuteMethodW(methodHandle,
  231. ControllerDevnode->WmiId,
  232. AddDeviceMethod,
  233. sizeof(SOFTPCI_DEVICE),
  234. Device,
  235. &outSize,
  236. NULL
  237. );
  238. if (status != ERROR_SUCCESS) {
  239. returnVal = FALSE;
  240. goto cleanup;
  241. }
  242. returnVal = TRUE;
  243. cleanup:
  244. if (returnVal == TRUE) {
  245. SoftPCI_Debug(SoftPciHotPlug, L"Add Device succeeded\n");
  246. } else {
  247. SoftPCI_Debug(SoftPciHotPlug, L"Add Device failed status=0x%x\n", status);
  248. }
  249. if (methodHandle) {
  250. WmiCloseBlock(methodHandle);
  251. }
  252. return returnVal;
  253. }
  254. BOOL
  255. SoftPCI_RemoveHotplugDevice(
  256. IN PPCI_DN ControllerDevnode,
  257. IN UCHAR SlotNum
  258. )
  259. {
  260. WMIHANDLE methodHandle = NULL;
  261. ULONG status = ERROR_INVALID_DATA;
  262. ULONG outSize;
  263. BOOL returnVal;
  264. if (!(ControllerDevnode->WmiId[0])) {
  265. SoftPCI_Debug(SoftPciHotPlug, L"GetHotplugDevice - No WMI id!\n");
  266. returnVal=FALSE;
  267. goto cleanup;
  268. }
  269. status = WmiOpenBlock((LPGUID)&GUID_HPS_SLOT_METHOD,
  270. WMIGUID_EXECUTE,
  271. &methodHandle
  272. );
  273. if (status != ERROR_SUCCESS) {
  274. returnVal = FALSE;
  275. goto cleanup;
  276. }
  277. outSize = 0;
  278. status = WmiExecuteMethodW(methodHandle,
  279. ControllerDevnode->WmiId,
  280. RemoveDeviceMethod,
  281. sizeof(UCHAR),
  282. &SlotNum,
  283. &outSize,
  284. NULL
  285. );
  286. if (status != ERROR_SUCCESS) {
  287. returnVal = FALSE;
  288. goto cleanup;
  289. }
  290. returnVal = TRUE;
  291. cleanup:
  292. if (returnVal == TRUE) {
  293. SoftPCI_Debug(SoftPciHotPlug, L"Remove Device - Slot %d succeeded\n", SlotNum);
  294. } else {
  295. SoftPCI_Debug(SoftPciHotPlug, L"Remove Device - Slot %d failed status=0x%x\n", SlotNum, status);
  296. }
  297. if (methodHandle) {
  298. WmiCloseBlock(methodHandle);
  299. }
  300. return returnVal;
  301. }
  302. BOOL
  303. SoftPCI_GetHotplugDevice(
  304. IN PPCI_DN ControllerDevnode,
  305. IN UCHAR SlotNum,
  306. OUT PSOFTPCI_DEVICE Device
  307. )
  308. {
  309. WMIHANDLE methodHandle = NULL;
  310. ULONG status = ERROR_INVALID_DATA;
  311. ULONG outSize;
  312. BOOL returnVal;
  313. PSOFTPCI_DEVICE bogus = NULL;
  314. if (!(ControllerDevnode->WmiId[0])) {
  315. SoftPCI_Debug(SoftPciHotPlug, L"GetHotplugDevice - No WMI id!\n");
  316. returnVal=FALSE;
  317. goto cleanup;
  318. }
  319. status = WmiOpenBlock((LPGUID)&GUID_HPS_SLOT_METHOD,
  320. WMIGUID_EXECUTE,
  321. &methodHandle
  322. );
  323. if (status != ERROR_SUCCESS) {
  324. SoftPCI_Debug(SoftPciHotPlug, L"GetHotplugDevice - Couldn't open wmi block! status = 0x%x\n", status);
  325. returnVal = FALSE;
  326. goto cleanup;
  327. }
  328. outSize = sizeof(SOFTPCI_DEVICE);
  329. SoftPCI_Debug(SoftPciHotPlug, L"GetHotplugDevice - WMI Id -\n\t");
  330. SoftPCI_Debug(SoftPciHotPlug, L"%s\n", ControllerDevnode->WmiId);
  331. status = WmiExecuteMethodW(methodHandle,
  332. ControllerDevnode->WmiId,
  333. GetDeviceMethod,
  334. sizeof(UCHAR),
  335. &SlotNum,
  336. &outSize,
  337. Device
  338. );
  339. if (status != ERROR_SUCCESS) {
  340. returnVal = FALSE;
  341. goto cleanup;
  342. }
  343. //SoftPCI_Debug(SoftPciHotPlug, L"succeeded\n");
  344. returnVal = TRUE;
  345. cleanup:
  346. if (returnVal == TRUE) {
  347. SoftPCI_Debug(SoftPciHotPlug, L"GetHotplugDevice - Slot %d succeeded\n", SlotNum);
  348. } else {
  349. SoftPCI_Debug(SoftPciHotPlug, L"GetHotplugDevice - Slot %d failed status=0x%x\n", SlotNum, status);
  350. }
  351. if (methodHandle) {
  352. WmiCloseBlock(methodHandle);
  353. }
  354. return returnVal;
  355. }
  356. BOOL
  357. SoftPCI_GetSlotStatus(
  358. IN PPCI_DN ControllerDevnode,
  359. IN UCHAR SlotNum,
  360. OUT PSHPC_SLOT_STATUS_REGISTER StatusReg
  361. )
  362. {
  363. WMIHANDLE methodHandle = NULL;
  364. ULONG status;
  365. ULONG outSize;
  366. BOOL returnVal;
  367. if (!(ControllerDevnode->WmiId[0])) {
  368. return FALSE;
  369. }
  370. status = WmiOpenBlock((LPGUID)&GUID_HPS_SLOT_METHOD,
  371. WMIGUID_EXECUTE,
  372. &methodHandle
  373. );
  374. if (status != ERROR_SUCCESS) {
  375. SoftPCI_Debug(SoftPciHotPlug, L"GetSlotStatus - Couldn't open wmi block! status = 0x%x\n", status);
  376. returnVal = FALSE;
  377. goto cleanup;
  378. }
  379. outSize = sizeof(SHPC_SLOT_STATUS_REGISTER);
  380. status = WmiExecuteMethodW(methodHandle,
  381. ControllerDevnode->WmiId,
  382. GetSlotStatusMethod,
  383. sizeof(UCHAR),
  384. &SlotNum,
  385. &outSize,
  386. StatusReg
  387. );
  388. if (status != ERROR_SUCCESS) {
  389. SoftPCI_Debug(SoftPciHotPlug, L"GetSlotStatus - Slot %d failed status=0x%x\n", SlotNum, status);
  390. returnVal = FALSE;
  391. goto cleanup;
  392. }
  393. returnVal = TRUE;
  394. cleanup:
  395. if (methodHandle) {
  396. WmiCloseBlock(methodHandle);
  397. }
  398. return returnVal;
  399. }
  400. VOID
  401. SoftPCI_CompleteCommand(
  402. IN PPCI_DN ControllerDevnode
  403. )
  404. {
  405. WMIHANDLE methodHandle = NULL;
  406. ULONG status;
  407. ULONG outSize, inBuffer, outBuffer;
  408. if (!(ControllerDevnode->WmiId[0])) {
  409. return;
  410. }
  411. status = WmiOpenBlock((LPGUID)&GUID_HPS_SLOT_METHOD,
  412. WMIGUID_EXECUTE,
  413. &methodHandle
  414. );
  415. if (status != ERROR_SUCCESS) {
  416. SoftPCI_Debug(SoftPciHotPlug, L"CompleteCommand - Couldn't open wmi block! status = 0x%x\n", status);
  417. goto cleanup;
  418. }
  419. outSize = sizeof(ULONG);
  420. status = WmiExecuteMethodW(methodHandle,
  421. ControllerDevnode->WmiId,
  422. CommandCompleteMethod,
  423. 0,
  424. &inBuffer,
  425. &outSize,
  426. &outBuffer
  427. );
  428. if (status != ERROR_SUCCESS) {
  429. SoftPCI_Debug(SoftPciHotPlug, L"CompleteCommand - failed status=0x%x\n", status);
  430. goto cleanup;
  431. }
  432. cleanup:
  433. if (methodHandle) {
  434. WmiCloseBlock(methodHandle);
  435. }
  436. return;
  437. }
  438. VOID
  439. SoftPCI_RegisterHotplugEvents(
  440. VOID
  441. )
  442. {
  443. WmiNotificationRegistrationW((LPGUID)&GUID_HPS_CONTROLLER_EVENT,
  444. TRUE,
  445. SoftPCI_HotplugEventCallback,
  446. (ULONG_PTR)0,
  447. NOTIFICATION_CALLBACK_DIRECT
  448. );
  449. }
  450. VOID
  451. SoftPCI_UnregisterHotplugEvents(
  452. VOID
  453. )
  454. {
  455. WmiNotificationRegistrationW((LPGUID)&GUID_HPS_CONTROLLER_EVENT,
  456. FALSE,
  457. SoftPCI_HotplugEventCallback,
  458. (ULONG_PTR)0,
  459. NOTIFICATION_CALLBACK_DIRECT
  460. );
  461. }
  462. VOID
  463. SoftPCI_HotplugEventCallback(
  464. IN PWNODE_HEADER WnodeHeader,
  465. IN ULONG Context
  466. )
  467. {
  468. PWNODE_SINGLE_INSTANCE WnodeSI = (PWNODE_SINGLE_INSTANCE)WnodeHeader;
  469. PWNODE_HEADER Wnode = WnodeHeader;
  470. PUCHAR WnodeDataPtr;
  471. LPGUID EventGuid = &WnodeHeader->Guid;
  472. WCHAR s[MAX_PATH];
  473. ULONG Status;
  474. WMIHANDLE Handle;
  475. PPCI_DN controllerDevnode;
  476. PHPS_CONTROLLER_EVENT event;
  477. ULONG slotNums;
  478. UCHAR currentSlot;
  479. SOFTPCI_ASSERT(EQUAL_GUID(EventGuid,&GUID_HPS_CONTROLLER_EVENT));
  480. if (!EQUAL_GUID(EventGuid,&GUID_HPS_CONTROLLER_EVENT)) {
  481. //
  482. // Not the event we expected. Return.
  483. //
  484. return;
  485. }
  486. SOFTPCI_ASSERT(WnodeSI->SizeDataBlock == (sizeof(HPS_CONTROLLER_EVENT) + sizeof(PCI_DN)));
  487. if (WnodeSI->SizeDataBlock != (sizeof(HPS_CONTROLLER_EVENT) + sizeof(PCI_DN))) {
  488. //
  489. // Not the buffer we expected. Return.
  490. //
  491. return;
  492. }
  493. WnodeDataPtr = (PUCHAR)WnodeHeader + WnodeSI->DataBlockOffset;
  494. controllerDevnode = (PPCI_DN)WnodeDataPtr;
  495. WnodeDataPtr += sizeof(PCI_DN);
  496. event = (PHPS_CONTROLLER_EVENT)WnodeDataPtr;
  497. if (event->SERRAsserted) {
  498. SoftPCI_UnregisterHotplugEvents();
  499. wsprintf(s, L"Hotplug Controller at bus 0x%x device 0x%x function 0x%x just caused an SERR!",
  500. controllerDevnode->Bus, controllerDevnode->Slot.Device, controllerDevnode->Slot.Function
  501. );
  502. MessageBox(g_SoftPCIMainWnd,
  503. s,
  504. L"FATAL ERROR",
  505. MB_OK
  506. );
  507. }
  508. currentSlot = 0;
  509. slotNums = event->SlotNums;
  510. while (slotNums != 0) {
  511. if (slotNums & 0x1) {
  512. if (event->Command.SlotOperation.SlotState == SHPC_SLOT_ENABLED) {
  513. SoftPCI_BringHotplugDeviceOnline(controllerDevnode,
  514. currentSlot
  515. );
  516. } else if (event->Command.SlotOperation.SlotState == SHPC_SLOT_OFF) {
  517. SoftPCI_TakeHotplugDeviceOffline(controllerDevnode,
  518. currentSlot
  519. );
  520. }
  521. }
  522. slotNums >>= 1;
  523. currentSlot++;
  524. }
  525. SoftPCI_CompleteCommand(controllerDevnode);
  526. return;
  527. }