|
推荐
楼主 |
发表于 2007-8-30 22:37:20
|
只看该作者
WinPE 驱动程序最终解决方案
1. 把每种驱动放在一个目录中(每个 INF 文件名前,加上“_”开头,作为起始标志),然后把所有的驱动程序打包成为一个 CAB 文件。
2. 用下面的程序代码,指定 CAB 路径,即可自动从 CAB 安装驱动:
1) 代码会自动检测所有 PCI 设备;
2) 然后遍历 CAB 内的一个 INF 文件内容;
3) 如果找到匹配的硬件,则解压缩 INF 所在目录中随后的 所有文件到 %TEMP% 中;
4) 安装驱动程序;
5) 转跳到 2,继续遍历下一个 INF。
代码如下:
// Header
#include <SetupAPI.h>
#include <DevGuid.h>
#include <RegStr.h>
#include <CfgMgr32.h>
#pragma comment(lib, "SetupAPI.lib")
#ifdef _UNICODE
#define STR_UpdateDriverForPlugAndPlayDevices "UpdateDriverForPlugAndPlayDevicesW"
#else
#define STR_UpdateDriverForPlugAndPlayDevices "UpdateDriverForPlugAndPlayDevicesA"
#endif
typedef BOOL (WINAPI* PUPNP)(HWND hWnd, PCTSTR ptzID, PCTSTR ptzPath, DWORD dwFlags, PBOOL bReboot);
// Compare device
PSTR DevCmp(PSTR pszStr1, PSTR pszStr2)
{
PSTR p = pszStr2;
for (UINT i = 0; *p; p++)
{
if ((*p == '&') && (++i == 2))
{
break;
}
}
UINT uCmp = (UINT) (p - pszStr2);
p = pszStr1;
while (*p)
{
if (UMemCmp(p, pszStr2, uCmp) == 0)
{
return p;
}
p++;
}
return NULL;
}
// CAB callback
UINT CALLBACK DevProc(PVOID pvContext, UINT uMsg, UINT_PTR upParam1, UINT_PTR upParam2)
{
static BOOL s_bExtract = FALSE;
static TCHAR s_tzDevID[MAX_NAME] = {0};
static TCHAR s_tzInfPath[MAX_PATH] = {0};
if (uMsg == SPFILENOTIFY_FILEINCABINET)
{
// Is INF file or followed by INF file
FILE_IN_CABINET_INFO *p = (FILE_IN_CABINET_INFO*) upParam1;
PCTSTR q = UStrRChr(p->NameInCabinet, '\\');
q = q ? (q + 1) : p->NameInCabinet;
if ((*q == '_') || s_bExtract)
{
// Extract INF or driver file
if (*q == '_')
{
q++;
}
UStrCopy(p->FullTargetName + GetTempPath(MAX_PATH, p->FullTargetName), q);
return FILEOP_DOIT;
}
else
{
// Skip
return FILEOP_SKIP;
}
}
else if (uMsg == SPFILENOTIFY_FILEEXTRACTED)
{
PCTSTR ptzTarget = ((FILEPATHS*) upParam1)->Target;
if (UStrStr(ptzTarget, TEXT(".INF")) == NULL)
{
// Not INF
return NO_ERROR;
}
// Open INF
PSTR pszFile = (PSTR) UFileLoad(ptzTarget, NULL);
if (pszFile == NULL)
{
return NO_ERROR;
}
for (PSTR p = (PSTR) pvContext; *p; p += UAStrLen(p) + 1)
{
if ((*p != '#') && DevCmp(pszFile, p))
{
// Found Device
UAStrToStr(s_tzDevID, p, MAX_NAME);
UStrCopy(s_tzInfPath, ptzTarget);
//UTrack(TEXT("\r\nFound %s: %s\r\n\r\n"), s_tzDevID, s_tzInfPath);
s_bExtract = TRUE;
*p = '#';
return NO_ERROR;
}
}
// This is next INF
if (s_bExtract)
{
// Previous is uses INF
s_bExtract = FALSE;
HMODULE hLib = LoadLibrary(TEXT("NewDev"));
if (hLib)
{
// Install INF
PUPNP p = (PUPNP) GetProcAddress(hLib, STR_UpdateDriverForPlugAndPlayDevices);
if (p)
{
BOOL bReboot = FALSE;
p(NULL, s_tzDevID, s_tzInfPath, 3, &bReboot);
UTrack(TEXT("\r\nInstall %s: %s\r\n\r\n"), s_tzDevID, s_tzInfPath);
}
FreeLibrary(hLib);
}
}
// Delete INF
UFileDelete(ptzTarget);
}
return NO_ERROR;
}
#define MAX_DevID (MAX_STR * 4)
UINT DevEnum(PSTR pszDev, PCTSTR ptzClass = REGSTR_KEY_PCIENUM)
{
// Lookup device
HDEVINFO hDev = SetupDiGetClassDevs(NULL, ptzClass, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES );
if (hDev == INVALID_HANDLE_VALUE)
{
return E_FAIL;
}
// Lookup Device ID
UINT uSize = 0;
SP_DEVINFO_DATA sdDev = {sizeof(SP_DEVINFO_DATA)};
for (UINT i = 0; (uSize < MAX_DevID) && SetupDiEnumDeviceInfo(hDev, i, &sdDev); i++)
{
DWORD dwData;
DWORD dwSize = MAX_DevID- uSize;
if (SetupDiGetDeviceRegistryPropertyA(hDev, &sdDev, SPDRP_HARDWAREID, &dwData, (PBYTE) pszDev + uSize, dwSize, &dwSize))
{
#ifndef _DEBUG
// List problem device only
ULONG uProblem = 0;
ULONG uStatus = DN_HAS_PROBLEM;
CM_Get_DevNode_Status(&uStatus, &uProblem, sdDev.DevInst, 0);
if (uProblem)
#endif
{
uSize += UAStrLen(pszDev + uSize) + 1;
}
}
}
SetupDiDestroyDeviceInfoList(hDev);
pszDev[uSize] = pszDev[uSize + 1] = 0;
return uSize;
}
// Install device
HRESULT Devi(PTSTR ptzCmd)
{
// Skip if Control Key pressed.
if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
{
return S_FALSE;
}
// Enum device ID
CHAR szDev[MAX_DevID];
UINT uSize = DevEnum(szDev, TEXT("PCI"));
uSize += DevEnum(szDev + uSize, TEXT("USB"));
if (uSize == 0)
{
// No device
return ERROR_DEVICE_NOT_CONNECTED;
}
#ifdef _DEBUG
for (PSTR p = szDev; *p; p += UAStrLen(p) + 1)
{
UTrack(TEXT("%hs\r\n"), p);
}
#endif
// Lookup CAB file
TCHAR tzPath[MAX_PATH];
ExpandEnvironmentStrings(ptzCmd, tzPath, MAX_PATH);
SetupIterateCabinet(tzPath, 0, DevProc, szDev);
return S_OK;
} |
|