自动安装驱动程序代码

技术杂谈73
DWORD GetServiceInfFilePath_Passthru(
LPTSTR lpFilename,
DWORD nSize
)
{
// Get Path to This Module
DWORD nResult;
TCHAR szDrive[ _MAX_DRIVE ];
TCHAR szDir[ _MAX_DIR ];

nResult = GetModuleFileName( NULL, lpFilename, nSize );

if( nResult == 0 )
{
return 0;
}

_tsplitpath( lpFilename, szDrive, szDir, NULL, NULL );

_tmakepath( lpFilename, szDrive, szDir, _T ("netsf"), _T(".inf") );

return (DWORD )_tcslen( lpFilename );
}

DWORD GetServiceInfFilePath_PassthruMP(
LPTSTR lpFilename,
DWORD nSize
)
{
// Get Path to This Module
DWORD nResult;
TCHAR szDrive[ _MAX_DRIVE ];
TCHAR szDir[ _MAX_DIR ];

nResult = GetModuleFileName( NULL, lpFilename, nSize );

if( nResult == 0 )
{
return 0;
}

_tsplitpath( lpFilename, szDrive, szDir, NULL, NULL );

_tmakepath( lpFilename, szDrive, szDir, _T ("netsf_m"), _T(".inf") );

return (DWORD )_tcslen( lpFilename );
}

DWORD InstallDriver_Passthru()
{
DWORD nResult;

//_tprintf( _T("Installing %s...\n"), NDISPROT_FRIENDLY_NAME );

nResult = MessageBox(NULL, _T("你要安装 Passthru 网络驱动?" ), _T ("Passthru网络过滤驱动"), MB_OKCANCEL | MB_ICONINFORMATION );

if( nResult != IDOK )
{
return 0;
}

// Get Path to Service INF File
// ----------------------------
// The INF file is assumed to be in the same folder as this application...

TCHAR szFileFullPath[ _MAX_PATH ];

//-----------------------------------------------------------------------
//第一次在一个系统上使用这个程序安装Passthru时,会出现安装失败的情况,或者
//安装成功,但passthru miniport的部分没有安装上去,在windows 目录下 的setupapi.log文件中可以看到
//安装失败记录,错误是找不到文件。在"设备管理器"选择显示隐藏设备后
//也不会在 网络适配器 下面看到 passthru miniport项。但手动安装在'本地网络属性"->"安装"->"服务"选择
//硬盘上netsf.inf进行安装成功候,再用程序安装就可以了。
//在网络上查了一下,这个问题应该是因为 Passthru这个驱动需要两个inf文件,而netsf_m.inf并不没有被复制到
//系统的inf 目录(c:\windows\inf)去。虽然 netsf.inf 里面有[CopyInf = netsf_m.inf]项要求复制netsf_m.inf
//但这个不能 正常工作(The \"CopyINF\" directive, by design, is only observed if the original INF is
//not yet in the INF directory. So to work around the problem, you have to
//update your installation app (snetcfg) to also copy the Net class (miniport)
//inf using SetupCopyOEMInf when it comes to installing IM drivers. Make sure
//you specify a fully qualified path of the INF in the SetupCopyOEMInf
//arguments.

//)
//
//所以这个问题的解决就是自己把 netsf_m.inf这个文件放到c:\windows\inf目录去。这可以通过在 netsf.inf里面添加
//copyfile项,像copy Passthru.sys一样添加一项copy netsf_m.inf的项。另一种方法就是像下面这样添加调用
//SetupCopyOEMInfW来复制netsf_m.inf的代码
TCHAR szDrive[ _MAX_DRIVE ];
TCHAR szDir[ _MAX_DIR ];
TCHAR szDirWithDrive[_MAX_DRIVE+_MAX_DIR];
nResult = GetServiceInfFilePath_PassthruMP( szFileFullPath, MAX_PATH );
if( nResult == 0 )
{
//_tprintf( _T("Unable to get INF file path.\n") );
MessageBox(NULL, _T("获取INF文件路径失败!"),_T("安装程序错误提示"),MB_OK);
return 0;
}
//
// Get the path where the INF file is.

//
_tsplitpath( szFileFullPath, szDrive, szDir, NULL, NULL );

_tcscpy( szDirWithDrive, szDrive );
_tcscat( szDirWithDrive, szDir );
if ( !SetupCopyOEMInfW(
szFileFullPath,
szDirWithDrive, // Other files are in the
// same dir. as primary INF
SPOST_PATH, // First param is path to INF
0, // Default copy style
NULL, // Name of the INF after
// it's copied to %windir%\inf
0, // Max buf. size for the above
NULL, // Required size if non-null
NULL) // Optionally get the filename
// part of Inf name after it is copied.

)
{
MessageBox(NULL, _T("复制 PasstruMP 的inf安装文件到系统目录失败!"),_T("安装程序错误提示"),MB_OK);

}
//------------------------------------------------------------------------

nResult = GetServiceInfFilePath_Passthru( szFileFullPath, MAX_PATH );

if( nResult == 0 )
{
// _tprintf( _T("Unable to get INF file path.\n") );
MessageBox(NULL, _T("获取INF文件路径失败!"),_T("安装程序错误提示"),MB_OK);
return 0;
}

//_tprintf( _T("INF Path: %s\n"), szFileFullPath );

HRESULT hr=S_OK;

//_tprintf( _T("PnpID: %s\n"), _T( "ms_passthru"));

hr = InstallSpecifiedComponent(
szFileFullPath, //驱动安装的inf文件路径 , 适当修改吧
_T ("ms_passthru"), // NDISPROT_SERVICE_PNP_DEVICE_ID, //这个也要适当修改的
&GUID_DEVCLASS_NETSERVICE //NDIS Protocal 类型
);

if( hr != S_OK )
{
/*ErrMsg( hr, L"InstallSpecifiedComponent\n" );*/
MessageBox(NULL, _T("安装驱动失败!"),_T("安装程序错误提示"),MB_OK);
}else
{
MessageBox(NULL, _T("成功安装驱动!"),_T("安装程序提示"),MB_OK);
}

return 0;
}

