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