吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 24804|回复: 10
收起左侧

[C&C++ 转载] 【技术·水】浅谈Windows10的CompactOS特性

  [复制链接]
Mouri_Naruto 发表于 2016-8-16 19:41
本帖最后由 Mouri_Naruto 于 2016-8-16 19:56 编辑

================================注释开始================================
转载前最好告知楼主一声

感谢不离不弃的包子,zifeityzyicq和ART-Master

本技术贴原名《【水·技术】浅谈Windows 10 Build 9879的磁盘清理的System Compression》
远景地址:http://bbs.pcbeta.com/viewthread-1567726-1-1.html
================================注释结束================================

一:前言

上次,我在远景发布了《【水·技术】浅谈Windows 10 Build 9879的磁盘清理的System Compression》;
虽然文笔稚嫩(可以算黑历史了),但依旧上了远景首页

这个帖子发布了快两年了,这个世界也有了不少变化

Windows10早已从Build 9879进入到了Build 14901;
System Compression也改名为CompactOS;
Windows10下可以使用compact命令行工具;Win7/8/8.1也有Dism++可以帮你;
MSDN也公开了CompactOS的调用方法

在这样的情形下,我打算写个总结帖子

二:CompactOS原理

CompactOS是通过Windows Overlay Filter过滤驱动实现的,该过滤驱动同时也负责WIMBoot的实现

CompactOS在一般人看来如同NTFS压缩和Bitlocker加密一样是透明的
但是CompactOS可以选用压缩率更高的用于压缩WIM文件的算法,你可以使用以下算法

XPRESS4K(WIMBoot压缩算法,CompactOS默认算法;压缩率最低,速度最快)
XPRESS8K
XPRESS16K
LZX(WIM最大压缩;压缩率最高,速度最慢)

于是这也是CompactOS比只使用LZNT压缩算法的NTFS压缩压缩率更高的奥秘所在

三:如何使用CompactOS压缩

第一种途径,你可以通过Windows10开始系统自带的compact命令行工具对文件使用CompactOS压缩

这个用法只适用于Windows 10 Build 10074或更高版本

同时按下键盘上的Win和X键,出现菜单;点击命令提示符(管理员);
接下来弹出用户账户控制对话框,点是就出现了命令提示符窗口。


若安装系统时想对系统文件使用默认CompactOS算法进行全盘压缩,可以执行这样的指令:
DISM /Apply-Image /ImageFile:install.wim /Index:1/ApplyDir:D:\ /compact (D为系统盘符)

如果你要查询你的系统有没有被CompactOS,可以在管理员权限的命令提示符下输入以下命令并回车(在线系统适用)
compact /compactos:query
如果你的系统被CompactOS的话,会显示以下信息:“系统处于压缩状态。它将保持此状态,除非管理员更改它。”

如果你想要进行OSCompact的话,可以在管理员权限的命令提示符下输入以下命令并回车(在线系统适用)
compact /compactos:always

如果你要撤销OSCompact,可以在管理员权限的命令提示符下输入以下命令并回车(在线系统适用)
compact /compactos:never

如果你想单独对一个文件进行CompactOS压缩,那怎么办呢?下面举个例子

如果我要对E:\ToolKit\procexp.exe进行lzx算法的Compact压缩,我可以输入以下命令并回车(在线和离线都可以)。
compact /c /exe:lzx E:\ToolKit\procexp.exe

既然介绍了压缩,那么介绍如何解压也是不可少的。
compact /u /exe E:\ToolKit\procexp.exe

如果你的系统不符合要求,或者不习惯命令提示符操作,推荐使用Dism++。使用方法参考Dism++的相关说明,这里不再叙述。

第二种途径,通过API调用对文件进行CompactOS压缩


你可以通过DeviceIoControl传入相应IO控制码实现对文件的CompactOS压缩

SDK要求Windows 10 Build 10240及之后版本;且使用CompactOS前要
#include <winioctl.h>

而且CompactOS压缩对传入和传出的结构有要求
WOF_EXTERNAL_INFO和FILE_PROVIDER_EXTERNAL_INFO_V1这两个结构的内容要放在一个Buffer内传输
且WOF_EXTERNAL_INFO结构的内容要放在FILE_PROVIDER_EXTERNAL_INFO_V1结构内容的前面


为了方便起见,我定义了一个结构
[C++] 纯文本查看 复制代码
typedef struct _WOF_FILE_EXTERNAL_BACKING_V1
{
        WOF_EXTERNAL_INFO WofInfo;
        FILE_PROVIDER_EXTERNAL_INFO_V1 FileProviderInfo;
} WOF_FILE_EXTERNAL_BACKING_V1, *PWOF_FILE_EXTERNAL_BACKING_V1;


FSCTL_SET_EXTERNAL_BACKING - 压缩
FSCTL_GET_EXTERNAL_BACKING - 获取压缩信息
FSCTL_DELETE_EXTERNAL_BACKING - 解压缩


