smbd: avoid a panic in close_directory()
[samba4-gss.git] / testdata / compression / decompressed / generate-windows-test-vectors.c.decomp
blob28724d2e10333c89c3e3b591d277e1639ba590a4
1 /*\r
2  * Generate test vectorsa for Windows LZ77 Huffman compression.\r
3  *\r
4  * Copyright (c) 2022 Douglas Bagnall <dbagnall@samba.org>\r
5  *\r
6  * GPLv3+.\r
7  *\r
8  * Can be compiled on Windows 2012r2 under Cygwin\r
9  *\r
10  * gcc -o generate-windows-test-vectors  \\r
11  *       generate-windows-test-vectors.c \\r
12  *       C:\Windows\SysWOW64\cabinet.dll \\r
13  *       -lcabinet\r
14  *\r
15  * There might be better ways.\r
16  *\r
17  * See https://learn.microsoft.com/en-us/windows/win32/cmpapi/-compression-portal\r
18  */\r
21 #include <stddef.h>\r
22 #include <stdint.h>\r
23 #include <stdlib.h>\r
24 #include <stdbool.h>\r
25 #include <stdio.h>\r
26 #include <sys/types.h>\r
27 #include <sys/stat.h>\r
28 #include <unistd.h>\r
30 /* compressapi.h is in the Windows API. mingw-w64 has a copy. */\r
31 #include <compressapi.h>\r
32 #include <errhandlingapi.h>\r
34 struct blob {\r
35         uint8_t *data;\r
36         size_t length;\r
37 };\r
39 /* Windows size_t is different than Cygwin size_t (though still 64 bit) */\r
40 typedef unsigned long long wsize_t;\r
43 #define compression_flags (COMPRESS_ALGORITHM_XPRESS_HUFF | COMPRESS_RAW)\r
45 int32_t compression_level = 0;\r
47 static struct blob compress(struct blob input)\r
48 {\r
49         COMPRESSOR_HANDLE handle;\r
50         struct blob output;\r
51         bool ok;\r
52         wsize_t used;\r
54         ok = CreateCompressor(compression_flags, NULL, &handle);\r
56         if (! ok) {\r
57                 fprintf(stderr, "CreateCompressor failed\n");\r
58                 exit(1);\r
59         }\r
61         output.length = input.length * 3 + 256;\r
62         output.data = malloc(output.length);\r
63         if (output.data == NULL) {\r
64                 fprintf(stderr, "output allocation failed (estimated %zu)\n",\r
65                         output.length);\r
66                 exit(1);\r
67         }\r
70         ok = SetCompressorInformation(handle,\r
71                                       COMPRESS_INFORMATION_CLASS_LEVEL,\r
72                                       &compression_level,\r
73                                       sizeof(compression_level));\r
75         if (! ok) {\r
76           fprintf(stderr, "SetCompressorInformation failed: %d\n",\r
77                   GetLastError());\r
78           //exit(1);\r
79         }\r
81         ok = Compress(handle,\r
82                       input.data,\r
83                       input.length,\r
84                       output.data,\r
85                       output.length,\r
86                       &used);\r
87         if (! ok) {\r
88                 fprintf(stderr, "Compress failed\n");\r
89                 exit(1);\r
90         }\r
91         output.data = realloc(output.data, used);\r
92         if (output.data == NULL) {\r
93                 fprintf(stderr,\r
94                         "failed to shrinkwrap output! (from %zu to %llu)\n",\r
95                         output.length, used);\r
96                 exit(1);\r
97         }\r
98         output.length = used;\r
99         CloseCompressor(handle);\r
100         return output;\r
104 struct blob decompress(struct blob input,\r
105                        size_t expected_size)\r
107         DECOMPRESSOR_HANDLE handle;\r
108         struct blob output;\r
109         bool ok;\r
110         wsize_t used;\r
112         ok = CreateDecompressor(compression_flags, NULL, &handle);\r
114         if (! ok) {\r
115                 fprintf(stderr, "CreateDecompressor failed\n");\r
116                 exit(1);\r
117         }\r
119         output.length = expected_size;\r
120         output.data = malloc(output.length);\r
121         if (output.data == NULL) {\r
122                 fprintf(stderr, "output allocation failed (%zu)\n",\r
123                         output.length);\r
124                 exit(1);\r
125         }\r
127         ok = Decompress(handle,\r
128                         input.data,\r
129                         input.length,\r
130                         output.data,\r
131                         output.length,\r
132                         &used);\r
133         if (! ok) {\r
134                 fprintf(stderr, "Decompress failed\n");\r
135                 exit(1);\r
136         }\r
137         CloseDecompressor(handle);\r
138         return output;\r
142 static void __attribute__((noreturn)) usage(int ret)\r
144         fprintf(stderr,\r
145                 "USAGE: test-win-vectors {c,d} filename [length|level] > DEST\n\n");\r
146         fprintf(stderr, "c for< compression, d for decompression\n");\r
147         fprintf(stderr, "decompressed length is required for decompression\n");\r
148         fprintf(stderr, "compression level flag is optional [default 0]\n");\r
149         exit(ret);\r
152 int main(int argc, const char *argv[])\r
154         FILE *fh;\r
155         const char *filename;\r
156         struct stat s;\r
157         int ret;\r
158         struct blob input = {0};\r
159         struct blob output = {0};\r
161         if (argc < 3 || argc > 4) {\r
162                 usage(1);\r
163         }\r
164         filename = argv[2];\r
166         fh = fopen(filename, "rb");\r
167         if (fh == NULL) {\r
168                 fprintf(stderr, "Could not open %s\n", filename);\r
169                 usage(1);\r
170         }\r
172         ret = fstat(fileno(fh), &s);\r
173         if (ret != 0) {\r
174                 fprintf(stderr, "Could not stat %s: %d\n", filename, ret);\r
175                 usage(1);\r
176         }\r
177         input.length = s.st_size;\r
178         input.data = malloc(input.length);\r
179         if (input.data == NULL) {\r
180                 fprintf(stderr, "input too big for memory?! (%zu)\n",\r
181                         s.st_size);\r
182                 exit(1);\r
183         }\r
185         fread(input.data, 1, input.length, fh);\r
187         if (strcmp(argv[1], "c") == 0) {\r
188                 if (argc == 4 && strcmp(argv[3], "0")) {\r
189                         compression_level = 1;\r
190                 }                       \r
191                 output = compress(input);\r
192         } else if (strcmp(argv[1], "d") == 0) {\r
193                 size_t decomp_size;\r
194                 if (argc != 4) {\r
195                         fprintf(stderr, "no length given\n");\r
196                         usage(1);\r
197                 }\r
198                 decomp_size = atoi(argv[3]);\r
199                 output = decompress(input, decomp_size);\r
200         } else {\r
201                 usage(1);\r
202         }\r
203         fwrite(output.data, 1, output.length, stdout);\r
204         free(output.data);\r
205         return 0;\r