mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-31 10:56:12 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			857 lines
		
	
	
	
		
			27 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			857 lines
		
	
	
	
		
			27 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /***********************************************************************/
 | |
| /*  TABWMI: Author Olivier Bertrand -- PlugDB -- 2012 - 2017           */
 | |
| /*  TABWMI: Virtual table to get WMI information.                      */
 | |
| /***********************************************************************/
 | |
| #if !defined(_WIN32)
 | |
| #error This is a WINDOWS only table type
 | |
| #endif   // !_WIN32
 | |
| #include "my_global.h"
 | |
| #include "m_string.h"
 | |
| #include <stdio.h>
 | |
| 
 | |
| #include "global.h"
 | |
| #include "plgdbsem.h"
 | |
| #include "mycat.h"
 | |
| //#include "reldef.h"
 | |
| #include "xtable.h"
 | |
| #include "tabext.h"
 | |
| #include "colblk.h"
 | |
| //#include "filter.h"
 | |
| //#include "xindex.h"
 | |
| #include "tabwmi.h"
 | |
| #include "valblk.h"
 | |
| #include "plgcnx.h"                       // For DB types
 | |
| #include "resource.h"
 | |
| 
 | |
| /* ------------------- Functions WMI Column info --------------------- */
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  Initialize WMI operations.                                         */
 | |
| /***********************************************************************/
 | |
| PWMIUT InitWMI(PGLOBAL g, PCSZ nsp, PCSZ classname)
 | |
| {
 | |
|   IWbemLocator *loc;
 | |
|   char         *p;
 | |
|   HRESULT       res;
 | |
|   PWMIUT        wp = (PWMIUT)PlugSubAlloc(g, NULL, sizeof(WMIUTIL));
 | |
| 
 | |
|   if (trace(1))
 | |
|     htrc("WMIColumns class %s space %s\n", SVP(classname), SVP(nsp));
 | |
| 
 | |
|   /*********************************************************************/
 | |
|   /*  Set default values for the namespace and class name.             */
 | |
|   /*********************************************************************/
 | |
|   if (!nsp)
 | |
|     nsp = "root\\cimv2";
 | |
| 
 | |
|   if (!classname) {
 | |
|     if (!stricmp(nsp, "root\\cimv2"))
 | |
|       classname = "ComputerSystemProduct";
 | |
|     else if (!stricmp(nsp, "root\\cli"))
 | |
|       classname = "Msft_CliAlias";
 | |
|     else {
 | |
|       safe_strcpy(g->Message, sizeof(g->Message), "Missing class name");
 | |
|       return NULL;
 | |
|       } // endif classname
 | |
| 
 | |
|     } // endif classname
 | |
| 
 | |
|   /*********************************************************************/
 | |
|   /*  Initialize WMI.                                                  */
 | |
|   /*********************************************************************/
 | |
| //res = CoInitializeEx(NULL, COINIT_MULTITHREADED);
 | |
|   res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
 | |
| 
 | |
|   if (FAILED(res)) {
 | |
|     snprintf(g->Message, sizeof(g->Message), "Failed to initialize COM library. "
 | |
|             "Error code = %x", res);
 | |
|     return NULL;
 | |
|     } // endif res
 | |
| 
 | |
| #if 0 // irrelevant for a DLL
 | |
|   res = CoInitializeSecurity(NULL, -1, NULL, NULL,
 | |
|                        RPC_C_AUTHN_LEVEL_CONNECT,
 | |
|                        RPC_C_IMP_LEVEL_IMPERSONATE,
 | |
|                        NULL, EOAC_NONE, NULL);
 | |
|   
 | |
|   if (res != RPC_E_TOO_LATE && FAILED(res)) {
 | |
|     snprintf(g->Message, sizeof(g->Message), "Failed to initialize security. "
 | |
|             "Error code = %p", res);
 | |
|     CoUninitialize();
 | |
|     return NULL;
 | |
|     }  // endif Res
 | |
| #endif // 0
 | |
| 
 | |
|   res = CoCreateInstance(CLSID_WbemLocator, NULL, 
 | |
|                          CLSCTX_INPROC_SERVER, IID_IWbemLocator, 
 | |
|                          (void**) &loc);
 | |
|   if (FAILED(res)) {
 | |
|     snprintf(g->Message, sizeof(g->Message), "Failed to create Locator. "
 | |
|             "Error code = %x", res);
 | |
|     CoUninitialize();
 | |
|     return NULL;
 | |
|     }  // endif res
 | |
|     
 | |
|   res = loc->ConnectServer(_bstr_t(nsp), 
 | |
|                     NULL, NULL, NULL, 0, NULL, NULL, &wp->Svc);
 | |
| 
 | |
|   if (FAILED(res)) {
 | |
|     snprintf(g->Message, sizeof(g->Message), "Could not connect. Error code = %x", res);
 | |
|     loc->Release();     
 | |
|     CoUninitialize();
 | |
|     return NULL;
 | |
|     }  // endif res
 | |
| 
 | |
|   loc->Release();
 | |
| 
 | |
|   if (trace(1))
 | |
|     htrc("Successfully connected to namespace.\n");
 | |
| 
 | |
|   /*********************************************************************/
 | |
|   /*  Perform a full class object retrieval.                           */
 | |
|   /*********************************************************************/
 | |
|   p = (char*)PlugSubAlloc(g, NULL, strlen(classname) + 7);
 | |
| 
 | |
|   if (strchr(classname, '_'))
 | |
|     strcpy(p, classname);
 | |
|   else
 | |
|     strcat(strcpy(p, "Win32_"), classname);
 | |
| 
 | |
|   res = wp->Svc->GetObject(bstr_t(p), 0, 0, &wp->Cobj, 0);
 | |
| 
 | |
|   if (FAILED(res)) {
 | |
|     snprintf(g->Message, sizeof(g->Message), "failed GetObject %s in %s\n", classname, nsp);
 | |
|     wp->Svc->Release();
 | |
|     wp->Svc = NULL;    // MUST be set to NULL  (why?)
 | |
|     return NULL;
 | |
|     }  // endif res
 | |
| 
 | |
|   return wp;
 | |
| } // end of InitWMI
 | |