PS:CompactOS压缩过的文件,如果以可写方式打开系统会自动解压缩文件(也许微软这么做是为了保证性能)

为了方便起见,我用NativeAPI对CompactOS的调用做了封装

CompactLib.h
[C++] 纯文本查看 复制代码
// CompactLib By Mouri_Naruto

#pragma once

// Wof压缩算法定义

#define FILE_PROVIDER_COMPRESSION_XPRESS4K   (0x00000000)
#define FILE_PROVIDER_COMPRESSION_LZX        (0x00000001)
#define FILE_PROVIDER_COMPRESSION_XPRESS8K   (0x00000002)
#define FILE_PROVIDER_COMPRESSION_XPRESS16K  (0x00000003)
#define FILE_PROVIDER_COMPRESSION_MAXIMUM    (0x00000004)

/*
对指定文件执行Wof压缩
*/
HRESULT WINAPI WofCompactFile(
	_In_ HANDLE FileHandle,
	_In_ DWORD CompactAlgorithm
	);

/*
对指定文件执行Wof解压缩
*/
HRESULT WINAPI WofUnCompactFile(
	_In_ HANDLE FileHandle
	);

/*
获取指定文件的Wof压缩算法
(如果文件未压缩或者执行失败返回 -1,否则为Wof压缩算法定义值)
*/
DWORD WINAPI WofGetFileCompactAlgorithm(
	_In_ HANDLE FileHandle
	);

/*
对指定文件执行NTFS压缩
*/
HRESULT WINAPI NTFSCompactFile(
	_In_ HANDLE FileHandle
	);

/*
对指定文件执行NTFS解压缩
*/
HRESULT WINAPI NTFSUnCompactFile(
	_In_ HANDLE FileHandle
	);


CompactLib.cpp

[C++] 纯文本查看 复制代码
// CompactLib By Mouri_Naruto

#include <Windows.h>

#include "CompactLib.h"

#ifndef NativeAPI
#define NativeAPI

#pragma comment(lib,"ntdll.lib")

#define NT_SUCCESS(status) ((NTSTATUS)(status) >= 0)

