1 /***********************************************************************/
2 /*  TABWMI: Author Olivier Bertrand -- PlugDB -- 2012 - 2017           */
3 /*  TABWMI: Virtual table to get WMI information.                      */
4 /***********************************************************************/
5 #if !defined(_WIN32)
6 #error This is a WINDOWS only table type
7 #endif   // !_WIN32
8 #include "my_global.h"
9 #include <stdio.h>
10 
11 #include "global.h"
12 #include "plgdbsem.h"
13 #include "mycat.h"
14 //#include "reldef.h"
15 #include "xtable.h"
16 #include "tabext.h"
17 #include "colblk.h"
18 //#include "filter.h"
19 //#include "xindex.h"
20 #include "tabwmi.h"
21 #include "valblk.h"
22 #include "plgcnx.h"                       // For DB types
23 #include "resource.h"
24 
25 /* ------------------- Functions WMI Column info --------------------- */
26 
27 /***********************************************************************/
28 /*  Initialize WMI operations.                                         */
29 /***********************************************************************/
InitWMI(PGLOBAL g,PCSZ nsp,PCSZ classname)30 PWMIUT InitWMI(PGLOBAL g, PCSZ nsp, PCSZ classname)
31 {
32   IWbemLocator *loc;
33   char         *p;
34   HRESULT       res;
35   PWMIUT        wp = (PWMIUT)PlugSubAlloc(g, NULL, sizeof(WMIUTIL));
36 
37   if (trace(1))
38     htrc("WMIColumns class %s space %s\n", SVP(classname), SVP(nsp));
39 
40   /*********************************************************************/
41   /*  Set default values for the namespace and class name.             */
42   /*********************************************************************/
43   if (!nsp)
44     nsp = "root\\cimv2";
45 
46   if (!classname) {
47     if (!stricmp(nsp, "root\\cimv2"))
48       classname = "ComputerSystemProduct";
49     else if (!stricmp(nsp, "root\\cli"))
50       classname = "Msft_CliAlias";
51     else {
52       strcpy(g->Message, "Missing class name");
53       return NULL;
54       } // endif classname
55 
56     } // endif classname
57 
58   /*********************************************************************/
59   /*  Initialize WMI.                                                  */
60   /*********************************************************************/
61 //res = CoInitializeEx(NULL, COINIT_MULTITHREADED);
62   res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
63 
64   if (FAILED(res)) {
65     sprintf(g->Message, "Failed to initialize COM library. "
66             "Error code = %x", res);
67     return NULL;
68     } // endif res
69 
70 #if 0 // irrelevant for a DLL
71   res = CoInitializeSecurity(NULL, -1, NULL, NULL,
72                        RPC_C_AUTHN_LEVEL_CONNECT,
73                        RPC_C_IMP_LEVEL_IMPERSONATE,
74                        NULL, EOAC_NONE, NULL);
75 
76   if (res != RPC_E_TOO_LATE && FAILED(res)) {
77     sprintf(g->Message, "Failed to initialize security. "
78             "Error code = %p", res);
79     CoUninitialize();
80     return NULL;
81     }  // endif Res
82 #endif // 0
83 
84   res = CoCreateInstance(CLSID_WbemLocator, NULL,
85                          CLSCTX_INPROC_SERVER, IID_IWbemLocator,
86                          (void**) &loc);
87   if (FAILED(res)) {
88     sprintf(g->Message, "Failed to create Locator. "
89             "Error code = %x", res);
90     CoUninitialize();
91     return NULL;
92     }  // endif res
93 
94   res = loc->ConnectServer(_bstr_t(nsp),
95                     NULL, NULL, NULL, 0, NULL, NULL, &wp->Svc);
96 
97   if (FAILED(res)) {
98     sprintf(g->Message, "Could not connect. Error code = %x", res);
99     loc->Release();
100     CoUninitialize();
101     return NULL;
102     }  // endif res
103 
104   loc->Release();
105 
106   if (trace(1))
107     htrc("Successfully connected to namespace.\n");
108 
109   /*********************************************************************/
110   /*  Perform a full class object retrieval.                           */
111   /*********************************************************************/
112   p = (char*)PlugSubAlloc(g, NULL, strlen(classname) + 7);
113 
114   if (strchr(classname, '_'))
115     strcpy(p, classname);
116   else
117     strcat(strcpy(p, "Win32_"), classname);
118 
119   res = wp->Svc->GetObject(bstr_t(p), 0, 0, &wp->Cobj, 0);
120 
121   if (FAILED(res)) {
122     sprintf(g->Message, "failed GetObject %s in %s\n", classname, nsp);
123     wp->Svc->Release();
124     wp->Svc = NULL;    // MUST be set to NULL  (why?)
125     return NULL;
126     }  // endif res
127 
128   return wp;
129 } // end of InitWMI
130 
131 /***********************************************************************/
132 /* WMIColumns: constructs the result blocks containing the description */
133 /* of all the columns of a WMI table of a specified class.             */
134 /***********************************************************************/
WMIColumns(PGLOBAL g,PCSZ nsp,PCSZ cls,bool info)135 PQRYRES WMIColumns(PGLOBAL g, PCSZ nsp, PCSZ cls, bool info)
136   {
137   static int  buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
138                           TYPE_INT,   TYPE_INT, TYPE_SHORT};
139   static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE,   FLD_TYPENAME,
140                           FLD_PREC, FLD_LENGTH, FLD_SCALE};
141   static unsigned int len, length[] = {0, 6, 8, 10, 10, 6};
142   int     i = 0, n = 0, ncol = sizeof(buftyp) / sizeof(int);
143   int     lng, typ, prec;
144   LONG    low, upp;
145   BSTR    propname;
146   VARIANT val;
147   CIMTYPE type;
148   HRESULT res;
149   PWMIUT  wp;
150   SAFEARRAY *prnlist = NULL;
151   PQRYRES qrp = NULL;
152   PCOLRES crp;
153 
154   if (!info) {
155     /*******************************************************************/
156     /*  Initialize WMI if not done yet.                                */
157     /*******************************************************************/
158     if (!(wp = InitWMI(g, nsp, cls)))
159       return NULL;
160 
161     /*******************************************************************/
162     /*  Get the number of properties to return.                        */
163     /*******************************************************************/
164     res = wp->Cobj->Get(bstr_t("__Property_Count"), 0, &val, NULL, NULL);
165 
166     if (FAILED(res)) {
167       sprintf(g->Message, "failed Get(__Property_Count) res=%d\n", res);
168       goto err;
169       }  // endif res
170 
171     if (!(n = val.lVal)) {
172       sprintf(g->Message, "Class %s in %s has no properties\n",
173                           cls, nsp);
174       goto err;
175       }  // endif res
176 
177     /*******************************************************************/
178     /*  Get max property name length.                                  */
179     /*******************************************************************/
180     res = wp->Cobj->GetNames(NULL,
181           WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY,
182           NULL, &prnlist);
183 
184     if (FAILED(res)) {
185       sprintf(g->Message, "failed GetNames res=%d\n", res);
186       goto err;
187       }  // endif res
188 
189     res = SafeArrayGetLBound(prnlist, 1, &low);
190     res = SafeArrayGetUBound(prnlist, 1, &upp);
191 
192     for (long i = low; i <= upp; i++) {
193       // Get this property name.
194       res = SafeArrayGetElement(prnlist, &i, &propname);
195 
196       if (FAILED(res)) {
197         sprintf(g->Message, "failed GetArrayElement res=%d\n", res);
198         goto err;
199         }  // endif res
200 
201       len = (unsigned)SysStringLen(propname);
202       length[0] = MY_MAX(length[0], len);
203       } // enfor i
204 
205     res = SafeArrayDestroy(prnlist);
206   } else
207     length[0] = 128;
208 
209   /*********************************************************************/
210   /*  Allocate the structures used to refer to the result set.         */
211   /*********************************************************************/
212   qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
213                           buftyp, fldtyp, length, false, true);
214 
215   if (info || !qrp)
216     return qrp;
217 
218   /*********************************************************************/
219   /*  Now get the results into blocks.                                 */
220   /*********************************************************************/
221   res = wp->Cobj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
222 
223   if (FAILED(res)) {
224     sprintf(g->Message, "failed BeginEnumeration hr=%d\n", res);
225     qrp = NULL;
226     goto err;
227     }  // endif hr
228 
229   while (TRUE) {
230     res = wp->Cobj->Next(0, &propname, &val, &type, NULL);
231 
232     if (FAILED(res)) {
233       sprintf(g->Message, "failed getting Next hr=%d\n", res);
234       qrp = NULL;
235       goto err;
236     }  else if (res == WBEM_S_NO_MORE_DATA) {
237       VariantClear(&val);
238       break;
239     } // endif res
240 
241     if (i >= n)
242       break;                 // Should never happen
243     else
244       prec = 0;
245 
246     switch (type) {
247       case CIM_STRING:
248         typ = TYPE_STRING;
249         lng = 255;
250         prec = 1;   // Case insensitive
251         break;
252       case CIM_SINT32:
253       case CIM_UINT32:
254       case CIM_BOOLEAN:
255         typ = TYPE_INT;
256         lng = 11;
257         break;
258       case CIM_SINT8:
259       case CIM_UINT8:
260         typ = TYPE_TINY;
261         lng = 4;
262         break;
263       case CIM_SINT16:
264       case CIM_UINT16:
265         typ = TYPE_SHORT;
266         lng = 6;
267         break;
268       case CIM_REAL64:
269       case CIM_REAL32:
270         prec = 2;
271         typ = TYPE_DOUBLE;
272         lng = 15;
273         break;
274       case CIM_SINT64:
275       case CIM_UINT64:
276         typ = TYPE_BIGINT;
277         lng = 20;
278         break;
279       case CIM_DATETIME:
280         typ = TYPE_DATE;
281         lng = 19;
282         break;
283       case CIM_CHAR16:
284         typ = TYPE_STRING;
285         lng = 16;
286         break;
287       case CIM_EMPTY:
288         typ = TYPE_STRING;
289         lng = 24;             // ???
290         break;
291       default:
292         qrp->BadLines++;
293         goto suite;
294       } // endswitch type
295 
296     crp = qrp->Colresp;                    // Column Name
297     crp->Kdata->SetValue(_com_util::ConvertBSTRToString(propname), i);
298     crp = crp->Next;                       // Data Type
299     crp->Kdata->SetValue(typ, i);
300     crp = crp->Next;                       // Type Name
301     crp->Kdata->SetValue(GetTypeName(typ), i);
302     crp = crp->Next;                       // Precision
303     crp->Kdata->SetValue(lng, i);
304     crp = crp->Next;                       // Length
305     crp->Kdata->SetValue(lng, i);
306     crp = crp->Next;                       // Scale (precision)
307     crp->Kdata->SetValue(prec, i);
308     i++;
309 
310  suite:
311     SysFreeString(propname);
312     VariantClear(&val);
313     } // endfor i
314 
315   qrp->Nblin = i;
316 
317  err:
318   // Cleanup
319   wp->Cobj->Release();
320   wp->Svc->Release();
321   wp->Svc = NULL;    // MUST be set to NULL  (why?)
322   CoUninitialize();
323 
324   /*********************************************************************/
325   /*  Return the result pointer for use by GetData routines.           */
326   /*********************************************************************/
327   return qrp;
328   } // end of WMIColumns
329 
330 /* -------------- Implementation of the WMI classes  ------------------ */
331 
332 /***********************************************************************/
333 /*  DefineAM: define specific AM values for WMI table.                 */
334 /***********************************************************************/
DefineAM(PGLOBAL g,LPCSTR am,int poff)335 bool WMIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
336   {
337   Nspace = GetStringCatInfo(g, "Namespace", "Root\\CimV2");
338   Wclass = GetStringCatInfo(g, "Class",
339           (!stricmp(Nspace, "root\\cimv2") ? "ComputerSystemProduct" :
340            !stricmp(Nspace, "root\\cli")   ? "Msft_CliAlias" : ""));
341 
342   if (!*Wclass) {
343     sprintf(g->Message, "Missing class name for %s", Nspace);
344     return true;
345   } else if (!strchr(Wclass, '_')) {
346     char *p = (char*)PlugSubAlloc(g, NULL, strlen(Wclass) + 7);
347     Wclass = strcat(strcpy(p, "Win32_"), Wclass);
348   } // endif Wclass
349 
350   if (Catfunc == FNC_NO)
351     Ems = GetIntCatInfo("Estimate", 100);
352 
353   return false;
354   } // end of DefineAM
355 
356 /***********************************************************************/
357 /*  GetTable: makes a new TDB of the proper type.                      */
358 /***********************************************************************/
GetTable(PGLOBAL g,MODE m)359 PTDB WMIDEF::GetTable(PGLOBAL g, MODE m)
360   {
361   if (Catfunc == FNC_NO)
362     return new(g) TDBWMI(this);
363   else if (Catfunc == FNC_COL)
364     return new(g) TDBWCL(this);
365 
366   sprintf(g->Message, "Bad catfunc %ud for WMI", Catfunc);
367   return NULL;
368   } // end of GetTable
369 
370 /* ------------------------------------------------------------------- */
371 
372 /***********************************************************************/
373 /*  Implementation of the TDBWMI class.                                */
374 /***********************************************************************/
TDBWMI(PWMIDEF tdp)375 TDBWMI::TDBWMI(PWMIDEF tdp) : TDBASE(tdp)
376   {
377   Svc = NULL;
378   Enumerator = NULL;
379   ClsObj = NULL;
380   Nspace = tdp->Nspace;
381   Wclass = tdp->Wclass;
382   ObjPath = NULL;
383   Kvp = NULL;
384   Ems = tdp->Ems;
385   Kcol = NULL;
386   Vbp = NULL;
387   Init = false;
388   Done = false;
389   Res = 0;
390   Rc = 0;
391   N = -1;
392   } // end of TDBWMI constructor
393 
394 /***********************************************************************/
395 /*  Allocate WMI column description block.                             */
396 /***********************************************************************/
MakeCol(PGLOBAL g,PCOLDEF cdp,PCOL cprec,int n)397 PCOL TDBWMI::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
398   {
399   PCOL colp;
400 
401   colp = new(g) WMICOL(cdp, this, n);
402 
403   if (cprec) {
404     colp->SetNext(cprec->GetNext());
405     cprec->SetNext(colp);
406   } else {
407     colp->SetNext(Columns);
408     Columns = colp;
409   } // endif cprec
410 
411   return colp;
412   } // end of MakeCol
413 
414 /***********************************************************************/
415 /*  Initialize: Initialize WMI operations.                             */
416 /***********************************************************************/
Initialize(PGLOBAL g)417 bool TDBWMI::Initialize(PGLOBAL g)
418   {
419   if (Init)
420     return false;
421 
422   // Initialize COM.
423   Res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
424 
425   if (FAILED(Res)) {
426     sprintf(g->Message, "Failed to initialize COM library. "
427             "Error code = %x", Res);
428     return true;              // Program has failed.
429     } // endif Res
430 
431   // Obtain the initial locator to Windows Management
432   // on a particular host computer.
433   IWbemLocator *loc;        // Initial Windows Management locator
434 
435   Res = CoCreateInstance(CLSID_WbemLocator, 0,  CLSCTX_INPROC_SERVER,
436                          IID_IWbemLocator, (LPVOID*) &loc);
437 
438   if (FAILED(Res)) {
439     sprintf(g->Message, "Failed to create Locator. "
440                         "Error code = %x", Res);
441     CoUninitialize();
442     return true;       // Program has failed.
443     }  // endif Res
444 
445   // Connect to the specified namespace with the
446   // current user and obtain pointer to Svc
447   // to make IWbemServices calls.
448   Res = loc->ConnectServer(_bstr_t(Nspace),
449                              NULL, NULL,0, NULL, 0, 0, &Svc);
450 
451   if (FAILED(Res)) {
452     sprintf(g->Message, "Could not connect. Error code = %x", Res);
453     loc->Release();
454     CoUninitialize();
455     return true;                // Program has failed.
456     }  // endif hres
457 
458   loc->Release();                // Not used anymore
459 
460   // Set the IWbemServices proxy so that impersonation
461   // of the user (client) occurs.
462   Res = CoSetProxyBlanket(Svc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE,
463                           NULL, RPC_C_AUTHN_LEVEL_CALL,
464                           RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
465 
466   if (FAILED(Res)) {
467     sprintf(g->Message, "Could not set proxy. Error code = %x", Res);
468     Svc->Release();
469     CoUninitialize();
470     return true;               // Program has failed.
471     }  // endif Res
472 
473   Init = true;
474   return false;
475   } // end of Initialize
476 
477 /***********************************************************************/
478 /*  Changes '\' into '\\' in the filter.                               */
479 /***********************************************************************/
DoubleSlash(PGLOBAL g)480 void TDBWMI::DoubleSlash(PGLOBAL g)
481   {
482   if (To_CondFil && strchr(To_CondFil->Body, '\\')) {
483     char *body = To_CondFil->Body;
484     char *buf = (char*)PlugSubAlloc(g, NULL, strlen(body) * 2);
485     int   i = 0, k = 0;
486 
487     do {
488       if (body[i] == '\\')
489         buf[k++] = '\\';
490 
491       buf[k++] = body[i];
492       } while (body[i++]);
493 
494     To_CondFil->Body = buf;
495     } // endif To_CondFil
496 
497   } // end of DoubleSlash
498 
499 /***********************************************************************/
500 /*  MakeWQL: make the WQL statement use with WMI ExecQuery.            */
501 /***********************************************************************/
MakeWQL(PGLOBAL g)502 char *TDBWMI::MakeWQL(PGLOBAL g)
503   {
504   char  *colist, *wql/*, *pw = NULL*/;
505   int    len, ncol = 0;
506   bool   first = true, noloc = false;
507   PCOL   colp;
508 
509   // Normal WQL statement to retrieve results
510   for (colp = Columns; colp; colp = colp->GetNext())
511     if (!colp->IsSpecial() && (colp->GetColUse(U_P | U_J_EXT) || noloc))
512       ncol++;
513 
514   if (ncol) {
515     colist = (char*)PlugSubAlloc(g, NULL, (NAM_LEN + 4) * ncol);
516 
517     for (colp = Columns; colp; colp = colp->GetNext())
518       if (!colp->IsSpecial()) {
519         if (colp->GetResultType() == TYPE_DATE)
520           ((DTVAL*)colp->GetValue())->SetFormat(g, "YYYYMMDDhhmmss", 19);
521 
522         if (colp->GetColUse(U_P | U_J_EXT) || noloc) {
523           if (first) {
524             strcpy(colist, colp->GetName());
525             first = false;
526           } else
527             strcat(strcat(colist, ", "), colp->GetName());
528 
529           } // endif ColUse
530 
531         } // endif Special
532 
533   } else {
534     // ncol == 0 can occur for queries such that sql count(*) from...
535     // for which we will count the rows from sql * from...
536     colist = (char*)PlugSubAlloc(g, NULL, 2);
537     strcpy(colist, "*");
538   } // endif ncol
539 
540   // Below 14 is length of 'select ' + length of ' from ' + 1
541   len = (strlen(colist) + strlen(Wclass) + 14);
542   len += (To_CondFil ? strlen(To_CondFil->Body) + 7 : 0);
543   wql = (char*)PlugSubAlloc(g, NULL, len);
544   strcat(strcat(strcpy(wql, "SELECT "), colist), " FROM ");
545   strcat(wql, Wclass);
546 
547   if (To_CondFil)
548     strcat(strcat(wql, " WHERE "), To_CondFil->Body);
549 
550   return wql;
551   } // end of MakeWQL
552 
553 /***********************************************************************/
554 /*  GetWMIInfo: Get info for the WMI class.                            */
555 /***********************************************************************/
GetWMIInfo(PGLOBAL g)556 bool TDBWMI::GetWMIInfo(PGLOBAL g)
557   {
558   if (Done)
559     return false;
560 
561   char *cmd = MakeWQL(g);
562 
563   if (cmd == NULL) {
564     sprintf(g->Message, "Error making WQL statement");
565     Svc->Release();
566     CoUninitialize();
567     return true;               // Program has failed.
568     }  // endif cmd
569 
570   // Query for Wclass in Nspace
571   Rc = Svc->ExecQuery(bstr_t("WQL"), bstr_t(cmd),
572 //    WBEM_FLAG_BIDIRECTIONAL | WBEM_FLAG_RETURN_IMMEDIATELY,
573       WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
574       NULL, &Enumerator);
575 
576   if (FAILED(Rc)) {
577     sprintf(g->Message, "Query %s failed. Error code = %x", cmd, Rc);
578     Svc->Release();
579     CoUninitialize();
580     return true;               // Program has failed.
581     }  // endif Rc
582 
583   Done = true;
584   return false;
585   } // end of GetWMIInfo
586 
587 /***********************************************************************/
588 /*  WMI: Get the number returned instances.                            */
589 /***********************************************************************/
GetMaxSize(PGLOBAL g)590 int TDBWMI::GetMaxSize(PGLOBAL g)
591   {
592   if (MaxSize < 0) {
593     /*******************************************************************/
594     /*  Loop enumerating to get the count. This is prone to last a     */
595     /*  very long time for some classes such as DataFile, this is why  */
596     /*  we just return an estimated value that will be ajusted later.  */
597     /*******************************************************************/
598     MaxSize = Ems;
599 #if 0
600     if (Initialize(g))
601       return -1;
602     else if (GetWMIInfo(g))
603       return -1;
604     else
605       MaxSize = 0;
606 
607     PDBUSER dup = PlgGetUser(g);
608 
609     while (Enumerator) {
610       Res = Enumerator->Next(WBEM_INFINITE, 1, &ClsObj, &Rc);
611 
612       if (Rc == 0)
613         break;
614 
615       MaxSize++;
616       } // endwile Enumerator
617 
618     Res = Enumerator->Reset();
619 #endif // 0
620     } // endif MaxSize
621 
622   return MaxSize;
623   } // end of GetMaxSize
624 
625 /***********************************************************************/
626 /*  When making a Kindex, must provide the Key column info.            */
627 /***********************************************************************/
GetRecpos(void)628 int TDBWMI::GetRecpos(void)
629   {
630   if (!Kcol || !Vbp)
631     return N;
632 
633   Kcol->Reset();
634   Kcol->Eval(NULL);
635   Vbp->SetValue(Kcol->GetValue(), N);
636   return N;
637   }  // end of GetRecpos
638 
639 /***********************************************************************/
640 /*  WMI Access Method opening routine.                                 */
641 /***********************************************************************/
OpenDB(PGLOBAL g)642 bool TDBWMI::OpenDB(PGLOBAL g)
643   {
644   if (Use == USE_OPEN) {
645     /*******************************************************************/
646     /*  Table already open.                                            */
647     /*******************************************************************/
648     Res = Enumerator->Reset();
649     N = 0;
650     return false;
651     } // endif use
652 
653   if (Mode != MODE_READ) {
654     /*******************************************************************/
655     /* WMI tables cannot be modified.                                  */
656     /*******************************************************************/
657     strcpy(g->Message, "WMI tables are read only");
658     return true;
659     } // endif Mode
660 
661   if (!To_CondFil && !stricmp(Wclass, "CIM_Datafile")
662                   && !stricmp(Nspace, "root\\cimv2")) {
663     strcpy(g->Message,
664       "Would last forever when not filtered, use DIR table instead");
665     return true;
666   } else
667     DoubleSlash(g);
668 
669   Use = USE_OPEN;       // Do it now in case we are recursively called
670 
671   /*********************************************************************/
672   /*  Initialize the WMI processing.                                   */
673   /*********************************************************************/
674   if (Initialize(g))
675     return true;
676   else
677     return GetWMIInfo(g);
678 
679   } // end of OpenDB
680 
681 /***********************************************************************/
682 /*  Data Base read routine for WMI access method.                      */
683 /***********************************************************************/
ReadDB(PGLOBAL g)684 int TDBWMI::ReadDB(PGLOBAL g)
685   {
686   Res = Enumerator->Next(WBEM_INFINITE, 1, &ClsObj, &Rc);
687 
688   if (Rc == 0)
689     return RC_EF;
690 
691   N++;
692   return RC_OK;
693   } // end of ReadDB
694 
695 /***********************************************************************/
696 /*  WriteDB: Data Base write routine for WMI access methods.           */
697 /***********************************************************************/
WriteDB(PGLOBAL g)698 int TDBWMI::WriteDB(PGLOBAL g)
699   {
700   strcpy(g->Message, "WMI tables are read only");
701   return RC_FX;
702   } // end of WriteDB
703 
704 /***********************************************************************/
705 /*  Data Base delete line routine for WMI access methods.              */
706 /***********************************************************************/
DeleteDB(PGLOBAL g,int irc)707 int TDBWMI::DeleteDB(PGLOBAL g, int irc)
708   {
709   strcpy(g->Message, "Delete not enabled for WMI tables");
710   return RC_FX;
711   } // end of DeleteDB
712 
713 /***********************************************************************/
714 /*  Data Base close routine for WMI access method.                     */
715 /***********************************************************************/
CloseDB(PGLOBAL g)716 void TDBWMI::CloseDB(PGLOBAL g)
717   {
718   // Cleanup
719   if (ClsObj)
720     ClsObj->Release();
721 
722   if (Enumerator)
723     Enumerator->Release();
724 
725   if (Svc)
726     Svc->Release();
727 
728   CoUninitialize();
729   } // end of CloseDB
730 
731 // ------------------------ WMICOL functions ----------------------------
732 
733 /***********************************************************************/
734 /*  WMICOL public constructor.                                         */
735 /***********************************************************************/
WMICOL(PCOLDEF cdp,PTDB tdbp,int n)736 WMICOL::WMICOL(PCOLDEF cdp, PTDB tdbp, int n)
737       : COLBLK(cdp, tdbp, n)
738   {
739   Tdbp = (PTDBWMI)tdbp;
740   VariantInit(&Prop);
741   Ctype = CIM_ILLEGAL;
742   Res = 0;
743   } // end of WMICOL constructor
744 
745 #if 0
746 /***********************************************************************/
747 /*  WMICOL constructor used for copying columns.                       */
748 /*  tdbp is the pointer to the new table descriptor.                   */
749 /***********************************************************************/
750 WMICOL::WMICOL(WMICOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
751   {
752   } // end of WMICOL copy constructor
753 #endif // 0
754 
755 /***********************************************************************/
756 /*  Read the next WMI address elements.                                */
757 /***********************************************************************/
ReadColumn(PGLOBAL g)758 void WMICOL::ReadColumn(PGLOBAL g)
759   {
760   // Get the value of the Name property
761   Res = Tdbp->ClsObj->Get(_bstr_t(Name), 0, &Prop, &Ctype, 0);
762 
763   switch (Prop.vt) {
764     case VT_EMPTY:
765     case VT_NULL:
766     case VT_VOID:
767       Value->Reset();
768       break;
769     case VT_BSTR:
770       Value->SetValue_psz(_com_util::ConvertBSTRToString(Prop.bstrVal));
771       break;
772     case VT_I4:
773     case VT_UI4:
774       Value->SetValue(Prop.lVal);
775       break;
776     case VT_I2:
777     case VT_UI2:
778       Value->SetValue(Prop.iVal);
779       break;
780     case VT_INT:
781     case VT_UINT:
782       Value->SetValue((int)Prop.intVal);
783       break;
784     case VT_BOOL:
785       Value->SetValue(((int)Prop.boolVal) ? 1 : 0);
786       break;
787     case VT_R8:
788       Value->SetValue(Prop.dblVal);
789       break;
790     case VT_R4:
791       Value->SetValue((double)Prop.fltVal);
792       break;
793     case VT_DATE:
794       switch (Value->GetType()) {
795         case TYPE_DATE:
796          {SYSTEMTIME stm;
797           struct tm  ptm;
798           int        rc = VariantTimeToSystemTime(Prop.date, &stm);
799 
800           ptm.tm_year = stm.wYear;
801           ptm.tm_mon  = stm.wMonth;
802           ptm.tm_mday  = stm.wDay;
803           ptm.tm_hour = stm.wHour;
804           ptm.tm_min  = stm.wMinute;
805           ptm.tm_sec  = stm.wSecond;
806           ((DTVAL*)Value)->MakeTime(&ptm);
807          }break;
808         case TYPE_STRING:
809          {SYSTEMTIME stm;
810           char       buf[24];
811           int        rc = VariantTimeToSystemTime(Prop.date, &stm);
812 
813           sprintf(buf, "%02d/%02d/%d %02d:%02d:%02d",
814                        stm.wDay, stm.wMonth, stm.wYear,
815                        stm.wHour, stm.wMinute, stm.wSecond);
816           Value->SetValue_psz(buf);
817          }break;
818         default:
819           Value->SetValue((double)Prop.fltVal);
820         } // endswitch Type
821 
822       break;
823     default:
824       // This will reset numeric column value
825       Value->SetValue_psz("Type not supported");
826       break;
827     } // endswitch vt
828 
829   VariantClear(&Prop);
830   } // end of ReadColumn
831 
832 /* ---------------------------TDBWCL class --------------------------- */
833 
834 /***********************************************************************/
835 /*  TDBWCL class constructor.                                          */
836 /***********************************************************************/
TDBWCL(PWMIDEF tdp)837 TDBWCL::TDBWCL(PWMIDEF tdp) : TDBCAT(tdp)
838   {
839   Nsp = tdp->Nspace;
840   Cls = tdp->Wclass;
841   } // end of TDBWCL constructor
842 
843 /***********************************************************************/
844 /*  GetResult: Get the list of the WMI class properties.               */
845 /***********************************************************************/
GetResult(PGLOBAL g)846 PQRYRES TDBWCL::GetResult(PGLOBAL g)
847   {
848   return WMIColumns(g, Nsp, Cls, false);
849 	} // end of GetResult
850 
851 
852