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
653 lines
17 KiB
#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;
|
|
}
|
|
|