mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
2ff01e763e
Old style C functions `strcpy()`, `strcat()` and `sprintf()` are vulnerable to security issues due to lacking memory boundary checks. Replace these in the Connect storage engine with safe new and/or custom functions such as `snprintf()` `safe_strcpy()` and `safe_strcat()`. With this change FlawFinder and other static security analyzers report 287 fewer findings. All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services, Inc.
857 lines
27 KiB
C++
857 lines
27 KiB
C++
/***********************************************************************/
|
|
/* TABWMI: Author Olivier Bertrand -- PlugDB -- 2012 - 2017 */
|
|
/* TABWMI: Virtual table to get WMI information. */
|
|
/***********************************************************************/
|
|
#if !defined(_WIN32)
|
|
#error This is a WINDOWS only table type
|
|
#endif // !_WIN32
|
|
#include "my_global.h"
|
|
#include "m_string.h"
|
|
#include <stdio.h>
|
|
|
|
#include "global.h"
|
|
#include "plgdbsem.h"
|
|
#include "mycat.h"
|
|
//#include "reldef.h"
|
|
#include "xtable.h"
|
|
#include "tabext.h"
|
|
#include "colblk.h"
|
|
//#include "filter.h"
|
|
//#include "xindex.h"
|
|
#include "tabwmi.h"
|
|
#include "valblk.h"
|
|
#include "plgcnx.h" // For DB types
|
|
#include "resource.h"
|
|
|
|
/* ------------------- Functions WMI Column info --------------------- */
|
|
|
|
/***********************************************************************/
|
|
/* Initialize WMI operations. */
|
|
/***********************************************************************/
|
|
PWMIUT InitWMI(PGLOBAL g, PCSZ nsp, PCSZ classname)
|
|
{
|
|
IWbemLocator *loc;
|
|
char *p;
|
|
HRESULT res;
|
|
PWMIUT wp = (PWMIUT)PlugSubAlloc(g, NULL, sizeof(WMIUTIL));
|
|
|
|
if (trace(1))
|
|
htrc("WMIColumns class %s space %s\n", SVP(classname), SVP(nsp));
|
|
|
|
/*********************************************************************/
|
|
/* Set default values for the namespace and class name. */
|
|
/*********************************************************************/
|
|
if (!nsp)
|
|
nsp = "root\\cimv2";
|
|
|
|
if (!classname) {
|
|
if (!stricmp(nsp, "root\\cimv2"))
|
|
classname = "ComputerSystemProduct";
|
|
else if (!stricmp(nsp, "root\\cli"))
|
|
classname = "Msft_CliAlias";
|
|
else {
|
|
safe_strcpy(g->Message, sizeof(g->Message), "Missing class name");
|
|
return NULL;
|
|
} // endif classname
|
|
|
|
} // endif classname
|
|
|
|
/*********************************************************************/
|
|
/* Initialize WMI. */
|
|
/*********************************************************************/
|
|
//res = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
|
res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
|
|
|
if (FAILED(res)) {
|
|
snprintf(g->Message, sizeof(g->Message), "Failed to initialize COM library. "
|
|
"Error code = %x", res);
|
|
return NULL;
|
|
} // endif res
|
|
|
|
#if 0 // irrelevant for a DLL
|
|
res = CoInitializeSecurity(NULL, -1, NULL, NULL,
|
|
RPC_C_AUTHN_LEVEL_CONNECT,
|
|
RPC_C_IMP_LEVEL_IMPERSONATE,
|
|
NULL, EOAC_NONE, NULL);
|
|
|
|
if (res != RPC_E_TOO_LATE && FAILED(res)) {
|
|
snprintf(g->Message, sizeof(g->Message), "Failed to initialize security. "
|
|
"Error code = %p", res);
|
|
CoUninitialize();
|
|
return NULL;
|
|
} // endif Res
|
|
#endif // 0
|
|
|
|
res = CoCreateInstance(CLSID_WbemLocator, NULL,
|
|
CLSCTX_INPROC_SERVER, IID_IWbemLocator,
|
|
(void**) &loc);
|
|
if (FAILED(res)) {
|
|
snprintf(g->Message, sizeof(g->Message), "Failed to create Locator. "
|
|
"Error code = %x", res);
|
|
CoUninitialize();
|
|
return NULL;
|
|
} // endif res
|
|
|
|
res = loc->ConnectServer(_bstr_t(nsp),
|
|
NULL, NULL, NULL, 0, NULL, NULL, &wp->Svc);
|
|
|
|
if (FAILED(res)) {
|
|
snprintf(g->Message, sizeof(g->Message), "Could not connect. Error code = %x", res);
|
|
loc->Release();
|
|
CoUninitialize();
|
|
return NULL;
|
|
} // endif res
|
|
|
|
loc->Release();
|
|
|
|
if (trace(1))
|
|
htrc("Successfully connected to namespace.\n");
|
|
|
|
/*********************************************************************/
|
|
/* Perform a full class object retrieval. */
|
|
/*********************************************************************/
|
|
p = (char*)PlugSubAlloc(g, NULL, strlen(classname) + 7);
|
|
|
|
if (strchr(classname, '_'))
|
|
strcpy(p, classname);
|
|
else
|
|
strcat(strcpy(p, "Win32_"), classname);
|
|
|
|
res = wp->Svc->GetObject(bstr_t(p), 0, 0, &wp->Cobj, 0);
|
|
|
|
if (FAILED(res)) {
|
|
snprintf(g->Message, sizeof(g->Message), "failed GetObject %s in %s\n", classname, nsp);
|
|
wp->Svc->Release();
|
|
wp->Svc = NULL; // MUST be set to NULL (why?)
|
|
return NULL;
|
|
} // endif res
|
|
|
|
return wp;
|
|
} // end of InitWMI
|
|
|
|
/***********************************************************************/
|
|
/* WMIColumns: constructs the result blocks containing the description */
|
|
/* of all the columns of a WMI table of a specified class. */
|
|
/***********************************************************************/
|
|
PQRYRES WMIColumns(PGLOBAL g, PCSZ nsp, PCSZ cls, bool info)
|
|
{
|
|
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
|
|
TYPE_INT, TYPE_INT, TYPE_SHORT};
|
|
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME,
|
|
FLD_PREC, FLD_LENGTH, FLD_SCALE};
|
|
static unsigned int len, length[] = {0, 6, 8, 10, 10, 6};
|
|
int i = 0, n = 0, ncol = sizeof(buftyp) / sizeof(int);
|
|
int lng, typ, prec;
|
|
LONG low, upp;
|
|
BSTR propname;
|
|
VARIANT val;
|
|
CIMTYPE type;
|
|
HRESULT res;
|
|
PWMIUT wp;
|
|
SAFEARRAY *prnlist = NULL;
|
|
PQRYRES qrp = NULL;
|
|
PCOLRES crp;
|
|
|
|
if (!info) {
|
|
/*******************************************************************/
|
|
/* Initialize WMI if not done yet. */
|
|
/*******************************************************************/
|
|
if (!(wp = InitWMI(g, nsp, cls)))
|
|
return NULL;
|
|
|
|
/*******************************************************************/
|
|
/* Get the number of properties to return. */
|
|
/*******************************************************************/
|
|
res = wp->Cobj->Get(bstr_t("__Property_Count"), 0, &val, NULL, NULL);
|
|
|
|
if (FAILED(res)) {
|
|
snprintf(g->Message, sizeof(g->Message), "failed Get(__Property_Count) res=%d\n", res);
|
|
goto err;
|
|
} // endif res
|
|
|
|
if (!(n = val.lVal)) {
|
|
snprintf(g->Message, sizeof(g->Message), "Class %s in %s has no properties\n",
|
|
cls, nsp);
|
|
goto err;
|
|
} // endif res
|
|
|
|
/*******************************************************************/
|
|
/* Get max property name length. */
|
|
/*******************************************************************/
|
|
res = wp->Cobj->GetNames(NULL,
|
|
WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY,
|
|
NULL, &prnlist);
|
|
|
|
if (FAILED(res)) {
|
|
snprintf(g->Message, sizeof(g->Message), "failed GetNames res=%d\n", res);
|
|
goto err;
|
|
} // endif res
|
|
|
|
res = SafeArrayGetLBound(prnlist, 1, &low);
|
|
res = SafeArrayGetUBound(prnlist, 1, &upp);
|
|
|
|
for (long i = low; i <= upp; i++) {
|
|
// Get this property name.
|
|
res = SafeArrayGetElement(prnlist, &i, &propname);
|
|
|
|
if (FAILED(res)) {
|
|
snprintf(g->Message, sizeof(g->Message), "failed GetArrayElement res=%d\n", res);
|
|
goto err;
|
|
} // endif res
|
|
|
|
len = (unsigned)SysStringLen(propname);
|
|
length[0] = MY_MAX(length[0], len);
|
|
} // enfor i
|
|
|
|
res = SafeArrayDestroy(prnlist);
|
|
} else
|
|
length[0] = 128;
|
|
|
|
/*********************************************************************/
|
|
/* Allocate the structures used to refer to the result set. */
|
|
/*********************************************************************/
|
|
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
|
|
buftyp, fldtyp, length, false, true);
|
|
|
|
if (info || !qrp)
|
|
return qrp;
|
|
|
|
/*********************************************************************/
|
|
/* Now get the results into blocks. */
|
|
/*********************************************************************/
|
|
res = wp->Cobj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
|
|
|
|
if (FAILED(res)) {
|
|
snprintf(g->Message, sizeof(g->Message), "failed BeginEnumeration hr=%d\n", res);
|
|
qrp = NULL;
|
|
goto err;
|
|
} // endif hr
|
|
|
|
while (TRUE) {
|
|
res = wp->Cobj->Next(0, &propname, &val, &type, NULL);
|
|
|
|
if (FAILED(res)) {
|
|
snprintf(g->Message, sizeof(g->Message), "failed getting Next hr=%d\n", res);
|
|
qrp = NULL;
|
|
goto err;
|
|
} else if (res == WBEM_S_NO_MORE_DATA) {
|
|
VariantClear(&val);
|
|
break;
|
|
} // endif res
|
|
|
|
if (i >= n)
|
|
break; // Should never happen
|
|
else
|
|
prec = 0;
|
|
|
|
switch (type) {
|
|
case CIM_STRING:
|
|
typ = TYPE_STRING;
|
|
lng = 255;
|
|
prec = 1; // Case insensitive
|
|
break;
|
|
case CIM_SINT32:
|
|
case CIM_UINT32:
|
|
case CIM_BOOLEAN:
|
|
typ = TYPE_INT;
|
|
lng = 11;
|
|
break;
|
|
case CIM_SINT8:
|
|
case CIM_UINT8:
|
|
typ = TYPE_TINY;
|
|
lng = 4;
|
|
break;
|
|
case CIM_SINT16:
|
|
case CIM_UINT16:
|
|
typ = TYPE_SHORT;
|
|
lng = 6;
|
|
break;
|
|
case CIM_REAL64:
|
|
case CIM_REAL32:
|
|
prec = 2;
|
|
typ = TYPE_DOUBLE;
|
|
lng = 15;
|
|
break;
|
|
case CIM_SINT64:
|
|
case CIM_UINT64:
|
|
typ = TYPE_BIGINT;
|
|
lng = 20;
|
|
break;
|
|
case CIM_DATETIME:
|
|
typ = TYPE_DATE;
|
|
lng = 19;
|
|
break;
|
|
case CIM_CHAR16:
|
|
typ = TYPE_STRING;
|
|
lng = 16;
|
|
break;
|
|
case CIM_EMPTY:
|
|
typ = TYPE_STRING;
|
|
lng = 24; // ???
|
|
break;
|
|
default:
|
|
qrp->BadLines++;
|
|
goto suite;
|
|
} // endswitch type
|
|
|
|
crp = qrp->Colresp; // Column Name
|
|
crp->Kdata->SetValue(_com_util::ConvertBSTRToString(propname), i);
|
|
crp = crp->Next; // Data Type
|
|
crp->Kdata->SetValue(typ, i);
|
|
crp = crp->Next; // Type Name
|
|
crp->Kdata->SetValue(GetTypeName(typ), i);
|
|
crp = crp->Next; // Precision
|
|
crp->Kdata->SetValue(lng, i);
|
|
crp = crp->Next; // Length
|
|
crp->Kdata->SetValue(lng, i);
|
|
crp = crp->Next; // Scale (precision)
|
|
crp->Kdata->SetValue(prec, i);
|
|
i++;
|
|
|
|
suite:
|
|
SysFreeString(propname);
|
|
VariantClear(&val);
|
|
} // endfor i
|
|
|
|
qrp->Nblin = i;
|
|
|
|
err:
|
|
// Cleanup
|
|
wp->Cobj->Release();
|
|
wp->Svc->Release();
|
|
wp->Svc = NULL; // MUST be set to NULL (why?)
|
|
CoUninitialize();
|
|
|
|
/*********************************************************************/
|
|
/* Return the result pointer for use by GetData routines. */
|
|
/*********************************************************************/
|
|
return qrp;
|
|
} // end of WMIColumns
|
|
|
|
/* -------------- Implementation of the WMI classes ------------------ */
|
|
|
|
/***********************************************************************/
|
|
/* DefineAM: define specific AM values for WMI table. */
|
|
/***********************************************************************/
|
|
bool WMIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
|
{
|
|
Nspace = GetStringCatInfo(g, "Namespace", "Root\\CimV2");
|
|
Wclass = GetStringCatInfo(g, "Class",
|
|
(!stricmp(Nspace, "root\\cimv2") ? "ComputerSystemProduct" :
|
|
!stricmp(Nspace, "root\\cli") ? "Msft_CliAlias" : ""));
|
|
|
|
if (!*Wclass) {
|
|
snprintf(g->Message, sizeof(g->Message), "Missing class name for %s", Nspace);
|
|
return true;
|
|
} else if (!strchr(Wclass, '_')) {
|
|
char *p = (char*)PlugSubAlloc(g, NULL, strlen(Wclass) + 7);
|
|
Wclass = strcat(strcpy(p, "Win32_"), Wclass);
|
|
} // endif Wclass
|
|
|
|
if (Catfunc == FNC_NO)
|
|
Ems = GetIntCatInfo("Estimate", 100);
|
|
|
|
return false;
|
|
} // end of DefineAM
|
|
|
|
/***********************************************************************/
|
|
/* GetTable: makes a new TDB of the proper type. */
|
|
/***********************************************************************/
|
|
PTDB WMIDEF::GetTable(PGLOBAL g, MODE m)
|
|
{
|
|
if (Catfunc == FNC_NO)
|
|
return new(g) TDBWMI(this);
|
|
else if (Catfunc == FNC_COL)
|
|
return new(g) TDBWCL(this);
|
|
|
|
snprintf(g->Message, sizeof(g->Message), "Bad catfunc %ud for WMI", Catfunc);
|
|
return NULL;
|
|
} // end of GetTable
|
|
|
|
/* ------------------------------------------------------------------- */
|
|
|
|
/***********************************************************************/
|
|
/* Implementation of the TDBWMI class. */
|
|
/***********************************************************************/
|
|
TDBWMI::TDBWMI(PWMIDEF tdp) : TDBASE(tdp)
|
|
{
|
|
Svc = NULL;
|
|
Enumerator = NULL;
|
|
ClsObj = NULL;
|
|
Nspace = tdp->Nspace;
|
|
Wclass = tdp->Wclass;
|
|
ObjPath = NULL;
|
|
Kvp = NULL;
|
|
Ems = tdp->Ems;
|
|
Kcol = NULL;
|
|
Vbp = NULL;
|
|
Init = false;
|
|
Done = false;
|
|
Res = 0;
|
|
Rc = 0;
|
|
N = -1;
|
|
} // end of TDBWMI constructor
|
|
|
|
/***********************************************************************/
|
|
/* Allocate WMI column description block. */
|
|
/***********************************************************************/
|
|
PCOL TDBWMI::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
|
|
{
|
|
PCOL colp;
|
|
|
|
colp = new(g) WMICOL(cdp, this, n);
|
|
|
|
if (cprec) {
|
|
colp->SetNext(cprec->GetNext());
|
|
cprec->SetNext(colp);
|
|
} else {
|
|
colp->SetNext(Columns);
|
|
Columns = colp;
|
|
} // endif cprec
|
|
|
|
return colp;
|
|
} // end of MakeCol
|
|
|
|
/***********************************************************************/
|
|
/* Initialize: Initialize WMI operations. */
|
|
/***********************************************************************/
|
|
bool TDBWMI::Initialize(PGLOBAL g)
|
|
{
|
|
if (Init)
|
|
return false;
|
|
|
|
// Initialize COM.
|
|
Res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
|
|
|
if (FAILED(Res)) {
|
|
snprintf(g->Message, sizeof(g->Message), "Failed to initialize COM library. "
|
|
"Error code = %x", Res);
|
|
return true; // Program has failed.
|
|
} // endif Res
|
|
|
|
// Obtain the initial locator to Windows Management
|
|
// on a particular host computer.
|
|
IWbemLocator *loc; // Initial Windows Management locator
|
|
|
|
Res = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
|
|
IID_IWbemLocator, (LPVOID*) &loc);
|
|
|
|
if (FAILED(Res)) {
|
|
snprintf(g->Message, sizeof(g->Message), "Failed to create Locator. "
|
|
"Error code = %x", Res);
|
|
CoUninitialize();
|
|
return true; // Program has failed.
|
|
} // endif Res
|
|
|
|
// Connect to the specified namespace with the
|
|
// current user and obtain pointer to Svc
|
|
// to make IWbemServices calls.
|
|
Res = loc->ConnectServer(_bstr_t(Nspace),
|
|
NULL, NULL,0, NULL, 0, 0, &Svc);
|
|
|
|
if (FAILED(Res)) {
|
|
snprintf(g->Message, sizeof(g->Message), "Could not connect. Error code = %x", Res);
|
|
loc->Release();
|
|
CoUninitialize();
|
|
return true; // Program has failed.
|
|
} // endif hres
|
|
|
|
loc->Release(); // Not used anymore
|
|
|
|
// Set the IWbemServices proxy so that impersonation
|
|
// of the user (client) occurs.
|
|
Res = CoSetProxyBlanket(Svc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE,
|
|
NULL, RPC_C_AUTHN_LEVEL_CALL,
|
|
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
|
|
|
|
if (FAILED(Res)) {
|
|
snprintf(g->Message, sizeof(g->Message), "Could not set proxy. Error code = %x", Res);
|
|
Svc->Release();
|
|
CoUninitialize();
|
|
return true; // Program has failed.
|
|
} // endif Res
|
|
|
|
Init = true;
|
|
return false;
|
|
} // end of Initialize
|
|
|
|
/***********************************************************************/
|
|
/* Changes '\' into '\\' in the filter. */
|
|
/***********************************************************************/
|
|
void TDBWMI::DoubleSlash(PGLOBAL g)
|
|
{
|
|
if (To_CondFil && strchr(To_CondFil->Body, '\\')) {
|
|
char *body = To_CondFil->Body;
|
|
char *buf = (char*)PlugSubAlloc(g, NULL, strlen(body) * 2);
|
|
int i = 0, k = 0;
|
|
|
|
do {
|
|
if (body[i] == '\\')
|
|
buf[k++] = '\\';
|
|
|
|
buf[k++] = body[i];
|
|
} while (body[i++]);
|
|
|
|
To_CondFil->Body = buf;
|
|
} // endif To_CondFil
|
|
|
|
} // end of DoubleSlash
|
|
|
|
/***********************************************************************/
|
|
/* MakeWQL: make the WQL statement use with WMI ExecQuery. */
|
|
/***********************************************************************/
|
|
char *TDBWMI::MakeWQL(PGLOBAL g)
|
|
{
|
|
char *colist, *wql/*, *pw = NULL*/;
|
|
int len, ncol = 0;
|
|
bool first = true, noloc = false;
|
|
PCOL colp;
|
|
|
|
// Normal WQL statement to retrieve results
|
|
for (colp = Columns; colp; colp = colp->GetNext())
|
|
if (!colp->IsSpecial() && (colp->GetColUse(U_P | U_J_EXT) || noloc))
|
|
ncol++;
|
|
|
|
if (ncol) {
|
|
size_t colist_sz = (NAM_LEN + 4) * ncol;
|
|
colist = (char*)PlugSubAlloc(g, NULL, colist_sz);
|
|
|
|
for (colp = Columns; colp; colp = colp->GetNext())
|
|
if (!colp->IsSpecial()) {
|
|
if (colp->GetResultType() == TYPE_DATE)
|
|
((DTVAL*)colp->GetValue())->SetFormat(g, "YYYYMMDDhhmmss", 19);
|
|
|
|
if (colp->GetColUse(U_P | U_J_EXT) || noloc) {
|
|
if (first) {
|
|
snprintf(colist, colist_sz, colp->GetName());
|
|
first = false;
|
|
} else {
|
|
strcat(strcat(colist, ", "), colp->GetName());
|
|
safe_strcat(colist, colist_sz, ", ");
|
|
safe_strcat(colist, colist_sz, colp->GetName());
|
|
}
|
|
|
|
} // endif ColUse
|
|
|
|
} // endif Special
|
|
|
|
} else {
|
|
// ncol == 0 can occur for queries such that sql count(*) from...
|
|
// for which we will count the rows from sql * from...
|
|
colist = (char*)PlugSubAlloc(g, NULL, 2);
|
|
snprintf(colist, 2, "*");
|
|
} // endif ncol
|
|
|
|
// Below 14 is length of 'select ' + length of ' from ' + 1
|
|
len = (strlen(colist) + strlen(Wclass) + 14);
|
|
len += (To_CondFil ? strlen(To_CondFil->Body) + 7 : 0);
|
|
wql = (char*)PlugSubAlloc(g, NULL, len);
|
|
snprintf(wql, len, "SELECT %s FROM %s", colist, Wclass);
|
|
|
|
if (To_CondFil) {
|
|
safe_strcat(wql, len, " WHERE ");
|
|
safe_strcat(wql, len, To_CondFil->Body);
|
|
}
|
|
|
|
return wql;
|
|
} // end of MakeWQL
|
|
|
|
/***********************************************************************/
|
|
/* GetWMIInfo: Get info for the WMI class. */
|
|
/***********************************************************************/
|
|
bool TDBWMI::GetWMIInfo(PGLOBAL g)
|
|
{
|
|
if (Done)
|
|
return false;
|
|
|
|
char *cmd = MakeWQL(g);
|
|
|
|
if (cmd == NULL) {
|
|
snprintf(g->Message, sizeof(g->Message), "Error making WQL statement");
|
|
Svc->Release();
|
|
CoUninitialize();
|
|
return true; // Program has failed.
|
|
} // endif cmd
|
|
|
|
// Query for Wclass in Nspace
|
|
Rc = Svc->ExecQuery(bstr_t("WQL"), bstr_t(cmd),
|
|
// WBEM_FLAG_BIDIRECTIONAL | WBEM_FLAG_RETURN_IMMEDIATELY,
|
|
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
|
|
NULL, &Enumerator);
|
|
|
|
if (FAILED(Rc)) {
|
|
snprintf(g->Message, sizeof(g->Message), "Query %s failed. Error code = %x", cmd, Rc);
|
|
Svc->Release();
|
|
CoUninitialize();
|
|
return true; // Program has failed.
|
|
} // endif Rc
|
|
|
|
Done = true;
|
|
return false;
|
|
} // end of GetWMIInfo
|
|
|
|
/***********************************************************************/
|
|
/* WMI: Get the number returned instances. */
|
|
/***********************************************************************/
|
|
int TDBWMI::GetMaxSize(PGLOBAL g)
|
|
{
|
|
if (MaxSize < 0) {
|
|
/*******************************************************************/
|
|
/* Loop enumerating to get the count. This is prone to last a */
|
|
/* very long time for some classes such as DataFile, this is why */
|
|
/* we just return an estimated value that will be ajusted later. */
|
|
/*******************************************************************/
|
|
MaxSize = Ems;
|
|
#if 0
|
|
if (Initialize(g))
|
|
return -1;
|
|
else if (GetWMIInfo(g))
|
|
return -1;
|
|
else
|
|
MaxSize = 0;
|
|
|
|
PDBUSER dup = PlgGetUser(g);
|
|
|
|
while (Enumerator) {
|
|
Res = Enumerator->Next(WBEM_INFINITE, 1, &ClsObj, &Rc);
|
|
|
|
if (Rc == 0)
|
|
break;
|
|
|
|
MaxSize++;
|
|
} // endwile Enumerator
|
|
|
|
Res = Enumerator->Reset();
|
|
#endif // 0
|
|
} // endif MaxSize
|
|
|
|
return MaxSize;
|
|
} // end of GetMaxSize
|
|
|
|
/***********************************************************************/
|
|
/* When making a Kindex, must provide the Key column info. */
|
|
/***********************************************************************/
|
|
int TDBWMI::GetRecpos(void)
|
|
{
|
|
if (!Kcol || !Vbp)
|
|
return N;
|
|
|
|
Kcol->Reset();
|
|
Kcol->Eval(NULL);
|
|
Vbp->SetValue(Kcol->GetValue(), N);
|
|
return N;
|
|
} // end of GetRecpos
|
|
|
|
/***********************************************************************/
|
|
/* WMI Access Method opening routine. */
|
|
/***********************************************************************/
|
|
bool TDBWMI::OpenDB(PGLOBAL g)
|
|
{
|
|
if (Use == USE_OPEN) {
|
|
/*******************************************************************/
|
|
/* Table already open. */
|
|
/*******************************************************************/
|
|
Res = Enumerator->Reset();
|
|
N = 0;
|
|
return false;
|
|
} // endif use
|
|
|
|
if (Mode != MODE_READ) {
|
|
/*******************************************************************/
|
|
/* WMI tables cannot be modified. */
|
|
/*******************************************************************/
|
|
safe_strcpy(g->Message, sizeof(g->Message), "WMI tables are read only");
|
|
return true;
|
|
} // endif Mode
|
|
|
|
if (!To_CondFil && !stricmp(Wclass, "CIM_Datafile")
|
|
&& !stricmp(Nspace, "root\\cimv2")) {
|
|
safe_strcpy(g->Message, sizeof(g->Message),
|
|
"Would last forever when not filtered, use DIR table instead");
|
|
return true;
|
|
} else
|
|
DoubleSlash(g);
|
|
|
|
Use = USE_OPEN; // Do it now in case we are recursively called
|
|
|
|
/*********************************************************************/
|
|
/* Initialize the WMI processing. */
|
|
/*********************************************************************/
|
|
if (Initialize(g))
|
|
return true;
|
|
else
|
|
return GetWMIInfo(g);
|
|
|
|
} // end of OpenDB
|
|
|
|
/***********************************************************************/
|
|
/* Data Base read routine for WMI access method. */
|
|
/***********************************************************************/
|
|
int TDBWMI::ReadDB(PGLOBAL g)
|
|
{
|
|
Res = Enumerator->Next(WBEM_INFINITE, 1, &ClsObj, &Rc);
|
|
|
|
if (Rc == 0)
|
|
return RC_EF;
|
|
|
|
N++;
|
|
return RC_OK;
|
|
} // end of ReadDB
|
|
|
|
/***********************************************************************/
|
|
/* WriteDB: Data Base write routine for WMI access methods. */
|
|
/***********************************************************************/
|
|
int TDBWMI::WriteDB(PGLOBAL g)
|
|
{
|
|
safe_strcpy(g->Message, sizeof(g->Message), "WMI tables are read only");
|
|
return RC_FX;
|
|
} // end of WriteDB
|
|
|
|
/***********************************************************************/
|
|
/* Data Base delete line routine for WMI access methods. */
|
|
/***********************************************************************/
|
|
int TDBWMI::DeleteDB(PGLOBAL g, int irc)
|
|
{
|
|
safe_strcpy(g->Message, sizeof(g->Message), "Delete not enabled for WMI tables");
|
|
return RC_FX;
|
|
} // end of DeleteDB
|
|
|
|
/***********************************************************************/
|
|
/* Data Base close routine for WMI access method. */
|
|
/***********************************************************************/
|
|
void TDBWMI::CloseDB(PGLOBAL g)
|
|
{
|
|
// Cleanup
|
|
if (ClsObj)
|
|
ClsObj->Release();
|
|
|
|
if (Enumerator)
|
|
Enumerator->Release();
|
|
|
|
if (Svc)
|
|
Svc->Release();
|
|
|
|
CoUninitialize();
|
|
} // end of CloseDB
|
|
|
|
// ------------------------ WMICOL functions ----------------------------
|
|
|
|
/***********************************************************************/
|
|
/* WMICOL public constructor. */
|
|
/***********************************************************************/
|
|
WMICOL::WMICOL(PCOLDEF cdp, PTDB tdbp, int n)
|
|
: COLBLK(cdp, tdbp, n)
|
|
{
|
|
Tdbp = (PTDBWMI)tdbp;
|
|
VariantInit(&Prop);
|
|
Ctype = CIM_ILLEGAL;
|
|
Res = 0;
|
|
} // end of WMICOL constructor
|
|
|
|
#if 0
|
|
/***********************************************************************/
|
|
/* WMICOL constructor used for copying columns. */
|
|
/* tdbp is the pointer to the new table descriptor. */
|
|
/***********************************************************************/
|
|
WMICOL::WMICOL(WMICOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
|
|
{
|
|
} // end of WMICOL copy constructor
|
|
#endif // 0
|
|
|
|
/***********************************************************************/
|
|
/* Read the next WMI address elements. */
|
|
/***********************************************************************/
|
|
void WMICOL::ReadColumn(PGLOBAL g)
|
|
{
|
|
// Get the value of the Name property
|
|
Res = Tdbp->ClsObj->Get(_bstr_t(Name), 0, &Prop, &Ctype, 0);
|
|
|
|
switch (Prop.vt) {
|
|
case VT_EMPTY:
|
|
case VT_NULL:
|
|
case VT_VOID:
|
|
Value->Reset();
|
|
break;
|
|
case VT_BSTR:
|
|
Value->SetValue_psz(_com_util::ConvertBSTRToString(Prop.bstrVal));
|
|
break;
|
|
case VT_I4:
|
|
case VT_UI4:
|
|
Value->SetValue((long long)Prop.lVal);
|
|
break;
|
|
case VT_I2:
|
|
case VT_UI2:
|
|
Value->SetValue(Prop.iVal);
|
|
break;
|
|
case VT_INT:
|
|
case VT_UINT:
|
|
Value->SetValue((int)Prop.intVal);
|
|
break;
|
|
case VT_BOOL:
|
|
Value->SetValue(((int)Prop.boolVal) ? 1 : 0);
|
|
break;
|
|
case VT_R8:
|
|
Value->SetValue(Prop.dblVal);
|
|
break;
|
|
case VT_R4:
|
|
Value->SetValue((double)Prop.fltVal);
|
|
break;
|
|
case VT_DATE:
|
|
switch (Value->GetType()) {
|
|
case TYPE_DATE:
|
|
{SYSTEMTIME stm;
|
|
struct tm ptm;
|
|
int rc = VariantTimeToSystemTime(Prop.date, &stm);
|
|
|
|
ptm.tm_year = stm.wYear;
|
|
ptm.tm_mon = stm.wMonth;
|
|
ptm.tm_mday = stm.wDay;
|
|
ptm.tm_hour = stm.wHour;
|
|
ptm.tm_min = stm.wMinute;
|
|
ptm.tm_sec = stm.wSecond;
|
|
((DTVAL*)Value)->MakeTime(&ptm);
|
|
}break;
|
|
case TYPE_STRING:
|
|
{SYSTEMTIME stm;
|
|
char buf[24];
|
|
int rc = VariantTimeToSystemTime(Prop.date, &stm);
|
|
|
|
snprintf(buf, sizeof(buf), "%02d/%02d/%d %02d:%02d:%02d",
|
|
stm.wDay, stm.wMonth, stm.wYear,
|
|
stm.wHour, stm.wMinute, stm.wSecond);
|
|
Value->SetValue_psz(buf);
|
|
}break;
|
|
default:
|
|
Value->SetValue((double)Prop.fltVal);
|
|
} // endswitch Type
|
|
|
|
break;
|
|
default:
|
|
// This will reset numeric column value
|
|
Value->SetValue_psz("Type not supported");
|
|
break;
|
|
} // endswitch vt
|
|
|
|
VariantClear(&Prop);
|
|
} // end of ReadColumn
|
|
|
|
/* ---------------------------TDBWCL class --------------------------- */
|
|
|
|
/***********************************************************************/
|
|
/* TDBWCL class constructor. */
|
|
/***********************************************************************/
|
|
TDBWCL::TDBWCL(PWMIDEF tdp) : TDBCAT(tdp)
|
|
{
|
|
Nsp = tdp->Nspace;
|
|
Cls = tdp->Wclass;
|
|
} // end of TDBWCL constructor
|
|
|
|
/***********************************************************************/
|
|
/* GetResult: Get the list of the WMI class properties. */
|
|
/***********************************************************************/
|
|
PQRYRES TDBWCL::GetResult(PGLOBAL g)
|
|
{
|
|
return WMIColumns(g, Nsp, Cls, false);
|
|
} // end of GetResult
|
|
|
|
|