aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fake-winterop.c17
-rwxr-xr-xmakecab.py107
2 files changed, 112 insertions, 12 deletions
diff --git a/fake-winterop.c b/fake-winterop.c
index eb891c4..cc69179 100644
--- a/fake-winterop.c
+++ b/fake-winterop.c
@@ -26,7 +26,6 @@ uint32_t ResetAcls(const char16_t **pwzFiles, uint32_t cFiles)
26} 26}
27 27
28typedef struct CabCreateContext { 28typedef struct CabCreateContext {
29 char *tempdir;
30 char *outdir; 29 char *outdir;
31 char *outfile; 30 char *outfile;
32 31
@@ -43,14 +42,11 @@ uint32_t CreateCabBegin(const char16_t *wzCab, const char16_t *wzCabDir,
43 ctx->outdir = ascii(wzCabDir, true); 42 ctx->outdir = ascii(wzCabDir, true);
44 ctx->outfile = dupcat(ctx->outdir, "/", 43 ctx->outfile = dupcat(ctx->outdir, "/",
45 ascii(wzCab, true), (const char *)NULL); 44 ascii(wzCab, true), (const char *)NULL);
46 ctx->tempdir = dupcat(ctx->outdir, "/cabXXXXXX", (const char *)NULL);
47 if (!mkdtemp(ctx->tempdir))
48 err(1, "mkdtemp");
49 ctx->nargs = 0; 45 ctx->nargs = 0;
50 ctx->argsize = 16; 46 ctx->argsize = 16;
51 ctx->args = snewn(ctx->argsize, char *); 47 ctx->args = snewn(ctx->argsize, char *);
52 ctx->args[ctx->nargs++] = dupcat("lcab", (const char *)NULL); 48 ctx->args[ctx->nargs++] = dupcat("makecab.py", (const char *)NULL);
53 ctx->args[ctx->nargs++] = dupcat("-n", (const char *)NULL); 49 ctx->args[ctx->nargs++] = ctx->outfile;
54 *out_ctx = ctx; 50 *out_ctx = ctx;
55 return 0; 51 return 0;
56} 52}
@@ -61,16 +57,14 @@ uint32_t CreateCabAddFile(const char16_t *wzFile, const char16_t *wzToken,
61 char *file = ascii(wzFile, true); 57 char *file = ascii(wzFile, true);
62 char *file_abs = realpath(file, NULL); 58 char *file_abs = realpath(file, NULL);
63 char *cabname = ascii(wzToken, true); 59 char *cabname = ascii(wzToken, true);
64 char *cab_abs = dupcat(ctx->tempdir, "/", cabname, (const char *)NULL);
65 printf("CreateCabAddFile: %s :: %s <- %s\n", ctx->outfile, 60 printf("CreateCabAddFile: %s :: %s <- %s\n", ctx->outfile,
66 cabname, file_abs); 61 cabname, file_abs);
67 if (symlink(file_abs, cab_abs) < 0)
68 err(1, "symlink");
69 if (ctx->nargs + 1 >= ctx->argsize) { 62 if (ctx->nargs + 1 >= ctx->argsize) {
70 ctx->argsize = ctx->nargs * 5 / 4 + 16; 63 ctx->argsize = ctx->nargs * 5 / 4 + 16;
71 ctx->args = sresize(ctx->args, ctx->argsize, char *); 64 ctx->args = sresize(ctx->args, ctx->argsize, char *);
72 } 65 }
73 ctx->args[ctx->nargs++] = cab_abs; 66 ctx->args[ctx->nargs++] = cabname;
67 ctx->args[ctx->nargs++] = file_abs;
74 return 0; 68 return 0;
75} 69}
76 70
@@ -86,11 +80,10 @@ uint32_t CreateCabAddFiles(const char16_t *const *pwzFiles,
86 80
87uint32_t CreateCabFinish(CabCreateContext *ctx, void (*split_callback)(void)) 81uint32_t CreateCabFinish(CabCreateContext *ctx, void (*split_callback)(void))
88{ 82{
89 if (ctx->nargs + 2 >= ctx->argsize) { 83 if (ctx->nargs + 1 >= ctx->argsize) {
90 ctx->argsize = ctx->nargs * 5 / 4 + 16; 84 ctx->argsize = ctx->nargs * 5 / 4 + 16;
91 ctx->args = sresize(ctx->args, ctx->argsize, char *); 85 ctx->args = sresize(ctx->args, ctx->argsize, char *);
92 } 86 }
93 ctx->args[ctx->nargs++] = ctx->outfile;
94 ctx->args[ctx->nargs++] = NULL; 87 ctx->args[ctx->nargs++] = NULL;
95 system_argv_array(ctx->args); 88 system_argv_array(ctx->args);
96 return 0; 89 return 0;
diff --git a/makecab.py b/makecab.py
new file mode 100755
index 0000000..befa94a
--- /dev/null
+++ b/makecab.py
@@ -0,0 +1,107 @@
1#!/usr/bin/env python
2
3import sys
4import os
5import time
6import zlib
7import struct
8from collections import namedtuple
9
10CFHEADER_s = struct.Struct("<4sLLLLLBBHHHHH")
11CFHEADER = namedtuple("CFHEADER", "sig res0 size res1 firstfile res2 "
12 "verminor vermajor folders files flags setid icabinet")
13CFHEADER_sig = "MSCF"
14
15CFFOLDER_s = struct.Struct("<LHH")
16CFFOLDER = namedtuple("CFFOLDER", "firstdata ndata compresstype")
17
18CFFILE_s = struct.Struct("<LLHHHH")
19CFFILE = namedtuple("CFFILE", "size offset ifolder date time attrs")
20
21CFDATA_s = struct.Struct("<LHH")
22CFDATA = namedtuple("CFDATA", "checksum compressedlen uncompressedlen")
23
24def mszip(data):
25 compressor = zlib.compressobj(9, zlib.DEFLATED, -zlib.MAX_WBITS,
26 zlib.DEF_MEM_LEVEL, zlib.Z_DEFAULT_STRATEGY)
27 compressed = compressor.compress(data)
28 compressed += compressor.flush()
29 return "CK" + compressed # add MSZIP header
30
31def packdate(y,m,d):
32 return ((y - 1980) << 9) | (m << 5) | d
33def packtime(h,m,s):
34 return ((h << 11) | (m << 5) | (s >> 1))
35
36def checksum(data):
37 data += "\0" * (3 & -len(data)) # pad to multiple of 4 bytes
38 toret = 0
39 for offset in xrange(0, len(data), 4):
40 toret ^= struct.unpack_from("<L", data, offset)[0]
41 return toret
42
43def build_cab(files):
44 uncompressed_data = ""
45 fileheaders = ""
46 for name, data, mtime in files:
47 mtime_u = time.gmtime(mtime)
48 fileheader = CFFILE(
49 size=len(data), offset=len(uncompressed_data), ifolder=0, attrs=0,
50 date=packdate(mtime_u.tm_year, mtime_u.tm_mon, mtime_u.tm_mday),
51 time=packtime(mtime_u.tm_hour, mtime_u.tm_min, mtime_u.tm_sec))
52 uncompressed_data += data
53 fileheaders += CFFILE_s.pack(*fileheader) + name + "\0"
54
55 compressed_data = ""
56 offset = 0
57 n_data_blocks = 0
58 while offset < len(uncompressed_data):
59 uncompressed_block = uncompressed_data[offset:offset+0x8000]
60 compressed_block = mszip(uncompressed_block)
61 blockheader = CFDATA(
62 checksum=0,
63 compressedlen=len(compressed_block),
64 uncompressedlen=len(uncompressed_block))
65 header_after_checksum = CFDATA_s.pack(*blockheader)[4:]
66 blockheader = blockheader._replace(
67 checksum=checksum(header_after_checksum + compressed_block))
68 compressed_data += CFDATA_s.pack(*blockheader) + compressed_block
69 offset += len(uncompressed_block)
70 n_data_blocks += 1
71
72 totalsize = (CFHEADER_s.size +
73 CFFOLDER_s.size +
74 len(fileheaders) +
75 len(compressed_data))
76
77 header = CFHEADER(
78 sig=CFHEADER_sig, res0=0, res1=0, res2=0,
79 vermajor=1, verminor=3, folders=1, files=len(files),
80 flags=0, setid=0, icabinet=0, size=totalsize,
81 firstfile=CFHEADER_s.size + CFFOLDER_s.size)
82
83 folder = CFFOLDER(
84 ndata=n_data_blocks, compresstype=1,
85 firstdata = (CFHEADER_s.size + CFFOLDER_s.size + len(fileheaders)))
86
87 return (CFHEADER_s.pack(*header) +
88 CFFOLDER_s.pack(*folder) +
89 fileheaders +
90 compressed_data)
91
92def main():
93 args = sys.argv[1:]
94 outfile = args.pop(0)
95 files = []
96 while len(args) > 0:
97 cabname = args.pop(0)
98 filename = args.pop(0)
99 with open(filename, "rb") as f:
100 filedata = f.read()
101 files.append((cabname, filedata, os.stat(filename).st_mtime))
102 cabdata = build_cab(files)
103 with open(outfile, "wb") as f:
104 f.write(cabdata)
105
106if __name__ == '__main__':
107 main()