Recent

Author Topic: Windows: Calling a WMI function -- Working example?  (Read 2706 times)

oh_ha

  • New Member
  • *
  • Posts: 12
Windows: Calling a WMI function -- Working example?
« on: October 21, 2020, 12:33:20 pm »
Hallo all,

I am looking for sample code on how to call a WMI function. Does anyone has a working example in FreePascal, ideally including code on how to pass parameters to the function? Unfortunately, the "Delphi WMI code Creator" does not help me as the FreePascal code for creating a function does not work.

Just to be clear: This is not about querying WMI properties, but calling a function like Win32_OperatingSystem.LocalDateTime.

Thanks and regards, Olaf
« Last Edit: October 21, 2020, 12:35:16 pm by oh_ha »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11351
  • FPC developer.
Re: Windows: Calling a WMI function -- Working example?
« Reply #1 on: October 21, 2020, 01:00:43 pm »
If you click through, then it is just calling a method on the olevariant.

IOW use the query method to get the right object in an olevariant, and then call the method on it.

But I would find some other method to test, setdatetime has permission aspects to it (The calling process must have the SE_SYSTEMTIME_NAME privilege.) , so is not a suitable first test subject.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5444
  • Compiler Developer
Re: Windows: Calling a WMI function -- Working example?
« Reply #2 on: October 21, 2020, 11:32:21 pm »
The second example given here on the WMI Delphi Code Generator to start a process using WMI works correctly with FPC 3.2.0. So what exactly is the problem you have? Maybe it's indeed the priviledge as marcov mentioned?

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1228
Re: Windows: Calling a WMI function -- Working example?
« Reply #3 on: October 22, 2020, 01:54:18 pm »
hello,
you can try something like that :
Code: Pascal  [Select][+][-]
  1. program SetLocalDateTime;
  2. {$mode objfpc} {$H+}
  3. uses  SysUtils, ActiveX, ComObj;
  4.  
  5. procedure  Invoke_Win32_OperatingSystem_SetDateTime;
  6. const
  7.   WbemUser            ='';
  8.   WbemPassword        ='';
  9.   WbemComputer        ='localhost';
  10.   wbemFlagForwardOnly = $00000020;
  11. var
  12.   FSWbemLocator   : OLEVariant;
  13.   FWMIService     : OLEVariant;
  14.   FWbemObjectSet  : OLEVariant;
  15.   FWbemObject    :  OLEVariant;
  16.   FInParams       : OLEVariant;
  17.   FOutParams      : OLEVariant;
  18.   sValue          : string;
  19.   MyDateTime      : OLEVariant;
  20.   oEnum           : IEnumvariant;
  21.   dummy           : LongWord;
  22. begin
  23.   MyDateTime    := CreateOleObject('WbemScripting.SWbemDateTime');
  24.   FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  25.   FWMIService   := FSWbemLocator.ConnectServer(WbemPassword, 'root\CIMV2', WbemUser, WbemPassword);
  26.   FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_OperatingSystem','WQL',wbemFlagForwardOnly);
  27.   oEnum         := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
  28.   dummy := 0;
  29.   while oEnum.Next(1, FWbemObject, dummy) = 0 do
  30.   begin
  31.     sValue:= FWbemObject.Properties_.Item('LocalDateTime').Value;
  32.     Writeln(Format('ReturnValue           %s',[sValue]));
  33.     MyDateTime :=  FWbemObject.Properties_.Item('LocalDateTime');
  34.   end;
  35.  
  36.   FWbemObjectSet:= FWMIService.Get('Win32_OperatingSystem');
  37.   FInParams     := FWbemObjectSet.Methods_.Item('SetDateTime').InParameters.SpawnInstance_();
  38.   FInParams.LocalDatetime:= ????????????
  39.  
  40.   FOutParams    := FWMIService.ExecMethod('Win32_OperatingSystem', 'SetDateTime', FinParams);
  41.   sValue:=FOutParams.ReturnValue;
  42.   Writeln(Format('ReturnValue           %s',[sValue]));
  43.  
  44. end;
  45.  
  46.  
  47. begin
  48.  try
  49.     Invoke_Win32_OperatingSystem_SetDateTime;
  50.  except
  51.     on E:EOleException do
  52.         Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
  53.     on E:Exception do
  54.         Writeln(E.Classname, ':', E.Message);
  55.   end;
  56.  Writeln('Press Enter to exit');
  57.  Readln;
  58. end.

Quote
ReturnValue           20201022134901.176000+120
but :
1 - I can't find how to set    FInParams.LocalDatetime. I have tried some values but when i execute the ExecMethod i have always an exception :  OleException - ArgumentException :  The exception that is thrown when one of the arguments provided to a method is not valid
2 - The calling process must have the SE_SYSTEMTIME_NAME privilege.