| 
 | |
| /***********************************************************************/
 | |
| /* WMIColumns: constructs the result blocks containing the description */
 | |
| /* of all the columns of a WMI table of a specified class.             */
 | |
| /***********************************************************************/
 | |
| PQRYRES WMIColumns(PGLOBAL g, PCSZ nsp, PCSZ cls, bool info)
 | |
|   {
 | |
|   static int  buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
 | |
|                           TYPE_INT,   TYPE_INT, TYPE_SHORT};
 | |
|   static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE,   FLD_TYPENAME,
 | |
|                           FLD_PREC, FLD_LENGTH, FLD_SCALE};
 | |
|   static unsigned int len, length[] = {0, 6, 8, 10, 10, 6};
 | |
|   int     i = 0, n = 0, ncol = sizeof(buftyp) / sizeof(int);
 | |
|   int     lng, typ, prec;
 | |
|   LONG    low, upp;
 | |
|   BSTR    propname;
 | |
|   VARIANT val;
 | |
|   CIMTYPE type;
 | |
|   HRESULT res;
 | |
|   PWMIUT  wp; 
 | |
|   SAFEARRAY *prnlist = NULL;
 | |
|   PQRYRES qrp = NULL;
 | |
|   PCOLRES crp;
 | |
| 
 | |
