标题: WinPE 驱动程序最终解决方案
Yonsm
上尉
Rank: 4



UID 89638
精华 2
积分 2446
帖子 448
威望 1274
阅读权限 70
注册 2006-2-12
发表于 2007-1-4 21:21  资料  主页 短消息  加为好友  添加 Yonsm 为MSN好友 通过MSN和 Yonsm 交谈 QQ

WinPE 驱动程序最终解决方案

终于搞定了……!完美!

对于 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 编辑 ]

顶部
zts59
上将
Rank: 8Rank: 8
爱好者


UID 61523
精华 0
积分 28708
帖子 565
威望 1807
阅读权限 99
注册 2004-12-8
发表于 2007-1-4 21:26  资料  短消息  加为好友 

呵呵,不是很懂,感觉是把CMD批处理程序化。非常不错,效率提高。望能把成品发出来试试~~~

顶部
strongchen
少将
Rank: 7Rank: 7Rank: 7
call偶老猫。。。。。


UID 80205
精华 3
积分 13258
帖子 1654
威望 4218
阅读权限 99
注册 2005-4-27
来自 猫国
发表于 2007-1-4 21:29  资料  短消息  加为好友 

呵呵,又有新的亮点出现了。。。





坚决不回答能够在论坛找的到答案的问题。
顶部
Yonsm
上尉
Rank: 4



UID 89638
精华 2
积分 2446
帖子 448
威望 1274
阅读权限 70
注册 2006-2-12
发表于 2007-1-4 21:30  资料  主页 短消息  加为好友  添加 Yonsm 为MSN好友 通过MSN和 Yonsm 交谈 QQ



QUOTE:
原帖由 zts59 于 2007-1-4 09:26 PM 发表
呵呵,不是很懂,感觉是把CMD批处理程序化。非常不错,效率提高。望能把成品发出来试试~~~

并非如此!解压、查找、安装程序等都是自己搞定的,不需要 BartPE 等支持的。另外,不需要解压缩全部驱动(当然,CMD的也不要)。

内置外置都行。推荐内置,CAB 压缩后不大

顶部
潇湘晨光
大校
Rank: 6Rank: 6



UID 157581
精华 0
积分 9877
帖子 73
威望 197
阅读权限 90
注册 2007-1-4
发表于 2007-1-4 21:30  资料  短消息  加为好友 

又有新突破了。

顶部
acoa
少校
Rank: 5Rank: 5



UID 144287
精华 1
积分 3888
帖子 286
威望 759
阅读权限 90
注册 2006-12-4
发表于 2007-1-4 21:31  资料  短消息  加为好友 

支持,请把作品发出来让大家测试。

顶部
strongchen
少将
Rank: 7Rank: 7Rank: 7
call偶老猫。。。。。


UID 80205
精华 3
积分 13258
帖子 1654
威望 4218
阅读权限 99
注册 2005-4-27
来自 猫国
发表于 2007-1-4 21:32  资料  短消息  加为好友 


QUOTE:
原帖由 Yonsm 于 2007-1-4 09:30 PM 发表


并非如此!解压、查找、安装程序等都是自己搞定的,不需要 BartPE 等支持的。另外,不需要解压缩全部驱动(当然,CMD的也不要)。

内置外置都行。推荐内置,CAB 压缩后不大

嗯,这样省去了很多步骤。。。比较关系自己定制方面的问题,容易进行定制是yy的基本。。。^_^





坚决不回答能够在论坛找的到答案的问题。
顶部
Yonsm
上尉
Rank: 4



UID 89638
精华 2
积分 2446
帖子 448
威望 1274
阅读权限 70
注册 2006-2-12
发表于 2007-1-4 21:35  资料  主页 短消息  加为好友  添加 Yonsm 为MSN好友 通过MSN和 Yonsm 交谈 QQ


QUOTE:
原帖由 strongchen 于 2007-1-4 09:32 PM 发表


嗯,这样省去了很多步骤。。。比较关系自己定制方面的问题,容易进行定制是yy的基本。。。^_^

CAB 可随意订制,命令本身没什么好定制的了。上面我说的订制是指 代码。

但是 CAB 定制就 OK 了,只要把不同的驱动压缩在一起,即可。上面的代码会自动检测的。

顶部
wanghh
中将
Rank: 7Rank: 7Rank: 7



UID 118930
精华 0
积分 23433
帖子 1048
威望 2825
阅读权限 99
注册 2006-10-2
发表于 2007-1-4 21:37  资料  短消息  加为好友 
支持,请把作品发出来让大家测试。

顶部
Yonsm
上尉
Rank: 4



UID 89638
精华 2
积分 2446
帖子 448
威望 1274
阅读权限 70
注册 2006-2-12
发表于 2007-1-4 21:41  资料  主页 短消息  加为好友  添加 Yonsm 为MSN好友 通过MSN和 Yonsm 交谈 QQ
稍后上传。DEVI 自动安装只是其中之一,下面是所有的命令:

