delphiwmibcdstore

Accessing BcdStore from Delphi


I'm trying to convert this code fragment into Delphi and I got stuck on the for each objWBL in colObjects.

if not objBcdStore.EnumerateObjects( &h10200003, colObjects ) then
    WScript.Echo "ERROR objBcdStore.EnumerateObjects( &h10200003 ) failed."
    WScript.Quit(1)
end if

for each objWBL in colObjects
    WScript.Echo ""
    WScript.Echo "Windows Boot Loader"
    WScript.Echo "-------------------"

    WScript.Echo "identifier              " & GetBcdId( objWBL.Id )

    If objWBL.Id = current then

      if not objWBL.GetElement(BcdOSLoaderInteger_NumberOfProcessors, objElement ) then
          WScript.Echo "ERROR WBL GetElement for " & Hex(BcdOSLoaderInteger_NumberOfProcessors) & " failed."
          WScript.Quit(1)
      end if
      WScript.Echo "numproc              " & objElement.Integer

      if not objWBL.GetElement(BcdOSLoaderBoolean_UseBootProcessorOnly, objElement ) then
          WScript.Echo "ERROR WBL GetElement for " & Hex(BcdOSLoaderBoolean_UseBootProcessorOnly) & " failed."
          WScript.Quit(1)
      end if
      WScript.Echo "onecpu              " & objElement.Boolean

    end if
next

My partial q&d translation (caution, must be Admin to run it):

uses
  OleAuto,
  ActiveX;

function GetObject(const objectName: String): IDispatch;
var
  bindCtx: IBindCtx;
  moniker: IMoniker;
  chEaten: Integer;
begin
  OleCheck(CreateBindCtx(0, bindCtx));
  OleCheck(MkParseDisplayName(bindCtx, StringToOleStr(objectName), chEaten, moniker));
  OleCheck(moniker.BindToObject(bindCtx, nil, IDispatch, Result));
end;

procedure TForm44.btnClick(Sender: TObject);
var
  colObjects   : OleVariant;
  objBcdStore  : OleVariant;
  objWMIService: OleVariant;
begin
  objWMIService := GetObject('winmgmts:{impersonationlevel=Impersonate,(Backup,Restore)}!root/wmi:BcdStore');
  if not objWMIService.OpenStore('', objBcdStore) then
    Caption := 'error'
  else begin
    objBcdStore.EnumerateObjects($10200003, colObjects);
    //???
  end;
end;

EnumerateObjects is defined as

boolean EnumerateObjects(
  [in]   uint32 Type,
  [out]  BcdObject Objects[]
);

I have no idea how to walk over the BcdObject array in Delphi.


Solution

  • you must use the VarArrayLowBound and VarArrayHighBound functions to get the bounds of the variant array returned by the EnumerateObjects function and then you can use a for loop to iterate over the elements of the array.

    check this sample

    Uses
     ComObj,
     ActiveX;
    
    function GetObject(const objectName: String): IDispatch;
    var
      bindCtx: IBindCtx;
      moniker: IMoniker;
      chEaten: Integer;
    begin
      OleCheck(CreateBindCtx(0, bindCtx));
      OleCheck(MkParseDisplayName(bindCtx, StringToOleStr(objectName), chEaten, moniker));
      OleCheck(moniker.BindToObject(bindCtx, nil, IDispatch, Result));
    end;
    
    
    procedure TForm44.Button1Click(Sender: TObject);
    var
      colObjects   : OleVariant;
      objBcdStore  : OleVariant;
      objWMIService: OleVariant;
    
      i : Integer;
      objWBL : OleVariant;
    begin
      objWMIService := GetObject('winmgmts:{impersonationlevel=Impersonate,(Backup,Restore)}!root/wmi:BcdStore');
      if not objWMIService.OpenStore('', objBcdStore) then
        Caption := 'error'
      else
      begin
        objBcdStore.EnumerateObjects($10200003, colObjects);
           if not VarIsNull(colObjects) and VarIsArray(colObjects) then
           for i := VarArrayLowBound(colObjects, 1) to VarArrayHighBound(colObjects, 1) do
           begin
              objWBL:=colObjects[i];
              //do your stuff here
    
    
           end;
      end;
    end;