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.
 
 
 
 
 
 

460 lines
17 KiB

/*++
Copyright (c) 1997-1999 Microsoft Corporation
Module Name:
mofapi.c
Abstract:
WMI MOF access apis
Author:
16-Jan-1997 AlanWar
Revision History:
--*/
#include "wmiump.h"
#include "trcapi.h"
#include "common.h"
BOOLEAN EtwpCopyCountedString(
PUCHAR Base,
PULONG Offset,
PULONG BufferRemaining,
PWCHAR SourceString
)
{
PWCHAR w;
ULONG BufferUsed;
ULONG BytesUsed;
BOOLEAN BufferNotFull;
if (*BufferRemaining > 1)
{
w = (PWCHAR)OffsetToPtr(Base, *Offset);
(*BufferRemaining)--;
BufferNotFull = EtwpCopyMRString(w+1,
*BufferRemaining,
&BufferUsed,
SourceString);
if (BufferNotFull)
{
BytesUsed = BufferUsed * sizeof(WCHAR);
*w = (USHORT)BytesUsed;
(*BufferRemaining) -= BufferUsed;
(*Offset) += BytesUsed + sizeof(USHORT);
}
} else {
BufferNotFull = FALSE;
}
return(BufferNotFull);
}
ULONG EtwpBuildMofAddRemoveEvent(
IN PWNODE_SINGLE_INSTANCE WnodeSI,
IN PWMIMOFLIST MofList,
IN PWCHAR *LanguageList,
IN ULONG LanguageCount,
IN BOOLEAN IncludeNeutralLanguage,
IN NOTIFICATIONCALLBACK Callback,
IN ULONG_PTR DeliveryContext,
IN BOOLEAN IsAnsi
)
{
PWNODE_ALL_DATA WnodeAD;
ULONG BytesUsed, BufferUsed;
BOOLEAN BufferNotFull;
PWCHAR RegPath, ImagePath, ResourceName;
ULONG SizeNeeded;
ULONG InstanceCount, MaxInstanceCount;
ULONG Status;
ULONG Offset;
POFFSETINSTANCEDATAANDLENGTH DataLenPtr;
PWCHAR w;
PULONG InstanceNamesOffsets;
PWCHAR InstanceNames;
ULONG BufferRemaining;
ULONG i,j;
PWMIMOFENTRY MofEntry;
PWCHAR ImagePathStatic;
EtwpAssert(WnodeSI->WnodeHeader.Flags & WNODE_FLAG_SINGLE_INSTANCE);
ImagePathStatic = EtwpAlloc(MAX_PATH * sizeof(WCHAR));
if (ImagePathStatic != NULL)
{
//
// Figure out how large the WNODE_ALL_DATA will need to be and
// guess at how much space to allocate for the image paths and
// resource names
//
if (IncludeNeutralLanguage)
{
MaxInstanceCount = (LanguageCount + 1);
} else {
MaxInstanceCount = LanguageCount;
}
MaxInstanceCount *= MofList->MofListCount;
#if DBG
SizeNeeded = sizeof(WNODE_ALL_DATA) +
(MaxInstanceCount *
(sizeof(ULONG) + // offset to instance name
sizeof(USHORT) + // instance name length
sizeof(OFFSETINSTANCEDATAANDLENGTH))) +
64;
#else
SizeNeeded = sizeof(WNODE_ALL_DATA) +
(MaxInstanceCount *
(sizeof(ULONG) + // offset to instance name
sizeof(USHORT) + // instance name length
sizeof(OFFSETINSTANCEDATAANDLENGTH))) +
0x1000;
#endif
WnodeAD = NULL;
do
{
TryAgain:
if (WnodeAD != NULL)
{
EtwpFree(WnodeAD);
}
WnodeAD = EtwpAlloc(SizeNeeded);
if (WnodeAD != NULL)
{
//
// Build up WNODE_ALL_DATA with all mof resources
//
memset(WnodeAD, 0, SizeNeeded);
WnodeAD->WnodeHeader = WnodeSI->WnodeHeader;
WnodeAD->WnodeHeader.Flags = WNODE_FLAG_ALL_DATA |
WNODE_FLAG_EVENT_ITEM;
WnodeAD->WnodeHeader.BufferSize = SizeNeeded;
WnodeAD->WnodeHeader.Linkage = 0;
//
// Establish pointer to the data offset and length
// structure and allocate space for all instances
//
Offset = FIELD_OFFSET(WNODE_ALL_DATA,
OffsetInstanceDataAndLength);
DataLenPtr = (POFFSETINSTANCEDATAANDLENGTH)OffsetToPtr(WnodeAD,
Offset);
Offset = (Offset +
(MaxInstanceCount *
sizeof(OFFSETINSTANCEDATAANDLENGTH)) + 7) & ~7;
//
// Establish the instance name offsets and fill in
// the empty instance names. Note we point them all
// to the same offset which is an empty instance
// name.
//
InstanceNamesOffsets = (PULONG)OffsetToPtr(WnodeAD,
Offset);
WnodeAD->OffsetInstanceNameOffsets = Offset;
Offset = Offset + (MaxInstanceCount * sizeof(ULONG));
InstanceNames = (PWCHAR)OffsetToPtr(WnodeAD, Offset);
*InstanceNames = 0;
for (i = 0; i < MaxInstanceCount; i++)
{
InstanceNamesOffsets[i] = Offset;
}
//
// Establish a pointer to the data block for all of
// the instances
//
Offset = (Offset +
(MaxInstanceCount * sizeof(USHORT)) + 7) & ~7;
WnodeAD->DataBlockOffset = Offset;
BufferRemaining = (SizeNeeded - Offset) / sizeof(WCHAR);
InstanceCount = 0;
//
// Loop over all mof resources in list
//
for (j = 0; j < MofList->MofListCount; j++)
{
MofEntry = &MofList->MofEntry[j];
RegPath = (PWCHAR)OffsetToPtr(MofList,
MofEntry->RegPathOffset);
//
// Convert regpath to image path if needed
//
if ((MofEntry->Flags & WMIMOFENTRY_FLAG_USERMODE) == 0)
{
ImagePath = EtwpRegistryToImagePath(ImagePathStatic,
RegPath+1);
} else {
ImagePath = RegPath;
}
if (ImagePath != NULL)
{
ResourceName = (PWCHAR)OffsetToPtr(MofList,
MofEntry->ResourceOffset);
//
// Now lets go and build up the data for each
// instance. First fill in the language neutral mof
// if we are supposed to
//
if (IncludeNeutralLanguage)
{
DataLenPtr[InstanceCount].OffsetInstanceData = Offset;
if ((! EtwpCopyCountedString((PUCHAR)WnodeAD,
&Offset,
&BufferRemaining,
ImagePath)) ||
(! EtwpCopyCountedString((PUCHAR)WnodeAD,
&Offset,
&BufferRemaining,
ResourceName)))
{
SizeNeeded *=2;
goto TryAgain;
}
DataLenPtr[InstanceCount].LengthInstanceData = Offset -
DataLenPtr[InstanceCount].OffsetInstanceData;
InstanceCount++;
//
// We cheat here and do not align the offset on an
// 8 byte boundry for the next data block since we
// know the data type is a WCHAR and we know we are
// on a 2 byte boundry.
//
}
//
// Now loop over and build language specific mof
// resources
//
for (i = 0; i < LanguageCount; i++)
{
DataLenPtr[InstanceCount].OffsetInstanceData = Offset;
if (BufferRemaining > 1)
{
w = (PWCHAR)OffsetToPtr(WnodeAD, Offset);
Status = EtwpBuildMUIPath(w+1,
BufferRemaining - 1,
&BufferUsed,
ImagePath,
LanguageList[i],
&BufferNotFull);
if (Status == ERROR_SUCCESS)
{
if (BufferNotFull)
{
BufferRemaining--;
BytesUsed = BufferUsed * sizeof(WCHAR);
*w = (USHORT)BytesUsed;
BufferRemaining -= BufferUsed;
Offset += (BytesUsed + sizeof(USHORT));
if (! EtwpCopyCountedString((PUCHAR)WnodeAD,
&Offset,
&BufferRemaining,
ResourceName))
{
SizeNeeded *=2;
goto TryAgain;
}
DataLenPtr[InstanceCount].LengthInstanceData = Offset - DataLenPtr[InstanceCount].OffsetInstanceData;
//
// We cheat here and do not align the offset on an
// 8 byte boundry for the next data block since we
// know the data type is a WCHAR and we know we are
// on a 2 byte boundry.
//
InstanceCount++;
} else {
SizeNeeded *=2;
goto TryAgain;
}
}
} else {
SizeNeeded *=2;
goto TryAgain;
}
}
}
}
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
} while (FALSE);
if (WnodeAD != NULL)
{
WnodeAD->InstanceCount = InstanceCount;
EtwpMakeEventCallbacks((PWNODE_HEADER)WnodeAD,
Callback,
DeliveryContext,
IsAnsi);
EtwpFree(WnodeAD);
Status = ERROR_SUCCESS;
}
EtwpFree(ImagePathStatic);
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
return(Status);
}
void EtwpProcessMofAddRemoveEvent(
IN PWNODE_SINGLE_INSTANCE WnodeSI,
IN NOTIFICATIONCALLBACK Callback,
IN ULONG_PTR DeliveryContext,
IN BOOLEAN IsAnsi
)
{
PWCHAR RegPath, ResourceName;
PWCHAR *LanguageList;
ULONG LanguageCount;
ULONG Status;
PWMIMOFLIST MofList;
ULONG i;
PWMIMOFENTRY MofEntry;
ULONG Offset;
ULONG SizeNeeded;
PWCHAR w;
RegPath = (PWCHAR)OffsetToPtr(WnodeSI, WnodeSI->DataBlockOffset);
EtwpAssert(*RegPath != 0);
ResourceName = (PWCHAR)OffsetToPtr(WnodeSI,
WnodeSI->DataBlockOffset +
sizeof(USHORT) +
*RegPath++ +
sizeof(USHORT));
SizeNeeded = sizeof(WMIMOFLIST) + ((wcslen(RegPath) +
(wcslen(ResourceName) + 2)) * sizeof(WCHAR));
MofList = (PWMIMOFLIST)EtwpAlloc(SizeNeeded);
if (MofList != NULL)
{
Status = EtwpGetLanguageList(&LanguageList,
&LanguageCount);
if (Status == ERROR_SUCCESS)
{
MofList->MofListCount = 1;
MofEntry = &MofList->MofEntry[0];
Offset = sizeof(WMIMOFLIST);
MofEntry->RegPathOffset = Offset;
w = (PWCHAR)OffsetToPtr(MofList, Offset);
wcscpy(w, RegPath);
Offset += (wcslen(RegPath) + 1) * sizeof(WCHAR);
MofEntry->ResourceOffset = Offset;
w = (PWCHAR)OffsetToPtr(MofList, Offset);
wcscpy(w, ResourceName);
if (WnodeSI->WnodeHeader.ProviderId == MOFEVENT_ACTION_REGISTRY_PATH)
{
MofEntry->Flags = 0;
} else {
MofEntry->Flags = WMIMOFENTRY_FLAG_USERMODE;
}
Status = EtwpBuildMofAddRemoveEvent(WnodeSI,
MofList,
LanguageList,
LanguageCount,
TRUE,
Callback,
DeliveryContext,
IsAnsi);
//
// Free up memory used to hold the language list
//
for (i = 0; i < LanguageCount; i++)
{
EtwpFree(LanguageList[i]);
}
EtwpFree(LanguageList);
}
EtwpFree(MofList);
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
if (Status != ERROR_SUCCESS)
{
//
// If the WNODE_ALL_DATA event wasn't fired then just fire the
// WNDOE_SINGLE_INSTANCE event so at least we get the language
// neutral mof
//
WnodeSI->WnodeHeader.Flags &= ~WNODE_FLAG_INTERNAL;
EtwpMakeEventCallbacks((PWNODE_HEADER)WnodeSI,
Callback,
DeliveryContext,
IsAnsi);
}
}
void EtwpProcessLanguageAddRemoveEvent(
IN PWNODE_SINGLE_INSTANCE WnodeSI,
IN NOTIFICATIONCALLBACK Callback,
IN ULONG_PTR DeliveryContext,
IN BOOLEAN IsAnsi
)
{
ULONG Status;
PWMIMOFLIST MofList;
PWCHAR Language;
//
// Get list of mof resources and build an event with the list of
// resources for the language that is coming or going
//
Status = EtwpGetMofResourceList(&MofList);
if (Status == ERROR_SUCCESS)
{
Language = (PWCHAR)OffsetToPtr(WnodeSI,
WnodeSI->DataBlockOffset + sizeof(USHORT));
Status = EtwpBuildMofAddRemoveEvent(WnodeSI,
MofList,
&Language,
1,
FALSE,
Callback,
DeliveryContext,
IsAnsi);
}
}