/* wimlib - Library for working with WIM files Copyright (C) 2010 Carl Thijssen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include "lzx.h" typedef char CHAR ; typedef unsigned long DWORD ; typedef char GUID[16] ; typedef unsigned short USHORT ; typedef char BYTE ; typedef unsigned long long ULONGLONG; typedef long long LARGE_INTEGER; typedef unsigned long long ULARGE_INTEGER; typedef struct _RESHDR_DISK_SHORT { LARGE_INTEGER Size; BYTE Flags; LARGE_INTEGER Offset; LARGE_INTEGER OriginalSize; } RESHDR_DISK_SHORT ; typedef struct _FILE_RESOURCE_HEADER { RESHDR_DISK_SHORT ResourceHeader; USHORT PartNumber; DWORD ReferenceCount; BYTE Hash[20]; LARGE_INTEGER ResourceHeaderIndex; } FILE_RESOURCE_HEADER; typedef struct _SECURITY_DATA { DWORD TotalLength; DWORD NumEntries; ULARGE_INTEGER *Sizes; BYTE **Descriptors; } SECURITY_DATA; typedef struct _STREAM_ENTRY { LARGE_INTEGER Length; LARGE_INTEGER Unused1; BYTE Hash[20]; USHORT StreamNameLength; CHAR *StreamName; } STREAM_ENTRY; typedef struct _DIRENTRY { LARGE_INTEGER Length; DWORD Attributes; DWORD SecurityId; LARGE_INTEGER SubdirOffset; LARGE_INTEGER Unused1; LARGE_INTEGER Unused2; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; BYTE *Hash; DWORD ReparseTag; DWORD ReparseReserved; LARGE_INTEGER HardLink; USHORT Streams; USHORT ShortNameLength; USHORT FileNameLength; USHORT FileNameAsciiLength; CHAR *ShortFileName; CHAR *ShortFileNameAscii; CHAR *FileName; USHORT FileNamePad; CHAR *FileNameAscii; CHAR *fullpath; STREAM_ENTRY *StreamEntries; BYTE *rest; USHORT restsize; void *next; void *kids; void *nextbrother; LARGE_INTEGER DirContentSize; LARGE_INTEGER CurDirSize; } DIRENTRY; typedef struct _BOOT_META_DATA { SECURITY_DATA SecurityData; DIRENTRY *DirEntry; } BOOT_META_DATA ; #define RESHDR_FLAG_FREE 0x01 #define RESHDR_FLAG_METADATA 0x02 #define RESHDR_FLAG_COMPRESSED 0x04 #define RESHDR_FLAG_SPANNED 0x08 typedef struct _WIM_HEADER { CHAR ImageTag[8]; DWORD Size; DWORD Version; DWORD Flags; DWORD ChunckSize; CHAR Guid[16]; USHORT PartNumber; USHORT TotalParts; DWORD ImageCount; RESHDR_DISK_SHORT OffsetTable; RESHDR_DISK_SHORT XmlData; RESHDR_DISK_SHORT BootMetaData; DWORD BootIndex; RESHDR_DISK_SHORT Integrity; CHAR Unused[60]; } WIM_HEADER ; #define FLAG_HEADER_RESERVED 0x00000001 #define FLAG_HEADER_COMPRESSION 0x00000002 #define FLAG_HEADER_READONLY 0x00000004 #define FLAG_HEADER_SPANNED 0x00000008 #define FLAG_HEADER_RESOURCE_ONLY 0x00000010 #define FLAG_HEADER_METADATA_ONLY 0x00000020 #define FLAG_HEADER_WRITE_IN_PROGRESS 0x00000040 #define FLAG_HEADER_RP_FIX 0x00000080 // reparse point fixup #define FLAG_HEADER_COMPRESS_RESERVED 0x00010000 #define FLAG_HEADER_COMPRESS_XPRESS 0x00020000 #define FLAG_HEADER_COMPRESS_LZX 0x00040000 #define FILE_ATTRIBUTE_READONLY 0x1 #define FILE_ATTRIBUTE_HIDDEN 0x2 #define FILE_ATTRIBUTE_SYSTEM 0x4 #define FILE_ATTRIBUTE_DIRECTORY 0x10 #define FILE_ATTRIBUTE_ARCHIVE 0x20 #define FILE_ATTRIBUTE_DEVICE 0x40 #define FILE_ATTRIBUTE_NORMAL 0x80 #define FILE_ATTRIBUTE_TEMPORARY 0x100 #define FILE_ATTRIBUTE_SPARSE_FILE 0x200 #define FILE_ATTRIBUTE_REPARSE_POINT 0x400 #define FILE_ATTRIBUTE_COMPRESSED 0x800 #define FILE_ATTRIBUTE_OFFLINE 0x1000 #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x2000 #define FILE_ATTRIBUTE_ENCRYPTED 0x4000 #define FILE_ATTRIBUTE_VIRTUAL 0x10000 DWORD GetDWord(FILE *fp); USHORT GetUshort(FILE *fp); LARGE_INTEGER GetLargeInteger(FILE *fp); LARGE_INTEGER GetLargeInteger7(FILE *fp); BYTE GetFlags1(FILE *fp); static char *w2a(void *string, int len); static char *a2w(void *string, int len, int *out_len); int comparehashes (const void* x, const void *y); int compareoffsets (const void* a, const void *b); int ReadWimHeader(FILE *fp,WIM_HEADER *Header); FILE_RESOURCE_HEADER *ReadLookupTable(FILE *fp,LARGE_INTEGER offset,LARGE_INTEGER size,LARGE_INTEGER *numoffsets); SECURITY_DATA ReadSecurityData(FILE *fp,LARGE_INTEGER offset); BOOT_META_DATA ReadBootMetaDataTable(FILE *fp,RESHDR_DISK_SHORT BootMetaData); BYTE *ReadXML(FILE *fp, LARGE_INTEGER offset,LARGE_INTEGER size); int ReadFileResource(FILE *fp,LARGE_INTEGER offset, LARGE_INTEGER size, LARGE_INTEGER unpacksize, char *filename); DIRENTRY *ReadDir(FILE *fp,LARGE_INTEGER *offset,char *path,DIRENTRY *last); int PrintHeader (WIM_HEADER Header); int PrintBootMetaData(BOOT_META_DATA bmd); int WriteDirEntry(FILE *fp,DIRENTRY *direntry); int WriteSecurityData(FILE *fp,SECURITY_DATA sd); int WriteFile(FILE *fp,FILE_RESOURCE_HEADER *FileResourceHeader, char *filename); DIRENTRY *CreateFile(char *filename, char *destpath, BYTE *filehash); DIRENTRY *CreateDirectory(char *filename, char *destpath, BYTE *filehash); int WriteWimHeader(FILE *fp,WIM_HEADER *Header); RESHDR_DISK_SHORT WriteLookupTable(FILE *fp,FILE_RESOURCE_HEADER *frh,LARGE_INTEGER items); RESHDR_DISK_SHORT WriteXML(FILE *fp,BYTE *buf,LARGE_INTEGER size); RESHDR_DISK_SHORT WriteBootMetaData(FILE *fp,BOOT_META_DATA bmd); RESHDR_DISK_SHORT WriteIntegrity(FILE *fp); int CopyFileResource(FILE *infile, FILE_RESOURCE_HEADER *frh, FILE *of); int CopyFileResources(FILE *infile,FILE *of,FILE_RESOURCE_HEADER *frh,LARGE_INTEGER numitems); FILE_RESOURCE_HEADER *WriteUnCompressedFileResource(FILE *of,char *srcfilename); FILE_RESOURCE_HEADER *AddFileResource(CHAR *path,FILE *of); DIRENTRY *FindFile2(DIRENTRY *tree, CHAR *path, CHAR *filename); int ExtractFile(DIRENTRY *extractfile,FILE_RESOURCE_HEADER *frh, LARGE_INTEGER numoffsets, FILE *fp, CHAR *filename);