Delphi XE3 introduces a lot of new WinApi headers translations, between them is the Winapi.Wbem unit which is the Delphi (object pascal) translation for the wbemidl.h file which contains the WMI Component Object Model (COM) interface definitions. This means that from now you can access the WMI in a fastest way and directly using COM avoiding the use of the Microsoft WMIScripting Library and third party libraries.
Try this sample Delphi XE3 console application which access the Win32_Process WMI Class using the Winapi.Wbem unit.
{$APPTYPE CONSOLE} {$R *.res} uses Winapi.Windows, System.SysUtils, Winapi.ActiveX, Winapi.Wbem; const //Impersonation Level Constants //http://msdn.microsoft.com/en-us/library/ms693790%28v=vs.85%29.aspx RPC_C_AUTHN_LEVEL_DEFAULT = 0; RPC_C_IMP_LEVEL_ANONYMOUS = 1; RPC_C_IMP_LEVEL_IDENTIFY = 2; RPC_C_IMP_LEVEL_IMPERSONATE = 3; RPC_C_IMP_LEVEL_DELEGATE = 4; //Authentication Service Constants //http://msdn.microsoft.com/en-us/library/ms692656%28v=vs.85%29.aspx RPC_C_AUTHN_WINNT = 10; RPC_C_AUTHN_LEVEL_CALL = 3; RPC_C_AUTHN_DEFAULT = Longint($FFFFFFFF); EOAC_NONE = 0; //Authorization Constants //http://msdn.microsoft.com/en-us/library/ms690276%28v=vs.85%29.aspx RPC_C_AUTHZ_NONE = 0; RPC_C_AUTHZ_NAME = 1; RPC_C_AUTHZ_DCE = 2; RPC_C_AUTHZ_DEFAULT = Longint($FFFFFFFF); //Authentication-Level Constants //http://msdn.microsoft.com/en-us/library/aa373553%28v=vs.85%29.aspx RPC_C_AUTHN_LEVEL_PKT_PRIVACY = 6; SEC_WINNT_AUTH_IDENTITY_UNICODE = 2; //COAUTHIDENTITY Structure //http://msdn.microsoft.com/en-us/library/ms693358%28v=vs.85%29.aspx type PCOAUTHIDENTITY = ^TCOAUTHIDENTITY; _COAUTHIDENTITY = Record User : PChar; UserLength : ULONG; Domain : PChar; DomainLength : ULONG; Password : PChar; PassWordLength : ULONG; Flags : ULONG; End; COAUTHIDENTITY = _COAUTHIDENTITY; TCOAUTHIDENTITY = _COAUTHIDENTITY; function GetExtendedErrorInfo(hresErr: HRESULT):Boolean; var pStatus : IWbemStatusCodeText; hres : HRESULT; MessageText: WideString; begin Result:=False; hres := CoCreateInstance(CLSID_WbemStatusCodeText, nil, CLSCTX_INPROC_SERVER, IID_IWbemStatusCodeText, pStatus); if (hres = S_OK) then begin hres := pStatus.GetErrorCodeText(hresErr, 0, 0, MessageText); if(hres <> S_OK) then MessageText := 'Get last error failed'; Result:=(hres = S_OK); if Result then Writeln(Format( 'ErrorCode %x Description %s',[hresErr,MessageText])); end; end; procedure TestWbem; const WbemUser =''; WbemPassword =''; WbemComputer ='localhost'; WbemLocale =''; WbemAuthority ='kERBEROS:'+WbemComputer; var LWbemLocator : IWbemLocator; LWbemServices : IWbemServices; LUnsecuredApartment : IUnsecuredApartment; ppEnum : IEnumWbemClassObject; apObjects : IWbemClassObject; puReturned : ULONG; pVal : Variant; pType : PCIMTYPE; plFlavor : PInteger; OpResult : HRESULT; LocalConnection : Boolean; AuthInfo : TCOAUTHIDENTITY; begin ZeroMemory(@AuthInfo, 0); with AuthInfo do begin User := PChar(WbemUser); UserLength := Length(WbemUser); Domain := ''; DomainLength := 0; Password := PChar(WbemPassword); PasswordLength := Length(WbemPassword); Flags := SEC_WINNT_AUTH_IDENTITY_UNICODE; end; LocalConnection:=WbemComputer.IsEmpty or (WbemComputer.CompareTo('localhost')=0); if LocalConnection then if Failed(CoInitializeSecurity(nil, -1, nil, nil, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, nil, EOAC_NONE, nil)) then Exit else else if Failed(CoInitializeSecurity(nil, -1, nil, nil, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IDENTIFY, nil, EOAC_NONE, nil)) then Exit; OpResult:=CoCreateInstance(CLSID_WbemLocator, nil, CLSCTX_INPROC_SERVER, IID_IWbemLocator, LWbemLocator); if Succeeded(OpResult) then begin try Writeln('Connecting to the WMI Service'); if LocalConnection then OpResult:=LWbemLocator.ConnectServer(Format('\\%s\root\CIMV2',[WbemComputer]), WbemUser, WbemPassword, WbemLocale, WBEM_FLAG_CONNECT_USE_MAX_WAIT, '', nil, LWbemServices) else OpResult:=LWbemLocator.ConnectServer(Format('\\%s\root\CIMV2',[WbemComputer]), WbemUser, WbemPassword, WbemLocale, WBEM_FLAG_CONNECT_USE_MAX_WAIT, '', nil, LWbemServices); if Succeeded(OpResult) then begin Writeln('Connected'); try // Set security levels on a WMI connection if LocalConnection then if Failed(CoSetProxyBlanket(LWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nil, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nil, EOAC_NONE)) then Exit else else if Failed(CoSetProxyBlanket(LWbemServices, RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT, PWideChar(Format('\\%s',[WbemComputer])), RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, @AuthInfo, EOAC_NONE)) then Exit; if Succeeded(CoCreateInstance(CLSID_UnsecuredApartment, nil, CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment, LUnsecuredApartment)) then try Writeln('Running Wmi Query'); OpResult := LWbemServices.ExecQuery('WQL', 'SELECT Name, ProcessId FROM Win32_Process', WBEM_FLAG_FORWARD_ONLY, nil, ppEnum); if Succeeded(OpResult) then begin // Set security for the enumerator proxy if not LocalConnection then if Failed(CoSetProxyBlanket(ppEnum, RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT, PWideChar(Format('\\%s',[WbemComputer])), RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, @AuthInfo, EOAC_NONE)) then Exit; while (ppEnum.Next(Integer(WBEM_INFINITE), 1, apObjects, puReturned)=0) do begin pType:=nil; plFlavor:=nil; apObjects.Get('Name', 0, pVal, pType, plFlavor);// String Writeln(Format('Name %s',[String(pVal)]));//String VarClear(pVal); apObjects.Get('ProcessId', 0, pVal, pType, plFlavor);// Uint32 Writeln(Format('ProcessId %d',[Integer(pVal)]));//Uint32 VarClear(pVal); end; end else if not GetExtendedErrorInfo(OpResult) then Writeln(Format('Error executing WQL sentence %x',[OpResult])); finally LUnsecuredApartment := nil; end; finally LWbemServices := nil; end; end else if not GetExtendedErrorInfo(OpResult) then Writeln(Format('Error Connecting to the Server %x',[OpResult])); finally LWbemLocator := nil; end; end else if not GetExtendedErrorInfo(OpResult) then Writeln(Format('Failed to create IWbemLocator object %x',[OpResult])); end; begin try if Succeeded(CoInitializeEx(nil, COINIT_MULTITHREADED)) then try TestWbem; finally CoUninitialize; end; except on E:Exception do Writeln(E.Classname, ':', E.Message); end; Writeln('Press Enter to exit'); Readln; end.
September 7, 2012 at 3:53 pm
Very nice indeed.
Are there any other particularly interesting new header translations?
September 7, 2012 at 4:42 pm
This is the full list of the new WinApi headers included in Delphi XE3
Function Discovery API – functiondiscoverycategories.h – Winapi.Functiondiscovery
Location API – locationapi.h – Winapi.Locationapi
Shell Functions functions from the Userenv.dll library – userenv.h – Winapi.UserEnv
Sensor API – sensorsapi.h – Winapi.Sensorsapi
Sensor API – Sensors.h – Winapi.Sensors
Windows Portable Devices (WPD) – portabledevicetypes.h – Winapi.Portabledevicetypes
PenInputPanel interfaces – peninputpanel.h – Winapi.PenInputPanel
September 9, 2012 at 6:15 am
there is still no support for Windows Animation Library in XE3, and I haven’t found new features of D2D1 like Windows 8 effects
September 7, 2012 at 6:58 pm
CryptoApi is not there again?!
September 8, 2012 at 10:20 pm
Unfortunately the Windows Crypto Api is not included.
September 9, 2012 at 10:43 am
Cool, making things simple has always been one of Delphi’s strengths.
September 13, 2012 at 5:01 am
Note that you don’t need to call CoInitializeSecurity, CoSetProxyBlanket does the right job for the IWbemServices interface without side effects on the other COM interfaces.
Michel
September 13, 2012 at 10:06 am
Michel, is always recommended Initialize the COM process security by calling the CoInitializeSecurity method to set the default security settings for authentication, impersonation, or authentication service for the current process, the CoSetProxyBlanket method is only applied to the IWbemServices interface to impersonate the client login, you can try this MSDN link Setting the Default Process Security Level Using C++
Pingback: Michael Swindell » Exploring XE3 Win API Additions