From a175314c3e5827eb193872241446f2f8f5c9d33c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 4 May 2024 20:07:14 +0200 Subject: Adding upstream version 1:10.5.12. Signed-off-by: Daniel Baumann --- storage/connect/tabwmi.cpp | 851 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 851 insertions(+) create mode 100644 storage/connect/tabwmi.cpp (limited to 'storage/connect/tabwmi.cpp') diff --git a/storage/connect/tabwmi.cpp b/storage/connect/tabwmi.cpp new file mode 100644 index 00000000..a6aab7d2 --- /dev/null +++ b/storage/connect/tabwmi.cpp @@ -0,0 +1,851 @@ +/***********************************************************************/ +/* 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 + +#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 { + 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)) { + sprintf(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)) { + sprintf(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)) { + sprintf(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)) { + sprintf(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)) { + sprintf(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)) { + sprintf(g->Message, "failed Get(__Property_Count) res=%d\n", res); + goto err; + } // endif res + + if (!(n = val.lVal)) { + sprintf(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)) { + sprintf(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)) { + sprintf(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)) { + sprintf(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)) { + sprintf(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) { + sprintf(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); + + sprintf(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)) { + sprintf(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)) { + sprintf(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)) { + sprintf(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)) { + sprintf(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) { + 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); + len += (To_CondFil ? strlen(To_CondFil->Body) + 7 : 0); + wql = (char*)PlugSubAlloc(g, NULL, len); + strcat(strcat(strcpy(wql, "SELECT "), colist), " FROM "); + strcat(wql, Wclass); + + if (To_CondFil) + strcat(strcat(wql, " WHERE "), 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) { + sprintf(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)) { + sprintf(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. */ + /*******************************************************************/ + strcpy(g->Message, "WMI tables are read only"); + return true; + } // endif Mode + + if (!To_CondFil && !stricmp(Wclass, "CIM_Datafile") + && !stricmp(Nspace, "root\\cimv2")) { + strcpy(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) + { + 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: + Value->SetValue(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); + + sprintf(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 + + -- cgit v1.2.3