DWORD UninstallDriver_Passthru()
{
//_tprintf( _T("Uninstalling %s...\n"), NDISPROT_FRIENDLY_NAME );

int nResult = MessageBox(NULL, _T("你要卸载Passthru网络驱动?" ), _T ("Passthru网络过滤驱动"), MB_OKCANCEL | MB_ICONINFORMATION );

if( nResult != IDOK )
{
return 0;
}

INetCfg *pnc;
INetCfgComponent *pncc;
INetCfgClass *pncClass;
INetCfgClassSetup *pncClassSetup;
LPTSTR lpszApp;
GUID guidClass;
OBO_TOKEN obo;
HRESULT hr;

hr = HrGetINetCfg( TRUE, APP_NAME, &pnc, &lpszApp );

if ( hr == S_OK ) {

//
// Get a reference to the network component to uninstall.

//
hr = pnc->FindComponent( _T ("ms_passthru"), &pncc );

if ( hr == S_OK )
{
//
// Get the class GUID.

//
hr = pncc->GetClassGuid( &guidClass );

if ( hr == S_OK )
{
//
// Get a reference to component's class.

//

hr = pnc->QueryNetCfgClass( &guidClass,
IID_INetCfgClass,
(PVOID *)&pncClass );
if ( hr == S_OK )
{
//
// Get the setup interface.

//

hr = pncClass->QueryInterface( IID_INetCfgClassSetup,
(LPVOID *)&pncClassSetup );

if ( hr == S_OK )
{
//
// Uninstall the component.

//

ZeroMemory( &obo,
sizeof(OBO_TOKEN) );

obo.Type = OBO_USER;

hr = pncClassSetup->DeInstall( pncc,
&obo,
NULL );
if ( (hr == S_OK) || (hr == NETCFG_S_REBOOT) )
{
hr = pnc->Apply();

if ( (hr != S_OK) && (hr != NETCFG_S_REBOOT) )
{
//ErrMsg( hr,
// L"Couldn't apply the changes after"
// L" uninstalling %s.",
// _T ("ms_passthru" ));
MessageBox(NULL, _T ("卸载驱动之后无法成功应用!"),_T ("安装程序错误提示"),MB_OK);
}else
{
MessageBox(NULL, _T("成功卸载驱动!"),_T("安装程序提示"),MB_OK);
}
}
else
{
//ErrMsg( hr,
// L"Failed to uninstall %s.",
// _T("ms_passthru" ));
MessageBox(NULL, _T("卸载网络组件失败!"),_T("安装程序错误提示"),MB_OK);
}

ReleaseRef( pncClassSetup );
}
else
{
//ErrMsg( hr,
// L"Couldn't get an interface to setup class." );
MessageBox(NULL, _T("无法得到安装类接口!"),_T("安装程序错误提示"),MB_OK);
}

ReleaseRef( pncClass );
}
else
{
//ErrMsg( hr,
// L"Couldn't get a pointer to class interface "
// L"of %s.",
// _T ("ms_passthru") );
MessageBox(NULL, _T("无法得到安装类接口!"),_T("安装程序错误提示"),MB_OK);
}
}
else
{
//ErrMsg( hr,
// L"Couldn't get the class guid of %s.",
// _T("ms_passthru") );
MessageBox(NULL, _T("无法得到安装类接口的 GUID !"),_T("安装程序错误提示"),MB_OK);
}

ReleaseRef( pncc );
}
else
{
//ErrMsg( hr,
// L"Couldn't get an interface pointer to %s.",
// _T ("ms_passthru") );

MessageBox(NULL, _T("无法得到一个接口指针!"),_T("安装程序错误提示"),MB_OK);
}

HrReleaseINetCfg( pnc,
TRUE );
}
else
{
if ( (hr == NETCFG_E_NO_WRITE_LOCK) && lpszApp )
{
// ErrMsg( hr,
// L"%s currently holds the lock, try later.",
// lpszApp );
MessageBox(NULL, _T("碰到死锁问题,稍后再试!"),_T("安装程序错误提示"),MB_OK);
CoTaskMemFree( lpszApp );
}
else
{
// ErrMsg( hr, L"Couldn't get the notify object interface." );
MessageBox(NULL, _T("无法得到通知对象接口!"),_T("安装程序错误提示"),MB_OK);
}
}

return 0;
}

