1509 lines
50 KiB
C
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);
|
||
|
}
|
||
|
|
||
|
}
|