summaryrefslogtreecommitdiffstats
path: root/storage/connect/tabwmi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/connect/tabwmi.cpp')
-rw-r--r--storage/connect/tabwmi.cpp857
1 files changed, 857 insertions, 0 deletions
diff --git a/storage/connect/tabwmi.cpp b/storage/connect/tabwmi.cpp
new file mode 100644
index 00000000..1cd46a74
--- /dev/null
+++ b/storage/connect/tabwmi.cpp
@@ -0,0 +1,857 @@
+/***********************************************************************/
+/* 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
+
+