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