Delphi版inf方式加载驱动


本文整理自网络,侵删。

 
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.

来源:https://www.delphi6.com/article/sw21q7xj.html

相关阅读 >>

Delphi 字符串替换函数[单元文件 sysutils]

Delphi编程如何判断图片文件的真实类型?

Delphi中判断是否是64位操作系统

Delphi 将程序加裁到启动项

Delphi 启动程序隐藏主窗体

Delphi 取出一个字符在字符串出现的次数

Delphi listview 设置固定列宽

Delphi xe10 手机内部系统相关操作(手机信息、震动、剪贴板、键盘、电话、拨号)

Delphi将图片转换成文本支持转换回去

Delphi中多线程下使用使用 unidac+mssql 需要注意的问题

更多相关阅读请进入《Delphi》频道 >>



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...