aboutsummaryrefslogtreecommitdiff
path: root/fake-msi.c
diff options
context:
space:
mode:
Diffstat (limited to 'fake-msi.c')
-rw-r--r--fake-msi.c190
1 files changed, 158 insertions, 32 deletions
diff --git a/fake-msi.c b/fake-msi.c
index 59e0a4b..3f82f74 100644
--- a/fake-msi.c
+++ b/fake-msi.c
@@ -1,3 +1,4 @@
1#include <assert.h>
1#include <stdio.h> 2#include <stdio.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <stdint.h> 4#include <stdint.h>
@@ -25,74 +26,199 @@ uint32_t MsiGetFileVersionW(const char16_t *filename,
25 return 0; 26 return 0;
26} 27}
27 28
29typedef struct MsiTypePrefix {
30 enum { MAIN, VIEW, RECORD } type;
31} MsiTypePrefix;
32
33typedef struct MsiMainCtx {
34 MsiTypePrefix t;
35
36 char *tempdir;
37 char *outfile;
38
39 char **args;
40 int nargs, argsize;
41} MsiMainCtx;
42
43
28uint32_t MsiOpenDatabaseW(const char16_t *filename, 44uint32_t MsiOpenDatabaseW(const char16_t *filename,
29 const char16_t *persist, 45 const char16_t *persist,
30 void **handle) 46 MsiMainCtx **out_ctx)
31{ 47{
32 char *file = ascii(filename, true); 48 MsiMainCtx *ctx = snew(MsiMainCtx);
33 warnx("FIXME: MsiOpenDatabaseW(%s,%p)", file, persist); 49 ctx->t.type = MAIN;
34 close(open(file, O_WRONLY | O_CREAT, 0666)); 50 ctx->outfile = ascii(filename, true);
35 *handle = (void *)1; 51 close(open(ctx->outfile, O_CREAT | O_WRONLY, 0666));
52 ctx->outfile = realpath(ctx->outfile, NULL);
53 unlink(ctx->outfile);
54 ctx->tempdir = dupcat(ctx->outfile, "-msiXXXXXX", (const char *)NULL);
55 if (!mkdtemp(ctx->tempdir))
56 err(1, "%s: mkdtemp", ctx->tempdir);
57 ctx->nargs = 0;
58 ctx->argsize = 16;
59 ctx->args = snewn(ctx->argsize, char *);
60 ctx->args[ctx->nargs++] = dupcat("sh", (const char *)NULL);
61 ctx->args[ctx->nargs++] = dupcat("-c", (const char *)NULL);
62 ctx->args[ctx->nargs++] = dupcat("cd \"$0\" && \"$@\"",
63 (const char *)NULL);
64 ctx->args[ctx->nargs++] = dupcat(ctx->tempdir, (const char *)NULL);
65 ctx->args[ctx->nargs++] = dupcat("msibuild", (const char *)NULL);
66 ctx->args[ctx->nargs++] = dupcat(ctx->outfile, (const char *)NULL);
67 *out_ctx = ctx;
36 return 0; 68 return 0;
37} 69}
38 70
39uint32_t MsiCloseHandle(void *handle) 71uint32_t MsiDatabaseImportW(MsiMainCtx *ctx, const char16_t *folder,
72 const char16_t *file)
40{ 73{
41 warnx("FIXME: MsiCloseHandle(%p)", handle); 74 assert(ctx->t.type == MAIN);
75 system_argv("sh", "-c", "cd \"$0\" && cp \"$1\" \"$2\"",
76 ascii(folder, true), ascii(file, true), ctx->tempdir,
77 (const char *)NULL);
78 if (ctx->nargs + 2 >= ctx->argsize) {
79 ctx->argsize = ctx->nargs * 5 / 4 + 16;
80 ctx->args = sresize(ctx->args, ctx->argsize, char *);
81 }
82 ctx->args[ctx->nargs++] = dupcat("-i", (const char *)NULL);
83 ctx->args[ctx->nargs++] = dupcat(ctx->tempdir, "/", ascii(file, true),
84 (const char *)NULL);
42 return 0; 85 return 0;
43} 86}
44 87
45uint32_t MsiDatabaseImportW(void *handle, const char16_t *folder, 88typedef struct MsiView {
46 const char16_t *file) 89 MsiTypePrefix t;
90
91 FILE *fp;
92 char *targetdir;
93 MsiMainCtx *ctx;
94} MsiView;
95
96uint32_t MsiDatabaseOpenViewW(MsiMainCtx *ctx, const char16_t *query,
97 MsiView **outview)
47{ 98{
48 warnx("FIXME: MsiDatabaseImport(%p,%s,%s)", handle, ascii(folder, true), 99 assert(ctx->t.type == MAIN);
49 ascii(file, true)); 100 MsiView *view = snew(MsiView);
101 view->t.type = VIEW;
102 view->ctx = ctx;
103 char *cquery = ascii(query, false);
104 if (!strcmp(cquery, "SELECT `Name`, `Data` FROM `_Streams`"))
105 view->fp = NULL; /* special case */
106 else {
107 if (!strcmp(cquery, "SELECT `Name`, `Data` FROM `Binary`")) {
108 view->fp = fopen(dupcat(ctx->tempdir, "/", "Binary.idt",
109 (const char *)NULL), "a");
110 view->targetdir = dupcat(ctx->tempdir, "/", "Binary",
111 (const char *)NULL);
112 } else if (!strcmp(cquery, "SELECT `Name`, `Data` FROM `Icon`")) {
113 view->fp = fopen(dupcat(ctx->tempdir, "/", "Icon.idt",
114 (const char *)NULL), "a");
115 view->targetdir = dupcat(ctx->tempdir, "/", "Icon",
116 (const char *)NULL);
117 } else
118 errx(1, "unrecognised query: %s", cquery);
119 if (!view->fp)
120 err(1, "open");
121 if (mkdir(view->targetdir, 0777) < 0)
122 err(1, "%s: mkdir", view->targetdir);
123 }
124 *outview = view;
50 return 0; 125 return 0;
51} 126}
52 127
53uint32_t MsiDatabaseOpenViewW(void *handle, const char16_t *query, 128uint32_t MsiViewExecute(MsiView *view, void *params)
54 void **outhandle)
55{ 129{
56 warnx("FIXME: MsiDatabaseOpenView(%p,%s)", handle, ascii(query, false)); 130 assert(view->t.type == VIEW);
57 *outhandle = (void *)2;
58 return 0; 131 return 0;
59} 132}
60 133
61uint32_t MsiViewExecute(void *handle, void *params) 134typedef struct MsiRecord {
135 MsiTypePrefix t;
136
137 char *name, *data;
138} MsiRecord;
139
140MsiRecord *MsiCreateRecord(uint32_t nparams)
62{ 141{
63 warnx("FIXME: MsiViewExecute(%p)", handle); 142 MsiRecord *rec = snew(MsiRecord);
64 return 0; 143 rec->t.type = RECORD;
144
145 if (nparams != 2)
146 errx(1, "bad MsiCreateRecord param count %u", (unsigned)nparams);
147 rec->name = rec->data = NULL;
148 return rec;
65} 149}
66 150
67void *MsiCreateRecord(uint32_t nparams) 151uint32_t MsiRecordSetStringW(MsiRecord *rec, uint32_t field, char16_t *value)
68{ 152{
69 warnx("FIXME: MsiCreateRecord(%u)", (unsigned)nparams); 153 assert(rec->t.type == RECORD);
70 return (void *)3; 154 if (field != 1)
155 errx(1, "bad MsiRecordSetString param index %u", (unsigned)field);
156 rec->name = ascii(value, false);
157 return 0;
71} 158}
72 159
73uint32_t MsiRecordSetStringW(void *handle, uint32_t field, char16_t *value) 160uint32_t MsiRecordSetStreamW(MsiRecord *rec, uint32_t field, char16_t *path)
74{ 161{
75 warnx("FIXME: MsiRecordSetString(%p,%u,%s)", handle, (unsigned)field, 162 assert(rec->t.type == RECORD);
76 ascii(value, false)); 163 if (field != 2)
164 errx(1, "bad MsiRecordSetStream param index %u", (unsigned)field);
165 rec->data = ascii(path, true);
77 return 0; 166 return 0;
78} 167}
79 168
80uint32_t MsiRecordSetStreamW(void *handle, uint32_t field, char16_t *path) 169uint32_t MsiViewModify(MsiView *view, uint32_t mode, MsiRecord *rec)
81{ 170{
82 warnx("FIXME: MsiRecordSetStream(%p,%u,%s)", handle, (unsigned)field, 171 assert(view->t.type == VIEW);
83 ascii(path, true)); 172 assert(rec->t.type == RECORD);
173 if (view->fp) {
174 system_argv("sh", "-c", "cp \"$0\" \"$1\"/\"$2\"",
175 rec->data, view->targetdir, rec->name,
176 (const char *)NULL);
177 fprintf(view->fp, "%s\t%s\r\n", rec->name, rec->name);
178 } else {
179 MsiMainCtx *ctx = view->ctx;
180 if (ctx->nargs + 3 >= ctx->argsize) {
181 ctx->argsize = ctx->nargs * 5 / 4 + 16;
182 ctx->args = sresize(ctx->args, ctx->argsize, char *);
183 }
184 ctx->args[ctx->nargs++] = dupcat("-s", (const char *)NULL);
185 ctx->args[ctx->nargs++] = dupcat(rec->name, (const char *)NULL);
186 ctx->args[ctx->nargs++] = dupcat(rec->data, (const char *)NULL);
187 }
84 return 0; 188 return 0;
85} 189}
86 190
87uint32_t MsiViewModify(void *vhandle, uint32_t mode, void *rechandle) 191uint32_t MsiCloseHandle(MsiTypePrefix *t)
88{ 192{
89 warnx("FIXME: MsiViewModify(%p,%u,%p)", 193 if (t->type == VIEW) {
90 vhandle, (unsigned)mode, rechandle); 194 MsiView *view = (MsiView *)t;
195 if (view->fp)
196 fclose(view->fp);
197 }
91 return 0; 198 return 0;
92} 199}
93 200
94uint32_t MsiDatabaseCommit(void *handle) 201uint32_t MsiDatabaseCommit(MsiMainCtx *ctx)
95{ 202{
96 warnx("FIXME: MsiDatabaseCommit(%p)", handle); 203 assert(ctx->t.type == MAIN);
204 printf("commit:");
205 for (int i = 0; i < ctx->nargs; i++) {
206 printf(" '");
207 for (const char *p = ctx->args[i]; *p; p++) {
208 if (*p == '\'')
209 printf("'\\''");
210 else
211 putchar(*p);
212 }
213 printf("'");
214 }
215 printf("\n");
216
217 if (ctx->nargs + 1 >= ctx->argsize) {
218 ctx->argsize = ctx->nargs * 5 / 4 + 16;
219 ctx->args = sresize(ctx->args, ctx->argsize, char *);
220 }
221 ctx->args[ctx->nargs++] = NULL;
222 system_argv_array(ctx->args);
97 return 0; 223 return 0;
98} 224}