Using a callback to display file names from an external decompression library in Inno Setup

It was originally asked here , but it was suggested that it be presented as a separate issue.

I have the following dll encoded in C below, which I use in the Inno Setup Installer to extract game files. This is a removable installer for a game that originally used the 16-bit installer and the files were copied from the CD. I would like to use InnoTools InnoCallback to display the file names extracted using my DLL, but since this is my first C coding venture, I have no idea how to do this. An example of this function can be found here: http://freearc.org/InnoSetup.aspx

I would like to be able to set WizardForm.FilenameLabel.Caption using the file name from my external dll.

Relevant sections of my Inno script installation:

function VolEx( filename, outputpath: String ): Integer; external ' VolEx@files :volex.dll stdcall'; 

(DriveLetter is the path for the CD-ROM, that is, “D: \”, so the output is currently reading “D: \ world \ archive.vol.” The result I'm aiming for is “C: \ game- path \ world \ archive \ file.ext ")

 procedure VolExtract(); begin if not DirExists(WizardDirValue() + '\' + Worlds[w]) then begin CreateDir(WizardDirValue() + '\' + Worlds[w]); end; for n := 0 to 3 do begin WizardForm.FilenameLabel.Caption := DriveLetter + Worlds[w] + '\' + Reslists[n] + '.vol'; if VolEx(DriveLetter + Worlds[w] + '\' + Reslists[n] + '.vol', WizardDirValue() + '\' + Worlds[w] + '\' + Reslists[n]) <> 0 then begin // Handle Fail MsgBox(CustomMessage('FileErr'), mbInformation, MB_OK); WizardForm.Close; end; 

VolEx.c (includes blast.c and blast.h from here: https://github.com/madler/zlib/tree/master/contrib/blast )

 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <sys/stat.h> #include <time.h> #include <utime.h> #include "blast.h" #define local static #define VOLID "RESLIST" struct inbuf { unsigned long left; unsigned char *buf; unsigned size; FILE *in; }; struct stat statbuf; time_t mtime; time_t voltime; struct utimbuf new_times; local unsigned inf(void *how, unsigned char **buf) { unsigned len; struct inbuf *inb = how; len = inb->size > inb->left ? inb->left : inb->size; len = fread(inb->buf, 1, len, inb->in); inb->left -= len; *buf = inb->buf; return len; } local int outf(void *how, unsigned char *buf, unsigned len) { return fwrite(buf, 1, len, (FILE *)how) != len; } #define BUFSIZE 16384 /* must fit in unsigned */ local int extract(char *name, unsigned long len, FILE *in, const char *path, time_t prevtime) { int err; FILE *out; struct inbuf inb; unsigned char buf[BUFSIZE]; inb.left = len; inb.buf = buf; inb.size = BUFSIZE; inb.in = in; mkdir(path); char outPath[strlen(path) + 20]; strcpy(outPath, path); strcat(outPath, "\\"); strcat(outPath, name); out = fopen(outPath, "wb"); if (out == NULL) return 2; err = blast(inf, &inb, outf, out); fclose(out); if (stat(outPath, &statbuf) < 0) { perror(outPath); return 1; } mtime = statbuf.st_mtime; /* seconds since the epoch */ new_times.actime = statbuf.st_atime; /* keep atime unchanged */ new_times.modtime = prevtime; /* set mtime to current time */ if (utime(outPath, &new_times) < 0) { perror(outPath); return 1; } return err; } int __stdcall __declspec(dllexport) VolEx(const char *filename, const char *outputpath) { FILE *in = fopen(filename,"rb"); unsigned long off, next; int err; unsigned char head[24]; if (stat(filename, &statbuf) < 0) { perror(filename); return 1; } voltime = statbuf.st_mtime; /* seconds since the epoch */ if (fread(head, 1, 8, in) != 8 || memcmp(head, VOLID, 8)) { /* fprintf(stderr, "not the expected .vol format\n"); */ return 1; } off = 8; while ((next = fread(head, 1, 24, in)) == 24) { off += 24; next = head[20] + (head[21] << 8) + ((unsigned long)(head[22]) << 16) + ((unsigned long)(head[23]) << 24); head[20] = 0; err = extract((char *)head, next - off, in, outputpath, voltime); if (err) { /* fprintf(stderr, "extraction error %d on %s\n", err, head); */ return 1; } off = next; } /* if (next) fprintf(stderr, "%lu bytes ignored at the end\n", next); */ return 0; } 
+1
source share
1 answer

Check out the sample script included in the InnoTools callback .

It's pretty simple, you just declare a procedure like this (again, assuming you are using ANSI Inno - some types had to be changed for the Unicode version):

 [Code] type TMyCallback = procedure(Filename: PChar); function WrapMyCallback(Callback: TMyCallback; ParamCount: Integer): LongWord; external ' WrapCallback@files :innocallback.dll stdcall'; procedure DoSomethingInTheDll(Blah: Integer; Foo: String; ...; Callback: LongWord); external ' DoSomethingInTheDll@files :mydll.dll stdcall'; procedure MyCallback(Filename: PChar); begin // do whatever, eg. update the filename label end; // wherever you're about to call your DLL var Callback : LongWord; // ... Callback := WrapMyCallback(@MyCallback, 1); // 1 parameter // pass the callback to your DLL either via a dedicated function // or as a parameter of your existing function DoSomethingInTheDll(blah, foo, ..., Callback); 

From the side of the DLL:

 typedef void (__stdcall *MyCallback)(const char *filename); 

Then you can declare variables of type MyCallback in the function parameters, and then call them as if they were native C functions, and it will run the code inside the Inno script.

 void __stdcall __declspec(dllexport) DoSomethingInTheDll(int blah, const char *foo, ..., MyCallback callback) { // ... callback(foo); } 
+2
source

All Articles