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.
 
 
 
 
 
 

674 lines
20 KiB

/*++
Copyright(c) 2001 Microsoft Corporation
Module Name:
nlbwmi.c
Abstract:
Network Load Balancing (NLB)
Driver - WMI event generation
Author:
karthicn
--*/
#include "wlbsparm.h"
#include <wmistr.h>
#include <wmiguid.h>
#include <wmilib.h>
#include "main.h"
#include "univ.h"
#include "nlbwmimof.h"
#include "nlbwmi.h"
#include "nlbwmi.tmh"
//
// MOF Resource Name
//
WCHAR NLBMofResourceName[] = L"NLBMofResource";
//
// Base Instance Name
//
WCHAR NLBBaseInstanceName[] = L"NLB_Block";
// NLB Event Guids - the MicrosoftNLB* variables are autogenerated (in nlbwmimof.h)
GUID NodeControlEventGuid = MicrosoftNLB_NodeControlEventGuid;
GUID PortRuleControlEventGuid = MicrosoftNLB_PortControlEventGuid;
GUID ConvergingEventGuid = MicrosoftNLB_ConvergingEventGuid;
GUID ConvergedEventGuid = MicrosoftNLB_ConvergedEventGuid;
GUID StartupEventGuid = MicrosoftNLB_StartupEventGuid;
GUID ShutdownEventGuid = MicrosoftNLB_ShutdownEventGuid;
// NLB Event Guid Registration Information
WMIGUIDREGINFO NlbWmiGuidList[] =
{
{
&NodeControlEventGuid,
1,
WMIREG_FLAG_EVENT_ONLY_GUID
},
{
&PortRuleControlEventGuid,
1,
WMIREG_FLAG_EVENT_ONLY_GUID
},
{
&ConvergingEventGuid,
1,
WMIREG_FLAG_EVENT_ONLY_GUID
},
{
&ConvergedEventGuid,
1,
WMIREG_FLAG_EVENT_ONLY_GUID
},
{
&StartupEventGuid,
1,
WMIREG_FLAG_EVENT_ONLY_GUID
},
{
&ShutdownEventGuid,
1,
WMIREG_FLAG_EVENT_ONLY_GUID
},
// Add new event info here
};
#define NlbWmiGuidCount (ULONG)(sizeof(NlbWmiGuidList)/sizeof(WMIGUIDREGINFO))
// NLB Event Information
NLB_WMI_EVENT NlbWmiEvents[] =
{
{
&NodeControlEventGuid,
FALSE
},
{
&PortRuleControlEventGuid,
FALSE
},
{
&ConvergingEventGuid,
FALSE
},
{
&ConvergedEventGuid,
FALSE
},
{
&StartupEventGuid,
FALSE
},
{
&ShutdownEventGuid,
FALSE
},
// Add new event info here as well
};
//
// Prototype declarations
//
NTSTATUS
NlbWmi_Query_RegInfo(
IN PDEVICE_OBJECT DeviceObject,
OUT ULONG *RegFlags,
OUT PUNICODE_STRING InstanceName,
OUT PUNICODE_STRING *RegistryPath,
OUT PUNICODE_STRING MofResourceName,
OUT PDEVICE_OBJECT *Pdo
);
NTSTATUS
NlbWmi_Query_DataBlock(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN ULONG GuidIndex,
IN ULONG InstanceIndex,
IN ULONG InstanceCount,
IN OUT PULONG InstanceLengthArray,
IN ULONG BufferAvail,
OUT PUCHAR Buffer
);
NTSTATUS
NlbWmi_Function_Control(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN ULONG GuidIndex,
IN WMIENABLEDISABLECONTROL Function,
IN BOOLEAN Enable
);
//
// WMI Helper Library context
//
WMILIB_CONTEXT NlbWmiLibContext =
{
NlbWmiGuidCount,
NlbWmiGuidList,
NlbWmi_Query_RegInfo,
NlbWmi_Query_DataBlock,
NULL,
NULL,
NULL,
NlbWmi_Function_Control
};
/*
Name : NlbWmi_Initialize
Description : This function initializes the data structures and registers the supported guids with the wmi system
Arguments : None
Return Value: status
*/
NTSTATUS NlbWmi_Initialize()
{
ULONG idx;
NTSTATUS status;
TRACE_VERB("->%!FUNC!");
/* Disable event generation for all events */
for (idx = 0 ; idx < NlbWmiGuidCount ; idx++)
{
NlbWmiEvents[idx].Enable = FALSE;
}
if (univ_device_object != NULL)
{
/* Register with WMI */
status = IoWMIRegistrationControl(univ_device_object, WMIREG_ACTION_REGISTER);
if (status != STATUS_SUCCESS)
{
TRACE_CRIT("%!FUNC! IoWMIRegistrationControl(DeviceObject : %p, REGISTER) returned Error : 0x%x",univ_device_object, status);
}
}
else // Device Object is NULL
{
status = STATUS_INVALID_DEVICE_OBJECT_PARAMETER;
TRACE_CRIT("%!FUNC! Device Object is NULL, Could not call IoWMIRegistrationControl() to register with WMI");
}
TRACE_VERB("<-%!FUNC! return : 0x%x", status);
return status;
}
/*
Name : NlbWmi_Shutdown
Description : This function de-registers with the wmi system
Arguments : None
Return Value: void
*/
VOID NlbWmi_Shutdown()
{
NTSTATUS ntStatus;
TRACE_VERB("->%!FUNC!");
if (univ_device_object != NULL)
{
/* DeRegister with WMI */
ntStatus = IoWMIRegistrationControl(univ_device_object, WMIREG_ACTION_DEREGISTER);
if (ntStatus != STATUS_SUCCESS)
{
TRACE_CRIT("%!FUNC! IoWMIRegistrationControl(DeviceObject : %p, DEREGISTER) returned Error : 0x%x",univ_device_object, ntStatus);
}
}
else
{
TRACE_CRIT("%!FUNC! Device Object is NULL, Could not call IoWMIRegistrationControl() to deregister with WMI");
}
TRACE_VERB("<-%!FUNC!");
return;
}
/*
Name : NlbWmi_System_Control
Description : This function is responsible for handling the IRP_MJ_SYSTEM_CONTROL irps. It uses the wmi helper
library function to crack the irp to have the appropriate call back functions called
Arguments : Device Object, Irp
Return Value: status
*/
NTSTATUS NlbWmi_System_Control (PVOID DeviceObject, PIRP pIrp)
{
NTSTATUS status;
SYSCTL_IRP_DISPOSITION disposition;
TRACE_VERB("->%!FUNC!");
//
// Call Wmilib helper function to crack the irp. If this is a wmi irp
// that is targetted for the supported guids, then WmiSystemControl will callback
// at the appropriate callback routine.
//
status = WmiSystemControl(
&NlbWmiLibContext,
DeviceObject,
pIrp,
&disposition
);
switch(disposition)
{
case IrpProcessed:
//
// This irp has been processed and may be completed or pending.
//
break;
case IrpNotCompleted:
//
// This irp has not been completed, but has been fully processed.
// so we need to complete it
// (Must be a IRP_MN_REG_INFO)
//
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
break;
default:
case IrpNotWmi:
case IrpForward:
{
TRACE_CRIT("%!FUNC! WmiSystemControl returned disposition : 0x%x, Unexpected", disposition);
pIrp->IoStatus.Status = status;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
break;
}
}
if( !NT_SUCCESS( status ))
{
TRACE_CRIT("%!FUNC! WmiSystemControl returned error : 0x%x", status);
}
TRACE_VERB("<-%!FUNC! return : 0x%x", status);
return status;
} // NlbWmi_System_Control
/*
Name : NlbWmi_Query_RegInfo
Description : This function is called back by the Wmi helper library to process a IRP_MN_REG_INFO irp. It
registers the Instance name, registry path & Mof resource name with wmi. For more information
about this function, please look in the DDK under "WMI library Callback Routines"->"DpWmiQueryReginfo"
Return Value: status
*/
NTSTATUS
NlbWmi_Query_RegInfo(
IN PDEVICE_OBJECT DeviceObject,
OUT ULONG *RegFlags,
OUT PUNICODE_STRING InstanceName,
OUT PUNICODE_STRING *RegistryPath,
OUT PUNICODE_STRING MofResourceName,
OUT PDEVICE_OBJECT *Pdo
)
{
PAGED_CODE();
TRACE_VERB("->%!FUNC!");
//
// Tell WMI to generate instance names off of a static base name
//
*RegFlags = WMIREG_FLAG_INSTANCE_BASENAME;
//
// Set our base instance name. WmiLib will call ExFreePool on the buffer
// of the string, so we need to allocate it from paged pool.
//
InstanceName->Length = wcslen( NLBBaseInstanceName ) * sizeof( WCHAR );
InstanceName->MaximumLength = InstanceName->Length + sizeof( UNICODE_NULL );
InstanceName->Buffer = ExAllocatePoolWithTag(
PagedPool,
InstanceName->MaximumLength,
UNIV_POOL_TAG
);
if( NULL != InstanceName->Buffer )
{
RtlCopyMemory(
InstanceName->Buffer,
NLBBaseInstanceName,
InstanceName->Length
);
InstanceName->Buffer[InstanceName->Length / sizeof(WCHAR)] = UNICODE_NULL;
}
else
{
TRACE_CRIT("%!FUNC! Error allocating memory");
TRACE_VERB("<-%!FUNC! return status = STATUS_INSUFFICIENT_RESOURCES");
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Return the registry path for this driver. This is required so WMI
// can find your driver image and can attribute any eventlog messages to
// your driver.
//
*RegistryPath = &DriverEntryRegistryPath;
//
// Return the name specified in the .rc file of the resource which
// contains the binary mof data.
//
RtlInitUnicodeString(MofResourceName, NLBMofResourceName);
TRACE_VERB("<-%!FUNC! return=0x%x", STATUS_SUCCESS);
return STATUS_SUCCESS;
} // NlbWmi_Query_RegInfo
/*
Name : NlbWmi_Query_DataBlock
Description : This function is called back by the Wmi helper library to process IRP_MN_QUERY_ALL_DATA
& IRP_MN_QUERY_SINGLE_INSTANCE irps. We DO NOT SUPPORT these irps. However, this is a
required callback and hence we implement it. We DO NOT EXPECT THIS FUNCTION TO BE CALLED.
For more information about this function, please look in the DDK under
"WMI library Callback Routines"->"DpWmiQueryDataBlock"
Return Value: status
*/
NTSTATUS
NlbWmi_Query_DataBlock(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN ULONG GuidIndex,
IN ULONG InstanceIndex,
IN ULONG InstanceCount,
IN OUT PULONG InstanceLengthArray,
IN ULONG BufferAvail,
OUT PUCHAR Buffer
)
{
NTSTATUS status;
PAGED_CODE();
TRACE_VERB("->%!FUNC!");
status = WmiCompleteRequest(
DeviceObject,
Irp,
STATUS_WMI_GUID_NOT_FOUND,
0,
IO_NO_INCREMENT
);
TRACE_VERB("<-%!FUNC! return=0x%x", status);
return status;
} // NlbWmi_Query_DataBlock
/*
Name : NlbWmi_Function_Control
Description : This function is called back by the Wmi helper library to process IRP_MN_ENABLE_EVENTS,
IRP_MN_DISABLE_EVENTS, IRP_MN_ENABLE_COLLECTION & IRP_MN_DISABLE_COLLECTION irps. We only
support IRP_MN_ENABLE_EVENTS & IRP_MN_DISABLE_EVENTS irps. The function enables/disables
events generation. For more information about this function, please look in the DDK under
"WMI library Callback Routines"->"DpWmiQueryReginfo"
Return Value: status
*/
NTSTATUS
NlbWmi_Function_Control(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN ULONG GuidIndex,
IN WMIENABLEDISABLECONTROL Function,
IN BOOLEAN Enable
)
{
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE();
TRACE_VERB("->%!FUNC! %ls Event Index : %d", Enable ? L"ENABLE" : L"DISABLE", GuidIndex);
if( WmiEventControl == Function )
{
// Verify that the guid index is in the range 0 - (NlbWmiGuidCount - 1)
// Also, verify that the guid has not been flagged as removed. Although
// we never flag a guid as being removed, do this check as part of
// following "best practices".
if( (GuidIndex < NlbWmiGuidCount)
&& !(NlbWmiGuidList[GuidIndex].Flags & WMIREG_FLAG_REMOVE_GUID))
{
NlbWmiEvents[GuidIndex].Enable = Enable;
}
else
{
//
// Invalid guid index.
//
status = STATUS_WMI_GUID_NOT_FOUND;
TRACE_CRIT("%!FUNC! Invalid WMI guid or guid flagged as removed, guid index: %d", GuidIndex);
}
}
else
{
//
// We currently don't have any (expensive) data blocks
//
status = STATUS_INVALID_DEVICE_REQUEST;
TRACE_CRIT("%!FUNC! Invalid Device Request");
}
status = WmiCompleteRequest(
DeviceObject,
Irp,
status,
0,
IO_NO_INCREMENT
);
TRACE_VERB("<-%!FUNC! return status = 0x%x", status);
return status;
} // NlbWmi_Function_Control
/*
Name : NlbWmi_Fire_Event
Description : This function fires wmi events. It allocates memory, fills it in with the
incoming event data and calls WmiFireEvent to fire the event.
Arguments : Event Id, Event Data (statically allocated)
Return Value: status
*/
NTSTATUS NlbWmi_Fire_Event(NlbWmiEventId EventId, PVOID pvInEventData, ULONG ulInEventDataSize)
{
NTSTATUS status;
PVOID pvOutEventData;
TRACE_VERB("->%!FUNC! Event : %d", EventId);
if (ulInEventDataSize > 0)
{
pvOutEventData = ExAllocatePoolWithTag(NonPagedPool, ulInEventDataSize, UNIV_POOL_TAG);
if (pvOutEventData == NULL)
{
TRACE_CRIT("%!FUNC! Error allocating memory");
TRACE_VERB("<-%!FUNC! return status = STATUS_INSUFFICIENT_RESOURCES");
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(pvOutEventData, pvInEventData, ulInEventDataSize);
}
else
{
pvOutEventData = NULL;
}
status = WmiFireEvent(univ_device_object, NlbWmiEvents[EventId].pGuid, 0, ulInEventDataSize, pvOutEventData);
if( !NT_SUCCESS( status ))
{
TRACE_CRIT("%!FUNC! WmiFireEvent returned error : 0x%x", status);
}
TRACE_VERB("<-%!FUNC! return status = 0x%x", status);
return status;
} // NlbWmi_Fire_Event
// This macro fills in the common properties(Adapter Guid, IP Address, Host priority) of all events
#define FillCommonProperties() \
{ \
Event.AdapterGuid[0] = sizeof(Event.AdapterGuid) - sizeof(Event.AdapterGuid[0]); \
wcsncpy(&(Event.AdapterGuid[1]), univ_adapters[ctxtp->adapter_id].device_name + 8, Event.AdapterGuid[0]/sizeof(WCHAR)); \
Event.ClusterIPAddress[0] = sizeof(Event.ClusterIPAddress) - sizeof(Event.ClusterIPAddress[0]); \
wcsncpy(&(Event.ClusterIPAddress[1]), ctxtp->params.cl_ip_addr, Event.ClusterIPAddress[0]/sizeof(WCHAR)); \
Event.HostPriority = ctxtp->params.host_priority; \
}
/*
Name : NlbWmi_Fire_NodeControlEvent
Description : This function fires Node Control events. It extracts the common event properties
(out of the given pointer to the MAIN_CTXT structure) and fills in a local
structure. It also fills in Node Control Event specific fields from the arguments
passed to it. It then fires the actual event by calling NlbWmi_Fire_Event.
Arguments : Pointer to MAIN_CTXT, NodeControlEventId
Return Value: void
*/
void NlbWmi_Fire_NodeControlEvent(PMAIN_CTXT ctxtp, NodeControlEventId Id)
{
MicrosoftNLB_NodeControlEvent Event;
TRACE_VERB("->%!FUNC! Event : %d", Id);
NdisZeroMemory(&Event, MicrosoftNLB_NodeControlEvent_SIZE);
// Fill in common properties - Adapter Guid, Cluster IP Address & Host Priority
FillCommonProperties()
// Fill event specific properties
Event.Id = Id;
// Fire the event
NlbWmi_Fire_Event(NodeControlEvent, &Event, MicrosoftNLB_NodeControlEvent_SIZE);
TRACE_VERB("<-%!FUNC!");
return;
}
/*
Name : NlbWmi_Fire_PortControlEvent
Description : This function fires Port Control events. It extracts the common event properties
(out of the given pointer to the MAIN_CTXT structure) and fills in a local
structure. It also fills in Port Control Event specific fields (id, vip, port) from the arguments
passed to it. It then fires the actual event by calling NlbWmi_Fire_Event.
Arguments : Pointer to MAIN_CTXT, PortControlEventId, Vip, Port
Return Value: void
*/
void NlbWmi_Fire_PortControlEvent(PMAIN_CTXT ctxtp, PortControlEventId Id, WCHAR *pwcVip, ULONG ulPort)
{
MicrosoftNLB_PortControlEvent Event;
TRACE_VERB("->%!FUNC! Event : %d, Vip : %ls, Start Port : %d", Id, pwcVip, ulPort);
NdisZeroMemory(&Event, MicrosoftNLB_PortControlEvent_SIZE);
// Fill in common properties - Adapter Guid, Cluster IP Address & Host Priority
FillCommonProperties()
// Fill event specific properties
Event.Id = Id;
Event.VirtualIPAddress[0] = sizeof(Event.VirtualIPAddress) - sizeof(Event.VirtualIPAddress[0]);
wcsncpy(&(Event.VirtualIPAddress[1]), pwcVip, Event.VirtualIPAddress[0]/sizeof(WCHAR));
Event.Port = ulPort;
// Fire the event
NlbWmi_Fire_Event(PortRuleControlEvent, &Event, MicrosoftNLB_PortControlEvent_SIZE);
TRACE_VERB("<-%!FUNC!");
return;
}
/*
Name : NlbWmi_Fire_ConvergingEvent
Description : This function fires Converging events. It extracts the common event properties
(out of the given pointer to the MAIN_CTXT structure) and fills in a local
structure. It also fills in Converging Event specific fields from the arguments
passed to it. It then fires the actual event by calling NlbWmi_Fire_Event.
Arguments : Pointer to MAIN_CTXT, NodeControlEventId, Initiator DIP, Initiator Host Priority
Return Value: void
*/
void NlbWmi_Fire_ConvergingEvent(
PMAIN_CTXT ctxtp,
ConvergingEventId Cause,
WCHAR *pwcInitiatorDip,
ULONG ulInitiatorHostPriority)
{
MicrosoftNLB_ConvergingEvent Event;
TRACE_VERB("->%!FUNC! Cause : %d, Initiator DIP : %ls, Initiator Host Priority : %d", Cause, pwcInitiatorDip, ulInitiatorHostPriority);
NdisZeroMemory(&Event, MicrosoftNLB_ConvergingEvent_SIZE);
// Fill in common properties - Adapter Guid, Cluster IP Address & Host Priority
FillCommonProperties()
// Fill event specific properties
Event.Cause = Cause;
Event.InitiatorDedicatedIP[0] = sizeof(Event.InitiatorDedicatedIP) - sizeof(Event.InitiatorDedicatedIP[0]);
wcsncpy(&(Event.InitiatorDedicatedIP[1]), pwcInitiatorDip, Event.InitiatorDedicatedIP[0]/sizeof(WCHAR));
Event.InitiatorHostPriority = ulInitiatorHostPriority;
// Fire the event
NlbWmi_Fire_Event(ConvergingEvent, &Event, MicrosoftNLB_ConvergingEvent_SIZE);
TRACE_VERB("<-%!FUNC!");
return;
}
/*
Name : NlbWmi_Fire_ConvergedEvent
Description : This function fires Converged events. It extracts the common event properties
(out of the given pointer to the MAIN_CTXT structure) and fills in a local
structure. It also fills in Converged Event specific fields from the arguments
passed to it. It then fires the actual event by calling NlbWmi_Fire_Event.
Arguments : Pointer to MAIN_CTXT, HostMap
Return Value: void
*/
void NlbWmi_Fire_ConvergedEvent(PMAIN_CTXT ctxtp, ULONG ulHostMap)
{
MicrosoftNLB_ConvergedEvent Event;
TRACE_VERB("->%!FUNC! Host Map : %d", ulHostMap);
NdisZeroMemory(&Event, MicrosoftNLB_ConvergedEvent_SIZE);
// Fill in common properties - Adapter Guid, Cluster IP Address & Host Priority
FillCommonProperties()
// Fill event specific properties
Event.HostMap = ulHostMap;
// Fire the event
NlbWmi_Fire_Event(ConvergedEvent, &Event, MicrosoftNLB_ConvergedEvent_SIZE);
TRACE_VERB("<-%!FUNC!");
return;
}