|   if (!info) {
 | |
|     /*******************************************************************/
 | |
|     /*  Initialize WMI if not done yet.                                */
 | |
|     /*******************************************************************/
 | |
|     if (!(wp = InitWMI(g, nsp, cls)))
 | |
|       return NULL;
 | |
| 
 | |
|     /*******************************************************************/
 | |
|     /*  Get the number of properties to return.                        */
 | |
|     /*******************************************************************/
 | |
|     res = wp->Cobj->Get(bstr_t("__Property_Count"), 0, &val, NULL, NULL);
 | |
| 
 | |
|     if (FAILED(res)) {
 | |
|       snprintf(g->Message, sizeof(g->Message), "failed Get(__Property_Count) res=%d\n", res);
 | |
|       goto err;
 | |
|       }  // endif res
 | |
| 
 | |
|     if (!(n = val.lVal)) {
 | |
|       snprintf(g->Message, sizeof(g->Message), "Class %s in %s has no properties\n",
 | |
|                           cls, nsp);
 | |
|       goto err;
 | |
|       }  // endif res
 | |
| 
 | |
|     /*******************************************************************/
 | |
|     /*  Get max property name length.                                  */
 | |
|     /*******************************************************************/
 | |
|     res = wp->Cobj->GetNames(NULL, 
 | |
|           WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY, 
 | |
|           NULL, &prnlist);
 | |
| 
 | |
|     if (FAILED(res)) {
 | |
|       snprintf(g->Message, sizeof(g->Message), "failed GetNames res=%d\n", res);
 | |
|       goto err;
 | |
|       }  // endif res
 | |
| 
 | |
|     res = SafeArrayGetLBound(prnlist, 1, &low);
 | |
|     res = SafeArrayGetUBound(prnlist, 1, &upp);
 | |
| 
 | |
|     for (long i = low; i <= upp; i++) {
 | |
|       // Get this property name.
 | |
|       res = SafeArrayGetElement(prnlist, &i, &propname);
 | |
| 
 | |
|       if (FAILED(res)) {
 | |
|         snprintf(g->Message, sizeof(g->Message), "failed GetArrayElement res=%d\n", res);
 | |
|         goto err;
 | |
|         }  // endif res
 | |
| 
 | |
|       len = (unsigned)SysStringLen(propname);
 | |
|       length[0] = MY_MAX(length[0], len);
 | |
|       } // enfor i
 | |
| 
 | |
|     res = SafeArrayDestroy(prnlist);
 | |
|   } else
 | |
|     length[0] = 128;
 | |
| 
 | |
|   /*********************************************************************/
 | |
|   /*  Allocate the structures used to refer to the result set.         */
 | |
|   /*********************************************************************/
 | |
|   qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
 | |
|                           buftyp, fldtyp, length, false, true);
 | |
| 
 | |
|   if (info || !qrp)
 | |
|     return qrp;
 | |
| 
 | |
|   /*********************************************************************/
 | |
|   /*  Now get the results into blocks.                                 */
 | |
|   /*********************************************************************/
 | |
|   res = wp->Cobj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
 | |
| 
 | |
|   if (FAILED(res)) {
 | |
|     snprintf(g->Message, sizeof(g->Message), "failed BeginEnumeration hr=%d\n", res);
 | |
|     qrp = NULL;
 | |
|     goto err;
 | |
|     }  // endif hr
 | |
| 
 | |
