| 
 | 
 
终于搞定了……!完美! 
 
对于 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 编辑 ] |   
 
 
 
 |