1. Introduction
InstallScript language is actually a limited subversion of C/C++ language. An InstallScript syntax and data types are similar to C/C++ ones with some limitations lead from InstallScript compiler specifics. All InstallScript data types are automatically converted to NUMBER
and STRING
types and occupy 4 bytes in a memory.
When these data types are defined inside structures (typedef
), they take their original memory sizes, like in C/C++.
Type Name | typedef Size | Regular Size | Comments |
Char | 1b | 4b | |
Short | 2b | 4b | |
Int | 4b | 4b | Internally equals to NUMBER type |
Bool | 4b | 4b | Internally equals to NUMBER type |
HWND | 4b | 4b | Internally equals to NUMBER type |
Long | 4b | 4b | Internally equals to NUMBER type |
String | 1b/2b | 1b/2b | Pointer to dynamically allocated null-terminated array of ASCII characters |
WString | 1b/2b | 1b/2b | Pointer to dynamically allocated null-terminated array of Unicode characters (it is not implemented yet in IS2010) |
Number | 4b | 4b | 4 bytes signed integer |
Pointer | 4b | 4b | Internally equals to NUMBER type |
Variant | 12b | error | Structured type which holds a numeric value or an address of any other data type |
2. Member and Pointer Operators in C/C++ and their alternatives in InstallScript
Let's see how different types of C/C++ pointers can be implemented in an InstallScript code.
2.1. a[b] Array Subscript
An array subscripting is permitted for a STRING
data type only:
function TestPointers()
STRING str[10]; WSTRING wstr[10]; NUMBER num[10]; begin
end;
This method can also be used for accessing arrays of integers (but not for changing ones). This is managed by adding bytes to the pointer address:
typedef STRUCT
begin
CHAR chval;
end;
function TestPointers()
STRUCT pointer stt;
STRING str;
begin
str="1234567890";
stt = &str+3;
SprintfBox(0,"","%c",stt->chval); end;
The correct amount of an allocated memory is checked by the SizeOf
function. The StrLength
and StrLengthChar
functions show a number of characters or bytes for dynamically allocated strings
. The array subscription operator that is used at an initialization step has no influence on these functions.
function TestPointers()
STRING str[10];
begin
SprintfBox(0,"","[%d,%d]",SizeOf(str),StrLegth(str)); end;
The next code sample is the standard way to allocate memory and initialize an integer array. It uses Windows Kernel function:
typedef STRUCT
begin
INT intval;
end;
prototype NUMBER KERNEL.LocalAlloc ( NUMBER, NUMBER );
#define LPTR 0x0040
function TestLocalAlloc()
STRUCT pointer stt;
begin
stt = LocalAlloc(LPTR, 12);
stt->intval = 1; stt += 4;
stt->intval = 2; stt += 4;
stt->intval = 3;
stt -=4;
SprintfBox(0,"","%d",stt->intval);
end;
The same result can be reached if we use pointer to any variable type.
It looks like InstallScript doesn't validate memory access for pointers. Weird.
function TestLocalAlloc()
number nvPtr;
begin
stt = &nvPtr;
stt->intval = 1; stt += 4;
stt->intval = 2; stt += 4;
stt->intval = 3;
stt -=4;
SprintfBox(0,"","%d",stt->intval);
end;
2.2. &a ("address of a")
The address references are supported in InstallScript the same way as in C/C++. A referenced memory address occupies 4 bytes and can be treated as a regular integer value.
Below is an example of the Windows Kernel function use for memory copy instead of an InstallScript structure pointer.
prototype void kernel32.RtlMoveMemory(pointer,pointer,long);
function TestMoveMemory()
INT intval,intval2;
POINTER pint;
begin
pint = &intval;
intval = 10;
RtlMoveMemory(&intval2,pint,4);
SprintfBox(0,"","%d",intval2);
end;
2.3. *a Indirection ("variable pointed by a")
The indirection operator returns an integer value. InstallScript supports it only in the right side of the expression. For using it at the left side, you can use a pointer to a structure.
function TestIndirection()
INT intval, resval;
pointer stt;
begin
intval = 10;
stt = &intval;
resval = *stt;
SprintfBox(0,"","%d",resval); end;
typedef STRUCT
begin
INT intval;
end;
function TestIndirection()
STRUCT pointer stt;
INT intval;
begin
intval = 10;
stt = &intval;
SprintfBox(0,"","%d",Stt->intval); end;
2.4. &a Reference types (inside function arguments)
Referenced types in InstallScript can be defined inside function arguments only.
Prototype BOOL MyFunc(HWND,byref int,byref string);
Two examples of redefinitions of windows function. Original declarations in C\C++:
UINT MsiGetProperty(
__in MSIHANDLE hInstall,
__in LPCTSTR szName,
__out LPTSTR szValueBuf,
__in_out DWORD* pchValueBuf
);
Function arguments as byref string
s:
prototype number MSI.MsiGetPropertyA(HWND, byval string, byref string, byref int);
function TestByrefArguments()
number nBuff;
string szProp;
begin
nBuff = MAX_PATH;
MSI.MsiGetPropertyA(ISMSI_HANDLE,"ARPPRODUCTICON",szProp,nBuff);
MessageBox(szProp,0);
end;
Function arguments as pointers:
prototype int MSI.MsiGetPropertyA(HWND, pointer, pointer, pointer);
function TestPointerArguments()
string szProp[MAX_PATH],szPropName;
number nBuff;
pointer ptProp;
begin
nBuff = MAX_PATH;
szPropName = "ARPPRODUCTICON";
ptProp = &szProp;
MSI.MsiGetPropertyA(ISMSI_HANDLE,&szPropName,ptProp,&nBuff);
PointerToStr(szProp,ptProp);
MessageBox(szProp,0);
end;
2.5. a->b Member b of object pointed to by a
This operator is supported in InstallScript the same way as in C/C++.
2.6. a.b Member b of object a
This operator is supported in InstallScript the same way as in C/C++.
2.9. NULL Pointers
NULL
pointer equals to an integer value of 0
.
2.10. Function Pointers in C/C++ and their alternative in InstallScript
The function pointers are not supported in InstallScript and throw compilation error. The callback functions can be defined in external DLLs and their addresses can be exported to an InstallScript code. The GetModuleHandle
and GetProcAddress
functions are defined in InstallScript, but are not documented (as many other interesting windows functions).
prototype int User32.SetTimer(HWND,int,int,pointer);
function TestFunctionPointers()
HWND hDLL;
POINTER pFunc;
NUMBER nTimerID;
begin
UseDLL("timerproc.dll");
hDLL = GetModuleHandle("timerproc.dll");
pFunc = GetProcAddress(hDLL,"TimerProc");
nTimerID = SetTimer(NULL,1,1000, pFunc);
end;
4. Variant Type
As we said before, the Variant data type is actually a structure which holds a numeric value or an address of any other data type:
typedef __VARIANT
begin
SHORT vt;
SHORT wReserver1;
SHORT wReserved2;
SHORT wReserved3;
NUMBER nData;
end;
A Variant variable’s value can be accessed directly after incrementing its address in memory:
typedef STRUCT
begin
NUMBER nval;
end;
function TestVariant()
STRUCT pointer ret;
__VARIANT vt;
begin
vt = 10;
ret = &vt + 8;
SprintfBox(0,"","%d",ret->nval);
SprintfBox(0,"","%d",*ret);
end;
5. Arrays as Pointers
An InstallScript array is actually a VARIANT
type variable which holds an address of a SAFEARRAY
structure. It can be used for a memory allocation instead of Windows functions, like LocalAlloc
.
typedef __VARIANT
begin
SHORT vt;
SHORT wReserver1;
SHORT wReserved2;
SHORT wReserved3;
NUMBER nData;
end;
typedef __SAFEARRAY
begin
SHORT cDims;
SHORT fFeatures;
LONG cbElements;
LONG cLocks;
POINTER pvData;
end;
typedef STRUCT
begin
NUMBER nval;
end;
function GetArrayMember()
NUMBER nArr(10);
__SAFEARRAY pointer psArray;
__VARIANT pointer psVariant;
STRUCT pointer ret;
begin
nArr(5) = 10;
psVariant = &nArr;
psArray = psVariant->nData;
ret = psArray->pvData + 5*4;
SprintfBox(0,"","%d",ret->nval);
endif;
By using this approach, we can create a very elegant C/C++ style memory allocation function:
typedef STRUCT
begin
NUMBER nval;
end;
prototype pointer new(number);
function pointer new(nSize)
NUMBER nArr();
STRUCT pointer ret;
begin
Resize(nArr, nSize);
ret = &nArr + 8;
ret = ret->nval + 12;
return ret->nval;
end;
It can be used like is shown below:
POINTER ret;
ret = new(100);
The above code allocates 100*4 bytes of memory. The problem here is that at the moment when the memory allocator function returns a value, we have already left the scope of the array used for the memory allocation so, an InstallScript engine can formally take that memory for any of its own needs. In order to solve this issue, we can create a global array and use it together with memory management and optimization algorithms.
6. Examples
These examples are written in «C» and InstallScript languages. They show string
and pointer implementation techniques discussed throughout this article.