Original: https://www.cnblogs.com/MaxWoods/p/4156654.html
Author: Max Woods
Title: 自动安装驱动程序代码



相关阅读

Title: AT&T汇编语言——工具及程序组成

1. 开发工具

在汇编语言中,用到的工具主要用下面几个:

汇编器、连接器、调试器、编译器

由于我在这里的是AT&T 汇编语言。所以工具下也都是gnu 下的那些。

1.1 汇编器(as)

汇编器有非常多,masm ,nasm,gas 等,不像高级语言,尽管都叫汇编语言。但不同的汇编器,其语法是存在非常大不同的。Intel 汇编的书籍到处可见,但是AT&T 的却少之又少。但想看Linux 内核的话,还是要对AT&T 汇编熟悉才行。这或许是自己为什么学习汇编的原因吧。说到汇编器,我们用的是as,其可选參数有非常多。但我们用的几个:

比方我们要汇编test.s 为ia-32 平台的test.o,

$ as  --32  -o test.o test.s

这里仅仅用到了两个參数

--32 :是指定为ia-32 平台代码,

-o :后接目标文件

1.2 连接器(ld)

我们选择ld.用到的參数主要有下面几个:

-m elf_i386 :将目标代码连接成elf_i386 格式(即32 位平台下的代码)

-o :后接目标文件

1.3 调试器(gdb)

基本的命令有:

list :列出指定的函数或行

break :设置断点

run :执行

next :下一条指令

step : 运行程序中的下一条指令

1.4 编译器(gcc)

纯汇编能够不用gcc 。

gcc 的參数用到的也不多。有下面几个:

-g :调试模式的代码

-o :后接目标代码

-m32:生成ia32 平台代码

1.5 其它一些工具

1.5.1 objdump

Objdump 是一个很实用的工具 。其能够实现反汇编

主要用到的參数有:-d 表示将目标代码反汇编成指令码

1.5.2 gprof

gprof打印出程序执行中各个函数消耗的时间,能够帮助程序猿找出众多函数中耗时最多的函数。

1.5.3 操作系统linux

2 .汇编语言的模板范例

事实上,单纯用汇编来开发的程序已经非常少了。

我学习这个。主要目的有两个:

1.看懂Linux 内核中的代码

2.看懂C/C++等程序生成的汇编代码

所以。我更希望所用的汇编格式能直接与C 语言链接起来。

2.1 汇编程序组成

汇编语言由定义好的段组成,每一个段都有不同的目的。

三个经常使用的段例如以下:

数据段(.section .data)

声明带有初始值的数据元素,用作汇编 语言程序中的变量

bss 段(.section .bss 请问中文该怎样翻译?)

用途汇编语言的缓冲区

文本段 (.section .text)

存放代码

2.1.1 定义段的方法

GNU 汇编器使用.section 命令语句声明段。.section 语句使用一个參数——它声明的段的类型。如下图所看到的。

这将是我们以后要使用的布局 。

2.1.2 定义段的起点

当汇编语言程序被转换成可运行文件时,连接器要知道指向的起点,gnu 汇编器声明一个默认标签_start,表明程序从这条指令開始。当然。也能够使用连接器參数-e 来定义新的起始名称。

好,以下来总结一下我们的汇编语言的基础模板:

.section .data

 .section .bss

.section .text

.globl _start

_start:

今天就写到这吧,明天用详细实例来说一下今天所说的工具的使用方法。

Original: https://www.cnblogs.com/mfrbuaa/p/5420812.html
Author: mfrbuaa
Title: AT&T汇编语言——工具及程序组成