typedef struct _IO_STATUS_BLOCK
{
	union
	{
		NTSTATUS Status;
		PVOID Pointer;
	};
	ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

typedef VOID(NTAPI *PIO_APC_ROUTINE)(
	_In_ PVOID ApcContext,
	_In_ PIO_STATUS_BLOCK IoStatusBlock,
	_In_ ULONG Reserved
	);

extern "C"
{
	NTSYSCALLAPI NTSTATUS NTAPI NtFsControlFile(
		_In_ HANDLE FileHandle,
		_In_opt_ HANDLE Event,
		_In_opt_ PIO_APC_ROUTINE ApcRoutine,
		_In_opt_ PVOID ApcContext,
		_Out_ PIO_STATUS_BLOCK IoStatusBlock,
		_In_ ULONG FsControlCode,
		_In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
		_In_ ULONG InputBufferLength,
		_Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
		_In_ ULONG OutputBufferLength
		);

	NTSYSAPI ULONG NTAPI RtlNtStatusToDosError(
		_In_ NTSTATUS Status
		);
}
#endif

#include <winioctl.h>

typedef struct _WOF_FILE_EXTERNAL_BACKING_V1
{
	WOF_EXTERNAL_INFO WofInfo;
	FILE_PROVIDER_EXTERNAL_INFO_V1 FileProviderInfo;
} WOF_FILE_EXTERNAL_BACKING_V1, *PWOF_FILE_EXTERNAL_BACKING_V1;

HRESULT WINAPI WofCompactFile(
	_In_ HANDLE FileHandle,
	_In_ DWORD CompactAlgorithm
	)
{
	if (WofGetFileCompactAlgorithm(FileHandle) == CompactAlgorithm)
		return S_OK;
	
	NTSTATUS status;
	IO_STATUS_BLOCK IoStatus = { 0 };
	WOF_FILE_EXTERNAL_BACKING_V1 WofFileInfo = { 0 };

	WofFileInfo.WofInfo.Version = WOF_CURRENT_VERSION;
	WofFileInfo.WofInfo.Provider = WOF_PROVIDER_FILE;
	WofFileInfo.FileProviderInfo.Version = FILE_PROVIDER_CURRENT_VERSION;
	WofFileInfo.FileProviderInfo.Algorithm = CompactAlgorithm;
	WofFileInfo.FileProviderInfo.Flags = 0;

	status = NtFsControlFile(
		FileHandle, NULL, NULL, NULL, &IoStatus, FSCTL_SET_EXTERNAL_BACKING,
		&WofFileInfo, sizeof(WofFileInfo), NULL, 0);

	return RtlNtStatusToDosError(status);
}

HRESULT WINAPI WofUnCompactFile(
	_In_ HANDLE FileHandle
	)
{
	NTSTATUS status;
	IO_STATUS_BLOCK IoStatus = { 0 };

	status = NtFsControlFile(
		FileHandle, NULL, NULL, NULL, &IoStatus,
		FSCTL_DELETE_EXTERNAL_BACKING, NULL, 0, NULL, 0);

	return RtlNtStatusToDosError(status);
}

DWORD WINAPI WofGetFileCompactAlgorithm(
	_In_ HANDLE FileHandle
	)
{
	NTSTATUS status;
	IO_STATUS_BLOCK IoStatus = { 0 };
	WOF_FILE_EXTERNAL_BACKING_V1 WofFileInfo = { 0 };

	status = NtFsControlFile(
		FileHandle, NULL, NULL, NULL, &IoStatus, FSCTL_GET_EXTERNAL_BACKING,
		NULL, 0, &WofFileInfo, sizeof(WofFileInfo));

	return !NT_SUCCESS(status) ? -1 : WofFileInfo.FileProviderInfo.Algorithm;
}

HRESULT WINAPI NTFSCompactFile(
	_In_ HANDLE FileHandle
	)
{
	NTSTATUS status;
	IO_STATUS_BLOCK IoStatus = { 0 };
	USHORT Type = COMPRESSION_FORMAT_DEFAULT;

	status = NtFsControlFile(
		FileHandle, NULL, NULL, NULL, &IoStatus,
		FSCTL_SET_COMPRESSION, &Type, sizeof(Type), NULL, 0);

	return RtlNtStatusToDosError(status);
}

HRESULT WINAPI NTFSUnCompactFile(
	_In_ HANDLE FileHandle
	)
{
	NTSTATUS status;
	IO_STATUS_BLOCK IoStatus = { 0 };
	USHORT Type = COMPRESSION_FORMAT_NONE;

	status = NtFsControlFile(
		FileHandle, NULL, NULL, NULL, &IoStatus,
		FSCTL_SET_COMPRESSION, &Type, sizeof(Type), NULL, 0);

	return RtlNtStatusToDosError(status);
}


四:性能影响和效果

度娘看了看,几乎都表示CompactOS基本上不会影响性能。但CompactOS易产生难整理型文件碎片,在机械硬盘上应注意。

下面附带下个人的体验
由于我使用了LZX算法,于是系统盘比以前腾出了将近一半的空间(原本占用50GB,现在25GB左右)
而且感受不到性能的损失,也许是我的CPU是E3 1230 V2,硬盘是256GB SSD的缘故吧

五:移植CompactOS特性到其他系统

前提条件系统是Windows 7/8/8.1及对应的服务器版本;而且你要使用Windows ADK 10的wofadk.sys

曾经和Dism++作者解决Dism++在Windows Vista下的兼容性问题时
发现Vista下一旦安装了wofadk驱动,bootmgr阶段会报错“启动文件证书无效”

而且你要排除Windows加载wofadk驱动前Windows需要用到的文件

详情可以参考无忧;或者你也可以使用Dism++

附:Windows10 CompactOS排除列表

IDA打开Windows10的compact.exe命令行工具就可以找到了)
[C++] 纯文本查看 复制代码
// 文件排除列表
wchar_t *FileExclusionList[] = 
{
        L"\\aow.wim",
        L"\\boot\\bcd",
        L"\\boot\\bcd.log",
        L"\\boot\\bootstat.dat",
        L"\\config\\drivers",
        L"\\config\\drivers.log",
        L"\\config\\system",
        L"\\config\\system.log",
        L"\\windows\\bootstat.dat",
        L"\\winload.efi",
        L"\\winload.efi.mui",
        L"\\winload.exe",
        L"\\winload.exe.mui",
        L"\\winresume.efi",
        L"\\winresume.efi.mui",
        L"\\winresume.exe",
        L"\\winresume.exe.mui"
};

// 目录排除列表
wchar_t *DirectoryExclusionList[] = 
{
        L"\\Backup\\",
        L"\\ManifestCache\\",
        L"\\Manifests\\"
};


感谢阅读,毛利于2016/8/16



发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Purewhite 发表于 2016-8-16 22:29
不明觉厉啊。。
dapinggue 发表于 2016-8-16 23:11
lolxzz 发表于 2016-8-18 06:38
os51 发表于 2016-8-18 10:13
 楼主| Mouri_Naruto 发表于 2016-8-18 12:33
os51 发表于 2016-8-18 10:13
http://www.52pojie.cn/forum-24-1.html
建议放到这里

建议got,谢谢
gcczm 发表于 2016-8-18 17:23

不明觉厉啊。。
旧城迷梦 发表于 2016-8-18 19:08 来自手机
不明觉厉加1。。。
chenmintian 发表于 2017-5-14 23:00
搜索到了.
谢楼主.
anyta 发表于 2017-12-2 12:44

不明觉厉啊。。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 10:51

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表