windows-nt/Source/XPSP1/NT/base/wmi/dll/mofapi.c
2020-09-26 16:20:57 +08:00

1509 lines
50 KiB
C

/*++
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"
ULONG
WMIAPI
WmiMofEnumerateResourcesA(
IN MOFHANDLE MofResourceHandle,
OUT ULONG *MofResourceCount,
OUT PMOFRESOURCEINFOA *MofResourceInfo
)
/*++
Routine Description:
ANSI thunk to WMIMofEnumerateResourcesA
--*/
{
ULONG Status;
PMOFRESOURCEINFOW MofResourceInfoUnicode;
PMOFRESOURCEINFOA MofResourceInfoAnsi;
PCHAR AnsiPtr;
PCHAR Ansi;
ULONG i, AnsiSize, AnsiStructureSize;
ULONG MofResourceCountUnicode;
ULONG AnsiLen;
ULONG AnsiImagePathSize;
ULONG AnsiResourceNameSize;
WmipInitProcessHeap();
Status = WmiMofEnumerateResourcesW(MofResourceHandle,
&MofResourceCountUnicode,
&MofResourceInfoUnicode);
if (Status == ERROR_SUCCESS)
{
//
// Walk the unicode MOFRESOURCEINFOW to determine the ansi size needed
// for all of the ansi MOFRESOURCEINFOA structures and strings. We
// determine the entire size and allocate a single block that holds
// all of it since that is what WMIMofEnumerateResourceInfoW does.
AnsiStructureSize = MofResourceCountUnicode * sizeof(MOFRESOURCEINFOA);
AnsiSize = AnsiStructureSize;
for (i = 0; i < MofResourceCountUnicode; i++)
{
Status = AnsiSizeForUnicodeString(MofResourceInfoUnicode[i].ImagePath,
&AnsiImagePathSize);
if (Status != ERROR_SUCCESS)
{
goto Done;
}
Status = AnsiSizeForUnicodeString(MofResourceInfoUnicode[i].ResourceName,
&AnsiResourceNameSize);
if (Status != ERROR_SUCCESS)
{
goto Done;
}
AnsiSize += AnsiImagePathSize + AnsiResourceNameSize;
}
MofResourceInfoAnsi = WmipAlloc(AnsiSize);
if (MofResourceInfoAnsi != NULL)
{
AnsiPtr = (PCHAR)((PUCHAR)MofResourceInfoAnsi + AnsiStructureSize);
for (i = 0; i < MofResourceCountUnicode; i++)
{
MofResourceInfoAnsi[i].ResourceSize = MofResourceInfoUnicode[i].ResourceSize;
MofResourceInfoAnsi[i].ResourceBuffer = MofResourceInfoUnicode[i].ResourceBuffer;
MofResourceInfoAnsi[i].ImagePath = AnsiPtr;
Status = UnicodeToAnsi(MofResourceInfoUnicode[i].ImagePath,
&MofResourceInfoAnsi[i].ImagePath,
&AnsiLen);
if (Status != ERROR_SUCCESS)
{
break;
}
AnsiPtr += AnsiLen;
MofResourceInfoAnsi[i].ResourceName = AnsiPtr;
Status = UnicodeToAnsi(MofResourceInfoUnicode[i].ResourceName,
&MofResourceInfoAnsi[i].ResourceName,
&AnsiLen);
if (Status != ERROR_SUCCESS)
{
break;
}
AnsiPtr += AnsiLen;
}
if (Status == ERROR_SUCCESS)
{
try
{
*MofResourceInfo = MofResourceInfoAnsi;
} except(EXCEPTION_EXECUTE_HANDLER) {
Status = ERROR_NOACCESS;
WmipFree(MofResourceInfoAnsi);
}
}
} else {
//
// Not enough memory for ansi thunking so free unicode
// mof class info and return an error.
Status = ERROR_NOT_ENOUGH_MEMORY;
}
Done:
WmiFreeBuffer(MofResourceInfoUnicode);
}
SetLastError(Status);
return(Status);
}
PTCHAR WmipRegistryToImagePath(
PTCHAR ImagePath,
PTCHAR RegistryPath
)
/*++
Routine Description:
This routine will determine the location of the device driver's image file
from its registry path
Arguments:
RegistryPath is a pointer to the driver's registry path
ImagePath is buffer of length MAX_PATH and returns the image path
Return Value:
pointer to Image path of driver or NULL if image path is unavailable
--*/
{
#define SystemRoot TEXT("\\SystemRoot\\")
#ifdef MEMPHIS
#define SystemRootDirectory TEXT("%WinDir%\\")
#else
#define SystemRootDirectory TEXT("%SystemRoot%\\")
#endif
#define SystemRootCharSize (( sizeof(SystemRoot) / sizeof(WCHAR) ) - 1)
#define DriversDirectory TEXT("\\System32\\Drivers\\")
#define NdisDriversDirectory TEXT("\\System\\")
#define QuestionPrefix TEXT("\\??\\")
#define QuestionPrefixSize (( sizeof(QuestionPrefix) / sizeof(WCHAR) ) - 1)
#define RegistryPrefix TEXT("\\Registry")
HKEY RegKey;
PTCHAR ImagePathPtr = NULL;
ULONG ValueType;
ULONG Size;
PTCHAR DriverName;
ULONG Len;
BOOLEAN DefaultImageName;
PTCHAR DriversDirectoryPath;
TCHAR *Buffer;
TCHAR *FullRegistryPath;
Buffer = (PTCHAR)WmipAlloc(2 * MAX_PATH * sizeof(TCHAR));
if (Buffer != NULL)
{
FullRegistryPath = Buffer + MAX_PATH;
#ifdef MEMPHIS
TCHAR Buffer2[MAX_PATH];
//
// On memphis the registry path could point to two places
// \Registry\Machine\System\CurrentControlSet\Services\Driver (Legacy)
// System\CurrentControlSet\Services\Class\USB\0001
if (_tcsnicmp(RegistryPath, RegistryPrefix, sizeof(RegistryPrefix)-1) != 0)
{
//
// This is a non legacy type registry path.
if (RegOpenKey(HKEY_LOCAL_MACHINE,
RegistryPath,
&RegKey) == ERROR_SUCCESS)
{
DriverName = Buffer2;
Size = MAX_PATH * sizeof(WCHAR);
if (RegQueryValueEx(RegKey,
TEXT("NTMPDriver"),
NULL,
&ValueType,
DriverName,
&Size) == ERROR_SUCCESS)
{
DriversDirectoryPath = DriversDirectory;
} else if (RegQueryValueEx(RegKey,
TEXT("DeviceVxDs"),
NULL,
&ValueType,
DriverName,
&Size) == ERROR_SUCCESS)
{
DriversDirectoryPath = NdisDriversDirectory;
} else {
DriversDirectoryPath = NULL;
}
if ((DriversDirectoryPath != NULL) && (ValueType == REG_SZ))
{
Size = GetWindowsDirectory(Buffer, MAX_PATH);
if ((Size != 0) &&
(Size <= (MAX_PATH - _tcslen(DriverName) - sizeof(DriversDirectory) - 1)))
{
if (Buffer[Size-1] == TEXT('\\'))
{
Buffer[Size-1] = 0;
}
_tcscpy(ImagePath, Buffer);
_tcscat(ImagePath, DriversDirectoryPath);
_tcscat(ImagePath, DriverName);
ImagePathPtr = ImagePath;
RegCloseKey(RegKey);
WmipFree(Buffer);
return(ImagePathPtr);
}
}
RegCloseKey(RegKey);
}
}
#endif
//
// Get the driver file name or the MOF image path from the KM
// registry path. Here are the rules:
//
// 1. First check the MofImagePath value in the registry in case the
// mof resource is in a different file from the driver.
// 2. Next check the ImagePath value since the mof resource is assumed
// to be part of the driver image.
// 3. If no MofImagePath or ImagePath values then assume the mof resource
// is in the driver file and compose the driver file name as
// %SystemRoot%\System32\driver.sys.
// 4. If MofImagePath or ImagePath was specified then
// - Check first char for % or second character for :, or prefix
// of \??\ and if so use ExpandEnvironmentStrings
// - Check first part of path for \SystemRoot\, if so rebuild string
// as %SystemRoot%\ and use ExpandEnvironementStrings
// - Assume format D below and prepend %SystemRoot%\ and use
// ExpandEnvironmentStrings
// If MofImagePath or ImagePath value is present and it is a REG_EXPAND_SZ
// then it is used to locate the file that holds the mof resource. It
// can be in one of the following formats:
// Format A - %SystemRoot%\System32\Foo.Dll
// Format B -C:\WINNT\SYSTEM32\Drivers\Foo.SYS
// Format C - \SystemRoot\System32\Drivers\Foo.SYS
// Format D - System32\Drivers\Foo.Sys
// Format E - \??\c:\foo.sys
Len = _tcslen(RegistryPath);
if (Len > 0)
{
DriverName = RegistryPath + Len;
while ((*(--DriverName) != '\\') && (--Len > 0)) ;
}
if (Len == 0)
{
WmipDebugPrint(("WMI: Badly formed registry path %ws\n", RegistryPath));
WmipFree(Buffer);
return(NULL);
}
DriverName++;
_tcscpy(FullRegistryPath, TEXT("System\\CurrentControlSet\\Services\\"));
_tcscat(FullRegistryPath, DriverName);
DefaultImageName = TRUE;
if (RegOpenKey(HKEY_LOCAL_MACHINE,
FullRegistryPath,
&RegKey) == ERROR_SUCCESS)
{
Size = MAX_PATH * sizeof(WCHAR);
if (RegQueryValueEx(RegKey,
TEXT("MofImagePath"),
NULL,
&ValueType,
(PBYTE)ImagePath,
&Size) == ERROR_SUCCESS)
{
DefaultImageName = FALSE;
} else {
Size = MAX_PATH * sizeof(WCHAR);
if (RegQueryValueEx(RegKey,
TEXT("ImagePath"),
NULL,
&ValueType,
(PBYTE)ImagePath,
&Size) == ERROR_SUCCESS)
{
DefaultImageName = FALSE;
}
}
RegCloseKey(RegKey);
}
if ((DefaultImageName) ||
((ValueType != REG_EXPAND_SZ) && (ValueType != REG_SZ)) ||
(Size < (2 * sizeof(WCHAR))))
{
//
// No special ImagePath or MofImagePath so assume image file is
// %SystemRoot%\System32\Drivers\Driver.Sys
#ifdef MEMPHIS
_tcscpy(Buffer, TEXT("%WinDir%\\System32\\Drivers\\"));
#else
_tcscpy(Buffer, TEXT("%SystemRoot%\\System32\\Drivers\\"));
#endif
_tcscat(Buffer, DriverName);
_tcscat(Buffer, TEXT(".SYS"));
} else {
if (_tcsnicmp(ImagePath,
SystemRoot,
SystemRootCharSize) == 0)
{
//
// Looks like format C
_tcscpy(Buffer, SystemRootDirectory);
_tcscat(Buffer, &ImagePath[SystemRootCharSize]);
} else if ((*ImagePath == '%') ||
( (Size > 3*sizeof(WCHAR)) && ImagePath[1] == TEXT(':')) )
{
//
// Looks like format B or format A
_tcscpy(Buffer, ImagePath);
} else if (_tcsnicmp(ImagePath,
QuestionPrefix,
QuestionPrefixSize) == 0)
{
//
// Looks like format E
_tcscpy(Buffer, ImagePath+QuestionPrefixSize);
} else {
//
// Assume format D
_tcscpy(Buffer, SystemRootDirectory);
_tcscat(Buffer, ImagePath);
}
}
Size = ExpandEnvironmentStrings(Buffer,
ImagePath,
MAX_PATH);
#ifdef MEMPHIS
WmipDebugPrint(("WMI: %s has mof in %s\n",
DriverName, ImagePath));
#else
WmipDebugPrint(("WMI: %ws has mof in %ws\n",
DriverName, ImagePath));
#endif
WmipFree(Buffer);
} else {
ImagePath = NULL;
}
return(ImagePath);
}
typedef struct
{
ULONG Count;
ULONG MaxCount;
PWCHAR *List;
} ENUMLANGCTX, *PENUMLANGCTX;
BOOL EnumUILanguageCallback(
LPWSTR Language,
LONG_PTR Context
)
{
PENUMLANGCTX EnumLangCtx = (PENUMLANGCTX)Context;
PWCHAR *p;
PWCHAR w;
ULONG NewMaxCount;
if (EnumLangCtx->Count == EnumLangCtx->MaxCount)
{
NewMaxCount = EnumLangCtx->MaxCount * 2;
p = WmipAlloc( sizeof(PWCHAR) * NewMaxCount);
if (p != NULL)
{
memset(p, 0, sizeof(PWCHAR) * NewMaxCount);
memcpy(p, EnumLangCtx->List, EnumLangCtx->Count * sizeof(PWCHAR));
WmipFree(EnumLangCtx->List);
EnumLangCtx->List = p;
EnumLangCtx->MaxCount = NewMaxCount;
} else {
return(FALSE);
}
}
w = WmipAlloc( (wcslen(Language)+1) * sizeof(WCHAR) );
if (w != NULL)
{
EnumLangCtx->List[EnumLangCtx->Count++] = w;
wcscpy(w, Language);
} else {
return(FALSE);
}
return(TRUE);
}
ULONG
WmipGetLanguageList(
PWCHAR **List,
PULONG Count
)
{
ENUMLANGCTX EnumLangCtx;
BOOL b;
ULONG Status;
*List = NULL;
*Count = 0;
EnumLangCtx.Count = 0;
EnumLangCtx.MaxCount = 8;
EnumLangCtx.List = WmipAlloc( 8 * sizeof(PWCHAR) );
if (EnumLangCtx.List != NULL)
{
b = EnumUILanguages(EnumUILanguageCallback,
0,
(LONG_PTR)&EnumLangCtx);
if (b)
{
*Count = EnumLangCtx.Count;
*List = EnumLangCtx.List;
Status = ERROR_SUCCESS;
} else {
if (EnumLangCtx.List != NULL)
{
WmipFree(EnumLangCtx.List);
}
Status = GetLastError();
}
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
return(Status);
}
BOOLEAN
WmipFileExists(
PWCHAR FileName
)
{
HANDLE FindHandle;
BOOLEAN Found;
PWIN32_FIND_DATA FindData;
FindData = (PWIN32_FIND_DATA)WmipAlloc(sizeof(WIN32_FIND_DATA));
if (FindData != NULL)
{
//
// Now we need to make sure that the file a ctually exists
//
FindHandle = FindFirstFile(FileName,
FindData);
if (FindHandle == INVALID_HANDLE_VALUE)
{
Found = FALSE;
} else {
FindClose(FindHandle);
Found = TRUE;
}
WmipFree(FindData);
} else {
Found = FALSE;
}
return(Found);
}
ULONG WmipGetWindowsDirectory(
PWCHAR *s,
PWCHAR Static,
ULONG StaticSize
)
{
ULONG Size;
ULONG Status = ERROR_SUCCESS;
Size = GetWindowsDirectory(Static, StaticSize);
if (Size > StaticSize)
{
Size += sizeof(UNICODE_NULL);
*s = WmipAlloc(Size * sizeof(WCHAR));
if (*s != NULL)
{
Size = GetWindowsDirectory(*s, Size);
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
} else if (Size == 0) {
Status = GetLastError();
} else {
*s = Static;
}
if (Status == ERROR_SUCCESS)
{
if ( (*s)[Size-1] == L'\\')
{
(*s)[Size-1] = 0;
}
}
return(Status);
}
BOOLEAN
WmipCopyMRString(
PWCHAR Buffer,
ULONG BufferRemaining,
PULONG BufferUsed,
PWCHAR SourceString
)
{
BOOLEAN BufferNotFull;
ULONG len;
len = wcslen(SourceString) + 1;
if (len <= BufferRemaining)
{
wcscpy(Buffer, SourceString);
*BufferUsed = len;
BufferNotFull = TRUE;
} else {
BufferNotFull = FALSE;
}
return(BufferNotFull);
}
BOOLEAN WmipCopyCountedString(
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 = WmipCopyMRString(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
WmipBuildMUIPath(
PWCHAR Buffer,
ULONG BufferRemaining,
PULONG BufferUsed,
PWCHAR EnglishPath,
PWCHAR Language,
PBOOLEAN BufferNotFull
)
{
#define FallbackDir L"\\MUI\\Fallback\\"
#define MUIPath L"\\MUI\\"
#define MUITail L".mui"
ULONG EnglishLen;
PWCHAR WinDir;
PWCHAR s, p;
ULONG len;
ULONG Status, SizeNeeded;
PWCHAR LanguagePath;
PWCHAR WinDirStatic;
WinDirStatic = WmipAlloc((MAX_PATH+1) * sizeof(WCHAR));
if (WinDirStatic != NULL)
{
Status = ERROR_FILE_NOT_FOUND;
LanguagePath = Buffer;
WmipDebugPrint(("WMI: Building MUI path for %ws in language %ws\n",
EnglishPath, Language));
EnglishLen = wcslen(EnglishPath);
p = EnglishPath + EnglishLen;
len = EnglishLen;
//
// Work from the end of the string to try to find the last \ so
// we can then slip in the language name
//
while ( (len != 0) && (*p != L'\\'))
{
len--;
p--;
}
if (len != 0)
{
p++;
}
WmipDebugPrint(("WMI: Tail of %ws is %ws\n", EnglishPath, p));
//
// First try looking in <path>\\MUI\\<lang id> which is where 3rd
// parties will install their resource only drivers. We look for
// foo.sys and then foo.sys.mui.
//
SizeNeeded = len + wcslen(Language) + wcslen(MUIPath) + 1 + wcslen(p) + 1 + wcslen(MUITail);
if (SizeNeeded <= BufferRemaining)
{
if (len != 0)
{
wcsncpy(LanguagePath, EnglishPath, len);
LanguagePath[len] = 0;
wcscat(LanguagePath, MUIPath);
} else {
LanguagePath[len] = 0;
}
wcscat(LanguagePath, Language);
wcscat(LanguagePath, L"\\");
wcscat(LanguagePath, p);
if (WmipFileExists(LanguagePath))
{
*BufferUsed = wcslen(LanguagePath) + 1;
*BufferNotFull = TRUE;
Status = ERROR_SUCCESS;
WmipDebugPrint(("WMI: #1 - Found %ws\n", LanguagePath));
} else {
wcscat(LanguagePath, MUITail);
if (WmipFileExists(LanguagePath))
{
*BufferUsed = wcslen(LanguagePath) + 1;
*BufferNotFull = TRUE;
Status = ERROR_SUCCESS;
WmipDebugPrint(("WMI: #2 - Found %ws\n", LanguagePath));
}
}
} else {
*BufferNotFull = FALSE;
Status = ERROR_SUCCESS;
}
if (Status != ERROR_SUCCESS)
{
//
// Next lets check the fallback directory,
// %windir%\MUI\Fallback\<lang id>. This is where system components
// are installed by default.
//
Status = WmipGetWindowsDirectory(&WinDir,
WinDirStatic,
sizeof(WinDirStatic)/ sizeof(WCHAR));
if (Status == ERROR_SUCCESS)
{
SizeNeeded = wcslen(WinDir) +
wcslen(FallbackDir) +
wcslen(Language) +
1 +
wcslen(p) + 1 +
wcslen(MUITail);
if (SizeNeeded <= BufferRemaining)
{
wcscpy(LanguagePath, WinDir);
wcscat(LanguagePath, FallbackDir);
wcscat(LanguagePath, Language);
wcscat(LanguagePath, L"\\");
wcscat(LanguagePath, p);
wcscat(LanguagePath, MUITail);
if ( WmipFileExists(LanguagePath))
{
*BufferUsed = wcslen(LanguagePath) + 1;
*BufferNotFull = TRUE;
Status = ERROR_SUCCESS;
WmipDebugPrint(("WMI: #3 - Found %ws\n", LanguagePath));
} else {
Status = ERROR_FILE_NOT_FOUND;
}
} else {
*BufferNotFull = FALSE;
Status = ERROR_SUCCESS;
}
if (WinDir != WinDirStatic)
{
WmipFree(WinDir);
}
}
}
WmipFree(WinDirStatic);
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
return(Status);
}
#if DBG
#define MOFLISTSIZEGUESS 1
#else
#define MOFLISTSIZEGUESS 10
#endif
ULONG
WmipGetMofResourceList(
PWMIMOFLIST *MofListPtr
)
{
ULONG MofListSize;
PWMIMOFLIST MofList;
ULONG RetSize;
ULONG Status;
//
// Make an intelligent guess as to the size needed to get all of
// the MOF resources
//
*MofListPtr = NULL;
MofListSize = MOFLISTSIZEGUESS * (sizeof(WMIMOFLIST) +
(MAX_PATH +
MAX_PATH) * sizeof(WCHAR));
MofList = WmipAlloc(MofListSize);
if (MofList != NULL)
{
Status = WmipSendWmiKMRequest(NULL,
IOCTL_WMI_ENUMERATE_MOF_RESOURCES,
NULL,
0,
MofList,
MofListSize,
&RetSize,
NULL);
if ((Status == ERROR_SUCCESS) && (RetSize == sizeof(ULONG)))
{
//
// The buffer was too small, but we now know how much we'll
// need.
//
MofListSize = MofList->MofListCount;
WmipFree(MofList);
MofList = WmipAlloc(MofListSize);
if (MofList != NULL)
{
//
// Now lets retry the query
//
Status = WmipSendWmiKMRequest(NULL,
IOCTL_WMI_ENUMERATE_MOF_RESOURCES,
NULL,
0,
MofList,
MofListSize,
&RetSize,
NULL);
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
}
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
if (Status == ERROR_SUCCESS)
{
if (RetSize >= sizeof(WMIMOFLIST))
{
*MofListPtr = MofList;
} else {
Status = ERROR_INVALID_PARAMETER;
WmipFree(MofList);
}
} else if (MofList != NULL) {
WmipFree(MofList);
}
return(Status);
}
ULONG
WmiMofEnumerateResourcesW(
IN MOFHANDLE MofResourceHandle,
OUT ULONG *MofResourceCount,
OUT PMOFRESOURCEINFOW *MofResourceInfo
)
/*++
Routine Description:
This routine will enumerate one or all of the MOF resources that are
registered with WMI.
Arguments:
MofResourceHandle is reserved and must be 0
*MofResourceCount returns with the count of MOFRESOURCEINFO structures
returned in *MofResourceInfo.
*MofResourceInfo returns with a pointer to an array of MOFRESOURCEINFO
structures. The caller MUST call WMIFreeBuffer with *MofResourceInfo
in order to ensure that there are no memory leaks.
Return Value:
ERROR_SUCCESS or an error code
--*/
{
ULONG Status, SubStatus;
PWMIMOFLIST MofList;
ULONG MofListCount;
ULONG MRInfoSize;
ULONG MRCount;
PWCHAR MRBuffer;
PMOFRESOURCEINFOW MRInfo;
PWCHAR RegPath, ResName, ImagePath;
PWMIMOFENTRY MofEntry;
ULONG i, j;
PWCHAR *LanguageList;
ULONG LanguageCount;
BOOLEAN b;
ULONG HeaderLen;
ULONG MRBufferRemaining;
PWCHAR ResourcePtr;
ULONG BufferUsed;
PWCHAR ImagePathStatic;
WmipInitProcessHeap();
if (MofResourceHandle != 0)
{
SetLastError(ERROR_INVALID_PARAMETER);
return(ERROR_INVALID_PARAMETER);
}
ImagePathStatic = WmipAlloc(MAX_PATH * sizeof(WCHAR));
if (ImagePathStatic != NULL)
{
*MofResourceInfo = NULL;
Status = WmipGetMofResourceList(&MofList);
if (Status == ERROR_SUCCESS)
{
//
// Ok, we have got a valid list of mofs. Now we need to
// loop over them all and convert the regpaths into image
// paths
//
Status = WmipGetLanguageList(&LanguageList,
&LanguageCount);
if (Status == ERROR_SUCCESS)
{
MofListCount = MofList->MofListCount;
//
// Take a guess as to the size of the buffer needed to
// satisfy the complete list of mof resources
//
HeaderLen = (MofListCount * (LanguageCount+1)) *
sizeof(MOFRESOURCEINFOW);
#if DBG
MRInfoSize = HeaderLen + 2 * (MAX_PATH * sizeof(WCHAR));
#else
MRInfoSize = HeaderLen + (2*MofListCount * (MAX_PATH * sizeof(WCHAR)));
#endif
MRInfo = NULL;
do
{
TryAgain:
if (MRInfo != NULL)
{
WmipDebugPrint(("WMI: MofList was too small, retry 0x%x bytes\n",
MRInfoSize));
WmipFree(MRInfo);
}
MRInfo = WmipAlloc(MRInfoSize);
if (MRInfo != NULL)
{
memset(MRInfo, 0, MRInfoSize);
MRBuffer = (PWCHAR)OffsetToPtr(MRInfo, HeaderLen);
MRBufferRemaining = (MRInfoSize - HeaderLen) / sizeof(WCHAR);
MRCount = 0;
for (i = 0; i < MofListCount; i++)
{
//
// Pull out thee image path and resource names
//
MofEntry = &MofList->MofEntry[i];
RegPath = (PWCHAR)OffsetToPtr(MofList, MofEntry->RegPathOffset);
ResName = (PWCHAR)OffsetToPtr(MofList, MofEntry->ResourceOffset);
if (*ResName != 0)
{
if ((MofEntry->Flags & WMIMOFENTRY_FLAG_USERMODE) == 0)
{
ImagePath = WmipRegistryToImagePath(ImagePathStatic,
RegPath);
} else {
ImagePath = RegPath;
}
if (ImagePath != NULL)
{
//
// If we've got a valid image path then
// out it and the resource name into the
// output buffer
//
MRInfo[MRCount].ImagePath = MRBuffer;
b = WmipCopyMRString(MRBuffer,
MRBufferRemaining,
&BufferUsed,
ImagePath);
if (! b)
{
//
// The buffer was not big enough so we
// double the size used and try again
//
MRInfoSize *= 2;
goto TryAgain;
}
MRBuffer += BufferUsed;
MRBufferRemaining -= BufferUsed;
WmipDebugPrint(("WMI: Add ImagePath %p (%ws) to MRList at position %d\n",
MRInfo[MRCount].ImagePath,
MRInfo[MRCount].ImagePath,
MRCount));
MRInfo[MRCount].ResourceName = MRBuffer;
ResourcePtr = MRBuffer;
WmipCopyMRString(MRBuffer,
MRBufferRemaining,
&BufferUsed,
ResName);
if (! b)
{
//
// The buffer was not big enough so we
// double the size used and try again
//
MRInfoSize *= 2;
goto TryAgain;
}
MRBuffer += BufferUsed;
MRBufferRemaining -= BufferUsed;
WmipDebugPrint(("WMI: Add Resource %p (%ws) to MRList at position %d\n",
MRInfo[MRCount].ResourceName,
MRInfo[MRCount].ResourceName,
MRCount));
MRCount++;
for (j = 0; j < LanguageCount; j++)
{
MRInfo[MRCount].ImagePath = MRBuffer;
SubStatus = WmipBuildMUIPath(MRBuffer,
MRBufferRemaining,
&BufferUsed,
ImagePath,
LanguageList[j],
&b);
if (SubStatus == ERROR_SUCCESS)
{
if (! b)
{
//
// The buffer was not big enough so we
// double the size used and try again
//
MRInfoSize *= 2;
goto TryAgain;
}
MRBuffer += BufferUsed;
MRBufferRemaining -= BufferUsed;
WmipDebugPrint(("WMI: Add ImagePath %p (%ws) to MRList at position %d\n",
MRInfo[MRCount].ImagePath,
MRInfo[MRCount].ImagePath,
MRCount));
//
// We did find a MUI resource
// so add it to the list
//
MRInfo[MRCount].ResourceName = ResourcePtr;
WmipDebugPrint(("WMI: Add Resource %p (%ws) to MRList at position %d\n",
MRInfo[MRCount].ResourceName,
MRInfo[MRCount].ResourceName,
MRCount));
MRCount++;
}
}
}
}
}
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
} while (FALSE);
//
// Free up memory used to hold the language list
//
for (i = 0; i < LanguageCount; i++)
{
WmipFree(LanguageList[i]);
}
WmipFree(LanguageList);
*MofResourceCount = MRCount;
*MofResourceInfo = MRInfo;
}
WmipFree(MofList);
}
WmipFree(ImagePathStatic);
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
SetLastError(Status);
return(Status);
}
ULONG WmipBuildMofAddRemoveEvent(
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;
WmipAssert(WnodeSI->WnodeHeader.Flags & WNODE_FLAG_SINGLE_INSTANCE);
ImagePathStatic = WmipAlloc(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)
{
WmipFree(WnodeAD);
}
WnodeAD = WmipAlloc(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 = WmipRegistryToImagePath(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 ((! WmipCopyCountedString((PUCHAR)WnodeAD,
&Offset,
&BufferRemaining,
ImagePath)) ||
(! WmipCopyCountedString((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 = WmipBuildMUIPath(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 (! WmipCopyCountedString((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;
WmipMakeEventCallbacks((PWNODE_HEADER)WnodeAD,
Callback,
DeliveryContext,
IsAnsi);
WmipFree(WnodeAD);
Status = ERROR_SUCCESS;
}
WmipFree(ImagePathStatic);
} else {
Status = ERROR_NOT_ENOUGH_MEMORY;
}
return(Status);
}
void WmipProcessMofAddRemoveEvent(
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);
WmipAssert(*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)WmipAlloc(SizeNeeded);
if (MofList != NULL)
{
Status = WmipGetLanguageList(&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 = WmipBuildMofAddRemoveEvent(WnodeSI,
MofList,
LanguageList,
LanguageCount,
TRUE,
Callback,
DeliveryContext,
IsAnsi);
//
// Free up memory used to hold the language list
//
for (i = 0; i < LanguageCount; i++)
{
WmipFree(LanguageList[i]);
}
WmipFree(LanguageList);
}
WmipFree(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;
WmipMakeEventCallbacks((PWNODE_HEADER)WnodeSI,
Callback,
DeliveryContext,
IsAnsi);
}
}
void WmipProcessLanguageAddRemoveEvent(
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 = WmipGetMofResourceList(&MofList);
if (Status == ERROR_SUCCESS)
{
Language = (PWCHAR)OffsetToPtr(WnodeSI,
WnodeSI->DataBlockOffset + sizeof(USHORT));
Status = WmipBuildMofAddRemoveEvent(WnodeSI,
MofList,
&Language,
1,
FALSE,
Callback,
DeliveryContext,
IsAnsi);
}
}