终于找到一点有关增量压缩的门了
使用系统自带的 msdelta.dll,对系统中的增量干缩文件进行有关操作,GetDeltaInfo、Apply,总是提示参数错误。
一直就以为定义的结构、类型有错误,直到放弃了这些操作,压缩了一个新文件,才知道前面的操作都是对的,只不过微软对标准的增量压缩文件进行了一些改造,在文件的前面加上了四个字节,即, 我们提到过的 DCN、DCD、DCM等,和一个分隔符。
去掉前面的四个字节以后,再进行 GetDeltaInfo、Apply 操作就正常了。
这只解决了一个问题,DCN 的问题。
但后面的也可以不管了。
DCM 文件,可以 GetDeltaInfo,但不能 Apply,还是提示参数错误。
DCD 文件,由于过于复杂,就不想管了。因为涉及到基准文件的问题,难于确定。
这也可以解释在日志看到有关解压缩时,微软使用的是 ApplyB 了,不是针对文件进行,而是针对数组进行的操作了。
读出文件来以后,去掉了前面的四个字节。
知道问题以后,代码实际上很简单:
[<Struct; StructLayoutAttribute(LayoutKind.Explicit)>]
type Anonymous_654d2e53_a177_4231_98a2_dbbc4dcf1d8a =
/// LPCVOID->void*
[<FieldOffsetAttribute(0)>]
val lpcStart : System.IntPtr
/// LPVOID->void*
[<FieldOffsetAttribute(0)>]
val lpStart : IntPtr
[<Struct; StructLayoutAttribute(LayoutKind.Sequential)>]
type DELTA_INPUT =
/// Anonymous_654d2e53_a177_4231_98a2_dbbc4dcf1d8a
val Union1 : Anonymous_654d2e53_a177_4231_98a2_dbbc4dcf1d8a
/// SIZE_T->ULONG_PTR->unsigned int
val uSize : UInt32
/// BOOL->int
[<MarshalAsAttribute(UnmanagedType.Bool)>]
val Editable : bool
[<Struct; StructLayoutAttribute(LayoutKind.Sequential)>]
type DELTA_OUTPUT =
/// LPVOID->void*
val lpStart : System.IntPtr
/// SIZE_T->ULONG_PTR->unsigned int
val uSize : UInt32
[<Struct; StructLayoutAttribute(LayoutKind.Sequential, CharSet=CharSet.Ansi)>]
type DELTA_HASH =
/// DWORD->unsigned int
val HashSize : UInt32
/// UCHAR[]
[<MarshalAsAttribute(UnmanagedType.ByValTStr,SizeConst=32)>]
val HashValue : string
[<Struct; StructLayoutAttribute(LayoutKind.Sequential)>]
type DELTA_HEADER_INFO =
/// DELTA_FILE_TYPE->__int64
val FileTypeSet : Int64
/// DELTA_FILE_TYPE->__int64
val FileType : Int64
/// DELTA_FLAG_TYPE->__int64
val Flags : Int64
/// SIZE_T->ULONG_PTR->unsigned int
val TargetSize : UInt32
/// FILETIME->_FILETIME
val TargetFileTime : ComTypes.FILETIME
/// ALG_ID->unsigned int
val TargetHashAlgId : UInt32
/// DELTA_HASH->_DELTA_HASH
// val TargetHash : DELTA_HASH[<DllImport("msdelta.dll")>]
extern bool GetDeltaInfo(
string lpDeltaName,
DELTA_HEADER_INFO& lpHeaderInfo
)
[<DllImportAttribute("msdelta.dll",SetLastError=true)>]
extern bool ApplyDelta(
int64 ApplyFlags,
string lpSourceName,
string lpDeltaName,
string lpTargetName)
let (++) a b = System.IO.Path.Combine(a, b)
let GetDeltaInfo FilePath =
let mutable hd = new DELTA_HEADER_INFO()
GetDeltaInfo ( FilePath, &hd )
hd
GetDeltaInfo @"d:\vmicshutdown-DCN.dll"
GetDeltaInfo @"d:\wnv-DCN.sys"
let ApplyDCN DCNFilePath =
// (IO.DirectoryInfo(noDCNFile)).Name
let basePath = IO.Path.GetDirectoryName(DCNFilePath)
let noDCNFile = IO.Path.GetTempFileName()
let Target = DCNFilePath + ".Apply"
use r = System.IO.File.OpenRead(DCNFilePath)
let mutable fileContent = Array.init (int r.Length) ( fun i -> byte 0)
r.Read(fileContent, 0, (int r.Length))
r.Close()
if ( System.Text.Encoding.ASCII.GetString( fileContent.[0..2] ) = "DCN" ) then
use w = System.IO.File.OpenWrite(noDCNFile)
w.Write(fileContent.[4..], 0, (fileContent.[4..]).Length)
w.Close()
ApplyDelta ( 0L, "", noDCNFile, Target ) |> ignore
IO.File.Delete(noDCNFile)
ApplyDCN @"d:\wnv.sys"
IO.Directory.GetFiles(@"S:\R\amd64_microsoft-windows-wnv_31bf3856ad364e35_6.3.9600.16384_none_a06476a92abb3455")
|>Seq.map ApplyDCN