QUOTE:
欢迎使用 RXPE - Rescue Windows XP Environment 扩展设置工具!


一、简介

RXPE 是为扩展设置 Windows PE 而制作的小工具。

    ◎ 支持常规的扩展设置命令。
    ◎ 支持外部命令增加程序的功能。
    ◎ 支持命令行、命令列表文件和图形界面,所有命令均使用统一格式,一看就会使用。
    ◎ 细微周到的功能支持。
    ◎ 短小精干,运行迅速。
    ◎ 源代码公开,方便更改定制。在源代码中增加扩展命令非常容易。


二、命令

■ Regi <HKLM|HKCU|HKCR|HKU|HKCC><\子项\>[键值][=[#]数据]

  ◎ 功能:设置或删除注册表数据。
  
  ◎ 参数:
    ※ 子项              所选 ROOTKEY 下注册表项的完整名。

    ※ 键值              要操作的键值。如果省略,则操作默认键值;如果为“!”且没有“=”,则用于删除整个子项。

    ※ 数据              要设置的数据。如果没有“=”则删除;如果有“#”则表示 REG_DWORD 整数类型的数据,否则为字符串。
  
  ◎ 示例:Regi HKCU\SOFTWRE\RXPE\Version=#1200

  ◎ 备注:无。

■ Envi [名称][=值]

  ◎ 功能:如果大写的 ENVI 将设置系统的环境变量;否则仅设置用于 RXPE.EXE 的环境变量。
  
  ◎ 参数:分别指定环境变量名称和值。如果不指定值,则删除环境变量;如果不指定名称和值,则设置以下环境变量:
         Favorites      收藏夹目录
         Desktop        桌面目录
         StartMenu      开始菜单目录
         Startup        启动菜单目录
         Programs       程序菜单目录
         Recent         新近文件目录
         SendTo         发送到目录
         System         系统目录
         Windows        Windows 目录
         Personal       我的文档目录
         QuickLaunch    快速启动目录
  
  ◎ 示例:ENVI

  ◎ 备注:如果名称的最后一个字符为大写,才会通知系系使环境变量更改生效。

■ Link <快捷方式路径><,目标路径>[,运行参数][,图标路径][,图标索引]

  ◎ 功能:添加快捷方式。
  
  ◎ 参数:

    ※ 快捷方式路径      指定要生成的快捷方式的路径(.lnk 可以省略)。

    ※ 目标路径          指定快捷方式的目标路径。如果目标路径的结尾处有字符“?”,则快捷方式的起始位置(或者说当前目录)为临时文件夹“%TEMP%”;否则,为目标文件所在的目录。如果目标路径的结尾处有字符“<”,则快捷方式的启动方式为最小化方式启动;如果是“>”,则以隐藏方式启动;否则,为正常方式启动。

    ※ 运行参数          目标程序运行参数。

    ※ 图标路径          快捷方式图标的路径。

    ※ 图标索引          快捷方式图标的在文件资源中的序号,0 为第一个图标(不填写则默认)。   
   
  ◎ 示例:Link $Desktop\宽带连接,PPPOE.CMD<,,RASDIAL.DLL,19

  ◎ 备注:无。

■ Dele <文件路径>

  ◎ 功能:删除文件或目录。
  
  ◎ 参数:指定要删除的文件路径,支持环境变量扩展和通配符。
  
  ◎ 示例:Dele %SystemRoot%\INF\*.PNF

  ◎ 备注:如果以 RAMDISK 方式启动系统,可删除一些启动后无用的文件(如 2 MB 的 NTOSKRNL.EXE)来增加 RAMDISK 的可写空间。

■ Devi <CAB 路径>

  ◎ 功能:从 CAB 文件中安装驱动程序。
   
  ◎ 参数:CAB 完整路径。把每个驱动单独放在一个目录中,然后把所有的驱动程序按备注中的说明,打包成 CAB 即可。
  
  ◎ 示例:DEVI %SystemRoot%\DRV.CAB

  ◎ 备注:CAB 文件中的。其中的 INF 文件必须以“_”开头(使用改名工具,添加“_”前缀);并且,请最后放一个目录和空的INF(如“ZZZ\ZZ.INF”),否则最后一个驱动不会自动安装(但会解压)。可以用此功能安装驱动程序,然后删除掉 CAB 文件(如果是 RAMDISK 方式启动),以腾出空间。

■ Send <按键代码1>[,按键代码2][,按键代码3]...

  ◎ 功能:模拟按键。
  
  ◎ 参数:虚拟按键代码,如 VK_RETURN,请参相关考编程文档。
  
  ◎ 示例:Send 0x12<,0x09<,0x09>,0x12>

  ◎ 备注:上面的示例模拟 Alt+Tab。如果按键代码以“<”结束,则仅模拟按键按下;“>”则仅模拟按键弹起;否则模拟按下并弹起。按键代码支持 16 进制,如“SendKey 0x90”表示按下 NumLock 键。

■ Wait <毫秒>

  ◎ 功能:等待指定时间后再继续执行命令。
  
  ◎ 参数:指定时间,单位为毫秒。
  
  ◎ 示例:Wait 5000

  ◎ 备注:无。

■ Shut [0|1|2]...

  ◎ 功能:注销|关机|重起。
  
  ◎ 参数:关机方式。
  
  ◎ 示例:Shut

  ◎ 备注:使用经修改的 USER32.DLL,配合此命令使用,将可以拦截所有的关闭系统调用,达到正确关闭的目的(注意,此功能是快速关机,可能不会保存所有数据)。

■ Exec <程序路径>[ 参数]

  ◎ 功能:执行外部命令。
  
  ◎ 格式:执行外部命令。
  
  ◎ 参数:指定程序路径。
  
  ◎ 示例:ExeCmd CMD.EXE /C "DEL /Q /F %TEMP%"

  ◎ 备注:如果路径结尾处有字符“?”,则等待外部命令执行完后才继续执行下一条命令;否则立即返回并执行下一条。如果目标路径的结尾处有字符“<”,则快捷方式的启动方式为最小化方式启动;如果是“>”,则以隐藏方式启动;否则,为正常方式启动。另外,此命令可以支持使用特定参数调用 DLL 函数,功能比 RegSvr32 强大的多,命令格式为“<DLL 路径,函数名称>[,[#]参数1][,[#]参数2][,[#]参数3][,[#]参数4]”。

■ Kill <进程名称>

  ◎ 功能:强制终止指定的进程。
  
  ◎ 参数:进程名称,即 EXE 文件名(不包含路径)。
  
  ◎ 示例:Kill WinLogon

  ◎ 备注:此命令将终止与 <进程名称> 前部分匹配的所有进程。

■ Load [文件路径]

  ◎ 功能:逐条运行命令文件中的命令。
   
  ◎ 参数:指定文件的路径。如果省略,假设 RXPE 本身的 EXE 文件名为 RXPE.EXE,则自动搜索每个分区上的 RXPE.INI 和 RXPE\RXPE.INI 文件。把 RXPE.EXE 改名即可实现自定义命令文件的名称。
  
  ◎ 示例:Load

  ◎ 备注:RXPE 支持把所有的命令写在一个文件种逐条执行。RXPE 命令文件最后一行必须是空行,否则最后一行无法被执行。注意,如果在命令文件中使用此命令,要仔细分析,防止嵌套调用。

■ Init [文件路径]

  ◎ 功能:初始化桌面,然后执行 Load 功能。
   
  ◎ 参数:请参看 Load。
  
  ◎ 示例:Init

  ◎ 备注:此功能用于代替 WinLogon 登录系统,RXPE 可以完全控制登录进度。

■ Logo [[!]文件路径]

  ◎ 功能:显示启动画面。
   
  ◎ 参数:图片文件路径,支持 BMP/JPG/PNG/GIF 等各式(需要 GDI+ 支持)。如果参数为空,则关闭启动画面(渐隐淡出)。
  
  ◎ 示例:Logo !%SystemRoot%\RXPE.JPG

  ◎ 备注:上例中,将使用内部图片显示启动画面。“!”表示后台执行,不阻塞。

■ Text [文字][#颜色][,Left][,Top][,Right][,Bottom]

  ◎ 功能:在启动画面中显示进度文字。
   
  ◎ 参数:文字为空则不显示文字。
  
  ◎ 示例:TEXT 正在注册组件……#0xFFDDDD,4,745,128,768

  ◎ 备注:首次显示文字的时候必须指定位置,否则不会显示。

■ Help

  ◎ 功能:显示帮助信息。
   
  ◎ 参数:无。
  
  ◎ 示例:Help

  ◎ 备注:无。


三、备注

◎ RXPE 命令文件必须使用 UNICODE 格式。

◎ RXPE 命令不区分大小写(ENVI 除外)。

◎ RXPE 命令之后可以跟数量不限的空格和制表符。

◎ 上面的命令中 <> 内的参数表示必须输入,[] 内的表示可以省略。

◎ RXPE 中使用的路径支持环境变量替换(如“%TEMP%\X.TXT”)。

◎ 通常情况下,您只需要编辑一个命令文件 RXPE.INI,里面列出需要执行的命令。然后在 PE 启动的时候执行“RXPE.EXE Init”即可。


四、致谢

◎ 感谢 老九 的热心帮助和意见。
◎ 感谢 无忧论坛 提供的讨论场所。


要获取更多信息,请访问 WWW.YONSM.NET


Yonsm
Yonsm@163.com
WWW.Yonsm.NET
2007.1.4,杭州


顶部
 



当前时区 GMT+8, 现在时间是 2010-9-3 18:10
闽ICP备05002490号

    本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz! 5.5.0  © 2001-2007 Comsenz Inc.
清除 Cookies - 联系我们 - 无忧启动 - Archiver - WAP