|
|
#include "pch.h"
#include "hpwmi.h"
//
// When SoftPCI creates a SHPC devnode, it needs to do the following:
//
// 1) Call SoftPCI_SetEventContext to set the event callback context.
// 2) Call SoftPCI_RegisterHotplugEvents to register for event callbacks.
//
// Potentially we should get the WMI instance name for the device by calling
// SoftPCI_AllocWmiInstanceName once when the devnode is created instead
// of every time we do something WMI related.
//
BOOL SoftPCI_AllocWmiInstanceName( OUT PWCHAR WmiInstanceName, IN PWCHAR DeviceId ) { ULONG numChar;
numChar = WmiDevInstToInstanceNameW(WmiInstanceName, MAX_PATH, DeviceId, 0 ); if (numChar > MAX_PATH) { return FALSE;
} else { return TRUE; } }
BOOL SoftPCI_AllocWnodeSI( IN PPCI_DN Pdn, IN LPGUID Guid, IN PVOID Buffer, IN ULONG BufferSize, OUT PWNODE_SINGLE_INSTANCE *WnodeForBuffer ) { PWNODE_HEADER Wnode; PWNODE_SINGLE_INSTANCE WnodeSI; ULONG sizeNeeded; PUCHAR WnodeDataPtr;
SOFTPCI_ASSERT(Buffer != NULL); SOFTPCI_ASSERT(BufferSize != 0);
if ((Buffer == NULL) || (BufferSize == 0)) {
return FALSE; } sizeNeeded = FIELD_OFFSET(WNODE_SINGLE_INSTANCE, VariableData) + BufferSize;
Wnode = (PWNODE_HEADER)malloc(sizeNeeded); if (!Wnode) {
return FALSE; }
Wnode->Flags = WNODE_FLAG_SINGLE_INSTANCE | WNODE_FLAG_PDO_INSTANCE_NAMES; Wnode->BufferSize = sizeNeeded; Wnode->Guid = *Guid;
WnodeSI = (PWNODE_SINGLE_INSTANCE)Wnode; WnodeSI->DataBlockOffset = FIELD_OFFSET(WNODE_SINGLE_INSTANCE, VariableData); WnodeSI->InstanceIndex = 0; WnodeSI->SizeDataBlock = BufferSize;
WnodeDataPtr = (PUCHAR)Wnode + WnodeSI->DataBlockOffset; RtlCopyMemory(WnodeDataPtr, Buffer, BufferSize);
*WnodeForBuffer = WnodeSI;
return TRUE; }
BOOL SoftPCI_SetEventContext( IN PPCI_DN ControllerDevnode ) { WMIHANDLE methodHandle = NULL; ULONG status; BOOL returnVal;
if (!(ControllerDevnode->WmiId[0])) { return FALSE; }
status = WmiOpenBlock((LPGUID)&GUID_HPS_EVENT_CONTEXT, WMIGUID_SET, &methodHandle ); if (status != ERROR_SUCCESS) {
returnVal = FALSE; goto cleanup; }
status = WmiSetSingleInstanceW(methodHandle, ControllerDevnode->WmiId, 1, sizeof(PCI_DN), ControllerDevnode );
if (status != ERROR_SUCCESS) {
returnVal = FALSE; goto cleanup; }
returnVal = TRUE;
cleanup:
if (methodHandle) { WmiCloseBlock(methodHandle); }
return returnVal; }
BOOL SoftPCI_GetHotplugData( IN PPCI_DN ControllerDevnode, IN PHPS_HWINIT_DESCRIPTOR HpData ) { WMIHANDLE methodHandle = NULL; PWNODE_SINGLE_INSTANCE wnodeSI = NULL; ULONG status; ULONG size; BOOL returnVal = FALSE;
if (!(ControllerDevnode->WmiId[0])) { return FALSE; }
status = WmiOpenBlock((LPGUID)&GUID_HPS_INIT_DATA, WMIGUID_QUERY, &methodHandle ); if (status != ERROR_SUCCESS) {
goto cleanup; }
size = sizeof(WNODE_TOO_SMALL); wnodeSI = malloc(size); if (wnodeSI == NULL) {
goto cleanup; }
status = WmiQuerySingleInstanceW(methodHandle, ControllerDevnode->WmiId, &size, wnodeSI); if (status == ERROR_INSUFFICIENT_BUFFER) { free(wnodeSI); wnodeSI = malloc(size); if (wnodeSI == NULL) {
goto cleanup; }
status = WmiQuerySingleInstanceW(methodHandle, ControllerDevnode->WmiId, &size, wnodeSI);
}
if (status == ERROR_SUCCESS) { returnVal = TRUE; if (wnodeSI->SizeDataBlock) { RtlCopyMemory(HpData,(PUCHAR)wnodeSI+wnodeSI->DataBlockOffset,wnodeSI->SizeDataBlock); }
}
cleanup:
if (methodHandle) { WmiCloseBlock(methodHandle); }
if (wnodeSI) { free(wnodeSI); }
return returnVal; }
BOOL SoftPCI_ExecuteHotplugSlotMethod( IN PPCI_DN ControllerDevnode, IN UCHAR SlotNum, IN HPS_SLOT_EVENT_TYPE EventType ) { HPS_SLOT_EVENT slotEvent; WMIHANDLE methodHandle = NULL; ULONG status; ULONG outSize; BOOL returnVal;
if (!(ControllerDevnode->WmiId[0])) { return FALSE; }
status = WmiOpenBlock((LPGUID)&GUID_HPS_SLOT_METHOD, WMIGUID_EXECUTE, &methodHandle ); if (status != ERROR_SUCCESS) {
returnVal = FALSE; goto cleanup; }
slotEvent.SlotNum = SlotNum; slotEvent.EventType = EventType; outSize = 0; status = WmiExecuteMethodW(methodHandle, ControllerDevnode->WmiId, SlotMethod, sizeof(HPS_SLOT_EVENT), &slotEvent, &outSize, NULL ); if (status != ERROR_SUCCESS) {
returnVal = FALSE; goto cleanup; }
returnVal = TRUE;
cleanup:
if (methodHandle) { WmiCloseBlock(methodHandle); }
return returnVal; }
BOOL SoftPCI_AddHotplugDevice( IN PPCI_DN ControllerDevnode, IN PSOFTPCI_DEVICE Device ) { WMIHANDLE methodHandle = NULL; ULONG status = ERROR_INVALID_DATA; ULONG outSize; BOOL returnVal; if (!(ControllerDevnode->WmiId[0])) { SoftPCI_Debug(SoftPciHotPlug, L"GetHotplugDevice - No WMI id!\n"); returnVal= FALSE; goto cleanup; }
status = WmiOpenBlock((LPGUID)&GUID_HPS_SLOT_METHOD, WMIGUID_EXECUTE, &methodHandle ); if (status != ERROR_SUCCESS) {
returnVal = FALSE; goto cleanup; }
outSize = 0; status = WmiExecuteMethodW(methodHandle, ControllerDevnode->WmiId, AddDeviceMethod, sizeof(SOFTPCI_DEVICE), Device, &outSize, NULL ); if (status != ERROR_SUCCESS) {
returnVal = FALSE; goto cleanup; }
returnVal = TRUE;
cleanup:
if (returnVal == TRUE) { SoftPCI_Debug(SoftPciHotPlug, L"Add Device succeeded\n"); } else { SoftPCI_Debug(SoftPciHotPlug, L"Add Device failed status=0x%x\n", status); }
if (methodHandle) { WmiCloseBlock(methodHandle); }
return returnVal; }
BOOL SoftPCI_RemoveHotplugDevice( IN PPCI_DN ControllerDevnode, IN UCHAR SlotNum ) { WMIHANDLE methodHandle = NULL; ULONG status = ERROR_INVALID_DATA; ULONG outSize; BOOL returnVal; if (!(ControllerDevnode->WmiId[0])) { SoftPCI_Debug(SoftPciHotPlug, L"GetHotplugDevice - No WMI id!\n"); returnVal=FALSE; goto cleanup; }
status = WmiOpenBlock((LPGUID)&GUID_HPS_SLOT_METHOD, WMIGUID_EXECUTE, &methodHandle ); if (status != ERROR_SUCCESS) {
returnVal = FALSE; goto cleanup; }
outSize = 0; status = WmiExecuteMethodW(methodHandle, ControllerDevnode->WmiId, RemoveDeviceMethod, sizeof(UCHAR), &SlotNum, &outSize, NULL ); if (status != ERROR_SUCCESS) { returnVal = FALSE; goto cleanup; }
returnVal = TRUE;
cleanup:
if (returnVal == TRUE) { SoftPCI_Debug(SoftPciHotPlug, L"Remove Device - Slot %d succeeded\n", SlotNum); } else { SoftPCI_Debug(SoftPciHotPlug, L"Remove Device - Slot %d failed status=0x%x\n", SlotNum, status); } if (methodHandle) { WmiCloseBlock(methodHandle); }
return returnVal; }
BOOL SoftPCI_GetHotplugDevice( IN PPCI_DN ControllerDevnode, IN UCHAR SlotNum, OUT PSOFTPCI_DEVICE Device ) { WMIHANDLE methodHandle = NULL; ULONG status = ERROR_INVALID_DATA; ULONG outSize; BOOL returnVal; PSOFTPCI_DEVICE bogus = NULL;
if (!(ControllerDevnode->WmiId[0])) { SoftPCI_Debug(SoftPciHotPlug, L"GetHotplugDevice - No WMI id!\n"); returnVal=FALSE; goto cleanup; }
status = WmiOpenBlock((LPGUID)&GUID_HPS_SLOT_METHOD, WMIGUID_EXECUTE, &methodHandle ); if (status != ERROR_SUCCESS) { SoftPCI_Debug(SoftPciHotPlug, L"GetHotplugDevice - Couldn't open wmi block! status = 0x%x\n", status); returnVal = FALSE; goto cleanup; }
outSize = sizeof(SOFTPCI_DEVICE); SoftPCI_Debug(SoftPciHotPlug, L"GetHotplugDevice - WMI Id -\n\t"); SoftPCI_Debug(SoftPciHotPlug, L"%s\n", ControllerDevnode->WmiId); status = WmiExecuteMethodW(methodHandle, ControllerDevnode->WmiId, GetDeviceMethod, sizeof(UCHAR), &SlotNum, &outSize, Device );
if (status != ERROR_SUCCESS) { returnVal = FALSE; goto cleanup; }
//SoftPCI_Debug(SoftPciHotPlug, L"succeeded\n");
returnVal = TRUE;
cleanup:
if (returnVal == TRUE) { SoftPCI_Debug(SoftPciHotPlug, L"GetHotplugDevice - Slot %d succeeded\n", SlotNum); } else { SoftPCI_Debug(SoftPciHotPlug, L"GetHotplugDevice - Slot %d failed status=0x%x\n", SlotNum, status); }
if (methodHandle) { WmiCloseBlock(methodHandle); }
return returnVal; }
BOOL SoftPCI_GetSlotStatus( IN PPCI_DN ControllerDevnode, IN UCHAR SlotNum, OUT PSHPC_SLOT_STATUS_REGISTER StatusReg ) { WMIHANDLE methodHandle = NULL; ULONG status; ULONG outSize; BOOL returnVal;
if (!(ControllerDevnode->WmiId[0])) { return FALSE; }
status = WmiOpenBlock((LPGUID)&GUID_HPS_SLOT_METHOD, WMIGUID_EXECUTE, &methodHandle ); if (status != ERROR_SUCCESS) { SoftPCI_Debug(SoftPciHotPlug, L"GetSlotStatus - Couldn't open wmi block! status = 0x%x\n", status); returnVal = FALSE; goto cleanup; }
outSize = sizeof(SHPC_SLOT_STATUS_REGISTER); status = WmiExecuteMethodW(methodHandle, ControllerDevnode->WmiId, GetSlotStatusMethod, sizeof(UCHAR), &SlotNum, &outSize, StatusReg ); if (status != ERROR_SUCCESS) { SoftPCI_Debug(SoftPciHotPlug, L"GetSlotStatus - Slot %d failed status=0x%x\n", SlotNum, status); returnVal = FALSE; goto cleanup; }
returnVal = TRUE;
cleanup:
if (methodHandle) { WmiCloseBlock(methodHandle); }
return returnVal; }
VOID SoftPCI_CompleteCommand( IN PPCI_DN ControllerDevnode ) { WMIHANDLE methodHandle = NULL; ULONG status; ULONG outSize, inBuffer, outBuffer;
if (!(ControllerDevnode->WmiId[0])) { return; }
status = WmiOpenBlock((LPGUID)&GUID_HPS_SLOT_METHOD, WMIGUID_EXECUTE, &methodHandle ); if (status != ERROR_SUCCESS) { SoftPCI_Debug(SoftPciHotPlug, L"CompleteCommand - Couldn't open wmi block! status = 0x%x\n", status); goto cleanup; }
outSize = sizeof(ULONG); status = WmiExecuteMethodW(methodHandle, ControllerDevnode->WmiId, CommandCompleteMethod, 0, &inBuffer, &outSize, &outBuffer ); if (status != ERROR_SUCCESS) { SoftPCI_Debug(SoftPciHotPlug, L"CompleteCommand - failed status=0x%x\n", status); goto cleanup; }
cleanup:
if (methodHandle) { WmiCloseBlock(methodHandle); }
return; }
VOID SoftPCI_RegisterHotplugEvents( VOID ) { WmiNotificationRegistrationW((LPGUID)&GUID_HPS_CONTROLLER_EVENT, TRUE, SoftPCI_HotplugEventCallback, (ULONG_PTR)0, NOTIFICATION_CALLBACK_DIRECT ); }
VOID SoftPCI_UnregisterHotplugEvents( VOID ) { WmiNotificationRegistrationW((LPGUID)&GUID_HPS_CONTROLLER_EVENT, FALSE, SoftPCI_HotplugEventCallback, (ULONG_PTR)0, NOTIFICATION_CALLBACK_DIRECT ); }
VOID SoftPCI_HotplugEventCallback( IN PWNODE_HEADER WnodeHeader, IN ULONG Context ) { PWNODE_SINGLE_INSTANCE WnodeSI = (PWNODE_SINGLE_INSTANCE)WnodeHeader; PWNODE_HEADER Wnode = WnodeHeader; PUCHAR WnodeDataPtr; LPGUID EventGuid = &WnodeHeader->Guid; WCHAR s[MAX_PATH]; ULONG Status; WMIHANDLE Handle; PPCI_DN controllerDevnode; PHPS_CONTROLLER_EVENT event; ULONG slotNums; UCHAR currentSlot;
SOFTPCI_ASSERT(EQUAL_GUID(EventGuid,&GUID_HPS_CONTROLLER_EVENT)); if (!EQUAL_GUID(EventGuid,&GUID_HPS_CONTROLLER_EVENT)) { //
// Not the event we expected. Return.
//
return; }
SOFTPCI_ASSERT(WnodeSI->SizeDataBlock == (sizeof(HPS_CONTROLLER_EVENT) + sizeof(PCI_DN))); if (WnodeSI->SizeDataBlock != (sizeof(HPS_CONTROLLER_EVENT) + sizeof(PCI_DN))) { //
// Not the buffer we expected. Return.
//
return; }
WnodeDataPtr = (PUCHAR)WnodeHeader + WnodeSI->DataBlockOffset; controllerDevnode = (PPCI_DN)WnodeDataPtr;
WnodeDataPtr += sizeof(PCI_DN); event = (PHPS_CONTROLLER_EVENT)WnodeDataPtr;
if (event->SERRAsserted) { SoftPCI_UnregisterHotplugEvents(); wsprintf(s, L"Hotplug Controller at bus 0x%x device 0x%x function 0x%x just caused an SERR!", controllerDevnode->Bus, controllerDevnode->Slot.Device, controllerDevnode->Slot.Function ); MessageBox(g_SoftPCIMainWnd, s, L"FATAL ERROR", MB_OK );
}
currentSlot = 0; slotNums = event->SlotNums; while (slotNums != 0) { if (slotNums & 0x1) {
if (event->Command.SlotOperation.SlotState == SHPC_SLOT_ENABLED) { SoftPCI_BringHotplugDeviceOnline(controllerDevnode, currentSlot );
} else if (event->Command.SlotOperation.SlotState == SHPC_SLOT_OFF) { SoftPCI_TakeHotplugDeviceOffline(controllerDevnode, currentSlot ); } } slotNums >>= 1; currentSlot++; }
SoftPCI_CompleteCommand(controllerDevnode);
return; }
|