2013-02-07 10:34:27 +01:00
|
|
|
/***********************************************************************/
|
2017-02-16 18:01:48 +01:00
|
|
|
/* TABWMI: Author Olivier Bertrand -- PlugDB -- 2012 - 2017 */
|
2013-02-07 10:34:27 +01:00
|
|
|
/* TABWMI: Virtual table to get WMI information. */
|
|
|
|
/***********************************************************************/
|
2021-06-08 17:44:43 +02:00
|
|
|
#if !defined(_WIN32)
|
2015-05-27 16:23:38 +02:00
|
|
|
#error This is a WINDOWS only table type
|
2021-06-08 17:44:43 +02:00
|
|
|
#endif // !_WIN32
|
2013-02-07 10:34:27 +01:00
|
|
|
#include "my_global.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "global.h"
|
|
|
|
#include "plgdbsem.h"
|
2013-02-12 12:34:14 +01:00
|
|
|
#include "mycat.h"
|
2017-02-16 18:01:48 +01:00
|
|
|
//#include "reldef.h"
|
2013-02-07 10:34:27 +01:00
|
|
|
#include "xtable.h"
|
2017-02-16 18:01:48 +01:00
|
|
|
#include "tabext.h"
|
2013-02-07 10:34:27 +01:00
|
|
|
#include "colblk.h"
|
2014-03-10 18:29:04 +01:00
|
|
|
//#include "filter.h"
|
2013-02-07 10:34:27 +01:00
|
|
|
//#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. */
|
|
|
|
/***********************************************************************/
|
2017-05-23 19:35:50 +02:00
|
|
|
PWMIUT InitWMI(PGLOBAL g, PCSZ nsp, PCSZ classname)
|
2013-02-07 10:34:27 +01:00
|
|
|
{
|
|
|
|
IWbemLocator *loc;
|
|
|
|
char *p;
|
|
|
|
HRESULT res;
|
|
|
|
PWMIUT wp = (PWMIUT)PlugSubAlloc(g, NULL, sizeof(WMIUTIL));
|
|
|
|
|
2018-01-30 15:43:20 +01:00
|
|
|
if (trace(1))
|
2013-02-07 10:34:27 +01:00
|
|
|
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 {
|
|
|
|
strcpy(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)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "Failed to initialize COM library. "
|
2017-03-02 12:12:53 +01:00
|
|
|
"Error code = %x", res);
|
2013-02-07 10:34:27 +01:00
|
|
|
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)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "Failed to initialize security. "
|
2013-02-07 10:34:27 +01:00
|
|
|
"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)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "Failed to create Locator. "
|
2017-03-02 12:12:53 +01:00
|
|
|
"Error code = %x", res);
|
2013-02-07 10:34:27 +01:00
|
|
|
CoUninitialize();
|
|
|
|
return NULL;
|
|
|
|
} // endif res
|
|
|
|
|
|
|
|
res = loc->ConnectServer(_bstr_t(nsp),
|
|
|
|
NULL, NULL, NULL, 0, NULL, NULL, &wp->Svc);
|
|
|
|
|
|
|
|
if (FAILED(res)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "Could not connect. Error code = %x", res);
|
2013-02-07 10:34:27 +01:00
|
|
|
loc->Release();
|
|
|
|
CoUninitialize();
|
|
|
|
return NULL;
|
|
|
|
} // endif res
|
|
|
|
|
|
|
|
loc->Release();
|
|
|
|
|
2018-01-30 15:43:20 +01:00
|
|
|
if (trace(1))
|
2013-02-07 10:34:27 +01:00
|
|
|
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)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "failed GetObject %s in %s\n", classname, nsp);
|
2013-02-07 10:34:27 +01:00
|
|
|
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. */
|
|
|
|
/***********************************************************************/
|
2017-05-23 19:35:50 +02:00
|
|
|
PQRYRES WMIColumns(PGLOBAL g, PCSZ nsp, PCSZ cls, bool info)
|
2013-02-07 10:34:27 +01:00
|
|
|
{
|
2013-02-11 00:31:03 +01:00
|
|
|
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};
|
2013-02-07 10:34:27 +01:00
|
|
|
static unsigned int len, length[] = {0, 6, 8, 10, 10, 6};
|
2013-05-10 20:22:21 +02:00
|
|
|
int i = 0, n = 0, ncol = sizeof(buftyp) / sizeof(int);
|
2013-02-07 10:34:27 +01:00
|
|
|
int lng, typ, prec;
|
|
|
|
LONG low, upp;
|
|
|
|
BSTR propname;
|
|
|
|
VARIANT val;
|
|
|
|
CIMTYPE type;
|
|
|
|
HRESULT res;
|
2013-02-11 00:31:03 +01:00
|
|
|
PWMIUT wp;
|
2013-02-07 10:34:27 +01:00
|
|
|
SAFEARRAY *prnlist = NULL;
|
|
|
|
PQRYRES qrp = NULL;
|
|
|
|
PCOLRES crp;
|
|
|
|
|
2013-02-11 00:31:03 +01:00
|
|
|
if (!info) {
|
|
|
|
/*******************************************************************/
|
|
|
|
/* Initialize WMI if not done yet. */
|
|
|
|
/*******************************************************************/
|
|
|
|
if (!(wp = InitWMI(g, nsp, cls)))
|
|
|
|
return NULL;
|
2013-02-07 10:34:27 +01:00
|
|
|
|
2013-02-11 00:31:03 +01:00
|
|
|
/*******************************************************************/
|
|
|
|
/* Get the number of properties to return. */
|
|
|
|
/*******************************************************************/
|
|
|
|
res = wp->Cobj->Get(bstr_t("__Property_Count"), 0, &val, NULL, NULL);
|
2013-02-07 10:34:27 +01:00
|
|
|
|
2013-02-11 00:31:03 +01:00
|
|
|
if (FAILED(res)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "failed Get(__Property_Count) res=%d\n", res);
|
2013-02-11 00:31:03 +01:00
|
|
|
goto err;
|
|
|
|
} // endif res
|
2013-02-07 10:34:27 +01:00
|
|
|
|
2013-02-11 00:31:03 +01:00
|
|
|
if (!(n = val.lVal)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "Class %s in %s has no properties\n",
|
2013-02-11 00:31:03 +01:00
|
|
|
cls, nsp);
|
|
|
|
goto err;
|
|
|
|
} // endif res
|
2013-02-07 10:34:27 +01:00
|
|
|
|
2013-02-11 00:31:03 +01:00
|
|
|
/*******************************************************************/
|
|
|
|
/* Get max property name length. */
|
|
|
|
/*******************************************************************/
|
|
|
|
res = wp->Cobj->GetNames(NULL,
|
|
|
|
WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY,
|
|
|
|
NULL, &prnlist);
|
2013-02-07 10:34:27 +01:00
|
|
|
|
|
|
|
if (FAILED(res)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "failed GetNames res=%d\n", res);
|
2013-02-07 10:34:27 +01:00
|
|
|
goto err;
|
|
|
|
} // endif res
|
|
|
|
|
2013-02-11 00:31:03 +01:00
|
|
|
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)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "failed GetArrayElement res=%d\n", res);
|
2013-02-11 00:31:03 +01:00
|
|
|
goto err;
|
|
|
|
} // endif res
|
|
|
|
|
|
|
|
len = (unsigned)SysStringLen(propname);
|
2014-09-17 00:51:40 +02:00
|
|
|
length[0] = MY_MAX(length[0], len);
|
2013-02-11 00:31:03 +01:00
|
|
|
} // enfor i
|
2013-02-07 10:34:27 +01:00
|
|
|
|
2013-02-11 00:31:03 +01:00
|
|
|
res = SafeArrayDestroy(prnlist);
|
|
|
|
} else
|
|
|
|
length[0] = 128;
|
2013-02-07 10:34:27 +01:00
|
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
/* Allocate the structures used to refer to the result set. */
|
|
|
|
/*********************************************************************/
|
|
|
|
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
|
2013-08-14 16:07:32 +02:00
|
|
|
buftyp, fldtyp, length, false, true);
|
2013-02-11 00:31:03 +01:00
|
|
|
|
2013-12-16 01:32:47 +01:00
|
|
|
if (info || !qrp)
|
2013-02-11 00:31:03 +01:00
|
|
|
return qrp;
|
2013-02-07 10:34:27 +01:00
|
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
/* Now get the results into blocks. */
|
|
|
|
/*********************************************************************/
|
|
|
|
res = wp->Cobj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
|
|
|
|
|
|
|
|
if (FAILED(res)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "failed BeginEnumeration hr=%d\n", res);
|
2013-02-07 10:34:27 +01:00
|
|
|
qrp = NULL;
|
|
|
|
goto err;
|
|
|
|
} // endif hr
|
|
|
|
|
|
|
|
while (TRUE) {
|
|
|
|
res = wp->Cobj->Next(0, &propname, &val, &type, NULL);
|
|
|
|
|
|
|
|
if (FAILED(res)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "failed getting Next hr=%d\n", res);
|
2013-02-07 10:34:27 +01:00
|
|
|
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;
|
2013-03-11 16:52:59 +01:00
|
|
|
lng = 11;
|
2013-02-07 10:34:27 +01:00
|
|
|
break;
|
|
|
|
case CIM_SINT8:
|
|
|
|
case CIM_UINT8:
|
2013-03-11 16:52:59 +01:00
|
|
|
typ = TYPE_TINY;
|
|
|
|
lng = 4;
|
|
|
|
break;
|
2013-02-07 10:34:27 +01:00
|
|
|
case CIM_SINT16:
|
|
|
|
case CIM_UINT16:
|
|
|
|
typ = TYPE_SHORT;
|
|
|
|
lng = 6;
|
|
|
|
break;
|
|
|
|
case CIM_REAL64:
|
|
|
|
case CIM_REAL32:
|
|
|
|
prec = 2;
|
2013-12-28 15:46:49 +01:00
|
|
|
typ = TYPE_DOUBLE;
|
2013-02-07 10:34:27 +01:00
|
|
|
lng = 15;
|
|
|
|
break;
|
2013-03-11 16:52:59 +01:00
|
|
|
case CIM_SINT64:
|
|
|
|
case CIM_UINT64:
|
|
|
|
typ = TYPE_BIGINT;
|
|
|
|
lng = 20;
|
|
|
|
break;
|
2013-02-07 10:34:27 +01:00
|
|
|
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:
|
2013-02-11 00:31:03 +01:00
|
|
|
// Cleanup
|
|
|
|
wp->Cobj->Release();
|
|
|
|
wp->Svc->Release();
|
|
|
|
wp->Svc = NULL; // MUST be set to NULL (why?)
|
|
|
|
CoUninitialize();
|
2013-02-07 10:34:27 +01:00
|
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
/* 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)
|
|
|
|
{
|
2014-04-14 14:26:48 +02:00
|
|
|
Nspace = GetStringCatInfo(g, "Namespace", "Root\\CimV2");
|
|
|
|
Wclass = GetStringCatInfo(g, "Class",
|
2013-02-07 10:34:27 +01:00
|
|
|
(!stricmp(Nspace, "root\\cimv2") ? "ComputerSystemProduct" :
|
|
|
|
!stricmp(Nspace, "root\\cli") ? "Msft_CliAlias" : ""));
|
|
|
|
|
|
|
|
if (!*Wclass) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "Missing class name for %s", Nspace);
|
2013-02-07 10:34:27 +01:00
|
|
|
return true;
|
|
|
|
} else if (!strchr(Wclass, '_')) {
|
|
|
|
char *p = (char*)PlugSubAlloc(g, NULL, strlen(Wclass) + 7);
|
|
|
|
Wclass = strcat(strcpy(p, "Win32_"), Wclass);
|
|
|
|
} // endif Wclass
|
|
|
|
|
2013-02-12 12:34:14 +01:00
|
|
|
if (Catfunc == FNC_NO)
|
2014-04-14 14:26:48 +02:00
|
|
|
Ems = GetIntCatInfo("Estimate", 100);
|
2013-02-07 10:34:27 +01:00
|
|
|
|
|
|
|
return false;
|
|
|
|
} // end of DefineAM
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* GetTable: makes a new TDB of the proper type. */
|
|
|
|
/***********************************************************************/
|
|
|
|
PTDB WMIDEF::GetTable(PGLOBAL g, MODE m)
|
|
|
|
{
|
2013-02-12 12:34:14 +01:00
|
|
|
if (Catfunc == FNC_NO)
|
2013-02-07 10:34:27 +01:00
|
|
|
return new(g) TDBWMI(this);
|
2013-02-12 12:34:14 +01:00
|
|
|
else if (Catfunc == FNC_COL)
|
2013-02-11 00:31:03 +01:00
|
|
|
return new(g) TDBWCL(this);
|
2013-02-07 10:34:27 +01:00
|
|
|
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "Bad catfunc %ud for WMI", Catfunc);
|
2013-02-11 00:31:03 +01:00
|
|
|
return NULL;
|
2013-02-07 10:34:27 +01:00
|
|
|
} // end of GetTable
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/***********************************************************************/
|
2013-02-11 00:31:03 +01:00
|
|
|
/* Implementation of the TDBWMI class. */
|
2013-02-07 10:34:27 +01:00
|
|
|
/***********************************************************************/
|
|
|
|
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)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "Failed to initialize COM library. "
|
2017-03-02 12:12:53 +01:00
|
|
|
"Error code = %x", Res);
|
2013-02-07 10:34:27 +01:00
|
|
|
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)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "Failed to create Locator. "
|
|
|
|
"Error code = %x", Res);
|
2013-02-07 10:34:27 +01:00
|
|
|
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)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "Could not connect. Error code = %x", Res);
|
2013-02-07 10:34:27 +01:00
|
|
|
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)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "Could not set proxy. Error code = %x", Res);
|
2013-02-07 10:34:27 +01:00
|
|
|
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)
|
|
|
|
{
|
2014-03-10 18:29:04 +01:00
|
|
|
if (To_CondFil && strchr(To_CondFil->Body, '\\')) {
|
|
|
|
char *body = To_CondFil->Body;
|
2013-11-06 18:22:09 +01:00
|
|
|
char *buf = (char*)PlugSubAlloc(g, NULL, strlen(body) * 2);
|
2013-02-07 10:34:27 +01:00
|
|
|
int i = 0, k = 0;
|
|
|
|
|
|
|
|
do {
|
2013-11-06 18:22:09 +01:00
|
|
|
if (body[i] == '\\')
|
2013-02-07 10:34:27 +01:00
|
|
|
buf[k++] = '\\';
|
|
|
|
|
2013-11-06 18:22:09 +01:00
|
|
|
buf[k++] = body[i];
|
|
|
|
} while (body[i++]);
|
2013-02-07 10:34:27 +01:00
|
|
|
|
2014-03-10 18:29:04 +01:00
|
|
|
To_CondFil->Body = buf;
|
|
|
|
} // endif To_CondFil
|
2013-02-07 10:34:27 +01:00
|
|
|
|
|
|
|
} // 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) {
|
|
|
|
colist = (char*)PlugSubAlloc(g, NULL, (NAM_LEN + 4) * ncol);
|
|
|
|
|
|
|
|
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) {
|
|
|
|
strcpy(colist, colp->GetName());
|
|
|
|
first = false;
|
|
|
|
} else
|
|
|
|
strcat(strcat(colist, ", "), 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);
|
|
|
|
strcpy(colist, "*");
|
|
|
|
} // endif ncol
|
|
|
|
|
|
|
|
// Below 14 is length of 'select ' + length of ' from ' + 1
|
|
|
|
len = (strlen(colist) + strlen(Wclass) + 14);
|
2014-03-10 18:29:04 +01:00
|
|
|
len += (To_CondFil ? strlen(To_CondFil->Body) + 7 : 0);
|
2013-02-07 10:34:27 +01:00
|
|
|
wql = (char*)PlugSubAlloc(g, NULL, len);
|
|
|
|
strcat(strcat(strcpy(wql, "SELECT "), colist), " FROM ");
|
|
|
|
strcat(wql, Wclass);
|
|
|
|
|
2014-03-10 18:29:04 +01:00
|
|
|
if (To_CondFil)
|
|
|
|
strcat(strcat(wql, " WHERE "), To_CondFil->Body);
|
2013-02-07 10:34:27 +01:00
|
|
|
|
|
|
|
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) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "Error making WQL statement");
|
2013-02-07 10:34:27 +01:00
|
|
|
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)) {
|
2022-07-19 21:06:55 +02:00
|
|
|
snprintf(g->Message, sizeof(g->Message), "Query %s failed. Error code = %x", cmd, Rc);
|
2013-02-07 10:34:27 +01:00
|
|
|
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. */
|
|
|
|
/*******************************************************************/
|
|
|
|
strcpy(g->Message, "WMI tables are read only");
|
|
|
|
return true;
|
|
|
|
} // endif Mode
|
|
|
|
|
2014-03-10 18:29:04 +01:00
|
|
|
if (!To_CondFil && !stricmp(Wclass, "CIM_Datafile")
|
|
|
|
&& !stricmp(Nspace, "root\\cimv2")) {
|
2013-02-07 10:34:27 +01:00
|
|
|
strcpy(g->Message,
|
|
|
|
"Would last forever when not filtered, use DIR table instead");
|
|
|
|
return true;
|
|
|
|
} else
|
|
|
|
DoubleSlash(g);
|
|
|
|
|
2013-11-11 13:00:39 +01:00
|
|
|
Use = USE_OPEN; // Do it now in case we are recursively called
|
|
|
|
|
2013-02-07 10:34:27 +01:00
|
|
|
/*********************************************************************/
|
|
|
|
/* 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)
|
|
|
|
{
|
|
|
|
strcpy(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)
|
|
|
|
{
|
|
|
|
strcpy(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:
|
2022-08-02 10:23:53 +02:00
|
|
|
Value->SetValue((long long)Prop.lVal);
|
2013-02-07 10:34:27 +01:00
|
|
|
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);
|
|
|
|
|
2022-09-28 16:45:25 +02:00
|
|
|
snprintf(buf, sizeof(buf), "%02d/%02d/%d %02d:%02d:%02d",
|
2013-02-07 10:34:27 +01:00
|
|
|
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 --------------------------- */
|
|
|
|
|
|
|
|
/***********************************************************************/
|
2013-02-11 00:31:03 +01:00
|
|
|
/* TDBWCL class constructor. */
|
2013-02-07 10:34:27 +01:00
|
|
|
/***********************************************************************/
|
2013-02-11 00:31:03 +01:00
|
|
|
TDBWCL::TDBWCL(PWMIDEF tdp) : TDBCAT(tdp)
|
2013-02-07 10:34:27 +01:00
|
|
|
{
|
2013-02-11 00:31:03 +01:00
|
|
|
Nsp = tdp->Nspace;
|
|
|
|
Cls = tdp->Wclass;
|
2013-02-07 10:34:27 +01:00
|
|
|
} // end of TDBWCL constructor
|
|
|
|
|
|
|
|
/***********************************************************************/
|
2013-02-11 00:31:03 +01:00
|
|
|
/* GetResult: Get the list of the WMI class properties. */
|
2013-02-07 10:34:27 +01:00
|
|
|
/***********************************************************************/
|
2013-02-11 00:31:03 +01:00
|
|
|
PQRYRES TDBWCL::GetResult(PGLOBAL g)
|
2013-02-07 10:34:27 +01:00
|
|
|
{
|
2013-02-11 00:31:03 +01:00
|
|
|
return WMIColumns(g, Nsp, Cls, false);
|
|
|
|
} // end of GetResult
|
2013-02-07 10:34:27 +01:00
|
|
|
|
|
|
|
|