unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls{SetupApi};
const
HardwareIDs = 'VKeyboard';
DeviceName = 'Virtual Keyboard';
MAX_CLASS_NAME_LEN = 128;
DIF_REMOVE = $00000005;
INSTALLFLAG_FORCE = $00000001;
SPDRP_HARDWAREID = $00000001;
DIF_REGISTERDEVICE = $00000019;
DIGCF_PRESENT = $0002;
DIGCF_ALLCLASSES = $0004;
DIGCF_PROFILE = $00000008;
DICD_GENERATE_ID = $00000001;
type
ULONG_PTR = DWORD;
DI_FUNCTION = UINT;
HDEVINFO = Pointer;
PSPDevInfoData = ^TSPDevInfoData;
SP_DEVINFO_DATA = packed record
cbSize: DWORD;
ClassGUID: TGUID;
DevInst: DWORD;
Reserved: ULONG_PTR;
end;
{$EXTERNALSYM SP_DEVINFO_DATA}
TSPDetsigCmpProc = function (DeviceInfoSet: HDEVINFO; NewDeviceData,
ExistingDeviceData: PSPDevInfoData; CompareContext: Pointer): DWORD; stdcall;
TSPDevInfoData = SP_DEVINFO_DATA;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
KeyboardClass:TGUID='{4D36E96B-E325-11CE-BFC1-08002BE10318}';
function SetupDiGetClassDevs(ClassGuid: PGUID; const Enumerator: PAnsiChar; hwndParent: HWND; Flags: DWORD): HDEVINFO; stdcall;external 'Setupapi.dll' name 'SetupDiGetClassDevsA';
function SetupDiEnumDeviceInfo(DeviceInfoSet: HDEVINFO; MemberIndex: DWORD; var DeviceInfoData: TSPDevInfoData): LongBool; stdcall;external 'Setupapi.dll' name 'SetupDiEnumDeviceInfo';
function SetupDiGetDeviceRegistryProperty(DeviceInfoSet: HDEVINFO; const DeviceInfoData: TSPDevInfoData; Property_: DWORD; var PropertyRegDataType: DWORD; PropertyBuffer: PBYTE; PropertyBufferSize: DWORD; var RequiredSize: DWORD): LongBool; stdcall;external 'Setupapi.dll' name 'SetupDiGetDeviceRegistryPropertyA';
function SetupDiDestroyDeviceInfoList(DeviceInfoSet: HDEVINFO): LongBool; stdcall;external 'Setupapi.dll' name 'SetupDiDestroyDeviceInfoList';
function SetupDiGetINFClass(const InfName: PAnsiChar; var ClassGuid: TGUID; ClassName: PAnsiChar; ClassNameSize: DWORD; RequiredSize: PDWORD): LongBool; stdcall;external 'Setupapi.dll' name 'SetupDiGetINFClassA';
function SetupDiCreateDeviceInfoList(ClassGuid: PGUID; hwndParent: HWND): HDEVINFO; stdcall;external 'Setupapi.dll' name 'SetupDiCreateDeviceInfoList';
function SetupDiCreateDeviceInfo(DeviceInfoSet: HDEVINFO; const DeviceName: PAnsiChar; var ClassGuid: TGUID; const DeviceDescription: PAnsiChar; hwndParent: HWND; CreationFlags: DWORD; DeviceInfoData: PSPDevInfoData): LongBool; stdcall;external 'Setupapi.dll' name 'SetupDiCreateDeviceInfoA';
function SetupDiSetDeviceRegistryProperty(DeviceInfoSet: HDEVINFO; var DeviceInfoData: TSPDevInfoData; Property_: DWORD; const PropertyBuffer: PBYTE; PropertyBufferSize: DWORD): LongBool; stdcall;external 'Setupapi.dll' name 'SetupDiSetDeviceRegistryPropertyA';
function SetupDiCallClassInstaller(InstallFunction: DI_FUNCTION; DeviceInfoSet: HDEVINFO; DeviceInfoData: PSPDevInfoData): LongBool; stdcall;external 'Setupapi.dll' name 'SetupDiCallClassInstaller';
function UpdateDriverForPlugAndPlayDevices(hwndParent: THandle; HardwareId: Pchar; FullInfPath: Pchar; InstallFlags: DWORD; bRebootRequired: PBOOL ): BOOL; stdcall;external 'newdev.dll' name 'UpdateDriverForPlugAndPlayDevicesA';
function SetupDiClassNameFromGuid(ClassGuid: PGUID; ClassName: PChar;ClassNameSize: DWORD; RequiredSize: PDWORD): BOOL; stdcall;external 'Setupapi.dll' name 'SetupDiClassNameFromGuidA';
function SetupDiRegisterDeviceInfo(DeviceInfoSet: HDEVINFO;var DeviceInfoData: TSPDevInfoData; Flags: DWORD; CompareProc: TSPDetSigCmpProc;CompareContext: Pointer; DupDeviceInfoData: PSPDevInfoData): LongBool; stdcall;external 'Setupapi.dll' name 'SetupDiRegisterDeviceInfo';
function DisplayMsg(msg:string):integer;
begin
result := MessageBox(0,pchar(msg),'message',MB_OK);
end;
function FindExistingDevice():boolean;
var
DeviceInfoSet:HDEVINFO;
Found:boolean;
DeviceInfoData:SP_DEVINFO_DATA;
i:DWord;
DataT:DWord;
buf:pchar;
buffsize:integer;
begin
DeviceInfoSet := SetupDiGetClassDevs(nil,0,0,(DIGCF_ALLCLASSES or DIGCF_PRESENT
or DIGCF_PROFILE));
if DeviceInfoSet = nil then
exit;
Found := false;
DeviceInfoData.cbSize := sizeof(SP_DEVINFO_DATA);
i := 0;
buffsize := 10240;
getmem(buf,buffsize);
while SetupDiEnumDeviceInfo(DeviceInfoSet,i,DeviceInfoData) do
begin
inc(i);
DataT := 0;
if not SetupDiGetDeviceRegistryProperty(DeviceInfoSet,DeviceInfoData,
SPDRP_HARDWAREID,
DataT,
PByte(buf),
buffsize,
DataT) then
begin
continue;
end;
if HardwareIDs = strpas(buf) then
begin
found := true;
break;
end;
end;
if buf <> nil then
freemem(buf);
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
result := found;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
FileName,Drive,Path,infile,sysfile:string;
DeviceInfoSet: HDEVINFO;
ClassGUID: TGUID;
dev:SP_DEVINFO_DATA;
status:Longbool;
RebootRequired :Longbool;
err:DWord;
begin
if FindExistingDevice then
begin
DisplayMsg('Virtual Keyboard already installed');
exit;
end;
FileName := application.ExeName;
Path := ExtractFilePath(FileName);
infile := path + 'keyfdo.inf';
sysfile := path + 'VKeyFdo.sys';
if not fileexists(infile) then
begin
DisplayMsg('Can''t find .INF file');
exit;
end;
if not FileExists(sysfile) then
begin
DisplayMsg('Can''t find .sys file');
exit;
end;
DeviceInfoSet := SetupDiCreateDeviceInfoList(@KeyboardClass,0);
if (DWORD(DeviceInfoSet) = INVALID_HANDLE_VALUE) then
begin
DisplayMsg('Can''t get device infolist');
exit;
end;
dev.cbSize := sizeof(SP_DEVINFO_DATA);
status := SetupDiCreateDeviceInfo
(DeviceInfoSet,pchar(DeviceName),
KeyboardClass,pchar(DeviceName),0,DICD_GENERATE_ID,@dev);
if not status then
begin
DisplayMsg('Can''t create device');
exit;
end;
status := SetupDiRegisterDeviceInfo(DeviceInfoSet,dev,0,nil,nil,nil);
if not status then
begin
DisplayMsg('Can''t register device');
exit;
end;
status := SetupDiSetDeviceRegistryProperty
(DeviceInfoSet,dev,SPDRP_HARDWAREID,Pbyte(PChar(HardwareIds)),
(lstrlen(HardwareIds)+1+1)*sizeof(char));
if not status then
begin
err := GetLastError();
DisplayMsg('Can''t set device HardwareID'+ inttostr(err));
exit;
end;
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
status := UpdateDriverForPlugAndPlayDevices(0,
HardwareIDs,pchar(infile),0,@RebootRequired);
if not status then
begin
err := GetLastError();
DisplayMsg('Can''t update device HardwareID'+ inttostr(err));
status := SetupDiCallClassInstaller(DIF_REMOVE,DeviceInfoSet,@dev);
if not status then
begin
DisplayMsg('Can''t install device HardwareID');
exit;
end;
end;
end;
end.