summaryrefslogtreecommitdiff
path: root/storage/connect/tabwmi.cpp
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mnogosearch.org>2013-02-07 13:34:27 +0400
committerAlexander Barkov <bar@mnogosearch.org>2013-02-07 13:34:27 +0400
commit30c4b0ebc24fe0106e146b1f6577a4150e71e258 (patch)
tree592673d8c2f5b418833c3ee5fcfeb9dbf4ba1681 /storage/connect/tabwmi.cpp
parent60c4cab3bd00621cc03afb1be6de01c8fab0c5f0 (diff)
downloadmariadb-git-30c4b0ebc24fe0106e146b1f6577a4150e71e258.tar.gz
- Fixing TAB to 2 spaces
- Fixing line endings from "\r\n" to "\n"
Diffstat (limited to 'storage/connect/tabwmi.cpp')
-rw-r--r--storage/connect/tabwmi.cpp2306
1 files changed, 1153 insertions, 1153 deletions
diff --git a/storage/connect/tabwmi.cpp b/storage/connect/tabwmi.cpp
index 5d33e06ff76..fd7e6eb345d 100644
--- a/storage/connect/tabwmi.cpp
+++ b/storage/connect/tabwmi.cpp
@@ -1,1153 +1,1153 @@
-/***********************************************************************/
-/* TABWMI: Author Olivier Bertrand -- PlugDB -- 2012 - 2013 */
-/* TABWMI: Virtual table to get WMI information. */
-/***********************************************************************/
-#if !defined(WIN32)
-#error This is a WIN32 only table type
-#endif // !WIN32
-#include "my_global.h"
-#include <stdio.h>
-
-#include "global.h"
-#include "plgdbsem.h"
-//#include "catalog.h"
-#include "reldef.h"
-#include "xtable.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"
-
-extern "C" int trace;
-
-/**************************************************************************/
-/* Allocate the result structure that will contain result data. */
-/**************************************************************************/
-PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
- int *dbtype, int *buftyp, unsigned int *length,
- bool blank = true, bool nonull = true);
-
-/* ------------------- Functions WMI Column info --------------------- */
-
-/***********************************************************************/
-/* Structure used by WMI column info functions. */
-/***********************************************************************/
-typedef struct _WMIutil {
- IWbemServices *Svc;
- IWbemClassObject *Cobj;
-} WMIUTIL, *PWMIUT;
-
-/***********************************************************************/
-/* Initialize WMI operations. */
-/***********************************************************************/
-PWMIUT InitWMI(PGLOBAL g, char *nsp, char *classname)
-{
- IWbemLocator *loc;
- char *p;
- HRESULT res;
- PWMIUT wp = (PWMIUT)PlugSubAlloc(g, NULL, sizeof(WMIUTIL));
-
- if (trace)
- 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 = %p", 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 = %p", 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 = %p", res);
- loc->Release();
- CoUninitialize();
- return NULL;
- } // endif res
-
- loc->Release();
-
- if (trace)
- 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, char *nsp, char *classname, PWMIUT wp)
- {
- static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
- DB_INT, DB_INT, DB_SHORT};
- static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
- TYPE_INT, TYPE_INT, TYPE_SHORT};
- static unsigned int len, length[] = {0, 6, 8, 10, 10, 6};
- int i = 0, n = 0, ncol = sizeof(dbtype) / sizeof(int);
- int lng, typ, prec;
- LONG low, upp;
- BOOL b1, b2 = TRUE;
- BSTR propname;
- VARIANT val;
- CIMTYPE type;
- HRESULT res;
- SAFEARRAY *prnlist = NULL;
- PQRYRES qrp = NULL;
- PCOLRES crp;
-
- /*********************************************************************/
- /* Initialize WMI if not done yet. */
- /*********************************************************************/
- if ((b1 = !wp) && !(wp = InitWMI(g, nsp, classname)))
- 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",
- classname, 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] = max(length[0], len);
- } // enfor i
-
- res = SafeArrayDestroy(prnlist);
-
- /*********************************************************************/
- /* Allocate the structures used to refer to the result set. */
- /*********************************************************************/
- qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
- dbtype, buftyp, length);
-
- /*********************************************************************/
- /* 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 = 9;
- break;
- case CIM_SINT8:
- case CIM_UINT8:
- case CIM_SINT16:
- case CIM_UINT16:
- typ = TYPE_SHORT;
- lng = 6;
- break;
- case CIM_REAL64:
- case CIM_REAL32:
- prec = 2;
- case CIM_SINT64:
- case CIM_UINT64:
- typ = TYPE_FLOAT;
- lng = 15;
- 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;
- b2 = b1;
-
- err:
- if (b2) {
- // Cleanup
- wp->Cobj->Release();
- wp->Svc->Release();
- wp->Svc = NULL; // MUST be set to NULL (why?)
- CoUninitialize();
- } // endif b
-
- /*********************************************************************/
- /* 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 = Cat->GetStringCatInfo(g, Name, "Namespace", "Root\\CimV2");
- Wclass = Cat->GetStringCatInfo(g, Name, "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 (!(Info = Cat->GetBoolCatInfo(Name, "Info", false)))
- Ems = Cat->GetIntCatInfo(Name, "Estimate", 100);
-
- return false;
- } // end of DefineAM
-
-/***********************************************************************/
-/* GetTable: makes a new TDB of the proper type. */
-/***********************************************************************/
-PTDB WMIDEF::GetTable(PGLOBAL g, MODE m)
- {
- if (Info)
- return new(g) TDBWCL(this);
- else
- return new(g) TDBWMI(this);
-
- } // 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 = %p", 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 = %p", 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 = %p", 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 = 0x", 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_Filter && strchr(To_Filter, '\\')) {
- char *buf = (char*)PlugSubAlloc(g, NULL, strlen(To_Filter) * 2);
- int i = 0, k = 0;
-
- do {
- if (To_Filter[i] == '\\')
- buf[k++] = '\\';
-
- buf[k++] = To_Filter[i];
- } while (To_Filter[i++]);
-
- To_Filter = buf;
- } // endif To_Filter
-
- } // 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_Filter ? strlen(To_Filter) + 7 : 0);
- wql = (char*)PlugSubAlloc(g, NULL, len);
- strcat(strcat(strcpy(wql, "SELECT "), colist), " FROM ");
- strcat(wql, Wclass);
-
- if (To_Filter)
- strcat(strcat(wql, " WHERE "), To_Filter);
-
- 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 = %p", 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_Filter && !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);
-
- /*********************************************************************/
- /* 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 --------------------------- */
-
-/***********************************************************************/
-/* Implementation of the TDBWCL class. */
-/***********************************************************************/
-TDBWCL::TDBWCL(PWMIDEF tdp) : TDBASE(tdp)
- {
- Svc = NULL;
- ClsObj = NULL;
- Propname = NULL;
- Nspace = tdp->Nspace;
- Wclass = tdp->Wclass;
- Init = false;
- Done = false;
- Res = 0;
- N = -1;
- Lng = 0;
- Typ = 0;
- Prec = 0;
- } // end of TDBWCL constructor
-
-/***********************************************************************/
-/* Allocate WCL column description block. */
-/***********************************************************************/
-PCOL TDBWCL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
- {
- PWCLCOL colp;
-
- colp = (PWCLCOL)new(g) WCLCOL(cdp, this, n);
-
- if (cprec) {
- colp->SetNext(cprec->GetNext());
- cprec->SetNext(colp);
- } else {
- colp->SetNext(Columns);
- Columns = colp;
- } // endif cprec
-
- if (!colp->Flag) {
- if (!stricmp(colp->Name, "Column_Name"))
- colp->Flag = 1;
- else if (!stricmp(colp->Name, "Data_Type"))
- colp->Flag = 2;
- else if (!stricmp(colp->Name, "Type_Name"))
- colp->Flag = 3;
- else if (!stricmp(colp->Name, "Precision"))
- colp->Flag = 4;
- else if (!stricmp(colp->Name, "Length"))
- colp->Flag = 5;
- else if (!stricmp(colp->Name, "Scale"))
- colp->Flag = 6;
-
- } // endif Flag
-
- return colp;
- } // end of MakeCol
-
-/***********************************************************************/
-/* Initialize: Initialize WMI operations. */
-/***********************************************************************/
-bool TDBWCL::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 = %p", 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 = %p", 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 = %p", Res);
- loc->Release();
- CoUninitialize();
- return true; // Program has failed.
- } // endif hres
-
- loc->Release(); // Not used anymore
-
- // Perform a full class object retrieval
- Res = Svc->GetObject(bstr_t(Wclass), 0, 0, &ClsObj, 0);
-
- if (FAILED(Res)) {
- sprintf(g->Message, "failed GetObject %s in %s\n", Wclass, Nspace);
- Svc->Release();
- Svc = NULL; // MUST be set to NULL (why?)
- return true;
- } // endif res
-
- Init = true;
- return false;
- } // end of Initialize
-
-/***********************************************************************/
-/* WCL: Get the number of properties. */
-/***********************************************************************/
-int TDBWCL::GetMaxSize(PGLOBAL g)
- {
- if (MaxSize < 0) {
- VARIANT val;
-
- if (Initialize(g))
- return -1;
-
- Res = ClsObj->Get(bstr_t("__Property_Count"), 0, &val, NULL, NULL);
-
- if (FAILED(Res)) {
- sprintf(g->Message, "failed Get(Property_Count) res=%d\n", Res);
- return -1;
- } // endif Res
-
- MaxSize = val.lVal;
- } // endif MaxSize
-
- return MaxSize;
- } // end of GetMaxSize
-
-/***********************************************************************/
-/* WCL Access Method opening routine. */
-/***********************************************************************/
-bool TDBWCL::OpenDB(PGLOBAL g)
- {
- if (Use == USE_OPEN) {
- /*******************************************************************/
- /* Table already open. */
- /*******************************************************************/
- ClsObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
- N = 0;
- return false;
- } // endif use
-
- if (Mode != MODE_READ) {
- /*******************************************************************/
- /* WMI tables cannot be modified. */
- /*******************************************************************/
- strcpy(g->Message, "WCL tables are read only");
- return true;
- } // endif Mode
-
- /*********************************************************************/
- /* Initialize the WMI processing. */
- /*********************************************************************/
- if (Initialize(g))
- return true;
-
- Res = ClsObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
-
- if (FAILED(Res)) {
- sprintf(g->Message, "failed BeginEnumeration hr=%d\n", Res);
- return NULL;
- } // endif hr
-
- return false;
- } // end of OpenDB
-
-/***********************************************************************/
-/* Data Base read routine for WCL access method. */
-/***********************************************************************/
-int TDBWCL::ReadDB(PGLOBAL g)
- {
- VARIANT val;
- CIMTYPE type;
-
- Res = ClsObj->Next(0, &Propname, &val, &type, NULL);
-
- if (FAILED(Res)) {
- sprintf(g->Message, "failed getting Next hr=%d\n", Res);
- return RC_FX;
- } else if (Res == WBEM_S_NO_MORE_DATA) {
- VariantClear(&val);
- return RC_EF;
- } // endif res
-
- 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 = 9;
- break;
- case CIM_SINT8:
- case CIM_UINT8:
- case CIM_SINT16:
- case CIM_UINT16:
- Typ = TYPE_SHORT;
- Lng = 6;
- break;
- case CIM_REAL64:
- case CIM_REAL32:
- Prec = 2;
- case CIM_SINT64:
- case CIM_UINT64:
- Typ = TYPE_FLOAT;
- Lng = 15;
- 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:
- return RC_NF;
- } // endswitch type
-
- N++;
- return RC_OK;
- } // end of ReadDB
-
-/***********************************************************************/
-/* WriteDB: Data Base write routine for WCL access methods. */
-/***********************************************************************/
-int TDBWCL::WriteDB(PGLOBAL g)
- {
- strcpy(g->Message, "WCL tables are read only");
- return RC_FX;
- } // end of WriteDB
-
-/***********************************************************************/
-/* Data Base delete line routine for WCL access methods. */
-/***********************************************************************/
-int TDBWCL::DeleteDB(PGLOBAL g, int irc)
- {
- strcpy(g->Message, "Delete not enabled for WCL tables");
- return RC_FX;
- } // end of DeleteDB
-
-/***********************************************************************/
-/* Data Base close routine for WMI access method. */
-/***********************************************************************/
-void TDBWCL::CloseDB(PGLOBAL g)
- {
- // Cleanup
- if (ClsObj)
- ClsObj->Release();
-
- if (Svc)
- Svc->Release();
-
- CoUninitialize();
- } // end of CloseDB
-
-// ------------------------ WCLCOL functions ----------------------------
-
-/***********************************************************************/
-/* WCLCOL public constructor. */
-/***********************************************************************/
-WCLCOL::WCLCOL(PCOLDEF cdp, PTDB tdbp, int n)
- : COLBLK(cdp, tdbp, n)
- {
- Tdbp = (PTDBWCL)tdbp;
- Flag = cdp->GetOffset();
- Res = 0;
- } // end of WMICOL constructor
-
-/***********************************************************************/
-/* Read the next WCL elements. */
-/***********************************************************************/
-void WCLCOL::ReadColumn(PGLOBAL g)
- {
- // Get the value of the Name property
- switch (Flag) {
- case 1:
- Value->SetValue_psz(_com_util::ConvertBSTRToString(Tdbp->Propname));
- break;
- case 2:
- Value->SetValue(Tdbp->Typ);
- break;
- case 3:
- Value->SetValue_psz(GetTypeName(Tdbp->Typ));
- break;
- case 4:
- case 5:
- Value->SetValue(Tdbp->Lng);
- break;
- case 6:
- Value->SetValue(Tdbp->Prec);
- break;
- default:
- Value->Reset();
- } // endswitch Flag
-
- } // end of ReadColumn
+/***********************************************************************/
+/* TABWMI: Author Olivier Bertrand -- PlugDB -- 2012 - 2013 */
+/* TABWMI: Virtual table to get WMI information. */
+/***********************************************************************/
+#if !defined(WIN32)
+#error This is a WIN32 only table type
+#endif // !WIN32
+#include "my_global.h"
+#include <stdio.h>
+
+#include "global.h"
+#include "plgdbsem.h"
+//#include "catalog.h"
+#include "reldef.h"
+#include "xtable.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"
+
+extern "C" int trace;
+
+/**************************************************************************/
+/* Allocate the result structure that will contain result data. */
+/**************************************************************************/
+PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
+ int *dbtype, int *buftyp, unsigned int *length,
+ bool blank = true, bool nonull = true);
+
+/* ------------------- Functions WMI Column info --------------------- */
+
+/***********************************************************************/
+/* Structure used by WMI column info functions. */
+/***********************************************************************/
+typedef struct _WMIutil {
+ IWbemServices *Svc;
+ IWbemClassObject *Cobj;
+} WMIUTIL, *PWMIUT;
+
+/***********************************************************************/
+/* Initialize WMI operations. */
+/***********************************************************************/
+PWMIUT InitWMI(PGLOBAL g, char *nsp, char *classname)
+{
+ IWbemLocator *loc;
+ char *p;
+ HRESULT res;
+ PWMIUT wp = (PWMIUT)PlugSubAlloc(g, NULL, sizeof(WMIUTIL));
+
+ if (trace)
+ 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 = %p", 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 = %p", 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 = %p", res);
+ loc->Release();
+ CoUninitialize();
+ return NULL;
+ } // endif res
+
+ loc->Release();
+
+ if (trace)
+ 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, char *nsp, char *classname, PWMIUT wp)
+ {
+ static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
+ DB_INT, DB_INT, DB_SHORT};
+ static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
+ TYPE_INT, TYPE_INT, TYPE_SHORT};
+ static unsigned int len, length[] = {0, 6, 8, 10, 10, 6};
+ int i = 0, n = 0, ncol = sizeof(dbtype) / sizeof(int);
+ int lng, typ, prec;
+ LONG low, upp;
+ BOOL b1, b2 = TRUE;
+ BSTR propname;
+ VARIANT val;
+ CIMTYPE type;
+ HRESULT res;
+ SAFEARRAY *prnlist = NULL;
+ PQRYRES qrp = NULL;
+ PCOLRES crp;
+
+ /*********************************************************************/
+ /* Initialize WMI if not done yet. */
+ /*********************************************************************/
+ if ((b1 = !wp) && !(wp = InitWMI(g, nsp, classname)))
+ 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",
+ classname, 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] = max(length[0], len);
+ } // enfor i
+
+ res = SafeArrayDestroy(prnlist);
+
+ /*********************************************************************/
+ /* Allocate the structures used to refer to the result set. */
+ /*********************************************************************/
+ qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
+ dbtype, buftyp, length);
+
+ /*********************************************************************/
+ /* 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 = 9;
+ break;
+ case CIM_SINT8:
+ case CIM_UINT8:
+ case CIM_SINT16:
+ case CIM_UINT16:
+ typ = TYPE_SHORT;
+ lng = 6;
+ break;
+ case CIM_REAL64:
+ case CIM_REAL32:
+ prec = 2;
+ case CIM_SINT64:
+ case CIM_UINT64:
+ typ = TYPE_FLOAT;
+ lng = 15;
+ 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;
+ b2 = b1;
+
+ err:
+ if (b2) {
+ // Cleanup
+ wp->Cobj->Release();
+ wp->Svc->Release();
+ wp->Svc = NULL; // MUST be set to NULL (why?)
+ CoUninitialize();
+ } // endif b
+
+ /*********************************************************************/
+ /* 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 = Cat->GetStringCatInfo(g, Name, "Namespace", "Root\\CimV2");
+ Wclass = Cat->GetStringCatInfo(g, Name, "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 (!(Info = Cat->GetBoolCatInfo(Name, "Info", false)))
+ Ems = Cat->GetIntCatInfo(Name, "Estimate", 100);
+
+ return false;
+ } // end of DefineAM
+
+/***********************************************************************/
+/* GetTable: makes a new TDB of the proper type. */
+/***********************************************************************/
+PTDB WMIDEF::GetTable(PGLOBAL g, MODE m)
+ {
+ if (Info)
+ return new(g) TDBWCL(this);
+ else
+ return new(g) TDBWMI(this);
+
+ } // 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 = %p", 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 = %p", 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 = %p", 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 = 0x", 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_Filter && strchr(To_Filter, '\\')) {
+ char *buf = (char*)PlugSubAlloc(g, NULL, strlen(To_Filter) * 2);
+ int i = 0, k = 0;
+
+ do {
+ if (To_Filter[i] == '\\')
+ buf[k++] = '\\';
+
+ buf[k++] = To_Filter[i];
+ } while (To_Filter[i++]);
+
+ To_Filter = buf;
+ } // endif To_Filter
+
+ } // 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_Filter ? strlen(To_Filter) + 7 : 0);
+ wql = (char*)PlugSubAlloc(g, NULL, len);
+ strcat(strcat(strcpy(wql, "SELECT "), colist), " FROM ");
+ strcat(wql, Wclass);
+
+ if (To_Filter)
+ strcat(strcat(wql, " WHERE "), To_Filter);
+
+ 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 = %p", 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_Filter && !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);
+
+ /*********************************************************************/
+ /* 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 --------------------------- */
+
+/***********************************************************************/
+/* Implementation of the TDBWCL class. */
+/***********************************************************************/
+TDBWCL::TDBWCL(PWMIDEF tdp) : TDBASE(tdp)
+ {
+ Svc = NULL;
+ ClsObj = NULL;
+ Propname = NULL;
+ Nspace = tdp->Nspace;
+ Wclass = tdp->Wclass;
+ Init = false;
+ Done = false;
+ Res = 0;
+ N = -1;
+ Lng = 0;
+ Typ = 0;
+ Prec = 0;
+ } // end of TDBWCL constructor
+
+/***********************************************************************/
+/* Allocate WCL column description block. */
+/***********************************************************************/
+PCOL TDBWCL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
+ {
+ PWCLCOL colp;
+
+ colp = (PWCLCOL)new(g) WCLCOL(cdp, this, n);
+
+ if (cprec) {
+ colp->SetNext(cprec->GetNext());
+ cprec->SetNext(colp);
+ } else {
+ colp->SetNext(Columns);
+ Columns = colp;
+ } // endif cprec
+
+ if (!colp->Flag) {
+ if (!stricmp(colp->Name, "Column_Name"))
+ colp->Flag = 1;
+ else if (!stricmp(colp->Name, "Data_Type"))
+ colp->Flag = 2;
+ else if (!stricmp(colp->Name, "Type_Name"))
+ colp->Flag = 3;
+ else if (!stricmp(colp->Name, "Precision"))
+ colp->Flag = 4;
+ else if (!stricmp(colp->Name, "Length"))
+ colp->Flag = 5;
+ else if (!stricmp(colp->Name, "Scale"))
+ colp->Flag = 6;
+
+ } // endif Flag
+
+ return colp;
+ } // end of MakeCol
+
+/***********************************************************************/
+/* Initialize: Initialize WMI operations. */
+/***********************************************************************/
+bool TDBWCL::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 = %p", 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 = %p", 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 = %p", Res);
+ loc->Release();
+ CoUninitialize();
+ return true; // Program has failed.
+ } // endif hres
+
+ loc->Release(); // Not used anymore
+
+ // Perform a full class object retrieval
+ Res = Svc->GetObject(bstr_t(Wclass), 0, 0, &ClsObj, 0);
+
+ if (FAILED(Res)) {
+ sprintf(g->Message, "failed GetObject %s in %s\n", Wclass, Nspace);
+ Svc->Release();
+ Svc = NULL; // MUST be set to NULL (why?)
+ return true;
+ } // endif res
+
+ Init = true;
+ return false;
+ } // end of Initialize
+
+/***********************************************************************/
+/* WCL: Get the number of properties. */
+/***********************************************************************/
+int TDBWCL::GetMaxSize(PGLOBAL g)
+ {
+ if (MaxSize < 0) {
+ VARIANT val;
+
+ if (Initialize(g))
+ return -1;
+
+ Res = ClsObj->Get(bstr_t("__Property_Count"), 0, &val, NULL, NULL);
+
+ if (FAILED(Res)) {
+ sprintf(g->Message, "failed Get(Property_Count) res=%d\n", Res);
+ return -1;
+ } // endif Res
+
+ MaxSize = val.lVal;
+ } // endif MaxSize
+
+ return MaxSize;
+ } // end of GetMaxSize
+
+/***********************************************************************/
+/* WCL Access Method opening routine. */
+/***********************************************************************/
+bool TDBWCL::OpenDB(PGLOBAL g)
+ {
+ if (Use == USE_OPEN) {
+ /*******************************************************************/
+ /* Table already open. */
+ /*******************************************************************/
+ ClsObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
+ N = 0;
+ return false;
+ } // endif use
+
+ if (Mode != MODE_READ) {
+ /*******************************************************************/
+ /* WMI tables cannot be modified. */
+ /*******************************************************************/
+ strcpy(g->Message, "WCL tables are read only");
+ return true;
+ } // endif Mode
+
+ /*********************************************************************/
+ /* Initialize the WMI processing. */
+ /*********************************************************************/
+ if (Initialize(g))
+ return true;
+
+ Res = ClsObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
+
+ if (FAILED(Res)) {
+ sprintf(g->Message, "failed BeginEnumeration hr=%d\n", Res);
+ return NULL;
+ } // endif hr
+
+ return false;
+ } // end of OpenDB
+
+/***********************************************************************/
+/* Data Base read routine for WCL access method. */
+/***********************************************************************/
+int TDBWCL::ReadDB(PGLOBAL g)
+ {
+ VARIANT val;
+ CIMTYPE type;
+
+ Res = ClsObj->Next(0, &Propname, &val, &type, NULL);
+
+ if (FAILED(Res)) {
+ sprintf(g->Message, "failed getting Next hr=%d\n", Res);
+ return RC_FX;
+ } else if (Res == WBEM_S_NO_MORE_DATA) {
+ VariantClear(&val);
+ return RC_EF;
+ } // endif res
+
+ 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 = 9;
+ break;
+ case CIM_SINT8:
+ case CIM_UINT8:
+ case CIM_SINT16:
+ case CIM_UINT16:
+ Typ = TYPE_SHORT;
+ Lng = 6;
+ break;
+ case CIM_REAL64:
+ case CIM_REAL32:
+ Prec = 2;
+ case CIM_SINT64:
+ case CIM_UINT64:
+ Typ = TYPE_FLOAT;
+ Lng = 15;
+ 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:
+ return RC_NF;
+ } // endswitch type
+
+ N++;
+ return RC_OK;
+ } // end of ReadDB
+
+/***********************************************************************/
+/* WriteDB: Data Base write routine for WCL access methods. */
+/***********************************************************************/
+int TDBWCL::WriteDB(PGLOBAL g)
+ {
+ strcpy(g->Message, "WCL tables are read only");
+ return RC_FX;
+ } // end of WriteDB
+
+/***********************************************************************/
+/* Data Base delete line routine for WCL access methods. */
+/***********************************************************************/
+int TDBWCL::DeleteDB(PGLOBAL g, int irc)
+ {
+ strcpy(g->Message, "Delete not enabled for WCL tables");
+ return RC_FX;
+ } // end of DeleteDB
+
+/***********************************************************************/
+/* Data Base close routine for WMI access method. */
+/***********************************************************************/
+void TDBWCL::CloseDB(PGLOBAL g)
+ {
+ // Cleanup
+ if (ClsObj)
+ ClsObj->Release();
+
+ if (Svc)
+ Svc->Release();
+
+ CoUninitialize();
+ } // end of CloseDB
+
+// ------------------------ WCLCOL functions ----------------------------
+
+/***********************************************************************/
+/* WCLCOL public constructor. */
+/***********************************************************************/
+WCLCOL::WCLCOL(PCOLDEF cdp, PTDB tdbp, int n)
+ : COLBLK(cdp, tdbp, n)
+ {
+ Tdbp = (PTDBWCL)tdbp;
+ Flag = cdp->GetOffset();
+ Res = 0;
+ } // end of WMICOL constructor
+
+/***********************************************************************/
+/* Read the next WCL elements. */
+/***********************************************************************/
+void WCLCOL::ReadColumn(PGLOBAL g)
+ {
+ // Get the value of the Name property
+ switch (Flag) {
+ case 1:
+ Value->SetValue_psz(_com_util::ConvertBSTRToString(Tdbp->Propname));
+ break;
+ case 2:
+ Value->SetValue(Tdbp->Typ);
+ break;
+ case 3:
+ Value->SetValue_psz(GetTypeName(Tdbp->Typ));
+ break;
+ case 4:
+ case 5:
+ Value->SetValue(Tdbp->Lng);
+ break;
+ case 6:
+ Value->SetValue(Tdbp->Prec);
+ break;
+ default:
+ Value->Reset();
+ } // endswitch Flag
+
+ } // end of ReadColumn