|   while (TRUE) {
 | |
|     res = wp->Cobj->Next(0, &propname, &val, &type, NULL);
 | |
| 
 | |
|     if (FAILED(res)) {
 | |
|       snprintf(g->Message, sizeof(g->Message), "failed getting Next hr=%d\n", res);
 | |
|       qrp = NULL;
 | |
|       goto err;
 | |
|     }  else if (res == WBEM_S_NO_MORE_DATA) {
 | |
|       VariantClear(&val);
 | |
|       break;
 | |
|     } // endif res
 | |
| 
 | |
|     if (i >= n)
 | |
|       break;                 // Should never happen
 | |
|     else
 | |
|       prec = 0;
 | |
| 
 | |
|     switch (type) {
 | |
|       case CIM_STRING:
 | |
|         typ = TYPE_STRING;
 | |
|         lng = 255;
 | |
|         prec = 1;   // Case insensitive
 | |
|         break;
 | |
|       case CIM_SINT32:                          
 | |
|       case CIM_UINT32:
 | |
|       case CIM_BOOLEAN:
 | |
|         typ = TYPE_INT;
 | |
|         lng = 11;
 | |
|         break;
 | |
|       case CIM_SINT8:
 | |
|       case CIM_UINT8:
 | |
|         typ = TYPE_TINY;
 | |
|         lng = 4;
 | |
|         break;
 | |
|       case CIM_SINT16:
 | |
|       case CIM_UINT16:
 | |
|         typ = TYPE_SHORT;
 | |
|         lng = 6;
 | |
|         break;
 | |
|       case CIM_REAL64:
 | |
|       case CIM_REAL32:
 | |
|         prec = 2;
 | |
|         typ = TYPE_DOUBLE;
 | |
|         lng = 15;
 | |
|         break;
 | |
|       case CIM_SINT64:
 | |
|       case CIM_UINT64:
 | |
|         typ = TYPE_BIGINT;
 | |
|         lng = 20;
 | |
|         break;
 | |
|       case CIM_DATETIME:
 | |
|         typ = TYPE_DATE;
 | |
|         lng = 19;
 | |
|         break;
 | |
|       case CIM_CHAR16:
 | |
|         typ = TYPE_STRING;
 | |
|         lng = 16;
 | |
|         break;
 | |
|       case CIM_EMPTY:
 | |
|         typ = TYPE_STRING;
 | |
|         lng = 24;             // ???
 | |
|         break;
 | |
|       default:
 | |
|         qrp->BadLines++;
 | |
|         goto suite;
 | |
|       } // endswitch type
 | |
| 
 | |
|     crp = qrp->Colresp;                    // Column Name
 | |
|     crp->Kdata->SetValue(_com_util::ConvertBSTRToString(propname), i);
 | |
|     crp = crp->Next;                       // Data Type
 | |
|     crp->Kdata->SetValue(typ, i);
 | |
|     crp = crp->Next;                       // Type Name
 | |
|     crp->Kdata->SetValue(GetTypeName(typ), i);
 | |
|     crp = crp->Next;                       // Precision
 | |
|     crp->Kdata->SetValue(lng, i);
 | |
|     crp = crp->Next;                       // Length
 | |
|     crp->Kdata->SetValue(lng, i);
 | |
|     crp = crp->Next;                       // Scale (precision)
 | |
|     crp->Kdata->SetValue(prec, i);
 | |
|     i++;
 | |
| 
 | |
|  suite:
 | |
|     SysFreeString(propname);
 | |
|     VariantClear(&val);
 | |
|     } // endfor i
 | |
| 
 | |
|   qrp->Nblin = i;
 | |
| 
 | |
|  err:
 | |
|   // Cleanup
 | |
|   wp->Cobj->Release();
 | |
|   wp->Svc->Release();
 | |
|   wp->Svc = NULL;    // MUST be set to NULL  (why?)
 | |
|   CoUninitialize();
 | |
| 
 | |
|   /*********************************************************************/
 | |
|   /*  Return the result pointer for use by GetData routines.           */
 | |
|   /*********************************************************************/
 | |
|   return qrp;
 | |
|   } // end of WMIColumns
 | |
| 
 | |
| /* -------------- Implementation of the WMI classes  ------------------ */
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  DefineAM: define specific AM values for WMI table.                 */
 | |
| /***********************************************************************/
 | |
| bool WMIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
 | |
