diff --git a/makemsi.c b/makemsi.c index 8b78448..a301319 100644 --- a/makemsi.c +++ b/makemsi.c @@ -41,10 +41,54 @@ typedef struct MsiMainCtx { int nargs, argsize; } MsiMainCtx; +/* + * The Msi functions will expect to identify things by 32-bit handles, + * not machine-word sized pointers. So we must keep a list of handles + * we've allocated. + */ +typedef uint32_t MsiHandle; +static void **msi_handles = NULL; +static size_t n_msi_handles = 0, msi_handles_size = 0; + +static MsiHandle make_handle(void *ptr) +{ + size_t index; + + if (n_msi_handles >= msi_handles_size) { + msi_handles_size = n_msi_handles * 5 / 4 + 512; + msi_handles = sresize(msi_handles, msi_handles_size, void *); + } + + index = n_msi_handles++; + msi_handles[index] = ptr; + + /* + * A mild error-correcting code, to ensure our handles make sense. + */ + return index * 59 + 17; +} + +static void *lookup_handle(MsiHandle h) +{ + size_t index; + + assert(h % 59 == 17); + index = h / 59; + + assert(index < n_msi_handles); + return msi_handles[index]; +} + +static MsiMainCtx *lookup_handle_main(MsiHandle handle) +{ + MsiMainCtx *toret = lookup_handle(handle); + assert(toret->t.type == MAIN); + return toret; +} uint32_t MsiOpenDatabaseW(const char16_t *filename, const char16_t *persist, - MsiMainCtx **out_ctx) + MsiHandle *out_handle) { MsiMainCtx *ctx = snew(MsiMainCtx); ctx->t.type = MAIN; @@ -64,14 +108,14 @@ uint32_t MsiOpenDatabaseW(const char16_t *filename, ctx->args[ctx->nargs++] = dupstr(ctx->tempdir); ctx->args[ctx->nargs++] = dupstr("msibuild"); ctx->args[ctx->nargs++] = dupstr(ctx->outfile); - *out_ctx = ctx; + *out_handle = make_handle(ctx); return 0; } -uint32_t MsiDatabaseImportW(MsiMainCtx *ctx, const char16_t *folder, +uint32_t MsiDatabaseImportW(MsiHandle handle, const char16_t *folder, const char16_t *file) { - assert(ctx->t.type == MAIN); + MsiMainCtx *ctx = lookup_handle_main(handle); system_argv("sh", "-c", "cd \"$0\" && cp \"$1\" \"$2\"", ascii(folder, true), ascii(file, true), ctx->tempdir, cNULL); if (ctx->nargs + 2 >= ctx->argsize) { @@ -92,10 +136,17 @@ typedef struct MsiView { MsiMainCtx *ctx; } MsiView; -uint32_t MsiDatabaseOpenViewW(MsiMainCtx *ctx, const char16_t *query, - MsiView **outview) +static MsiView *lookup_handle_view(MsiHandle handle) { - assert(ctx->t.type == MAIN); + MsiView *toret = lookup_handle(handle); + assert(toret->t.type == VIEW); + return toret; +} + +uint32_t MsiDatabaseOpenViewW(MsiHandle handle, const char16_t *query, + MsiHandle *outhandle) +{ + MsiMainCtx *ctx = lookup_handle_main(handle); MsiView *view = snew(MsiView); view->t.type = VIEW; view->ctx = ctx; @@ -118,13 +169,13 @@ uint32_t MsiDatabaseOpenViewW(MsiMainCtx *ctx, const char16_t *query, if (mkdir(view->targetdir, 0777) < 0) err(1, "%s: mkdir", view->targetdir); } - *outview = view; + *outhandle = make_handle(view); return 0; } -uint32_t MsiViewExecute(MsiView *view, void *params) +uint32_t MsiViewExecute(MsiHandle handle, void *params) { - assert(view->t.type == VIEW); + lookup_handle_view(handle); return 0; } @@ -134,7 +185,14 @@ typedef struct MsiRecord { char *name, *data; } MsiRecord; -MsiRecord *MsiCreateRecord(uint32_t nparams) +static MsiRecord *lookup_handle_record(MsiHandle handle) +{ + MsiRecord *toret = lookup_handle(handle); + assert(toret->t.type == RECORD); + return toret; +} + +MsiHandle MsiCreateRecord(uint32_t nparams) { MsiRecord *rec = snew(MsiRecord); rec->t.type = RECORD; @@ -142,31 +200,31 @@ MsiRecord *MsiCreateRecord(uint32_t nparams) if (nparams != 2) errx(1, "bad MsiCreateRecord param count %u", (unsigned)nparams); rec->name = rec->data = NULL; - return rec; + return make_handle(rec); } -uint32_t MsiRecordSetStringW(MsiRecord *rec, uint32_t field, char16_t *value) +uint32_t MsiRecordSetStringW(MsiHandle handle, uint32_t field, char16_t *value) { - assert(rec->t.type == RECORD); + MsiRecord *rec = lookup_handle_record(handle); 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) +uint32_t MsiRecordSetStreamW(MsiHandle handle, uint32_t field, char16_t *path) { - assert(rec->t.type == RECORD); + MsiRecord *rec = lookup_handle_record(handle); 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) +uint32_t MsiViewModify(MsiHandle viewhandle, uint32_t mode, MsiHandle rechandle) { - assert(view->t.type == VIEW); - assert(rec->t.type == RECORD); + MsiView *view = lookup_handle_view(viewhandle); + MsiRecord *rec = lookup_handle_record(rechandle); if (view->fp) { system_argv("sh", "-c", "cp \"$0\" \"$1\"/\"$2\"", rec->data, view->targetdir, rec->name, cNULL); @@ -184,8 +242,9 @@ uint32_t MsiViewModify(MsiView *view, uint32_t mode, MsiRecord *rec) return 0; } -uint32_t MsiCloseHandle(MsiTypePrefix *t) +uint32_t MsiCloseHandle(MsiHandle handle) { + MsiTypePrefix *t = lookup_handle(handle); if (t->type == VIEW) { MsiView *view = (MsiView *)t; if (view->fp) @@ -194,9 +253,9 @@ uint32_t MsiCloseHandle(MsiTypePrefix *t) return 0; } -uint32_t MsiDatabaseCommit(MsiMainCtx *ctx) +uint32_t MsiDatabaseCommit(MsiHandle handle) { - assert(ctx->t.type == MAIN); + MsiMainCtx *ctx = lookup_handle_main(handle); printf("commit:"); for (int i = 0; i < ctx->nargs; i++) { printf(" '");