402 lines
12 KiB
C++
402 lines
12 KiB
C++
|
/********************************************************************
|
||
|
|
||
|
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;
|
||
|
}
|