|   {
 | |
|   Nspace = GetStringCatInfo(g, "Namespace", "Root\\CimV2");
 | |
|   Wclass = GetStringCatInfo(g, "Class",
 | |
|           (!stricmp(Nspace, "root\\cimv2") ? "ComputerSystemProduct" : 
 | |
|            !stricmp(Nspace, "root\\cli")   ? "Msft_CliAlias" : ""));
 | |
| 
 | |
|   if (!*Wclass) {
 | |
|     snprintf(g->Message, sizeof(g->Message), "Missing class name for %s", Nspace);
 | |
|     return true;
 | |
|   } else if (!strchr(Wclass, '_')) {
 | |
|     char *p = (char*)PlugSubAlloc(g, NULL, strlen(Wclass) + 7);
 | |
|     Wclass = strcat(strcpy(p, "Win32_"), Wclass);
 | |
|   } // endif Wclass
 | |
| 
 | |
|   if (Catfunc == FNC_NO)
 | |
|     Ems = GetIntCatInfo("Estimate", 100);
 | |
| 
 | |
|   return false;
 | |
|   } // end of DefineAM
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  GetTable: makes a new TDB of the proper type.                      */
 | |
| /***********************************************************************/
 | |
| PTDB WMIDEF::GetTable(PGLOBAL g, MODE m)
 | |
|   {
 | |
|   if (Catfunc == FNC_NO)
 | |
|     return new(g) TDBWMI(this);
 | |
|   else if (Catfunc == FNC_COL)
 | |
|     return new(g) TDBWCL(this);
 | |
| 
 | |
|   snprintf(g->Message, sizeof(g->Message), "Bad catfunc %ud for WMI", Catfunc);
 | |
|   return NULL;
 | |
|   } // end of GetTable
 | |
| 
 | |
| /* ------------------------------------------------------------------- */
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  Implementation of the TDBWMI class.                                */
 | |
| /***********************************************************************/
 | |
| TDBWMI::TDBWMI(PWMIDEF tdp) : TDBASE(tdp)
 | |
|   {
 | |
|   Svc = NULL;
 | |
|   Enumerator = NULL;
 | |
|   ClsObj = NULL;
 | |
|   Nspace = tdp->Nspace;
 | |
|   Wclass = tdp->Wclass;
 | |
|   ObjPath = NULL;
 | |
|   Kvp = NULL;
 | |
|   Ems = tdp->Ems;
 | |
|   Kcol = NULL;
 | |
|   Vbp = NULL;
 | |
|   Init = false;
 | |
|   Done = false;
 | |
|   Res = 0;
 | |
|   Rc = 0;
 | |
|   N = -1;
 | |
|   } // end of TDBWMI constructor
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  Allocate WMI column description block.                             */
 | |
| /***********************************************************************/
 | |
| PCOL TDBWMI::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
 | |
|   {
 | |
|   PCOL colp;
 | |
| 
 | |
|   colp = new(g) WMICOL(cdp, this, n);
 | |
| 
 | |
|   if (cprec) {
 | |
|     colp->SetNext(cprec->GetNext());
 | |
|     cprec->SetNext(colp);
 | |
|   } else {
 | |
|     colp->SetNext(Columns);
 | |
|     Columns = colp;
 | |
|   } // endif cprec
 | |
| 
 | |
|   return colp;
 | |
|   } // end of MakeCol
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  Initialize: Initialize WMI operations.                             */
 | |
| /***********************************************************************/
 | |
| bool TDBWMI::Initialize(PGLOBAL g)
 | |
