program bb;
uses
Windows;
const
MAX_CLASS_NAME_LEN = 128;
DIF_REMOVE = $00000005;
DICD_GENERATE_ID = $00000001;
INSTALLFLAG_FORCE = $00000001;
SPDRP_HARDWAREID = $00000001;
DIF_REGISTERDEVICE = $00000019;
DIGCF_PRESENT = $0002;
DIGCF_ALLCLASSES = $0004;
SetupApiModuleName = 'SetupApi.dll';
NewDevModuleName = 'newdev.dll';
type
ULONG_PTR = DWORD;
DI_FUNCTION = UINT; // Function type for device installer
HDEVINFO = Pointer;
PSPDevInfoData = ^TSPDevInfoData;
SP_DEVINFO_DATA = packed record
cbSize: DWORD;
ClassGuid: TGUID;
DevInst: DWORD; // DEVINST handle
Reserved: ULONG_PTR;
end;
{$EXTERNALSYM SP_DEVINFO_DATA}
TSPDevInfoData = SP_DEVINFO_DATA;
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';
procedure SetPrivilege;
var
TPPrev, TP: TTokenPrivileges;
TokenHandle: THandle;
dwRetLen: DWORD;
lpLuid: TLargeInteger;
begin
OpenProcessToken(GetCurrentProcess, TOKEN_ALL_ACCESS, TokenHandle);
if (LookupPrivilegeValue(nil, 'SeDebugPrivilege', lpLuid)) then
begin
TP.PrivilegeCount := 1;
TP.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
TP.Privileges[0].Luid := lpLuid;
AdjustTokenPrivileges(TokenHandle, False, TP, SizeOf(TPPrev), TPPrev, dwRetLen);
end;
CloseHandle(TokenHandle);
end;
function GetDeviceClassName(aGUID: TGUID): string;
var
ClassName: PChar;
ClassNameSize: DWORD;
begin
ClassNameSize := 0;
GetMem(ClassName, ClassNameSize);
{ 利用GUID返回设备类型名 }
while not SetupDiClassNameFromGuid(@aGUID, ClassName, ClassNameSize,
@ClassNameSize) do
begin
if GetLastError() = ERROR_INSUFFICIENT_BUFFER then
begin
if ClassName <> nil then FreeMem(ClassName);
GetMem(ClassName, ClassNameSize);
end else
Break;
end;
Result := ClassName;
if ClassName <> nil then FreeMem(ClassName);
end;
function StrPas(const Str: PChar): string;
begin
Result := Str;
end;
function isinstalled(hardid:Pchar):bool;
var
DevInfo: HDEVINFO;
DeviceInfoData: SP_DEVINFO_DATA; {设备信息结构}
i: Integer;
DataT, Buffersize: DWORD;
Buffer: pchar;
index: Integer;
begin
result:=false;
DevInfo := SetupDiGetClassDevs(nil, 0, 0,DIGCF_PRESENT or DIGCF_ALLCLASSES);
if DevInfo = nil then Exit;
i := 0;
Buffersize := 256;
DeviceInfoData.cbSize := SizeOf(SP_DEVINFO_DATA);
GetMem(Buffer, Buffersize);
{ 枚举设备信息 }
while SetupDiEnumDeviceInfo(DevInfo, i, DeviceInfoData) do
begin
{ 获取设备信息包括GUID和名称 }
SetupDiGetDeviceRegistryProperty(DevInfo, DeviceInfoData,1, DataT, PByte(Buffer), Buffersize, DataT);
Inc(i);
if StrPas(hardid)= StrPas(Buffer) then
begin
result:=true;
break;
end;
end;
if Buffer <> nil then FreeMem(Buffer);
if (GetLastError() <> NO_ERROR) and (GetLastError() <> ERROR_NO_MORE_ITEMS) then
Exit;
SetupDiDestroyDeviceInfoList(DevInfo);
end;
function InstallRootEnumeratedDriver(HardwareId, INFFile: Pchar; RebootRequired: PBOOL): DWORD;
var
r: DWORD;
DeviceInfoSet: HDEVINFO;
DeviceInfoData: SP_DEVINFO_DATA;
ClassGUID: TGUID;
ClassName: array[0..MAX_CLASS_NAME_LEN - 1] of char;
label TheEnd;
begin
r := 0;
DeviceInfoSet := nil;
if isinstalled(HardwareId) then //如果已经有了服务,无需安装,直接加载即可
if not(UpdateDriverForPlugAndPlayDevices(0, HardwareId, pchar(INFFile),INSTALLFLAG_FORCE,RebootRequired)) then
begin
r := GetLastError();SetLastError(r);
goto TheEnd;
end;
if (not SetupDiGetINFClass(INFFile, ClassGUID, ClassName, sizeof(ClassName), nil)) then
begin
r := GetLastError();
goto TheEnd;
end;
DeviceInfoSet := SetupDiCreateDeviceInfoList(@ClassGUID, 0);
if (DWORD(DeviceInfoSet) = INVALID_HANDLE_VALUE) then
begin
r := GetLastError();
goto TheEnd;
end;
DeviceInfoData.cbSize := sizeof(SP_DEVINFO_DATA);
if (not SetupDiCreateDeviceInfo(DeviceInfoSet,ClassName,ClassGUID,nil,0,DICD_GENERATE_ID,@DeviceInfoData)) then
begin
r := GetLastError();
goto TheEnd;
end;
if (not SetupDiSetDeviceRegistryProperty(DeviceInfoSet,DeviceInfoData,SPDRP_HARDWAREID,PBYTE(HardwareId),(lstrlen(HardwareId) + 1 + 1) * sizeof(CHAR))) then
begin
r := GetLastError();
goto TheEnd;
end;
if (not SetupDiCallClassInstaller(DIF_REGISTERDEVICE,DeviceInfoSet,@DeviceInfoData)) then
begin
r := GetLastError();
goto TheEnd;
end;
if not(UpdateDriverForPlugAndPlayDevices(0,HardwareId,INFFile,INSTALLFLAG_FORCE,RebootRequired)) then
begin
r := GetLastError();
if (not SetupDiCallClassInstaller(DIF_REMOVE,DeviceInfoSet,@DeviceInfoData)) then messagebox(0,pchar('出错6'),'aa',0);
SetLastError(r);
goto TheEnd;
end;
TheEnd:
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
Result := r;
end;
function ExtractFilePath(path: string): string;
var
i: integer;
begin
i := length(path);
while i >= 1 do
begin
if (path[i] = '\') or (path[i] = '/') or (path[i] = ':') then
break;
dec(i);
end;
result := copy(path, 1, i);
end;
var
Msg: TMsg;
bReboot: BOOL ;
begin
GetInputState();
PostThreadMessage(GetCurrentThreadId(), 0, 0, 0);
GetMessage(Msg, 0, 0, 0);
//SetPrivilege;
InstallRootEnumeratedDriver('*OneDevice', pchar(extractfilepath(paramstr(0))+'One.inf') ,@bReboot);
end.