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