Qt调用wimlib库,读取/修改/装载WIM、ESD格式的镜像文件

在查找处理WIM,ESD文件的库,除了Wimgapi库还在找到一个开源库Wimlib处理WIM,ESD格式数据.
Wimlib是一个开源的跨平台库,用于创建、提取和修改Windows映像(WIM)档案,Wimlib及其命令行前端Wimlib-imagex为微软提供免费的跨平台替代方案
Wimlib更适合在Linux环境下使用,测试时部分功能无法在Windows环境下使用。

目录导读

    • WIMLIB描述
      • 数据预处理
      • 获取镜像的相关信息
      • 导出指定系统中的文件
      • 获取镜像目录结构(装载/卸载镜像)
      • 提取镜像到指定目录
      • 注意

WIMLIB描述

wimlib是一个开源的跨平台库,用于创建、提取和修改Windows映像(WIM)档案。WIM是一种文件归档格式,有点类似于ZIP(和许多其他文件归档格式);但与ZIP不同的是,它允许存储各种特定于Windows的元数据,允许在单个归档中存储多个“映像”,自动对所有文件内容进行重复数据删除,并支持可选的固体压缩以获得更好的压缩比。wimlib及其命令行前端wimlib-imagex为微软提供免费的跨平台替代方案Wimgapi, ImageX,以及DISM.除其他外,Wimlib:

  • 在Windows和类UNIX系统(如Mac OS X和Linux)上提供快速可靠的文件归档。
  • 允许非Windows操作系统的用户读写Windows映像(WIM)文件。
  • 支持在Windows风格的文件系统(如NTFS)上正确归档文件,而不会犯常见错误,如未正确处理ACL、文件属性、链接和命名数据流。
  • 允许从Linux等非Windows操作系统部署Windows操作系统。
  • 为多个应用程序提供独立、高质量的开源压缩器和解压缩器压缩格式由微软使用,不像更开放的格式那样广为人知,易于在不同的应用程序和文件格式中重用(不仅仅是WIM)。
  • wimlib作为源tarball(适用于UNIX/Linux)或现成的二进制文件(适用于Windows XP和更高版本)分发。该软件由一个C库和wimlib-imagex命令行前端及其相关文档。
    摘抄自官网:详见 [https://wimlib.net/]

数据预处理

通过github下载的wimlib-1.14.3-windows-x86_64-bin项目
将devel文件夹中的libwim.libwimlib.h添加到项目中,libwim-15.dll放在可执行程序同级目录中。
libwim.lib必须设置为完整路径

#include "devel/wimlib.h"
#pragma comment(lib,"E:\\data-bank\\Git\\Mirror_Image_READ\\Mirror_Image_DAL\\devel\\libwim.lib")
///进度条宏定义
#define TO_PERCENT(numerator, denominator) \
    ((float)(((denominator) == 0) ? 0 : ((numerator) * 100 / (float)(denominator))))

获取镜像的相关信息

wimlib库的使用和Wimgapi库基本差不多,参数这些一看就很明白,wimlib.h文件中也有参数说明,和所有的宏定义这些,但是:
wimlib库在调用获取镜像XML信息时,与Wimgapi有点不一样,传递的是一个FILE * 指针。
wimlib_extract_xml_data 方法描述:

/**
 * @ingroup G_wim_information
 *
 * Similar to wimlib_get_xml_data(), but the XML document will be written to the
 * specified standard C FILE* instead of retrieved in an in-memory
 * buffer.
 *
 * @return 0 on success; a ::wimlib_error_code value on failure.  This may
 * return any error code which can be returned by wimlib_get_xml_data() as well
 * as the following error codes:
 *
 * @retval ::WIMLIB_ERR_WRITE
 *	Failed to write the data to the requested file.
 */
WIMLIBAPI int
wimlib_extract_xml_data(WIMStruct *wim, FILE *fp);



实际调用:

//实际调用
/*
  * 唯一能解释这个问题:https://www.cnblogs.com/wsk3q/p/16964667.html
  * 异常 expression:(_osfile(fh) &fopen)
   FILE *fp=fopen("text.txt","at+");
    if (fp == NULL) {
           qDebug("无法打开文件...\n");
            goto out;
       }

//    fprintf(_file, "%s", "data-dsadsa"); // 写入数据到文件
//    fseek(_file,0L,SEEK_SET);
    // G_wim_information
    ret =wimlib_extract_xml_data(wim,fp);
    if (ret != 0) // Always should check the error codes.
    {
        if(fp!=NULL)
            fclose(fp);
        goto out;
    }

    if(fp!=NULL)
        fclose(fp);
    */

在做测试的时候,我FILE结构的所有打开方式都试了一遍,都愣是异常提示无法写入文件,最后找到唯一的解释就是:传递FILE*指针到dll里面之后引起异常
于是换了种方式改用
wimlib_get_wim_info方法获取WIM信息:
wimlib_get_image_property 方法获取XML节点信息;

/**
 * @ingroup G_wim_information
 *
 * Get basic information about a WIM file.
 *
 * @param wim
 *	Pointer to the ::WIMStruct to query.  This need not represent a
 *	standalone WIM (e.g. it could represent part of a split WIM).
 * @param info
 *	A ::wimlib_wim_info structure that will be filled in with information
 *	about the WIM file.
 *
 * @return 0
 */
WIMLIBAPI int
wimlib_get_wim_info(WIMStruct *wim, struct wimlib_wim_info *info);

/**
 * @ingroup G_wim_information
 *
 * Since wimlib v1.8.3: get a per-image property from the WIM's XML document.
 * This is an alternative to wimlib_get_image_name() and
 * wimlib_get_image_description() which allows getting any simple string
 * property.
 *
 * @param wim
 *	Pointer to the ::WIMStruct for the WIM.
 * @param image
 *	The 1-based index of the image for which to get the property.
 * @param property_name
 *	The name of the image property, for example "NAME", "DESCRIPTION", or
 *	"TOTALBYTES".  The name can contain forward slashes to indicate a nested
 *	XML element; for example, "WINDOWS/VERSION/BUILD" indicates the BUILD
 *	element nested within the VERSION element nested within the WINDOWS
 *	element.  Since wimlib v1.9.0, a bracketed number can be used to
 *	indicate one of several identically-named elements; for example,
 *	"WINDOWS/LANGUAGES/LANGUAGE[2]" indicates the second "LANGUAGE" element
 *	nested within the "WINDOWS/LANGUAGES" element.  Note that element names
 *	are case sensitive.
 *
 * @return
 *	The property's value as a ::wimlib_tchar string, or @c NULL if there is
 *	no such property.  The string may not remain valid after later library
 *	calls, so the caller should duplicate it if needed.
 */
WIMLIBAPI const wimlib_tchar *
wimlib_get_image_property(const WIMStruct *wim, int image,
			  const wimlib_tchar *property_name);

完整调用:

    int ret=0;
    WIMStruct *wim = NULL;
    wimlib_wim_info *info=new wimlib_wim_info;
    //QString Image_path; wim镜像路径
    wchar_t* wimage=_utf8_to_wchar(Image_path.toStdString().c_str());

 /* Open the WIM file as a WIMStruct.  */
    ret = wimlib_open_wim(wimage,  /* Path of WIM file to open  */
                          0,   /* WIMLIB_OPEN_FLAG_* flags (0 means all defaults)  */
                          &wim);    /* Return the WIMStruct pointer in this location  */
    if (ret != 0) /* Always should check the error codes.  */
        goto out;
    //通过wimlib_wim_info结构获取信息
    //Get basic information about a WIM file.
    ret =wimlib_get_wim_info(wim, info);
    if (ret != 0) /* Always should check the error codes.  */
        goto out;

    qDebug()<<"[image_count] "<<info->image_count;
    qDebug()<<"[boot_index] "<<info->boot_index;
    qDebug()<<"[wim_version] "<<info->wim_version;

    //!读取镜像属性 实际上就是读取xml文件结构数据
    /*
    for(int i=1;i<=info->image_count;i++)
    {
        XML_Wim_Version item_version;
        item_version.Index=i;
        item_version.DISPLAYNAME=QString::fromWCharArray(wimlib_get_image_property(wim,i,L"DISPLAYNAME"));

        QString image_size=QString::fromWCharArray(wimlib_get_image_property(wim,i,L"TOTALBYTES"));
        item_version.ISOSIZE=image_size.toDouble()!=0?(QString::number(image_size.toDouble()/MB,'f',1)+"MB"):"???";
        item_version.MAJOR=QString::fromWCharArray(wimlib_get_image_property(wim,i,L"WINDOWS/VERSION/MAJOR"));
        item_version.MINOR=QString::fromWCharArray(wimlib_get_image_property(wim,i,L"WINDOWS/VERSION/MINOR"));
        item_version.BUILD=QString::fromWCharArray(wimlib_get_image_property(wim,i,L"WINDOWS/VERSION/BUILD"));
        item_version.SPBUILD=QString::fromWCharArray(wimlib_get_image_property(wim,i,L"WINDOWS/VERSION/SPBUILD"));
        item_version.PRODUCTTYPE=QString::fromWCharArray(wimlib_get_image_property(wim,i,L"WINDOWS/PRODUCTTYPE"));
        item_version.VERSION=WINVERSION(item_version.PRODUCTTYPE,QString("%1.%2.%3.%4").arg(item_version.MAJOR).arg(item_version.MINOR).arg(item_version.BUILD).arg(item_version.SPBUILD));
        item_version.FILECOUNT=QString::fromWCharArray(wimlib_get_image_property(wim,i,L"FILECOUNT"));
        item_version.DIRCOUNT=QString::fromWCharArray(wimlib_get_image_property(wim,i,L"DIRCOUNT"));
        Versions.append(item_version);
    }
    */
	//系统版本数量
    //int Image_Count=Versions.count();
out:

    /* Free the WIMStruct.  Has no effect if the pointer to it is NULL.  */
    wimlib_free(wim);

    /* Check for error status.  */
    if (ret != 0) {
        qDebug()<<"wimlib error : "<<QString::fromWCharArray(wimlib_get_error_string((enum wimlib_error_code)ret));
    }

    /* Free global memory (optional).  */
    wimlib_global_cleanup();

    free(wimage);

Wimlib库自带异常捕获,能通过wimlib_get_error_string 完整获取错误信息。
在测试的时候,部分信息不完整的WIM文件无法通过wimlib_open_wim方法打开,暂时无解。

导出指定系统中的文件

可通过wimlib_extract_paths 导出指定系统版本中的文件,
wimlib_extract_paths 函数说明:

/**
 * @ingroup G_extracting_wims
 *
 * Extract zero or more paths (files or directory trees) from the specified WIM
 * image.
 *
 * By default, each path will be extracted to a corresponding subdirectory of
 * the target based on its location in the image.  For example, if one of the
 * paths to extract is /Windows/explorer.exe and the target is
 * outdir, the file will be extracted to
 * outdir/Windows/explorer.exe.  This behavior can be changed by
 * providing the flag ::WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE, which
 * will cause each file or directory tree to be placed directly in the target
 * directory --- so the same example would extract /Windows/explorer.exe
 * to outdir/explorer.exe.
 *
 * With globbing turned off (the default), paths are always checked for
 * existence strictly; that is, if any path to extract does not exist in the
 * image, then nothing is extracted and the function fails with
 * ::WIMLIB_ERR_PATH_DOES_NOT_EXIST.  But with globbing turned on
 * (::WIMLIB_EXTRACT_FLAG_GLOB_PATHS specified), globs are by default permitted
 * to match no files, and there is a flag (::WIMLIB_EXTRACT_FLAG_STRICT_GLOB) to
 * enable the strict behavior if desired.
 *
 * Symbolic links are not dereferenced when paths in the image are interpreted.
 *
 * @param wim
 *	WIM from which to extract the paths, specified as a pointer to the
 *	::WIMStruct for a standalone WIM file, a delta WIM file, or part 1 of a
 *	split WIM.  In the case of a WIM file that is not standalone, this
 *	::WIMStruct must have had any needed external resources previously
 *	referenced using wimlib_reference_resources() or
 *	wimlib_reference_resource_files().
 * @param image
 *	The 1-based index of the WIM image from which to extract the paths.
 * @param paths
 *	Array of paths to extract.  Each element must be the absolute path to a
 *	file or directory within the image.  Path separators may be either
 *	forwards or backwards slashes, and leading path separators are optional.
 *	The paths will be interpreted either case-sensitively (UNIX default) or
 *	case-insensitively (Windows default); however, the case sensitivity can
 *	be configured explicitly at library initialization time by passing an
 *	appropriate flag to wimlib_global_init().
 *	
* By default, "globbing" is disabled, so the characters @c * and @c ? are * interpreted literally. This can be changed by specifying * ::WIMLIB_EXTRACT_FLAG_GLOB_PATHS in @p extract_flags. * @param num_paths * Number of paths specified in @p paths. * @param target * Directory to which to extract the paths. * @param extract_flags * Bitwise OR of flags prefixed with WIMLIB_EXTRACT_FLAG. * * @return 0 on success; a ::wimlib_error_code value on failure. Most of the * error codes are the same as those returned by wimlib_extract_image(). Below, * some of the error codes returned in situations specific to path-mode * extraction are documented: * * @retval ::WIMLIB_ERR_NOT_A_REGULAR_FILE * ::WIMLIB_EXTRACT_FLAG_TO_STDOUT was specified in @p extract_flags, but * one of the paths to extract did not name a regular file. * @retval ::WIMLIB_ERR_PATH_DOES_NOT_EXIST * One of the paths to extract does not exist in the image; see discussion * above about strict vs. non-strict behavior. * * If a progress function is registered with @p wim, then it will receive * ::WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS. */
WIMLIBAPI int wimlib_extract_paths(WIMStruct *wim, int image, const wimlib_tchar *target, const wimlib_tchar * const *paths, size_t num_paths, int extract_flags);

获取镜像目录结构(装载/卸载镜像)

挂载WIM映像(仅限Linux);
这是在我测试的时候,把装载/卸载方法写完,调用失败查找官方文档才发现的问题…
wimlib_mount_image 装载函数:
wimlib_unmount_image 卸载函数:

/**
 * @ingroup G_mounting_wim_images
 *
 * Mount an image from a WIM file on a directory read-only or read-write.
 *
 * @param wim
 *	Pointer to the ::WIMStruct containing the image to be mounted.  This
 *	::WIMStruct must have a backing file.
 * @param image
 *	The 1-based index of the image to mount.  This image cannot have been
 *	previously modified in memory.
 * @param dir
 *	The path to an existing empty directory on which to mount the image.
 * @param mount_flags
 *	Bitwise OR of flags prefixed with WIMLIB_MOUNT_FLAG.  Use
 *	::WIMLIB_MOUNT_FLAG_READWRITE to request a read-write mount instead of a
 *	read-only mount.
 * @param staging_dir
 *	If non-NULL, the name of a directory in which a temporary directory for
 *	storing modified or added files will be created.  Ignored if
 *	::WIMLIB_MOUNT_FLAG_READWRITE is not specified in @p mount_flags.  If
 *	left @c NULL, the staging directory is created in the same directory as
 *	the backing WIM file.  The staging directory is automatically deleted
 *	when the image is unmounted.
 *
 * @return 0 on success; a ::wimlib_error_code value on failure.
 *
 * @retval ::WIMLIB_ERR_ALREADY_LOCKED
 *	Another process is currently modifying the WIM file.
 * @retval ::WIMLIB_ERR_FUSE
 *	A non-zero status code was returned by @c fuse_main().
 * @retval ::WIMLIB_ERR_IMAGE_HAS_MULTIPLE_REFERENCES
 *	There are currently multiple references to the image as a result of a
 *	call to wimlib_export_image().  Free one before attempting the
 *	read-write mount.
 * @retval ::WIMLIB_ERR_INVALID_IMAGE
 *	@p image does not exist in @p wim.
 * @retval ::WIMLIB_ERR_INVALID_PARAM
 *	@p wim was @c NULL; or @p dir was NULL or an empty string; or an
 *	unrecognized flag was specified in @p mount_flags; or the image has
 *	already been modified in memory (e.g. by wimlib_update_image()).
 * @retval ::WIMLIB_ERR_MKDIR
 *	::WIMLIB_MOUNT_FLAG_READWRITE was specified in @p mount_flags, but the
 *	staging directory could not be created.
 * @retval ::WIMLIB_ERR_WIM_IS_READONLY
 *	::WIMLIB_MOUNT_FLAG_READWRITE was specified in @p mount_flags, but the
 *	WIM file is considered read-only because of any of the reasons mentioned
 *	in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS flag.
 * @retval ::WIMLIB_ERR_UNSUPPORTED
 *	Mounting is not supported in this build of the library.
 *
 * This function can additionally return ::WIMLIB_ERR_DECOMPRESSION,
 * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_METADATA_NOT_FOUND,
 * ::WIMLIB_ERR_READ, or ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE, all of which
 * indicate failure (for different reasons) to read the metadata resource for
 * the image to mount.
 *
 * The ability to mount WIM images is implemented using FUSE (Filesystem in
 * UserSpacE).  Depending on how FUSE is set up on your system, this function
 * may work as normal users in addition to the root user.
 *
 * Mounting WIM images is not supported if wimlib was configured
 * --without-fuse.  This includes Windows builds of wimlib;
 * ::WIMLIB_ERR_UNSUPPORTED will be returned in such cases.
 *
 * Calling this function daemonizes the process, unless
 * ::WIMLIB_MOUNT_FLAG_DEBUG was specified or an early error occurs.
 *
 * It is safe to mount multiple images from the same WIM file read-only at the
 * same time, but only if different ::WIMStruct's are used.  It is @b not safe
 * to mount multiple images from the same WIM file read-write at the same time.
 *
 * To unmount the image, call wimlib_unmount_image().  This may be done in a
 * different process.
 */
WIMLIBAPI int
wimlib_mount_image(WIMStruct *wim,
		   int image,
		   const wimlib_tchar *dir,
		   int mount_flags,
		   const wimlib_tchar *staging_dir);


/**
 * @ingroup G_mounting_wim_images
 *
 * Unmount a WIM image that was mounted using wimlib_mount_image().
 *
 * When unmounting a read-write mounted image, the default behavior is to
 * discard changes to the image.  Use ::WIMLIB_UNMOUNT_FLAG_COMMIT to cause the
 * image to be committed.
 *
 * @param dir
 *	The directory on which the WIM image is mounted.
 * @param unmount_flags
 *	Bitwise OR of flags prefixed with @p WIMLIB_UNMOUNT_FLAG.
 *
 * @return 0 on success; a ::wimlib_error_code value on failure.
 *
 * @retval ::WIMLIB_ERR_NOT_A_MOUNTPOINT
 *	There is no WIM image mounted on the specified directory.
 * @retval ::WIMLIB_ERR_MOUNTED_IMAGE_IS_BUSY
 *	The read-write mounted image cannot be committed because there are file
 *	descriptors open to it, and ::WIMLIB_UNMOUNT_FLAG_FORCE was not
 *	specified.
 * @retval ::WIMLIB_ERR_MQUEUE
 *	Could not create a POSIX message queue.
 * @retval ::WIMLIB_ERR_NOT_PERMITTED_TO_UNMOUNT
 *	The image was mounted by a different user.
 * @retval ::WIMLIB_ERR_UNSUPPORTED
 *	Mounting is not supported in this build of the library.
 *
 * Note: you can also unmount the image by using the @c umount() system call, or
 * by using the @c umount or @c fusermount programs.  However, you need to call
 * this function if you want changes to be committed.
 */
WIMLIBAPI int
wimlib_unmount_image(const wimlib_tchar *dir, int unmount_flags);
		   

调用示例,建议Linux环境下测试,Windows环境下不支持:

    int WIM_INDEX=qMin(qMax(1,index.toInt()),Image_Count);
    wchar_t* wimage;
    int ret=0;
    WIMStruct *wim = NULL;
    //     wchar_t* wtemp=tempObj.GetTempDirU();
    wchar_t* wtemp=_utf8_to_wchar(QString("C:\\Users\\admin\\Desktop\\textxml\\text").toStdString().c_str());
    QDir tempMountDir(QString::fromWCharArray(wtemp)+"\\TempMount_WIMLIB");
    if(!tempMountDir.exists())
        tempMountDir.mkpath(QString::fromWCharArray(wtemp)+"\\TempMount_WIMLIB");
    wchar_t* wdst=_utf8_to_wchar(QString(QString::fromWCharArray(wtemp)+"\\TempMount_WIMLIB").toStdString().c_str());
    //TempFile 挂载路径
    QString TempFile=QString::fromWCharArray(wdst);
    qDebug()<<"[TempFile] "<<TempFile;
	//Image_path 镜像路径
    wimage=_utf8_to_wchar(Image_path.toStdString().c_str());
    /* Open the WIM file as a WIMStruct.  */
    ret = wimlib_open_wim(wimage,  /* Path of WIM file to open  */
                          0,   /* WIMLIB_OPEN_FLAG_* flags (0 means all defaults)  */
                          &wim);    /* Return the WIMStruct pointer in this location  */
    if (ret != 0) /* Always should check the error codes.  */
        goto out;

    //WIMLIB_MOUNT_FLAG_READWRITE
    //WIMLIB_MOUNT_FLAG_DEBUG
    //WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE
    //WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR
    //WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS
    //WIMLIB_MOUNT_FLAG_UNIX_DATA
    //WIMLIB_MOUNT_FLAG_ALLOW_OTHER
    ret=wimlib_mount_image(wim,WIM_INDEX,wdst,0,L"");
    if (ret != 0) /* Always should check the error codes.  */
    {
        goto out;
    }
	//遍历目录结构
    //Lib_Deploy_Environment::getInstance().EnumerateFiles(TempFile,Fetch_Files);
    
    //! 如果需要对镜像镜像修改 可以在此处操作文件目录/文件 然后提交保存
    //!WIMLIB_UNMOUNT_FLAG_COMMIT 保存装载后的更改!
    //WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY
    //WIMLIB_UNMOUNT_FLAG_COMMIT
    //WIMLIB_UNMOUNT_FLAG_REBUILD
    //WIMLIB_UNMOUNT_FLAG_RECOMPRESS
    //WIMLIB_UNMOUNT_FLAG_FORCE
    //WIMLIB_UNMOUNT_FLAG_NEW_IMAGE
    //不提交修改
    ret=wimlib_unmount_image(wdst, 0);
    if (ret != 0) /* Always should check the error codes.  */
    {
        goto out;
    }
out:

    /* Free the WIMStruct.  Has no effect if the pointer to it is NULL.  */
    wimlib_free(wim);

    /* Check for error status.  */
    if (ret != 0) {
        qDebug()<<"wimlib error : "<<QString::fromWCharArray(wimlib_get_error_string((enum wimlib_error_code)ret));
    }

    /* Free global memory (optional).  */
    wimlib_global_cleanup();

提取镜像到指定目录

WIMLIB通过wimlib_extract_image函数提取镜像。
也可通过wimlib_register_progress_function设置回调函数直接获取进度。

/**
 * @ingroup G_general
 *
 * Register a progress function with a ::WIMStruct.
 *
 * @param wim
 *	The ::WIMStruct for which to register the progress function.
 * @param progfunc
 *	Pointer to the progress function to register.  If the WIM already has a
 *	progress function registered, it will be replaced with this one.  If @p
 *	NULL, the current progress function (if any) will be unregistered.
 * @param progctx
 *	The value which will be passed as the third argument to calls to @p
 *	progfunc.
 */
WIMLIBAPI void
wimlib_register_progress_function(WIMStruct *wim,
				  wimlib_progress_func_t progfunc,
				  void *progctx);
				  
/**
 * @ingroup G_extracting_wims
 *
 * Extract an image, or all images, from a ::WIMStruct.
 *
 * The exact behavior of how wimlib extracts files from a WIM image is
 * controllable by the @p extract_flags parameter, but there also are
 * differences depending on the platform (UNIX-like vs Windows).  See the
 * documentation for wimapply for more information, including about the
 * NTFS-3G extraction mode.
 *
 * @param wim
 *	The WIM from which to extract the image(s), specified as a pointer to the
 *	::WIMStruct for a standalone WIM file, a delta WIM file, or part 1 of a
 *	split WIM.  In the case of a WIM file that is not standalone, this
 *	::WIMStruct must have had any needed external resources previously
 *	referenced using wimlib_reference_resources() or
 *	wimlib_reference_resource_files().
 * @param image
 *	The 1-based index of the image to extract, or ::WIMLIB_ALL_IMAGES to
 *	extract all images.  Note: ::WIMLIB_ALL_IMAGES is unsupported in NTFS-3G
 *	extraction mode.
 * @param target
 *	A null-terminated string which names the location to which the image(s)
 *	will be extracted.  By default, this is interpreted as a path to a
 *	directory.  Alternatively, if ::WIMLIB_EXTRACT_FLAG_NTFS is specified in
 *	@p extract_flags, then this is interpreted as a path to an unmounted
 *	NTFS volume.
 * @param extract_flags
 *	Bitwise OR of flags prefixed with WIMLIB_EXTRACT_FLAG.
 *
 * @return 0 on success; a ::wimlib_error_code value on failure.
 *
 * @retval ::WIMLIB_ERR_DECOMPRESSION
 *	The WIM file contains invalid compressed data.
 * @retval ::WIMLIB_ERR_INVALID_IMAGE
 *	@p image does not exist in @p wim.
 * @retval ::WIMLIB_ERR_INVALID_METADATA_RESOURCE
 *	The metadata for an image to extract was invalid.
 * @retval ::WIMLIB_ERR_INVALID_PARAM
 *	The extraction flags were invalid; more details may be found in the
 *	documentation for the specific extraction flags that were specified.  Or
 *	@p target was @c NULL or an empty string, or @p wim was @c NULL.
 * @retval ::WIMLIB_ERR_INVALID_RESOURCE_HASH
 *	The data of a file that needed to be extracted was corrupt.
 * @retval ::WIMLIB_ERR_LINK
 *	Failed to create a symbolic link or a hard link.
 * @retval ::WIMLIB_ERR_METADATA_NOT_FOUND
 *	@p wim does not contain image metadata; for example, it represents a
 *	non-first part of a split WIM.
 * @retval ::WIMLIB_ERR_MKDIR
 *	Failed create a directory.
 * @retval ::WIMLIB_ERR_NTFS_3G
 *	libntfs-3g reported that a problem occurred while writing to the NTFS
 *	volume.
 * @retval ::WIMLIB_ERR_OPEN
 *	Could not create a file, or failed to open an already-extracted file.
 * @retval ::WIMLIB_ERR_READ
 *	Failed to read data from the WIM.
 * @retval ::WIMLIB_ERR_READLINK
 *	Failed to determine the target of a symbolic link in the WIM.
 * @retval ::WIMLIB_ERR_REPARSE_POINT_FIXUP_FAILED
 *	Failed to fix the target of an absolute symbolic link (e.g. if the
 *	target would have exceeded the maximum allowed length).  (Only if
 *	reparse data was supported by the extraction mode and
 *	::WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS was specified in @p
 *	extract_flags.)
 * @retval ::WIMLIB_ERR_RESOURCE_NOT_FOUND
 *	A file data blob that needed to be extracted could not be found in the
 *	blob lookup table of @p wim.  See @ref G_nonstandalone_wims.
 * @retval ::WIMLIB_ERR_SET_ATTRIBUTES
 *	Failed to set attributes on a file.
 * @retval ::WIMLIB_ERR_SET_REPARSE_DATA
 *	Failed to set reparse data on a file (only if reparse data was supported
 *	by the extraction mode).
 * @retval ::WIMLIB_ERR_SET_SECURITY
 *	Failed to set security descriptor on a file.
 * @retval ::WIMLIB_ERR_SET_SHORT_NAME
 *	Failed to set the short name of a file.
 * @retval ::WIMLIB_ERR_SET_TIMESTAMPS
 *	Failed to set timestamps on a file.
 * @retval ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE
 *	Unexpected end-of-file occurred when reading data from the WIM.
 * @retval ::WIMLIB_ERR_UNSUPPORTED
 *	A requested extraction flag, or the data or metadata that must be
 *	extracted to support it, is unsupported in the build and configuration
 *	of wimlib, or on the current platform or extraction mode or target
 *	volume.  Flags affected by this include ::WIMLIB_EXTRACT_FLAG_NTFS,
 *	::WIMLIB_EXTRACT_FLAG_UNIX_DATA, ::WIMLIB_EXTRACT_FLAG_STRICT_ACLS,
 *	::WIMLIB_EXTRACT_FLAG_STRICT_SHORT_NAMES,
 *	::WIMLIB_EXTRACT_FLAG_STRICT_TIMESTAMPS, and
 *	::WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS.  For example, if
 *	::WIMLIB_EXTRACT_FLAG_STRICT_SHORT_NAMES is specified in @p
 *	extract_flags, ::WIMLIB_ERR_UNSUPPORTED will be returned if the WIM
 *	image contains one or more files with short names, but extracting short
 *	names is not supported --- on Windows, this occurs if the target volume
 *	does not support short names, while on non-Windows, this occurs if
 *	::WIMLIB_EXTRACT_FLAG_NTFS was not specified in @p extract_flags.
 * @retval ::WIMLIB_ERR_WIMBOOT
 *	::WIMLIB_EXTRACT_FLAG_WIMBOOT was specified in @p extract_flags, but
 *	there was a problem creating WIMBoot pointer files or registering a
 *	source WIM file with the Windows Overlay Filesystem (WOF) driver.
 * @retval ::WIMLIB_ERR_WRITE
 *	Failed to write data to a file being extracted.
 *
 * If a progress function is registered with @p wim, then as each image is
 * extracted it will receive ::WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_BEGIN, then
 * zero or more ::WIMLIB_PROGRESS_MSG_EXTRACT_FILE_STRUCTURE messages, then zero
 * or more ::WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS messages, then zero or more
 * ::WIMLIB_PROGRESS_MSG_EXTRACT_METADATA messages, then
 * ::WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_END.
 */
WIMLIBAPI int
wimlib_extract_image(WIMStruct *wim, int image,
		     const wimlib_tchar *target, int extract_flags);

调用示例:

enum wimlib_progress_status extract_progress(enum wimlib_progress_msg msg,
                                        union wimlib_progress_info *info, void *progctx)
{
    switch (msg) {
    case WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS:
        qDebug("Extracting files: %.2f%% complete\n",
               TO_PERCENT(info->extract.completed_bytes,
                          info->extract.total_bytes));
        break;
    default:
        break;
    }
    return WIMLIB_PROGRESS_STATUS_CONTINUE;
}

void Export_WIM(QString Imagepath,int index,QString descpath)
{
    //QString Imagepath; 镜像路径
    wchar_t* wimage=_utf8_to_wchar(Imagepath.toStdString().c_str());
    //QString descpath;输出目录
    wchar_t* wdst=_utf8_to_wchar(descpath.toStdString().c_str());

    int ret=0;
    WIMStruct *wim = NULL;
    /* Open the WIM file as a WIMStruct.  */
    ret = wimlib_open_wim(wimage,  /* Path of WIM file to open  */
                          0,   /* WIMLIB_OPEN_FLAG_* flags (0 means all defaults)  */
                          &wim);    /* Return the WIMStruct pointer in this location  */
    if (ret != 0) /* Always should check the error codes.  */
        goto out;

    /* Register our progress function.  */
    wimlib_register_progress_function(wim, extract_progress, NULL);

    /* Extract the first image.  */
    ret = wimlib_extract_image(wim,     /* WIMStruct from which to extract the image  */
                               index,       /* Image to extract  */
                               wdst, /* Directory to extract the image to  */
                               0);      /* WIMLIB_EXTRACT_FLAG_* flags (0 means all defaults)  */

    if (ret != 0) /* Always should check the error codes.  */
        goto out;
out:

    /* Free the WIMStruct.  Has no effect if the pointer to it is NULL.  */
    wimlib_free(wim);

    /* Check for error status.  */
    if (ret != 0) {
        QString Error=QString::fromWCharArray(wimlib_get_error_string((enum wimlib_error_code)ret));
        qDebug()<<"wimlib error : "<<Error;
    }

    /* Free global memory (optional).  */
    wimlib_global_cleanup();

    free(wimage);
    free(wdst);
}

注意

  • Wimlib库在Window环境下不如WIMGAPI库好用(个人感觉);Windows环境建议使用WIMGAPI开发,Linux环境建议使用Wimlib,实在不想这么麻烦,通过QProcess调用cmd执行wimlib-imagex.exe命令行的方式也很不错。
  • Wimlib库函数的调用可以参考
    https://github-wiki-see.page/m/openthos/openthos/wiki/wimlib-analysis
    中的说明(中文版),包括一些函数的使用规范,宏定义都有说明。
  • 在Gitbit上有一个wimlib-master项目,具体链接丢了,
    可以查看examples文件夹中的各种示例文件:
    applywim.c
    capturewim.c
    compressfile.c
    decompressfile.c
    updatewim.c

你可能感兴趣的:(Windows,Api,qt,WIMLIB,C++)