windows-nt/Source/XPSP1/NT/admin/pchealth/client/datacoll/wmiprov/util.cpp

402 lines
12 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/********************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name:
util.CPP
Abstract:
File containing utility classes
Revision History:
Ghim-Sim Chua (gschua) 04/27/99
- Created
Jim Martin (a-jammar) 04/30/99
- Changed to use global IWbemServices pointer, and added
GetWbemServices, CopyProperty, and GetCIMDataFile
Ghim-Sim Chua (gschua) 05/01/99
- Modified GetWbemServices, GetCIMDataFile
Kalyani Narlanka (kalyanin) 05/11/99
- Added the function GetCompletePath
********************************************************************/
#include "pchealth.h"
#define TRACE_ID DCID_UTIL
//-----------------------------------------------------------------------------
// Returns an IWbemServices pointer. The caller is responsible for releasing
// the object.
//-----------------------------------------------------------------------------
HRESULT GetWbemServices(IWbemServices **ppServices)
{
TraceFunctEnter("::GetWbemServices");
HRESULT hRes = S_OK;
CComPtr<IWbemLocator> pWbemLocator;
// If global variable already initialized, use it
if (g_pWbemServices)
{
*ppServices = g_pWbemServices;
(*ppServices)->AddRef();
goto End;
}
// First we have the get the IWbemLocator object with a CoCreateInstance.
hRes = CoCreateInstance(CLSID_WbemAdministrativeLocator, NULL,
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
IID_IUnknown, (void **)&pWbemLocator);
if (FAILED(hRes))
{
ErrorTrace(TRACE_ID, "CoCreateInstance failed to create IWbemAdministrativeLocator.");
goto End;
}
// Then we connect to the WMI server for the local CIMV2 namespace.
hRes = pWbemLocator->ConnectServer(CComBSTR(CIM_NAMESPACE), NULL, NULL, NULL, 0, NULL, NULL, ppServices);
if (FAILED(hRes))
{
ErrorTrace(TRACE_ID, "ConnectServer failed to connect to cimv2 namespace.");
goto End;
}
// Store it in the global variable
g_pWbemServices = *ppServices;
(*ppServices)->AddRef(); // CODEWORK: check out why this stops fault on NET STOP WINMGMT
End :
TraceFunctLeave();
return hRes;
}
//-----------------------------------------------------------------------------
// Executes the WQL query and returns the enumerated list
//-----------------------------------------------------------------------------
HRESULT ExecWQLQuery(IEnumWbemClassObject **ppEnumInst, BSTR bstrQuery)
{
TraceFunctEnter("::ExecWQLQuery");
HRESULT hRes;
CComPtr<IWbemServices> pWbemServices;
// Get pointer to WbemServices
hRes = GetWbemServices(&pWbemServices);
if (FAILED(hRes))
goto End;
// execute the query
hRes = pWbemServices->ExecQuery(
CComBSTR("WQL"),
bstrQuery,
WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
NULL,
ppEnumInst);
if (FAILED(hRes))
{
ErrorTrace(TRACE_ID, "ExecQuery failed.");
goto End;
}
End:
TraceFunctLeave();
return hRes;
}
//-----------------------------------------------------------------------------
// Copies the property named szFrom from pFrom to the property named szTo in
// to CInstance object pTo.
//-----------------------------------------------------------------------------
HRESULT CopyProperty(IWbemClassObject *pFrom, LPCWSTR szFrom, CInstance *pTo, LPCWSTR szTo)
{
TraceFunctEnter("::CopyProperty");
_ASSERT(pFrom && szFrom && pTo && szTo);
HRESULT hRes = S_OK;
CComVariant varValue;
CComBSTR bstrFrom(szFrom);
// First, get the property (as a variant) from the source class object.
hRes = pFrom->Get(bstrFrom, 0, &varValue, NULL, NULL);
if (FAILED(hRes))
ErrorTrace(TRACE_ID, "GetVariant on %s field failed.", szFrom);
else
{
// Then set the variant for the target CInstance object.
if (!pTo->SetVariant(szTo, varValue))
{
ErrorTrace(TRACE_ID, "SetVariant on %s field failed.", szTo);
hRes = WBEM_E_FAILED;
}
}
TraceFunctLeave();
return hRes;
}
//-----------------------------------------------------------------------------
// Returns an IWbemClassObject pointer for the CIM_DataFile object represented
// by the bstrFile parameter. The bstrFile parameter should contain the full
// path to the file. If the pServices parameter is non-null, it is used to
// retrieve the file info, otherwise a new (and temporary) services pointer is
// created.
//-----------------------------------------------------------------------------
HRESULT GetCIMDataFile(BSTR bstrFile, IWbemClassObject ** ppFileObject, BOOL fHasDoubleSlashes)
{
TraceFunctEnter("::GetCIMDataFile");
HRESULT hRes = S_OK;
CComBSTR bstrObjectPath("\\\\.\\root\\cimv2:CIM_DataFile.Name=\"");
wchar_t * pwch;
UINT uLen;
CComPtr<IWbemServices> pWbemServices;
hRes = GetWbemServices(&pWbemServices);
if (FAILED(hRes))
goto END;
if (bstrFile == NULL || ppFileObject == NULL)
{
ErrorTrace(TRACE_ID, "Parameter pointer is null.");
hRes = WBEM_E_INVALID_PARAMETER;
goto END;
}
// Construct the path for the file we are trying to get. Note, the path needs
// the have double backslashes for the GetObject call to work. We scan through
// the string and do this manually here.
//
// CODEWORK: there has to be a faster way to do this, although the Append is
// probably not too expensive, since the BSTR length can be found without
// scanning the string. Unless it's reallocating more memory as it goes.
pwch = bstrFile;
if (fHasDoubleSlashes)
bstrObjectPath.Append(pwch, SysStringLen(bstrFile));
else
for (uLen = SysStringLen(bstrFile); uLen > 0; uLen--)
{
if (*pwch == L'\\')
bstrObjectPath.Append("\\");
bstrObjectPath.Append(pwch, 1);
pwch++;
}
bstrObjectPath.Append("\"");
// Make the call to get the CIM_DataFile object.
hRes = pWbemServices->GetObject(bstrObjectPath, 0, NULL, ppFileObject, NULL);
if (FAILED(hRes))
ErrorTrace(TRACE_ID, "GetObject on CIM_DataFile failed.");
END:
TraceFunctLeave();
return hRes;
}
//*****************************************************************************
//
// Function Name : getCompletePath
//
// Input Parameters : bstrFileName
// CComBSTR which represents the file
// whose complete path is required.
// Output Parameters : bstrFileWithPathName
// CComBSTR which represents the file
// with the Path
// Returns : BOOL
// TRUE if bstrFileWithPathName can be set.
// FALSE if bstrFileWithPathName cannot be set.
//
//
// Synopsis : Given a file name (bstrFileName) this function
// searches the "System" directory for the existence
// of the file.
//
// If it finds the file it pre appends the directory
// path to the input file and copies into the output
// file (bstrFileWithPathName).
//
// If it doesnot find the file in "System" directory
// searches for the file in "Windows" Directoy and does
// the same as above.
//
//*****************************************************************************
BOOL getCompletePath(CComBSTR bstrFileName, CComBSTR &bstrFileWithPathName)
{
// Return
BOOL bFoundFile = FALSE;
ULONG uiReturn;
TCHAR szDirectory[MAX_PATH];
TCHAR temp[MAX_PATH];
TCHAR lpstrTemp[MAX_PATH];
struct _stat filestat;
CComVariant varValue = NULL;
CComBSTR bstrDirectory;
// Check for the File in the System Directory
uiReturn = GetSystemDirectory(szDirectory, MAX_PATH);
if (uiReturn != 0 && uiReturn < MAX_PATH)
{
bstrDirectory = szDirectory;
bstrDirectory.Append("\\");
bstrDirectory.Append(bstrFileName);
USES_CONVERSION;
int Result = _tstat(W2T(bstrDirectory), &filestat) ;
if (Result == 0)
{
bstrFileWithPathName = bstrDirectory;
bFoundFile = TRUE;
}
}
// If not there, then check in the windows directory.
if (!bFoundFile)
{
uiReturn = GetWindowsDirectory(szDirectory, MAX_PATH);
if (uiReturn != 0 && uiReturn < MAX_PATH)
{
bstrDirectory = szDirectory;
bstrDirectory.Append("\\");
bstrDirectory.Append(bstrFileName);
USES_CONVERSION;
int Result = _tstat(W2T(bstrDirectory), &filestat) ;
if (Result == 0)
{
bstrFileWithPathName = bstrDirectory;
bFoundFile = TRUE;
}
}
}
return(bFoundFile);
}
// Used by GetCim32NetDll and FreeCim32NetDll.
CCritSec g_csCim32Net;
HINSTANCE s_Handle = NULL;
// There is a problem with loading Cim32Net.dll over and over, so this code
// makes sure we only load it once, then unloads it at exit.
// these are used with GetCim32NetHandle
void FreeCim32NetHandle()
{
if (s_Handle)
{
FreeLibrary(s_Handle);
s_Handle = NULL;
}
}
HINSTANCE GetCim32NetHandle()
{
// Have we ever loaded it before?
if (s_Handle == NULL)
{
// Avoid contention on static
g_csCim32Net.Enter();
// Check for race condition
if (s_Handle == NULL)
{
s_Handle = LoadLibrary(_T("Cim32Net.dll"));
// Register to free the handle at exit
// NO! bad....badddd juju... call from FlushAll instead (o.w., when
// cimwin32.dll unloads this pointer is invalid, but atexit gets
// called when framedyn.dll unloads)
// atexit(FreeCim32NetHandle);
}
g_csCim32Net.Leave();
}
// By re-opening the handle, we ensure proper refcounting on the handle,
// and facilitate leak checking.
HINSTANCE hHandle = LoadLibrary(_T("Cim32Net.dll"));
return hHandle;
}
//
// Given a delimited string, convert tokens into strings and store them into an array
// returns the number of tokens parsed. Caller is responsible for freeing up the memory
// allocated using delete
//
#ifndef UNICODE
int DelimitedStringToArray(LPWSTR strString, LPTSTR strDelimiter, LPTSTR apstrArray[], int iMaxArraySize)
{
USES_CONVERSION;
LPTSTR szString = W2A(strString);
return DelimitedStringToArray(szString, strDelimiter, apstrArray, iMaxArraySize);
}
#endif
int DelimitedStringToArray(LPTSTR strString, LPTSTR strDelimiter, LPTSTR apstrArray[], int iMaxArraySize)
{
// make a copy of the string to begin parsing
LPTSTR strDelimitedString = (TCHAR *) new TCHAR [_tcslen(strString) + 1];
// if out of memory, just return error value -1
if (!strDelimitedString)
return -1;
// copy the token into the new allocated string
_tcscpy(strDelimitedString, strString);
// initialize _tcstok
LPTSTR strTok = _tcstok(strDelimitedString, strDelimiter);
int iCount = 0;
// loop through all tokens parsed
while ((strTok) && (iCount < iMaxArraySize))
{
LPTSTR strNewTok = (TCHAR *) new TCHAR[_tcslen(strTok) + 1];
// if out of memory, just return error value -1
if (!strNewTok)
return -1;
// copy the token into the new allocated string
_tcscpy(strNewTok, strTok);
// save it in the array
apstrArray[iCount] = strNewTok;
// increment the index
iCount++;
// get the next token
strTok = _tcstok(NULL, strDelimiter);
}
// free up the memory used
delete [] strDelimitedString;
return iCount;
}