Friendly,J.P
« Last Edit: October 22, 2020, 02:00:42 pm by Jurassic Pork »
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11351
  • FPC developer.
Re: Windows: Calling a WMI function -- Working example?
« Reply #4 on: October 26, 2020, 10:13:06 am »
OP put it on SO, and somebody posted a C++ example. I found some similar code in Delphi to setup the WMI with security identifiers, and changed the actual executing by translating the rest of the C++.

Total work searching and translating: about 2 hours.

This code works for me in 32-bit win32 (it uses Jedi units though)

Code: Pascal  [Select][+][-]
  1.  
  2. program wmiedidint2;
  3. // based on https://theroadtodelphi.com/2011/04/21/accesing-the-wmi-from-delphi-and-fpc-via-com-without-late-binding-or-wbemscripting_tlb/
  4. // modified to function as https://docs.microsoft.com/en-us/answers/questions/95631/wmi-c-application-problem-wmimonitordescriptormeth.html?childToView=96407#answer-96407
  5. {$IFDEF FPC}
  6.  {$MODE DELPHI} {$H+}
  7. {$ENDIF}
  8.  
  9. {$APPTYPE CONSOLE}
  10.  
  11. uses
  12.   Windows,
  13.   Variants,
  14.   SysUtils,
  15.   ActiveX,
  16.   JwaWbemCli;
  17.  
  18. const
  19.   RPC_C_AUTHN_LEVEL_DEFAULT = 0;
  20.   RPC_C_IMP_LEVEL_IMPERSONATE = 3;
  21.   RPC_C_AUTHN_WINNT = 10;
  22.   RPC_C_AUTHZ_NONE = 0;
  23.   RPC_C_AUTHN_LEVEL_CALL = 3;
  24.   EOAC_NONE = 0;
  25.  
  26.  
  27. function GetBytesFromVariant(const V: Variant): TBytes;
  28. // this function is a mess and only works for bytes. From SO
  29. var
  30.   Len: Integer;
  31.   SafeArray: PVarArray;
  32. begin
  33.   Len := 1+VarArrayHighBound(v, 1)-VarArrayLowBound(v, 1);
  34.   SetLength(Result, Len);
  35.   SafeArray := VarArrayAsPSafeArray(V);
  36.   Move(SafeArray.Data^, Pointer(Result)^, Length(result)*SizeOf(result[0]));
  37. end;
  38.  
  39. procedure Test_IWbemServices_ExecQuery;
  40. const
  41.   strLocale    = '';
  42.   strUser      = '';
  43.   strPassword  = '';
  44.   strNetworkResource = 'root\WMI';
  45.   strAuthority       = '';
  46.   WQL                = 'SELECT * FROM WmiMonitorDescriptorMethods';
  47.   EDIDMethodname      = 'WmiGetMonitorRawEEdidV1Block';
  48.   EDIDClassName       = 'WmiMonitorDescriptorMethods';
  49.  
  50. var
  51.   FWbemLocator         : IWbemLocator;
  52.   FWbemServices        : IWbemServices;
  53.   FUnsecuredApartment  : IUnsecuredApartment;
  54.   ppEnum               : IEnumWbemClassObject;
  55.   apObjects            : IWbemClassObject;
  56.   puReturned           : ULONG;
  57.   pVal                 : OleVariant;
  58.   pType                : Integer;
  59.   plFlavor             : Integer;
  60.   Succeed              : HRESULT;
  61.   varreturnvalue       : olevariant;
  62.   varotherval          : longint;
  63.   varcmd2 : tagVariant;
  64.   varcommand           : olevariant; // tagVARIANT;
  65.  
  66.   pOutParamsDefinition,
  67.   pInParamsDefinition,
  68.   pClass,
  69.   pClassInstance       : IWbemClassObject;
  70.   callres              : IWbemCallResult;
  71.   err : IErrorInfo;
  72.   aname,w2 : Widestring;
  73.   bytes : TBytes;
  74.   i : integer;
  75.  
  76. procedure teststatus(const msg:string);
  77. begin
  78.   if Succeeded(succeed) then
  79.     writeln('Successs:',msg)
  80.   else
  81.     writeln('Fail:',msg)
  82. end;
  83.  
  84. begin
  85.   // Set general COM security levels --------------------------
  86.   // Note: If you are using Windows 2000, you need to specify -
  87.   // the default authentication credentials for a user by using
  88.   // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
  89.   // parameter of CoInitializeSecurity ------------------------
  90.   if Failed(CoInitializeSecurity(nil, -1, nil, nil, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, nil, EOAC_NONE, nil)) then Exit;
  91.   // Obtain the initial locator to WMI -------------------------
  92.   if Succeeded(CoCreateInstance(CLSID_WbemLocator, nil, CLSCTX_INPROC_SERVER, IID_IWbemLocator, FWbemLocator)) then
  93.   try
  94.     // Connect to WMI through the IWbemLocator::ConnectServer method
  95.     if Succeeded(FWbemLocator.ConnectServer(strNetworkResource, strUser, strPassword, strLocale,  WBEM_FLAG_CONNECT_USE_MAX_WAIT, strAuthority, nil, FWbemServices)) then
  96.     try
  97.       // Set security levels on the proxy -------------------------
  98.       if Failed(CoSetProxyBlanket(FWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nil, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nil, EOAC_NONE)) then Exit;
  99.       if Succeeded(CoCreateInstance(CLSID_UnsecuredApartment, nil, CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment, FUnsecuredApartment)) then
  100.       try
  101.         // Use the IWbemServices pointer to make requests of WMI
  102.         //Succeed := FWbemServices.ExecQuery('WQL', WQL, WBEM_FLAG_FORWARD_ONLY OR WBEM_FLAG_RETURN_IMMEDIATELY, nil, ppEnum);
  103.         Succeed := FWbemServices.ExecQuery('WQL', WQL, WBEM_FLAG_FORWARD_ONLY, nil, ppEnum);
  104.         if Succeeded(Succeed) then
  105.         begin
  106.           Writeln('Running Wmi Query..Press Enter to exit');
  107.            // Get the data from the query
  108.            while (ppEnum.Next(WBEM_INFINITE, 1, apObjects, puReturned)=0) do
  109.            begin
  110.              succeed:= apObjects.Get('__PATH', 0, pVal, pType, plFlavor);
  111.              teststatus('get __PATH');
  112.              aname:=pval;
  113.              writeln('__PATH: ',aname);
  114.  
  115.  
  116.              succeed:=fwbemservices.GetObject(edidclassname,0,nil,pClass,callres);
  117.              teststatus('getobject');
  118.              succeed:=pClass.GetMethod(EDIDMethodname,0,pInParamsDefinition,pOutParamsDefinition);
  119.              teststatus('getmethod');
  120.              succeed:=pInParamsDefinition.SpawnInstance(0, pClassInstance);
  121.              teststatus('Spawn');
  122.  
  123.              fillchar(varcmd2,sizeof(varcommand),#0);
  124.              varcmd2.vt:=VT_UI1;
  125.              varcmd2.bval:=0;
  126.              move(varcmd2,varcommand,sizeof(varcmd2));
  127.  
  128.              succeed:= pClassInstance.Put('BlockId',0,@VarCommand,0);
  129.              teststatus('put blockid');
  130.              writeln('The BlockId is: ,',varCommand);
  131.              pOutParamsDefinition:=Nil;
  132.              callres:=nil;
  133.  
  134.              w2:=EDIDMethodname;
  135.              succeed:= fwbemservices.ExecMethod(aname,w2,0,nil,pClassInstance,pOutParamsDefinition,callres);
  136.              if succeeded(succeed) then
  137.                 begin
  138.                   writeln('execute success!');
  139.                 end;
  140.              succeed:= pOutParamsDefinition.Get('BlockType', 0, varreturnvalue,ptype,plFlavor);
  141.              if succeeded(succeed)  then
  142.                begin
  143.                  writeln('blocktype:',varreturnvalue);
  144.                  varotherval:=varreturnvalue;
  145.                  if varotherval=1 then
  146.                    begin
  147.                      succeed:= pOutParamsDefinition.Get('BlockContent', 0, varreturnvalue,ptype,plFlavor);
  148.                      if succeeded(succeed) then
  149.                      begin
  150.                      bytes:=GetBytesFromVariant(varreturnvalue);
  151.                      write('bytes:');
  152.                      for i:=0 to length(bytes)-1 do
  153.                        begin
  154.                          write('$',inttohex(bytes[i],2),' ');
  155.                        end;
  156.                      writeln;
  157.                      end;
  158.  
  159.                    end;
  160.                end;
  161.            end;
  162.         end
  163.         else
  164.         Writeln(Format('Error executing WQL sentence %x',[Succeed]));
  165.       finally
  166.         FUnsecuredApartment := nil;
  167.       end;
  168.     finally
  169.       FWbemServices := nil;
  170.     end;
  171.   finally
  172.     FWbemLocator := nil;
  173.   end;
  174. end;
  175.  
  176. begin
  177.   // Initialize COM. ------------------------------------------
  178.   if Succeeded(CoInitializeEx(nil, COINIT_MULTITHREADED)) then
  179.   try
  180.     Test_IWbemServices_ExecQuery;
  181.   finally
  182.     CoUninitialize();
  183.   end;
  184.   Readln;
  185. end.
  186.  

 

TinyPortal © 2005-2018