387 lines
13 KiB
C
387 lines
13 KiB
C
/* This file is part of REWise.
|
|
*
|
|
* REWise is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* REWise is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/*
|
|
DISCLAIMER
|
|
----------
|
|
The way the data is interpreted may be very wrong! It is the result of many
|
|
hours of puzzling with ImHex and this is what made the most sense to me with
|
|
the data (different installer executables) available at this time. Also what
|
|
most values represent inside a operation struct is still a mystery.
|
|
|
|
Another source of getting insight on how the Wise installer handles this would
|
|
be to disassemble wise0132.dll, I have done this with Cutter and its Ghidra
|
|
plugin but it was very hard since I couldn't rename about half of the variables,
|
|
which is a known issue of Cutter + the Ghidra plugin (at this time), but it
|
|
gave some hints.
|
|
|
|
|
|
INSEPCTED INSTALLERS
|
|
--------------------
|
|
|
|
NAME MD5 FILE
|
|
---- --- ----
|
|
HL:CS (CD) 43cd9aff74e04fa1b59321b898d9a6bd counter-strike.exe
|
|
HLGOTY (CD) f5b8b35ca02beeeb146e62a63a0273a6 SETUP.EXE
|
|
CS15 eedcfcf6545cef92f26fb9a7fdd77c42 csv15full.exe
|
|
RTCW (CD) f2d9e3e1eaaed66047210881d130384f Setup.exe
|
|
ET 5cc104767ecdf0feb3a36210adf46a8e WolfET.exe
|
|
|
|
The way this program currently interprets the binary Wise script file is as
|
|
follows:
|
|
|
|
1. Read 'struct WiseScriptHeader'
|
|
2. Read 'struct WiseScriptTexts'
|
|
3. Read one byte as operation code, we use this value to determine what struct
|
|
to read, after that struct is read, continue this step (read one operation
|
|
byte again etc..)
|
|
|
|
Operation codes:
|
|
|
|
0x00 // Custom deflate file header
|
|
0x03 // ?
|
|
0x04 // Form data?
|
|
0x05 // .ini file, section-name and values for that section
|
|
0x06 // Deflated file just used by the installer? (No filename)
|
|
0x07
|
|
0x08
|
|
0x09
|
|
0x0A
|
|
0x0B
|
|
0x0C
|
|
0x0D // Skip this byte?
|
|
0x0F // Start form data?
|
|
0x10 // End form data?
|
|
0x11
|
|
0x12 // File on install medium (CD/DVD), to copy?
|
|
0x14 // Deflated file just used by the installer? (No filename)
|
|
0x15
|
|
0x16 // Temp filename?
|
|
0x17
|
|
0x18 // Skip this byte? ET suggests to skip all tailing zeros
|
|
0x23
|
|
0x24 // Skip this byte? Only seen in RTCW
|
|
0x25 // Skip this byte? Only seen in RTCW
|
|
0x1B // Skip this byte?
|
|
0x1C
|
|
0x1E
|
|
*/
|
|
|
|
#ifndef H_WISESCRIPT
|
|
#define H_WISESCRIPT
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
|
|
|
|
#include "errors.h"
|
|
|
|
#define WIN_PATH_MAX 260
|
|
|
|
|
|
/* WiseScriptHeader */
|
|
typedef struct {
|
|
unsigned char unknown_44[44];
|
|
char * logPath; // \0 terminated string
|
|
char * font; // \0 terminated string
|
|
unsigned char unknown_14[14];
|
|
} WiseScriptHeader;
|
|
|
|
/* WiseScriptTexts */
|
|
typedef struct {
|
|
// 56 \0 terminated strings
|
|
char * installTexts[56];
|
|
} WiseScriptTexts;
|
|
|
|
/* 0x00 WiseScriptFileHeader */
|
|
typedef struct {
|
|
unsigned char unknown_2[2]; // seen: 0x8000, 0x8100, 0x0000, 0x9800 0xA100
|
|
uint32_t deflateStart;
|
|
uint32_t deflateEnd;
|
|
uint16_t date;
|
|
uint16_t time;
|
|
uint32_t inflatedSize;
|
|
unsigned char unknown_40[20];
|
|
uint32_t crc32;
|
|
char * destFile; // \0 terminated string
|
|
char * fileText; // \0 terminated string
|
|
unsigned char terminator; // always \0? terminator?
|
|
} WiseScriptFileHeader;
|
|
|
|
/* WiseScriptUnknown0x03 */
|
|
typedef struct {
|
|
unsigned char unknown_1; // unknown
|
|
char * unknownString_1; // \0 terminated string
|
|
char * unknownString_2; // \0 terminated string
|
|
} WiseScriptUnknown0x03;
|
|
|
|
/* WiseScriptUnknown0x04 Form data? */
|
|
typedef struct {
|
|
unsigned char no; // read this struct again until 'no' == 0 ?
|
|
char * dataString; // \0 terminated string
|
|
} WiseScriptUnknown0x04;
|
|
|
|
/* WiseScriptUnknown0x05 Something with .ini file */
|
|
typedef struct {
|
|
// write .ini file?
|
|
char * file; // open for writing in append mode
|
|
char * section; // ini section text
|
|
char * values; // multiline string containing values.
|
|
} WiseScriptUnknown0x05;
|
|
|
|
/* WiseScriptUnknown0x06 deflated Wise file? */
|
|
typedef struct {
|
|
unsigned char unknown[6];
|
|
uint32_t deflateStart;
|
|
uint32_t deflateEnd;
|
|
uint32_t inflatedSize;
|
|
unsigned char unknown1; // terminator?
|
|
} WiseScriptUnknown0x06;
|
|
|
|
/* WiseScriptUnknown0x07 */
|
|
typedef struct {
|
|
unsigned char unknown_1;
|
|
char * unknownString_1;
|
|
char * unknownString_2;
|
|
char * unknownString_3;
|
|
} WiseScriptUnknown0x07;
|
|
|
|
/* WiseScriptUnknown0x08 */
|
|
typedef struct {
|
|
unsigned char unknown_1;
|
|
} WiseScriptUnknown0x08;
|
|
|
|
/* WiseScriptUnknown0x09 */
|
|
typedef struct {
|
|
unsigned char unknown_1;
|
|
unsigned char unknown_2; // only when NOT 0x0901 or 0x0920
|
|
char * unknownString_1;
|
|
char * unknownString_2;
|
|
char * unknownString_3;
|
|
char * unknownString_4;
|
|
char * unknownString_5; // only when 0x0901 or 0x0920
|
|
} WiseScriptUnknown0x09;
|
|
|
|
/* WiseScriptUnknown0x0A */
|
|
typedef struct {
|
|
unsigned char unknown_2[2]; // 0x0200
|
|
char * unknownString_1;
|
|
char * unknownString_2;
|
|
char * unknownString_3;
|
|
} WiseScriptUnknown0x0A;
|
|
|
|
/* WiseScriptUnknown0x0B */
|
|
typedef struct {
|
|
unsigned char unknown_1;
|
|
char * unknownString_1;
|
|
} WiseScriptUnknown0x0B;
|
|
|
|
/* WiseScriptUnknown0x0C */
|
|
typedef struct {
|
|
unsigned char unknown_1;
|
|
char * unknownString_1;
|
|
char * unknownString_2;
|
|
} WiseScriptUnknown0x0C;
|
|
|
|
/* WiseScriptUnknown0x11 */
|
|
typedef struct {
|
|
char * unknownString_1;
|
|
} WiseScriptUnknown0x11;
|
|
|
|
/* WiseScriptUnknown0x12 File on install medium (CD/DVD) */
|
|
typedef struct {
|
|
unsigned char unknown_1; // 0C
|
|
unsigned char unknown_41[41];
|
|
char * sourceFile;
|
|
char * unknownString_1;
|
|
char * unknownString_2;
|
|
char * destFile;
|
|
} WiseScriptUnknown0x12;
|
|
|
|
/* WiseScriptUnknown0x14 Wise script file? */
|
|
typedef struct {
|
|
uint32_t deflateStart;
|
|
uint32_t deflateEnd;
|
|
uint32_t inflatedSize;
|
|
char * name;
|
|
char * message;
|
|
} WiseScriptUnknown0x14;
|
|
|
|
/* WiseScriptUnknown0x15 */
|
|
typedef struct {
|
|
unsigned char unknown_1;
|
|
char * unknownString_1;
|
|
char * unknownString_2;
|
|
} WiseScriptUnknown0x15;
|
|
|
|
/* WiseScriptUnknown0x16 (TempFileName) */
|
|
typedef struct {
|
|
char * name;
|
|
} WiseScriptUnknown0x16;
|
|
|
|
/* WiseScriptUnknown0x17 */
|
|
typedef struct {
|
|
unsigned char unknown_1;
|
|
unsigned char unknown_4[4];
|
|
char * unknownString_1;
|
|
} WiseScriptUnknown0x17;
|
|
|
|
/* WiseScriptUnknown0x1C */
|
|
typedef struct {
|
|
char * unknownString_1;
|
|
} WiseScriptUnknown0x1C;
|
|
|
|
/* WiseScriptUnknown0x1E */
|
|
typedef struct {
|
|
unsigned char unknown_2[2];
|
|
} WiseScriptUnknown0x1E;
|
|
|
|
/* WiseScriptUnknown0x23 */
|
|
typedef struct {
|
|
unsigned char unknown_1;
|
|
char * unknownString_1;
|
|
char * unknownString_2;
|
|
} WiseScriptUnknown0x23;
|
|
|
|
|
|
REWError readWiseScriptHeader(FILE * fp, WiseScriptHeader * header);
|
|
REWError readWiseScriptTexts(FILE * fp, WiseScriptTexts * texts);
|
|
REWError readWiseScriptFileHeader(FILE * fp, WiseScriptFileHeader * data);
|
|
REWError readWiseScriptUnknown0x03(FILE * fp, WiseScriptUnknown0x03 * data);
|
|
REWError readWiseScriptUnknown0x04(FILE * fp, WiseScriptUnknown0x04 * data);
|
|
REWError readWiseScriptUnknown0x05(FILE * fp, WiseScriptUnknown0x05 * data);
|
|
REWError readWiseScriptUnknown0x06(FILE * fp, WiseScriptUnknown0x06 * data); // no-free (no strings)
|
|
REWError readWiseScriptUnknown0x07(FILE * fp, WiseScriptUnknown0x07 * data);
|
|
REWError readWiseScriptUnknown0x08(FILE * fp, WiseScriptUnknown0x08 * data); // no-free (no strings)
|
|
REWError readWiseScriptUnknown0x09(FILE * fp, WiseScriptUnknown0x09 * data);
|
|
REWError readWiseScriptUnknown0x0A(FILE * fp, WiseScriptUnknown0x0A * data);
|
|
REWError readWiseScriptUnknown0x0B(FILE * fp, WiseScriptUnknown0x0B * data);
|
|
REWError readWiseScriptUnknown0x0C(FILE * fp, WiseScriptUnknown0x0C * data);
|
|
REWError readWiseScriptUnknown0x11(FILE * fp, WiseScriptUnknown0x11 * data);
|
|
REWError readWiseScriptUnknown0x12(FILE * fp, WiseScriptUnknown0x12 * data);
|
|
REWError readWiseScriptUnknown0x14(FILE * fp, WiseScriptUnknown0x14 * data);
|
|
REWError readWiseScriptUnknown0x15(FILE * fp, WiseScriptUnknown0x15 * data);
|
|
REWError readWiseScriptUnknown0x16(FILE * fp, WiseScriptUnknown0x16 * data);
|
|
REWError readWiseScriptUnknown0x17(FILE * fp, WiseScriptUnknown0x17 * data);
|
|
REWError readWiseScriptUnknown0x1C(FILE * fp, WiseScriptUnknown0x1C * data);
|
|
REWError readWiseScriptUnknown0x1E(FILE * fp, WiseScriptUnknown0x1E * data); // no-free (no strings)
|
|
REWError readWiseScriptUnknown0x23(FILE * fp, WiseScriptUnknown0x23 * data);
|
|
|
|
void freeWiseScriptHeader(WiseScriptHeader * header);
|
|
void freeWiseScriptTexts(WiseScriptTexts * texts);
|
|
void freeWiseScriptFileHeader(WiseScriptFileHeader * data);
|
|
void freeWiseScriptUnknown0x03(WiseScriptUnknown0x03 * data);
|
|
void freeWiseScriptUnknown0x04(WiseScriptUnknown0x04 * data);
|
|
void freeWiseScriptUnknown0x05(WiseScriptUnknown0x05 * data);
|
|
void freeWiseScriptUnknown0x07(WiseScriptUnknown0x07 * data);
|
|
void freeWiseScriptUnknown0x09(WiseScriptUnknown0x09 * data);
|
|
void freeWiseScriptUnknown0x0A(WiseScriptUnknown0x0A * data);
|
|
void freeWiseScriptUnknown0x0B(WiseScriptUnknown0x0B * data);
|
|
void freeWiseScriptUnknown0x0C(WiseScriptUnknown0x0C * data);
|
|
void freeWiseScriptUnknown0x11(WiseScriptUnknown0x11 * data);
|
|
void freeWiseScriptUnknown0x12(WiseScriptUnknown0x12 * data);
|
|
void freeWiseScriptUnknown0x14(WiseScriptUnknown0x14 * data);
|
|
void freeWiseScriptUnknown0x15(WiseScriptUnknown0x15 * data);
|
|
void freeWiseScriptUnknown0x16(WiseScriptUnknown0x16 * data);
|
|
void freeWiseScriptUnknown0x17(WiseScriptUnknown0x17 * data);
|
|
void freeWiseScriptUnknown0x1C(WiseScriptUnknown0x1C * data);
|
|
void freeWiseScriptUnknown0x23(WiseScriptUnknown0x23 * data);
|
|
|
|
|
|
// For debugging
|
|
void printWiseScriptHeader(WiseScriptHeader * header);
|
|
void printWiseScriptTexts(WiseScriptTexts * texts);
|
|
void printWiseScriptFileHeader(WiseScriptFileHeader * data);
|
|
void printWiseScriptUnknown0x03(WiseScriptUnknown0x03 * data);
|
|
void printWiseScriptUnknown0x04(WiseScriptUnknown0x04 * data);
|
|
void printWiseScriptUnknown0x05(WiseScriptUnknown0x05 * data);
|
|
void printWiseScriptUnknown0x06(WiseScriptUnknown0x06 * data);
|
|
void printWiseScriptUnknown0x07(WiseScriptUnknown0x07 * data);
|
|
void printWiseScriptUnknown0x08(WiseScriptUnknown0x08 * data);
|
|
void printWiseScriptUnknown0x09(WiseScriptUnknown0x09 * data);
|
|
void printWiseScriptUnknown0x0A(WiseScriptUnknown0x0A * data);
|
|
void printWiseScriptUnknown0x0B(WiseScriptUnknown0x0B * data);
|
|
void printWiseScriptUnknown0x0C(WiseScriptUnknown0x0C * data);
|
|
void printWiseScriptUnknown0x11(WiseScriptUnknown0x11 * data);
|
|
void printWiseScriptUnknown0x12(WiseScriptUnknown0x12 * data);
|
|
void printWiseScriptUnknown0x14(WiseScriptUnknown0x14 * data);
|
|
void printWiseScriptUnknown0x15(WiseScriptUnknown0x15 * data);
|
|
void printWiseScriptUnknown0x16(WiseScriptUnknown0x16 * data);
|
|
void printWiseScriptUnknown0x17(WiseScriptUnknown0x17 * data);
|
|
void printWiseScriptUnknown0x1C(WiseScriptUnknown0x1C * data);
|
|
void printWiseScriptUnknown0x1E(WiseScriptUnknown0x1E * data);
|
|
void printWiseScriptUnknown0x23(WiseScriptUnknown0x23 * data);
|
|
|
|
|
|
typedef struct {
|
|
void (*cb_header)(WiseScriptHeader*);
|
|
void (*cb_texts)(WiseScriptTexts*);
|
|
void (*cb_0x00)(WiseScriptFileHeader*);
|
|
void (*cb_0x03)(WiseScriptUnknown0x03*);
|
|
void (*cb_0x04)(WiseScriptUnknown0x04*);
|
|
void (*cb_0x05)(WiseScriptUnknown0x05*);
|
|
void (*cb_0x06)(WiseScriptUnknown0x06*);
|
|
void (*cb_0x07)(WiseScriptUnknown0x07*);
|
|
void (*cb_0x08)(WiseScriptUnknown0x08*);
|
|
void (*cb_0x09)(WiseScriptUnknown0x09*);
|
|
void (*cb_0x0A)(WiseScriptUnknown0x0A*);
|
|
void (*cb_0x0B)(WiseScriptUnknown0x0B*);
|
|
void (*cb_0x0C)(WiseScriptUnknown0x0C*);
|
|
void (*cb_0x0F)(void); // start form data?
|
|
void (*cb_0x10)(void); // end form data?
|
|
void (*cb_0x11)(WiseScriptUnknown0x11*);
|
|
void (*cb_0x12)(WiseScriptUnknown0x12*);
|
|
void (*cb_0x14)(WiseScriptUnknown0x14*);
|
|
void (*cb_0x15)(WiseScriptUnknown0x15*);
|
|
void (*cb_0x16)(WiseScriptUnknown0x16*);
|
|
void (*cb_0x17)(WiseScriptUnknown0x17*);
|
|
void (*cb_0x1C)(WiseScriptUnknown0x1C*);
|
|
void (*cb_0x1E)(WiseScriptUnknown0x1E*);
|
|
void (*cb_0x23)(WiseScriptUnknown0x23*);
|
|
} WiseScriptCallbacks;
|
|
|
|
|
|
typedef struct {
|
|
size_t totalInflatedSize;
|
|
size_t inflatedSize0x00;
|
|
size_t inflatedSize0x06;
|
|
size_t inflatedSize0x14;
|
|
// Deflated files described in the WiseScript have a offset to the deflated
|
|
// data, but this offset also has a offset which we can be found by iterating
|
|
// through all file structs and note the largest end-deflate offset, use that
|
|
// to subtract from the filesize.
|
|
//
|
|
// PE_filesize - largestEndDeflate
|
|
//
|
|
// This offset needs to be added to the offset described in the WiseScript to
|
|
// get to the real offset of the deflated data.
|
|
uint32_t inflateStartOffset;
|
|
} WiseScriptParsedInfo;
|
|
|
|
|
|
void initWiseScriptCallbacks(WiseScriptCallbacks * callbacks);
|
|
REWError parseWiseScript(const char * filepath, WiseScriptCallbacks * callbacks);
|
|
void stopWiseScriptParse(void);
|
|
|
|
WiseScriptParsedInfo * wiseScriptGetParsedInfo(const char * filepath);
|
|
|
|
// Debug print the parsed WiseScript structures
|
|
REWError wiseScriptDebugPrint(const char * filepath);
|
|
|
|
char * wiseScriptParsePath(char * path);
|
|
|
|
#endif
|