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

#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;
}