In order to enumerate all installed drivers and/or services on either your local computer or even a remote machine, you need to use EnumServicesStatus(). This function doesn't work with a callback function; instead it expects a static array in which it will return the information.
The example below implements a wrapper function ServiceGetList() that keeps this static array on the stack and returns the result in TStrings string list.
The FormCreate() event shows how to call the function. You can download a complete sample Delphi project here (5 kB).
unit fMain;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
ListBox1: TListBox;
ListBox2: TListBox;
Label1: TLabel;
Label2: TLabel;
procedure FormCreate(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
uses
WinSvc;
const
//
// Service Types
//
SERVICE_KERNEL_DRIVER = $00000001;
SERVICE_FILE_SYSTEM_DRIVER = $00000002;
SERVICE_ADAPTER = $00000004;
SERVICE_RECOGNIZER_DRIVER = $00000008;
SERVICE_DRIVER = (SERVICE_KERNEL_DRIVER or
SERVICE_FILE_SYSTEM_DRIVER or
SERVICE_RECOGNIZER_DRIVER);
SERVICE_WIN32_OWN_PROCESS = $00000010;
SERVICE_WIN32_SHARE_PROCESS = $00000020;
SERVICE_WIN32 = (SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS);
SERVICE_INTERACTIVE_PROCESS = $00000100;
SERVICE_TYPE_ALL = (SERVICE_WIN32 or
SERVICE_ADAPTER or
SERVICE_DRIVER or
SERVICE_INTERACTIVE_PROCESS);
//-------------------------------------
// Get a list of services
//
// return TRUE if successful
//
// sMachine:
// machine name, ie: \\SERVER
// empty = local machine
//
// dwServiceType
// SERVICE_WIN32,
// SERVICE_DRIVER or
// SERVICE_TYPE_ALL
//
// dwServiceState
// SERVICE_ACTIVE,
// SERVICE_INACTIVE or
// SERVICE_STATE_ALL
//
// slServicesList
// TStrings variable to storage
//
function ServiceGetList(sMachine: string;
dwServiceType, dwServiceState: DWord;
slServicesList: TStrings) : boolean;
const
// assume that the total number of services is less than 4096.
//Increase if necessary
cnMaxServices = 4096;
type
TSvcA = array [0..cnMaxServices] of TEnumServiceStatus;
PSvcA = ^TSvcA;
var
j: integer;
// service control manager handle
schm: SC_Handle;
// bytes needed for the next buffer, if any
nBytesNeeded,
// number of services
nServices,
// pointer to the next unread service entry
nResumeHandle: DWord;
// service status array
ssa: PSvcA;
begin { ServiceGetList }
Result := false;
// connect to the service control manager
schm := OpenSCManager(PChar(sMachine), nil, SC_MANAGER_ALL_ACCESS);
// if successful...
if (schm>0) then
begin
nResumeHandle := 0;
New(ssa);
EnumServicesStatus(schm, dwServiceType, dwServiceState, ssa^[0],
sizeof(ssa^), nBytesNeeded, nServices,
nResumeHandle);
// assume that our initial array was large enough to hold all
// entries. add code to enumerate if necessary.
for j := 0 to nServices-1 do
begin
slServicesList.Add(StrPas(ssa^[j].lpDisplayName));
end; { for j }
Result := true;
Dispose(ssa);
// close service control manager handle
CloseServiceHandle(schm);
end; { (schm>0) }
end; { ServiceGetList }
procedure TForm1.FormCreate(Sender: TObject);
begin { TForm1.FormCreate }
ServiceGetList('', SERVICE_TYPE_ALL, SERVICE_ACTIVE, ListBox1.Items);
ServiceGetList('', SERVICE_TYPE_ALL, SERVICE_INACTIVE, ListBox2.Items);
end; { TForm1.FormCreate }
end.