|   {
 | |
|   if (Init)
 | |
|     return false;
 | |
| 
 | |
|   // Initialize COM.
 | |
|   Res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
 | |
| 
 | |
|   if (FAILED(Res)) {
 | |
|     snprintf(g->Message, sizeof(g->Message), "Failed to initialize COM library. "
 | |
|             "Error code = %x", Res);
 | |
|     return true;              // Program has failed.
 | |
|     } // endif Res
 | |
| 
 | |
|   // Obtain the initial locator to Windows Management
 | |
|   // on a particular host computer.
 | |
|   IWbemLocator *loc;        // Initial Windows Management locator
 | |
| 
 | |
|   Res = CoCreateInstance(CLSID_WbemLocator, 0,  CLSCTX_INPROC_SERVER, 
 | |
|                          IID_IWbemLocator, (LPVOID*) &loc);
 | |
|  
 | |
|   if (FAILED(Res)) {
 | |
|     snprintf(g->Message, sizeof(g->Message), "Failed to create Locator. "
 | |
|              "Error code = %x", Res);
 | |
|     CoUninitialize();
 | |
|     return true;       // Program has failed.
 | |
|     }  // endif Res
 | |
| 
 | |
|   // Connect to the specified namespace with the
 | |
|   // current user and obtain pointer to Svc
 | |
|   // to make IWbemServices calls.
 | |
|   Res = loc->ConnectServer(_bstr_t(Nspace),
 | |
|                              NULL, NULL,0, NULL, 0, 0, &Svc);
 | |
|   
 | |
|   if (FAILED(Res)) {
 | |
|     snprintf(g->Message, sizeof(g->Message), "Could not connect. Error code = %x", Res); 
 | |
|     loc->Release();     
 | |
|     CoUninitialize();
 | |
|     return true;                // Program has failed.
 | |
|     }  // endif hres
 | |
| 
 | |
|   loc->Release();                // Not used anymore
 | |
| 
 | |
|   // Set the IWbemServices proxy so that impersonation
 | |
|   // of the user (client) occurs.
 | |
|   Res = CoSetProxyBlanket(Svc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, 
 | |
|                           NULL, RPC_C_AUTHN_LEVEL_CALL,
 | |
|                           RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
 | |
| 
 | |
|   if (FAILED(Res)) {
 | |
|     snprintf(g->Message, sizeof(g->Message), "Could not set proxy. Error code = %x", Res);
 | |
|     Svc->Release();
 | |
|     CoUninitialize();
 | |
|     return true;               // Program has failed.
 | |
|     }  // endif Res
 | |
| 
 | |
|   Init = true;
 | |
|   return false;
 | |
|   } // end of Initialize
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  Changes '\' into '\\' in the filter.                               */
 | |
| /***********************************************************************/
 | |
| void TDBWMI::DoubleSlash(PGLOBAL g)
 | |
|   {
 | |
|   if (To_CondFil && strchr(To_CondFil->Body, '\\')) {
 | |
|     char *body = To_CondFil->Body;
 | |
|     char *buf = (char*)PlugSubAlloc(g, NULL, strlen(body) * 2);
 | |
|     int   i = 0, k = 0;
 | |
| 
 | |
|     do {
 | |
|       if (body[i] == '\\')
 | |
|         buf[k++] = '\\';
 | |
| 
 | |
|       buf[k++] = body[i];
 | |
|       } while (body[i++]);
 | |
| 
 | |
|     To_CondFil->Body = buf;
 | |
|     } // endif To_CondFil
 | |
| 
 | |
|   } // end of DoubleSlash
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  MakeWQL: make the WQL statement use with WMI ExecQuery.            */
 | |
| /***********************************************************************/
 | |
| char *TDBWMI::MakeWQL(PGLOBAL g)
 | |
|   {
 | |
|   char  *colist, *wql/*, *pw = NULL*/;
 | |
|   int    len, ncol = 0;
 | |
|   bool   first = true, noloc = false;
 | |
|   PCOL   colp;
 | |
| 
 | |
|   // Normal WQL statement to retrieve results
 | |
|   for (colp = Columns; colp; colp = colp->GetNext())
 | |
|     if (!colp->IsSpecial() && (colp->GetColUse(U_P | U_J_EXT) || noloc))
 | |
|       ncol++;
 | |
| 
 | |
|   if (ncol) {
 | |
|     size_t colist_sz = (NAM_LEN + 4) * ncol;
 | |
|     colist = (char*)PlugSubAlloc(g, NULL, colist_sz);
 | |
| 
 | |
|     for (colp = Columns; colp; colp = colp->GetNext())
 | |
|       if (!colp->IsSpecial()) {
 | |
|         if (colp->GetResultType() == TYPE_DATE)
 | |
|           ((DTVAL*)colp->GetValue())->SetFormat(g, "YYYYMMDDhhmmss", 19);
 | |
| 
 | |
|         if (colp->GetColUse(U_P | U_J_EXT) || noloc) {
 | |
|           if (first) {
 | |
|             snprintf(colist, colist_sz, colp->GetName());
 | |
|             first = false;
 | |
|           } else {
 | |
|             strcat(strcat(colist, ", "), colp->GetName());
 | |
|             safe_strcat(colist, colist_sz, ", ");
 | |
|             safe_strcat(colist, colist_sz, colp->GetName());
 | |
|           }
 | |
|       
 | |
|           } // endif ColUse
 | |
| 
 | |
|         } // endif Special
 | |
| 
 | |
|   } else {
 | |
|     // ncol == 0 can occur for queries such that sql count(*) from...
 | |
|     // for which we will count the rows from sql * from...
 | |
|     colist = (char*)PlugSubAlloc(g, NULL, 2);
 | |
|     snprintf(colist, 2, "*");
 | |
|   } // endif ncol
 | |
| 
 | |
|   // Below 14 is length of 'select ' + length of ' from ' + 1
 | |
|   len = (strlen(colist) + strlen(Wclass) + 14);
 | |
|   len += (To_CondFil ? strlen(To_CondFil->Body) + 7 : 0);
 | |
|   wql = (char*)PlugSubAlloc(g, NULL, len);
 | |
|   snprintf(wql, len, "SELECT %s FROM %s", colist, Wclass);
 | |
| 
 | |
|   if (To_CondFil) {
 | |
|     safe_strcat(wql, len, " WHERE ");
 | |
|     safe_strcat(wql, len, To_CondFil->Body);
 | |
|   }
 | |
| 
 | |
|   return wql;
 | |
|   } // end of MakeWQL
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  GetWMIInfo: Get info for the WMI class.                            */
 | |
| /***********************************************************************/
 | |
| bool TDBWMI::GetWMIInfo(PGLOBAL g)
 | |
|   {
 | |
|   if (Done)
 | |
|     return false;
 | |
| 
 | |
|   char *cmd = MakeWQL(g);
 | |
| 
 | |
|   if (cmd == NULL) {
 | |
|     snprintf(g->Message, sizeof(g->Message), "Error making WQL statement");
 | |
|     Svc->Release();
 | |
|     CoUninitialize();
 | |
|     return true;               // Program has failed.
 | |
|     }  // endif cmd
 | |
| 
 | |
|   // Query for Wclass in Nspace
 | |
|   Rc = Svc->ExecQuery(bstr_t("WQL"), bstr_t(cmd),
 | |
| //    WBEM_FLAG_BIDIRECTIONAL | WBEM_FLAG_RETURN_IMMEDIATELY, 
 | |
|       WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
 | |
|       NULL, &Enumerator);
 | |
|   
 | |
|   if (FAILED(Rc)) {
 | |
|     snprintf(g->Message, sizeof(g->Message), "Query %s failed. Error code = %x", cmd, Rc);
 | |
|     Svc->Release();
 | |
|     CoUninitialize();
 | |
|     return true;               // Program has failed.
 | |
|     }  // endif Rc
 | |
| 
 | |
|   Done = true;
 | |
|   return false;
 | |
|   } // end of GetWMIInfo
 | |
| 
 | |
| /***********************************************************************/
 | |
| /*  WMI: Get the number returned instances.                            */
 | |
| /***********************************************************************/
 | |
| int TDBWMI::GetMaxSize(PGLOBAL g)
 | |
|   {
 | |
|   if (MaxSize < 0) {
 | |
|     /*******************************************************************/
 | |
|     /*  Loop enumerating to get the count. This is prone to last a     */
 | |
|     /*  very long time for some classes such as DataFile, this is why  */
 | |
|     /*  we just return an estimated value that will be adjusted 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++;
 | |
|       } // endwhile 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
 | |
| 
 | |
| 
 | 
