|
终于搞定了……!完美!
对于 WinPE 驱动程序外置或打包,chenall 已经作了 BAT 方式的解决方式。但是这依赖于繁琐的外部程序和BAT命令,效率不高且不适合定制。今天女里搞了一下,终于搞定了最终解决方案:
1. 把每种驱动放在一个目录中(每个 INF 文件名前,加上“_”开头,作为起始标志),然后把所有的驱动程序打包成为一个 CAB 文件(可能由于 INF 是 TXT 的关系,CAB 压缩率比 7Z 还高一点,且不需要使用固实压缩,解压缩单个文件时速度大大提高)。
2. 用下面的程序代码(完成功能和源代码稍后提供在其它的帖子中),指定 CAB 路径,即可自动从 CAB 安装驱动:
1) 代码会自动检测所有 PCI 设备;
2) 然后遍历 CAB 内的一个 INF 文件内容;
3) 如果找到匹配的硬件,则解压缩 INF 所在目录中随后的 所有文件到 %TEMP% 中;
4) 安装驱动程序;
5) 转跳到 2,继续遍历下一个 INF。
优点:
1) 支持把各种类型的驱动放在一个 CAB 中,如显卡 + 网卡,等。
2) 高压缩。经测试,12M 的所有网卡 驱动,压缩后为 2.9M。
3) 硬盘(或 RAMDISK 盘)空间要求少,不匹配的驱动不会被解压缩。
4) 安装驱动后,可以删除 CAB 文件,腾出空间。这样 RAMDISK 启动的WinPE就能腾出空间,不必使用 RAMDRV 和 FBWF。
5) CAB 解压缩不需要而外程序的支持,SetupAPI 是 Windows 内置的接口。(如何生成CAB,推荐用 RAR 等压缩工具压缩为 RAR 等,然后用 ArcConvert 转换即可)
代码片段如下,如有需要可以定制,想怎么样就怎么样:
- // 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;
- }
复制代码
[ 本帖最后由 Yonsm 于 2007-1-5 12:33 AM 编辑 ] |
|