From a568db73a69a934c09ad5c95f5a218fb6b869298 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 18 May 2017 08:26:44 +0100 Subject: Rename fake-msi.c to makemsi.c. It's now a sensible source flie containing a set of routines that do something coherently connected to each other, so it doesn't deserve that 'fake-' prefix that I used for the previous monolithic files full of tangled-together stuff. While I'm here, I've also made up nicer (i.e. more distinguishable) random magic numbers for the structure-type disambiguation. --- Makefile.am | 2 +- fake-msi.c | 212 --------------------------------------------------------- makemsi.c | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 221 insertions(+), 213 deletions(-) delete mode 100644 fake-msi.c create mode 100644 makemsi.c diff --git a/Makefile.am b/Makefile.am index a113320..1e25726 100644 --- a/Makefile.am +++ b/Makefile.am @@ -7,7 +7,7 @@ lib_LTLIBRARIES = libwinterop.so.la libmsi.so.la libpreload.la libwinterop_so_la_SOURCES = fake-winterop.c makecab.c memory.c \ memory.h dupstr.c dupstr.h subproc.c subproc.h uchars.c uchars.h -libmsi_so_la_SOURCES = fake-msi.c md5.c memory.c memory.h version.c \ +libmsi_so_la_SOURCES = makemsi.c md5.c memory.c memory.h version.c \ dupstr.c dupstr.h subproc.c subproc.h uchars.c uchars.h libpreload_la_SOURCES = preload.c diff --git a/fake-msi.c b/fake-msi.c deleted file mode 100644 index 7bdcdc6..0000000 --- a/fake-msi.c +++ /dev/null @@ -1,212 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "memory.h" -#include "dupstr.h" -#include "subproc.h" -#include "uchars.h" - -typedef struct MsiTypePrefix { - enum { MAIN, VIEW, RECORD } type; -} MsiTypePrefix; - -typedef struct MsiMainCtx { - MsiTypePrefix t; - - char *tempdir; - char *outfile; - - char **args; - int nargs, argsize; -} MsiMainCtx; - - -uint32_t MsiOpenDatabaseW(const char16_t *filename, - const char16_t *persist, - MsiMainCtx **out_ctx) -{ - MsiMainCtx *ctx = snew(MsiMainCtx); - ctx->t.type = MAIN; - ctx->outfile = ascii(filename, true); - close(open(ctx->outfile, O_CREAT | O_WRONLY, 0666)); - ctx->outfile = realpath(ctx->outfile, NULL); - unlink(ctx->outfile); - ctx->tempdir = dupcat(ctx->outfile, "-msiXXXXXX", cNULL); - if (!mkdtemp(ctx->tempdir)) - err(1, "%s: mkdtemp", ctx->tempdir); - ctx->nargs = 0; - ctx->argsize = 16; - ctx->args = snewn(ctx->argsize, char *); - ctx->args[ctx->nargs++] = dupstr("sh"); - ctx->args[ctx->nargs++] = dupstr("-c"); - ctx->args[ctx->nargs++] = dupstr("cd \"$0\" && \"$@\""); - ctx->args[ctx->nargs++] = dupstr(ctx->tempdir); - ctx->args[ctx->nargs++] = dupstr("msibuild"); - ctx->args[ctx->nargs++] = dupstr(ctx->outfile); - *out_ctx = ctx; - return 0; -} - -uint32_t MsiDatabaseImportW(MsiMainCtx *ctx, const char16_t *folder, - const char16_t *file) -{ - assert(ctx->t.type == MAIN); - system_argv("sh", "-c", "cd \"$0\" && cp \"$1\" \"$2\"", - ascii(folder, true), ascii(file, true), ctx->tempdir, cNULL); - if (ctx->nargs + 2 >= ctx->argsize) { - ctx->argsize = ctx->nargs * 5 / 4 + 16; - ctx->args = sresize(ctx->args, ctx->argsize, char *); - } - ctx->args[ctx->nargs++] = dupstr("-i"); - ctx->args[ctx->nargs++] = dupcat(ctx->tempdir, "/", ascii(file, true), - cNULL); - return 0; -} - -typedef struct MsiView { - MsiTypePrefix t; - - FILE *fp; - char *targetdir; - MsiMainCtx *ctx; -} MsiView; - -uint32_t MsiDatabaseOpenViewW(MsiMainCtx *ctx, const char16_t *query, - MsiView **outview) -{ - assert(ctx->t.type == MAIN); - MsiView *view = snew(MsiView); - view->t.type = VIEW; - view->ctx = ctx; - char *cquery = ascii(query, false); - if (!strcmp(cquery, "SELECT `Name`, `Data` FROM `_Streams`")) - view->fp = NULL; /* special case */ - else { - if (!strcmp(cquery, "SELECT `Name`, `Data` FROM `Binary`")) { - view->fp = fopen(dupcat(ctx->tempdir, "/", "Binary.idt", cNULL), - "a"); - view->targetdir = dupcat(ctx->tempdir, "/", "Binary", cNULL); - } else if (!strcmp(cquery, "SELECT `Name`, `Data` FROM `Icon`")) { - view->fp = fopen(dupcat(ctx->tempdir, "/", "Icon.idt", cNULL), - "a"); - view->targetdir = dupcat(ctx->tempdir, "/", "Icon", cNULL); - } else - errx(1, "unrecognised query: %s", cquery); - if (!view->fp) - err(1, "open"); - if (mkdir(view->targetdir, 0777) < 0) - err(1, "%s: mkdir", view->targetdir); - } - *outview = view; - return 0; -} - -uint32_t MsiViewExecute(MsiView *view, void *params) -{ - assert(view->t.type == VIEW); - return 0; -} - -typedef struct MsiRecord { - MsiTypePrefix t; - - char *name, *data; -} MsiRecord; - -MsiRecord *MsiCreateRecord(uint32_t nparams) -{ - MsiRecord *rec = snew(MsiRecord); - rec->t.type = RECORD; - - if (nparams != 2) - errx(1, "bad MsiCreateRecord param count %u", (unsigned)nparams); - rec->name = rec->data = NULL; - return rec; -} - -uint32_t MsiRecordSetStringW(MsiRecord *rec, uint32_t field, char16_t *value) -{ - assert(rec->t.type == RECORD); - if (field != 1) - errx(1, "bad MsiRecordSetString param index %u", (unsigned)field); - rec->name = ascii(value, false); - return 0; -} - -uint32_t MsiRecordSetStreamW(MsiRecord *rec, uint32_t field, char16_t *path) -{ - assert(rec->t.type == RECORD); - if (field != 2) - errx(1, "bad MsiRecordSetStream param index %u", (unsigned)field); - rec->data = ascii(path, true); - return 0; -} - -uint32_t MsiViewModify(MsiView *view, uint32_t mode, MsiRecord *rec) -{ - assert(view->t.type == VIEW); - assert(rec->t.type == RECORD); - if (view->fp) { - system_argv("sh", "-c", "cp \"$0\" \"$1\"/\"$2\"", - rec->data, view->targetdir, rec->name, cNULL); - fprintf(view->fp, "%s\t%s\r\n", rec->name, rec->name); - } else { - MsiMainCtx *ctx = view->ctx; - if (ctx->nargs + 3 >= ctx->argsize) { - ctx->argsize = ctx->nargs * 5 / 4 + 16; - ctx->args = sresize(ctx->args, ctx->argsize, char *); - } - ctx->args[ctx->nargs++] = dupstr("-a"); - ctx->args[ctx->nargs++] = dupstr(rec->name); - ctx->args[ctx->nargs++] = dupstr(rec->data); - } - return 0; -} - -uint32_t MsiCloseHandle(MsiTypePrefix *t) -{ - if (t->type == VIEW) { - MsiView *view = (MsiView *)t; - if (view->fp) - fclose(view->fp); - } - return 0; -} - -uint32_t MsiDatabaseCommit(MsiMainCtx *ctx) -{ - assert(ctx->t.type == MAIN); - printf("commit:"); - for (int i = 0; i < ctx->nargs; i++) { - printf(" '"); - for (const char *p = ctx->args[i]; *p; p++) { - if (*p == '\'') - printf("'\\''"); - else - putchar(*p); - } - printf("'"); - } - printf("\n"); - - if (ctx->nargs + 1 >= ctx->argsize) { - ctx->argsize = ctx->nargs * 5 / 4 + 16; - ctx->args = sresize(ctx->args, ctx->argsize, char *); - } - ctx->args[ctx->nargs++] = NULL; - system_argv_array(ctx->args); - return 0; -} diff --git a/makemsi.c b/makemsi.c new file mode 100644 index 0000000..8b78448 --- /dev/null +++ b/makemsi.c @@ -0,0 +1,220 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "memory.h" +#include "dupstr.h" +#include "subproc.h" +#include "uchars.h" + +/* + * The same routine MsiCloseHandle is used by our client to dispose of + * three kinds of structure that _we_ think of as completely different + * types. So we must ensure all three start with distinct magic number + * fields, so as to know what kind we're being asked to close. + */ +typedef struct MsiTypePrefix { + enum { + MAIN = 0x2B7FB8B8, + VIEW = 0x1570B0E3, + RECORD = 0x62365065 + } type; +} MsiTypePrefix; + +typedef struct MsiMainCtx { + MsiTypePrefix t; + + char *tempdir; + char *outfile; + + char **args; + int nargs, argsize; +} MsiMainCtx; + + +uint32_t MsiOpenDatabaseW(const char16_t *filename, + const char16_t *persist, + MsiMainCtx **out_ctx) +{ + MsiMainCtx *ctx = snew(MsiMainCtx); + ctx->t.type = MAIN; + ctx->outfile = ascii(filename, true); + close(open(ctx->outfile, O_CREAT | O_WRONLY, 0666)); + ctx->outfile = realpath(ctx->outfile, NULL); + unlink(ctx->outfile); + ctx->tempdir = dupcat(ctx->outfile, "-msiXXXXXX", cNULL); + if (!mkdtemp(ctx->tempdir)) + err(1, "%s: mkdtemp", ctx->tempdir); + ctx->nargs = 0; + ctx->argsize = 16; + ctx->args = snewn(ctx->argsize, char *); + ctx->args[ctx->nargs++] = dupstr("sh"); + ctx->args[ctx->nargs++] = dupstr("-c"); + ctx->args[ctx->nargs++] = dupstr("cd \"$0\" && \"$@\""); + ctx->args[ctx->nargs++] = dupstr(ctx->tempdir); + ctx->args[ctx->nargs++] = dupstr("msibuild"); + ctx->args[ctx->nargs++] = dupstr(ctx->outfile); + *out_ctx = ctx; + return 0; +} + +uint32_t MsiDatabaseImportW(MsiMainCtx *ctx, const char16_t *folder, + const char16_t *file) +{ + assert(ctx->t.type == MAIN); + system_argv("sh", "-c", "cd \"$0\" && cp \"$1\" \"$2\"", + ascii(folder, true), ascii(file, true), ctx->tempdir, cNULL); + if (ctx->nargs + 2 >= ctx->argsize) { + ctx->argsize = ctx->nargs * 5 / 4 + 16; + ctx->args = sresize(ctx->args, ctx->argsize, char *); + } + ctx->args[ctx->nargs++] = dupstr("-i"); + ctx->args[ctx->nargs++] = dupcat(ctx->tempdir, "/", ascii(file, true), + cNULL); + return 0; +} + +typedef struct MsiView { + MsiTypePrefix t; + + FILE *fp; + char *targetdir; + MsiMainCtx *ctx; +} MsiView; + +uint32_t MsiDatabaseOpenViewW(MsiMainCtx *ctx, const char16_t *query, + MsiView **outview) +{ + assert(ctx->t.type == MAIN); + MsiView *view = snew(MsiView); + view->t.type = VIEW; + view->ctx = ctx; + char *cquery = ascii(query, false); + if (!strcmp(cquery, "SELECT `Name`, `Data` FROM `_Streams`")) + view->fp = NULL; /* special case */ + else { + if (!strcmp(cquery, "SELECT `Name`, `Data` FROM `Binary`")) { + view->fp = fopen(dupcat(ctx->tempdir, "/", "Binary.idt", cNULL), + "a"); + view->targetdir = dupcat(ctx->tempdir, "/", "Binary", cNULL); + } else if (!strcmp(cquery, "SELECT `Name`, `Data` FROM `Icon`")) { + view->fp = fopen(dupcat(ctx->tempdir, "/", "Icon.idt", cNULL), + "a"); + view->targetdir = dupcat(ctx->tempdir, "/", "Icon", cNULL); + } else + errx(1, "unrecognised query: %s", cquery); + if (!view->fp) + err(1, "open"); + if (mkdir(view->targetdir, 0777) < 0) + err(1, "%s: mkdir", view->targetdir); + } + *outview = view; + return 0; +} + +uint32_t MsiViewExecute(MsiView *view, void *params) +{ + assert(view->t.type == VIEW); + return 0; +} + +typedef struct MsiRecord { + MsiTypePrefix t; + + char *name, *data; +} MsiRecord; + +MsiRecord *MsiCreateRecord(uint32_t nparams) +{ + MsiRecord *rec = snew(MsiRecord); + rec->t.type = RECORD; + + if (nparams != 2) + errx(1, "bad MsiCreateRecord param count %u", (unsigned)nparams); + rec->name = rec->data = NULL; + return rec; +} + +uint32_t MsiRecordSetStringW(MsiRecord *rec, uint32_t field, char16_t *value) +{ + assert(rec->t.type == RECORD); + if (field != 1) + errx(1, "bad MsiRecordSetString param index %u", (unsigned)field); + rec->name = ascii(value, false); + return 0; +} + +uint32_t MsiRecordSetStreamW(MsiRecord *rec, uint32_t field, char16_t *path) +{ + assert(rec->t.type == RECORD); + if (field != 2) + errx(1, "bad MsiRecordSetStream param index %u", (unsigned)field); + rec->data = ascii(path, true); + return 0; +} + +uint32_t MsiViewModify(MsiView *view, uint32_t mode, MsiRecord *rec) +{ + assert(view->t.type == VIEW); + assert(rec->t.type == RECORD); + if (view->fp) { + system_argv("sh", "-c", "cp \"$0\" \"$1\"/\"$2\"", + rec->data, view->targetdir, rec->name, cNULL); + fprintf(view->fp, "%s\t%s\r\n", rec->name, rec->name); + } else { + MsiMainCtx *ctx = view->ctx; + if (ctx->nargs + 3 >= ctx->argsize) { + ctx->argsize = ctx->nargs * 5 / 4 + 16; + ctx->args = sresize(ctx->args, ctx->argsize, char *); + } + ctx->args[ctx->nargs++] = dupstr("-a"); + ctx->args[ctx->nargs++] = dupstr(rec->name); + ctx->args[ctx->nargs++] = dupstr(rec->data); + } + return 0; +} + +uint32_t MsiCloseHandle(MsiTypePrefix *t) +{ + if (t->type == VIEW) { + MsiView *view = (MsiView *)t; + if (view->fp) + fclose(view->fp); + } + return 0; +} + +uint32_t MsiDatabaseCommit(MsiMainCtx *ctx) +{ + assert(ctx->t.type == MAIN); + printf("commit:"); + for (int i = 0; i < ctx->nargs; i++) { + printf(" '"); + for (const char *p = ctx->args[i]; *p; p++) { + if (*p == '\'') + printf("'\\''"); + else + putchar(*p); + } + printf("'"); + } + printf("\n"); + + if (ctx->nargs + 1 >= ctx->argsize) { + ctx->argsize = ctx->nargs * 5 / 4 + 16; + ctx->args = sresize(ctx->args, ctx->argsize, char *); + } + ctx->args[ctx->nargs++] = NULL; + system_argv_array(ctx->args); + return 0; +} -- cgit v1.2.3-55-g6feb