delphi版inf方式加载驱动

2018-10-31

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.

阅读83