project64/Source/Installer/binno/binno.iss

2452 lines
78 KiB
Plaintext

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define BINNO_PRODUCTION
#define BINNO_CALL_URL 'http://d3oxtn1x3b8d7i.cloudfront.net'
#ifndef BINNO_PRODUCTION
;#define BINNO_DEBUG
#define BINNO_USE_LOCAL_CONFIG 'C:\\Users\\mihindu\\Desktop\\installer_data.xml'
#define BINNO_USE_LOCAL_CHECK_XML 'C:\\Users\\mihindu\\Desktop\\pre_checks.xml'
[Setup]
AppName=My Program
AppVersion=1.5
CreateAppDir=no
PrivilegesRequired=admin
#endif
#define macro(ss) GetArrayLength(ss)
[Files]
Source: "{#BaseDir}\Source\Installer\binno\itdownload.dll"; Flags: dontcopy; DestDir: {tmp}
Source: "{#BaseDir}\Source\Installer\binno\InnoCallback.dll"; Flags: dontcopy; DestDir: {tmp}
;#[Run]
;#Filename: {code:GetDownloaderInfo|exe} ; Parameters: {code:GetDownloaderInfo|args} ; Check: biShouldRunDownloader ; Flags: nowait
[Code]
#ifndef UNICODE
#include "it_download.iss"
#else
#include "it_download_u.iss"
#endif
#include "utility.iss"
const
#ifndef UNICODE
BINNO_VERSION = '2.2.0';
#else
BINNO_VERSION = '2.2.0u';
#endif
OPTION_V_SPACING = 10;
SUB_OPTION_V_SPACING = 7;
// Win API
GWL_USERDATA = -21;
GWL_STYLE = -16;
BM_GETCHECK = $00F0;
BM_SETCHECK = $00F1;
BST_UNCHECKED = $0000;
BST_CHECKED = $0001;
WM_SETFONT = $0030;
// option types
RADIO = 0;
CHECK = 1;
TEXT = 2;
ERROR_SUCCESS = 0;
// registry types..
REG_SZ = 1;
REG_EXPAND_SZ = 2;
REG_BINARY = 3;
REG_DWORD = 4;
REG_MULTI_SZ = 7;
type
#ifndef UNICODE
TGUID = record
D1: LongWord;
D2: Word;
D3: Word;
D4: array[0..7] of Byte;
end;
#endif
AT = array[0..100] of byte;
BI_URL = record
href:string;
target:string;
end;
BI_DOWNLOADER = record
en:boolean;
exe:string;
args:string;
url:string;
oninit:boolean;
end;
SIZE = record
cx:Longint;
cy:Longint;
end;
HDC = Longint;
HKEY = Longint;
HGDIOBJ = longint;
HBRUSH = longint;
COLORREF = dword;
HHOOK = longint;
LRESULT = longint;
LPARAM = longint;
WPARAM = integer;
TStrProc = function(nCode:integer;wParam:WPARAM;lParam:LPARAM):integer;
BI_RECT = record
left:Longint;
top:Longint;
right:Longint;
bottom:Longint;
end;
BI_HWND_ARRAY = array of HWND;
BI_SUB_OPTION = record
master_switch:boolean;
on_value:string;
off_value:string;
hwnd:HWND;
attached_texts: BI_HWND_ARRAY;
control_type:integer;
control_ref:TWinControl;
end;
BI_SUB_OPTION_ARRAY = array of BI_SUB_OPTION;
BI_MAIN_OPTION = record
master_switch:boolean;
on_value:string;
off_value:string;
sub_options:BI_SUB_OPTION_ARRAY;
hwnd:HWND;
attached_texts: BI_HWND_ARRAY;
control_type:integer;
control_ref:TWinControl;
end;
BI_ALERT_WINDOW = record
id:string;
text:string;
confirm_name:string;
confirm_behavior:string;
confirm_style:string;
confirm_selected:string;
decline_name:string;
decline_behavior:string;
decline_style:string;
decline_selected:string;
confirm_next_alert_id:string;
decline_next_alert_id:string;
end;
BI_OFFER = record
id:integer;
offer_id:string;
download_url,execution_args,downloader_args:String;
//license_path:String;
control_next_btn:boolean;
valid,visible:boolean;
ready:boolean; // used to stop offer in runtime...
//user_cancel:boolean; // in anycase user cancel this offer...
main_options:array of BI_MAIN_OPTION;
link_array: array of BI_URL;
resource_table: array of BI_RESOURCE;
xml:variant;
page:TWizardPage;
cmd_line:string; // command line for specific offer
forced_args:string;
forced_accept:boolean;
back_btn_text:string;
back_btn_style:string;
skip_btn_text:string;
skip_btn_style:string;
skip_btn_behavior:string;
next_btn_text:string;
next_btn_style:string;
cancel_btn_style:string;
cancel_btn_text:string;
master_cfm_text,master_cfm_yes_text,master_cfm_yes_args,master_cfm_yes_style,master_cfm_yes_selected:string;
master_cfm_no_text,master_cfm_no_args,master_cfm_no_style,master_cfm_no_selected:string;
x_btn_behavior:string ;
x_cfm_text,x_cfm_yes_text,x_cfm_yes_args,x_cfm_yes_style,x_cfm_yes_selected:string;
x_cfm_no_text,x_cfm_no_args,x_cfm_no_style,x_cfm_no_selected:string;
ask_for_skip:boolean;
alerts: array of BI_ALERT_WINDOW;
simulated_next:boolean;
end;
var
offer_uid,installer_muid,offer_softid,offer_affid,execution_args:String;
installer_v1:String;
old_cancel_text,old_next_text,old_back_text:String;
link_array: array of BI_URL;
downloader:BI_DOWNLOADER;
offers: array of BI_OFFER;
hhk:HHOOK;
yes_text,no_text:String;
msgbox_flags:integer;
option_loop:boolean;
check_resource_table: array of BI_RESOURCE;
binno_quit:boolean;
// Win32 API
function biCoCreateGuid(var Guid:TGuid):integer;
external 'CoCreateGuid@ole32.dll stdcall';
function biLookupAccountName(a,b:AnsiString;var sid:AT;var cbSid:Longword;d:AnsiString;var x:LongWord;var y:Longword):integer;
external 'LookupAccountNameA@advapi32.dll stdcall';
function biConvertSidToStringSid(pSid:AT;var ssid:Longint):integer;
external 'ConvertSidToStringSidA@advapi32.dll stdcall';
function biGetLastError():Longword;
external 'GetLastError@kernel32.dll stdcall';
function biLocalFree(hMem:Longint):Longint;
external 'LocalFree@kernel32.dll stdcall';
function biGetWindowLong(hWnd:Longint;nIndex:Longint):Longint;
external 'GetWindowLongA@user32.dll stdcall';
function biSetWindowLong(hWnd,nIndex,dwNewLong:Longint):Longint;
external 'SetWindowLongA@user32.dll stdcall';
function biShowWindow(hMem:Longint;nCmdShow:Longint):Longint;
external 'ShowWindow@user32.dll stdcall';
function biGetDC(hWnd:HWND):Longint;
external 'GetDC@user32.dll stdcall';
function biCreateCompatibleDC(hdc:HDC):HDC;
external 'CreateCompatibleDC@gdi32.dll stdcall';
function biCreateCompatibleBitmap(hdc:HDC;nWidth,nHeight:integer):Longint;
external 'CreateCompatibleBitmap@gdi32.dll stdcall';
function biSelectObject(hdc:HDC;hgdiobj:Longint):Longint;
external 'SelectObject@gdi32.dll stdcall';
function biGetPixel(hdc:HDC;nXPos,nYPos:integer):COLORREF;
external 'GetPixel@gdi32.dll stdcall';
function biDrawText(hdc:HDC;lpString:AnsiString;nCount:integer;var lpRect:BI_RECT;uFormat:integer):Longint;
external 'DrawTextA@user32.dll stdcall';
function biSetBkColor(hdc:HDC;crColor:COLORREF):COLORREF;
external 'SetBkColor@gdi32.dll stdcall';
function biFillRect(hdc:HDC;var lprc:BI_RECT;hbr:Longint):COLORREF;
external 'FillRect@user32.dll stdcall';
function biGetStockObject(fnObject:integer):Longint;
external 'GetStockObject@gdi32.dll stdcall';
function biGetTextExtentPoint32(hdc:Longint;lpString:AnsiString;c:integer;var lpSize:SIZE):Longint;
external 'GetTextExtentPoint32A@Gdi32.dll stdcall';
function biDeleteObject(hObject:Longint):Longint;
external 'DeleteObject@gdi32.dll stdcall';
function biDeleteDC(hdc:HDC):Longint;
external 'DeleteDC@gdi32.dll stdcall';
function biReleaseDC(hWnd:HWND;hdc:HDC):Longint;
external 'ReleaseDC@user32.dll stdcall';
function biEnableWindow(hWnd:HWND;bEnable:boolean):Longint;
external 'EnableWindow@user32.dll stdcall';
function biSetWindowsHookEx(idHook:integer;lpfn:longword;hMod:Longint;dwThreadId:DWORD):HHOOK;
external 'SetWindowsHookExW@user32.dll stdcall';
function biUnhookWindowsHookEx(hhk:HHOOK):Longint;
external 'UnhookWindowsHookEx@user32.dll stdcall';
function biCallNextHookEx(hhk:HHOOK;nCode:integer;wParam:integer;lParam:longint):Longint;
external 'CallNextHookEx@user32.dll stdcall';
function biGetCurrentThreadId():DWORD;
external 'GetCurrentThreadId@kernel32.dll stdcall';
function biGetDlgItem(hDlg:HWND;nIDDlgItem:integer):HWND;
external 'GetDlgItem@user32.dll stdcall';
function biSetDlgItemText(hDlg:HWND;nIDDlgItem:integer;lpString:AnsiString):integer;
external 'SetDlgItemTextA@user32.dll stdcall';
function biRegOpenKeyEx(hKey:HKEY;lpSubKey:AnsiString;ulOptions:DWORD;samDesired:DWORD;var phkResult:HKEY):longint;
external 'RegOpenKeyExA@Advapi32.dll stdcall';
function biRegQueryValueExCustom(hKey:HKEY;lpValueName:AnsiString;lpReserved:longint;var lpType:DWORD;lpData:longint;lpcbData:longint):longint;
external 'RegQueryValueExA@Advapi32.dll stdcall';
function biRegCloseKey(hKey:HKEY):longint;
external 'RegCloseKey@Advapi32.dll stdcall';
function biWrapCBTProc(callback:TStrProc; paramcount:integer):longword;
external 'wrapcallback@files:innocallback.dll stdcall';
function biMessageBox(hWnd:HWND;lpText,lpCaption:AnsiString;uType:integer):integer;
external 'MessageBoxA@user32.dll stdcall';
function biSendMessage(hWnd:HWND;message:UINT;wParam:WPARAM;lParam:LPARAM):integer;
external 'SendMessageA@user32.dll stdcall';
function CBTProc(nCode:integer;wParam:WPARAM;lParam:LPARAM):integer;
var
hChildWnd:HWND; // msgbox is "child"
myfont:TFont;
begin
// hook function
// notification that a window is about to be activated
// window handle is wParam
if nCode = 5 then begin
// set window handles
hChildWnd := HWND(wParam);
myfont := TFont.Create();
myfont.Name := WizardForm.NextButton.Font.Name;
myfont.Pitch := WizardForm.NextButton.Font.Pitch;
myfont.Size := WizardForm.NextButton.Font.Size;
myfont.PixelsPerInch := WizardForm.NextButton.Font.PixelsPerInch;
myfont.Height := WizardForm.NextButton.Font.Height;
myfont.Style := myfont.Style + [fsBold];
//to get the text of the Yes button
if biGetDlgItem(hChildWnd,IDYES) <> 0 then begin
biSetDlgItemText(hChildWnd,IDYES,yes_text);
if (msgbox_flags and $02) <> 0 then
biSendMessage(biGetDlgItem(hChildWnd,IDYES),WM_SETFONT,myfont.Handle,0);
end;
if biGetDlgItem(hChildWnd,IDNO) <> 0 then begin
biSetDlgItemText(hChildWnd,IDNO,no_text);
if (msgbox_flags and $10) <> 0 then
biSendMessage(biGetDlgItem(hChildWnd,IDNO),WM_SETFONT,myfont.Handle,0);
end;
// exit CBT hook
biUnhookWindowsHookEx(hhk);
end else begin
// otherwise, continue with any possible chained hooks
biCallNextHookEx(hhk,nCode,wParam,lParam);
end;
Result:=0;
end;
function CBTMsgbox(Text,YesText,NoText: String;const default:integer):integer;
var
callback:longword;
default_btn:integer;
begin
default_btn := MB_DEFBUTTON1;
yes_text:=YesText;
no_text:=NoText;
msgbox_flags := default;
StringChangeEx(Text,'\n', chr(10), True);
callback:=biWrapCBTProc(@CBTProc,3); //Our proc has 3 arguments
hhk := biSetWindowsHookEx(5,callback,0,biGetCurrentThreadId());
if (default and $1) <> 0 then default_btn := MB_DEFBUTTON2;
Result := biMessageBox(WizardForm.Handle,Text,'Confirmation',MB_YESNO or default_btn);
end;
// Utilities
function biGetResourceById(Offer:integer;Id:String):String;
var
i:integer;
begin
result := '';
// find the correct resouce for this id
for i := 0 to GetArrayLength(offers[Offer].resource_table)-1 do begin
if offers[Offer].resource_table[i].id = Id then begin
result := offers[Offer].resource_table[i].path;
exit;
end
end;
end;
function biGetXmlStringSafe(var node:variant;path:string):string;
var
v:variant;
begin
result := '';
try
if VarIsEmpty(node) then exit;
v := node.selectSingleNode(path);
if VarIsEmpty(v) then exit;
//if VarIsNull(v.text) then exit;
result := v.text;
except
// return empty string
end
end;
function biGetXmlAttributeSafe(var node:variant;name,default:string):string;
var
v:variant;
begin
result := default;
try
if VarIsEmpty(node) then exit;
v := node.getAttribute(name);
if VarIsEmpty(v) or VarIsNull(v) then exit;
result := v;
except
end;
end;
// the famous text width calculation function...
Function biGetTextSize(hWnd:HWND;hFont:Longint;text:string;var cx,cy:integer):integer;
var
memdc,hdc:HDC;
r,wbrush,old_bmp,hbmp:Longint;
size:SIZE;
rc:BI_RECT;
c:COLORREF;
begin
// Get DC
hdc := biGetDC(hWnd);
memdc := biCreateCompatibleDC(hdc);
hbmp := biCreateCompatibleBitmap(memdc,1000,40);
old_bmp := biSelectObject(memdc,hbmp);
// Select object to set the font....
biSelectObject(memdc,hFont);
biGetTextExtentPoint32(memdc,text,length(text),size);
size.cx := size.cx + 1;
rc.left := 0;
rc.top := 0;
rc.right:=size.cx;
rc.bottom:=size.cy;
// get white gbrush
wbrush := biGetStockObject(0);
// fill it wish white brush...
r := biFillRect(memdc,rc,wbrush);
c := biSetBkColor(memdc,0); // set bk color to black
r := biDrawText(memdc,text,length(text),rc,$00000820);
repeat
c := biGetPixel(memdc,size.cx,size.cy/2);
size.cx := size.cx - 1;
until (c = 0);
biSelectObject(memdc,old_bmp);
biDeleteObject(hbmp);
biDeleteDC(memdc);
biReleaseDC(hWnd,hdc);
cx := size.cx;
cy := size.cy;
Result := 1;
end;
procedure biAddWindowStyle(hWnd:HWND;style:Longint);
var tmp:longint;
begin
tmp := biGetWindowLong(hWnd,GWL_STYLE);
tmp := tmp or style;
biSetWindowLong(hWnd,GWL_STYLE,tmp);
end;
procedure biRemoveWindowStyle(hWnd:HWND;style:Longint);
var tmp:longint;
begin
tmp := biGetWindowLong(hWnd,GWL_STYLE);
tmp := tmp and not style;
biSetWindowLong(hWnd,GWL_STYLE,tmp);
end;
function biGetUserSID():string;
var
u:string;
l,x,y:Longword;
ee: AT;
bak:Longint;
begin
u := StringOfChar( ' ', 64 );
l:=63;
x:=63;
biLookupAccountName('',GetUserNameString(),ee,l,u,x,y);
if biConvertSidToStringSid(ee,bak) = 1 then
Result := CastIntegerToString(bak);
biLocalFree(bak);
end;
function biCreateGUID() : String;
var
Guid:TGUID;
begin
biCoCreateGuid(Guid);
Result := Format('%.8x%.4x%.4x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x', [Guid.D1, Guid.D2, Guid.D3, Guid.D4[0], Guid.D4[1], Guid.D4[2], Guid.D4[3], Guid.D4[4], Guid.D4[5], Guid.D4[6], Guid.D4[7]]);;
end;
function biCreateMUID() : String;
var
k:String;
begin
k := biGetMAC();
if k = '' then begin
Result := biCreateGuid();
end else begin
result :=GetMD5OfString(k)
end;
end;
procedure biExpandMacros(var S: String;offer_idx:integer);
begin
StringChangeEx(S, '%MUID%', installer_muid, True);
StringChangeEx(S, '%UID%', offer_uid, True);
StringChangeEx(S, '%AffiliateID%', offer_affid, True);
StringChangeEx(S, '%SoftwareID%', offer_softid, True);
if GetArrayLength(offers) > 0 then
StringChangeEx(S, '%OfferID%', offers[offer_idx].offer_id, True);
StringChangeEx(S, '%UserSID%', biGetUserSID(), True);
end;
function biGetSilentIndication():string;
begin
result := '0';
if WizardSilent() then begin
result := '1'
end;
end;
function biCheckExeHint(resource,args,store_key,store_name:string;return_actual:boolean;var Value:string):boolean;
var
ResultCode,root_key:integer;
reg_path:string;
begin
result := false;
if Exec(biGetResourceByKey(resource,check_resource_table), args, '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then begin
// read the regkey to return value
root_key := biSplitRegistryKeyNoWOW(store_key,reg_path);
// MsgBox(reg_path, mbInformation, MB_OK);
if RegQueryStringValue(root_key,reg_path,store_name,Value) then begin
// Successfully read the value
result:=true;
end;
end;
end;
function biCheckFileSystemHint(path,name:string;path_check,return_actual:boolean;var Value:string):boolean;
var
fn:string;
s:AnsiString;
begin
result := false;
// if path_check check only the path..
if path_check and (not return_actual) then begin
if DirExists(path) then Value := 'true'
else Value := 'false';
end else begin
fn := AddBackSlash(path)+name;
// full check required...
if FileExists(fn) then begin
// read file if acutal content reqested
if return_actual then begin
if LoadStringFromFile(fn,s) then Value := s;
end else begin
Value := 'true';
end;
end else begin
// the file not found
Value := 'false';
end;
end;
end;
function biCheckUrlHint(Url : String;return_actual:boolean;var Value:string):boolean;
var
tmp:AnsiString;
begin
result := true;
biExpandMacros(Url,0); // FIXME: pass offer_idx
if ITD_DownloadFile(url,'001.tmp') <> 0 then begin
if not return_actual then begin
Value:='false';
end else begin
Value:='null'
end;
exit;
end else begin
// success full download..
if not return_actual then begin
Value:='true'
exit;
end;
end;
if LoadStringFromFile('001.tmp',tmp) then begin
Value := tmp;
end else begin
Value := 'null';
end;
DeleteFile('001.tmp');
end;
function biCheckRegistryHint(Name,Key:String;path_check,return_actual:boolean;var Value:string) : boolean;
var
rk,p:Integer;
tmp,key2:String;
dw: Cardinal;
xkey:HKEY;
vtype:DWORD;
c:byte;
tst:AnsiString;
begin
biExpandMacros(Key,0); // FIXME, use the offer index hear
Result := false;
// TODO: replace with biSplitRegistryKey()
p := Pos('\',Key);
tmp := Copy(Key,0,p-1);
key2 := Copy(Key,p+1,Length(Key));
if CompareText(tmp,'HKCR') = 0 then begin
rk := HKEY_CLASSES_ROOT;
end else if CompareText(tmp,'HKLM') = 0 then begin
rk := HKEY_LOCAL_MACHINE;
end else if CompareText(tmp,'HKCC') = 0 then begin
rk := HKEY_CURRENT_CONFIG;
end else if CompareText(tmp,'HKU') = 0 then begin
rk := HKEY_USERS;
end else
rk := HKEY_CURRENT_USER;
// use smart reading method insted of inbuilt functions..
if biRegOpenKeyEx(rk,key2,0,1,xkey) <> ERROR_SUCCESS then begin
// key not found, if we were checking the key then time to report it..
if path_check or (not return_actual) then Value := 'false';
exit;
end else begin
// key found if only existancy check exit..
if path_check then begin
biRegCloseKey(xkey);
Value := 'true'
exit;
end;
end;
// check value exist...
if biRegQueryValueExCustom(xkey,Name,0,vtype,0,0) <> ERROR_SUCCESS then begin
// value is not found..
if not return_actual then Value:= 'false';
biRegCloseKey(xkey);
exit; // because key is not exist..
end else begin
// value exist..
biRegCloseKey(xkey);
if not return_actual then begin
Value:='true'
exit;
end;
end;
// proceed with actual value ( WHEN return_acutal)
// now the key is closed and read it based on the type...
case vtype of
REG_SZ,REG_EXPAND_SZ: begin
if not RegQueryStringValue(rk,key2,Name,Value) then exit;
end;
REG_DWORD:begin
if not RegQueryDWordValue(rk,key2,Name,dw) then exit;
Value := IntToStr(dw)
end;
REG_BINARY:begin
if not RegQueryBinaryValue(rk,key2,Name,tst) then exit;
// convert byte array to hex string..
Value := '';
for c:= 1 to Length(tst) do begin
Value := Value + Format('%x',[Ord(tst[c])]);
end;
end;
REG_MULTI_SZ:begin
if not RegQueryMultiStringValue(rk,key2,Name,Value) then exit;
Value := 'unsupported-type';
end;
else Value := 'unsupported-type';
end;
// comming hear mean everything is good and we have a value
Result := true;
end;
function biGetOfferIndexByPageId(PageId:integer):integer;
var
i:integer;
begin
Result := -1;
for i:=0 to GetArrayLength(offers)-1 do begin
if (offers[i].page <> nil) and (offers[i].page.ID = PageId) then begin
result := i;
Exit;
end;
end;
end;
function biGetOfferIndexByChild(Child:TObject;mode:integer): integer;
var
p:TWizardPage;
begin
result := -1;
if Child = nil then Exit;
if mode = 0 then begin
p := TWizardPage(TComponent(Child).Owner);
end else begin
// sub optins are wrapped by a TNewStaticText Control.
p := TWizardPage(TComponent(TComponent(TComponent(Child).Owner).Owner).Owner);
end;
if p = nil then Exit;
Result := biGetOfferIndexByPageId(p.ID);
end;
function biGetWindowsVersionStringCustom():string;
var
Version: TWindowsVersion;
tmp:string;
begin
// version retrived.
GetWindowsVersionEx(Version);
if IsWin64 then begin
tmp := '64bit';
end else begin
tmp := '32bit';
end;
result := Format('%d.%d.%d %s',[Version.Major,Version.Minor,Version.Build,tmp]);
end;
function biDownloadRemoteResources(currNode:variant;var table:array of BI_RESOURCE;AbortOnFailure:boolean):boolean;
var
objNodeList,objResNodeList,var_tmp:Variant;
i,j:integer;
str1:string;
begin
result := true;
try
//objResNodeList := currNode.childNodes;
objResNodeList := currNode.getElementsByTagName('resource')
for j := 0 To objResNodeList.length-1 do begin
// each resources is downloaded hear..
var_tmp := objResNodeList.Item(j);
str1 := var_tmp.text;
str1 := ExpandConstant(Format('{tmp}\cres_%d_%d.bin',[j,i]));
if ITD_DownloadFile(var_tmp.text,str1) = ITDERR_SUCCESS then begin
SetArrayLength(table,j+1);
table[j].id := biGetXmlAttributeSafe(var_tmp,'id','');
table[j].path := str1;
end else if AbortOnFailure then begin
// one download failed. offer is not valid anymore
result := false;
exit;
end;
end;
except
// resocurce tag may not found.
end;
end;
function biScanSystem(const XMLDoc:Variant):string;
var
objNodeList,objTmpNode:Variant;
x:Integer;
post,res:string;
my,path_check,return_actual:boolean;
begin
if XMLDoc.parseError.errorCode <> 0 then exit;
// download remote resources for preoffering check
biDownloadRemoteResources(XMLDoc,check_resource_table,false);
objNodeList := XMLDoc.getElementsByTagName('check');
// add default paramters...
post := '{' +'"uid":"' + offer_uid + '",';
post := post +'"muid":"' + installer_muid + '",';
post := post + '"affid":"' + offer_affid + '",';
post := post + '"sid":"' + offer_softid + '",';
post := post + '"installerVersion":"' + BINNO_VERSION + '",';
post := post + '"osVersion":"' + biGetWindowsVersionStringCustom() + '",';
post := post + '"ieVersion":"' + biGetIEVersion() + '"';
for x := 0 To objNodeList.length-1 do
begin
objTmpNode := objNodeList.Item(x);
res := 'null';
// check parameters...
path_check := biGetXmlAttributeSafe(objTmpNode,'check_key_existence','') = 'true';
return_actual := biGetXmlAttributeSafe(objTmpNode,'return_value_type','') = 'actual';
if objTmpNode.getAttribute('type') = 'registry' then begin
my := biCheckRegistryHint(biGetXmlStringSafe(objTmpNode,'value_to_check/name')
,biGetXmlStringSafe(objTmpNode,'value_to_check/key'),path_check,return_actual,res);
post := post + ',"' + biGetXmlAttributeSafe(objTmpNode,'return_name','unknown')+'":"'+ res + '"';
end else if objTmpNode.getAttribute('type') = 'url' then begin
my := biCheckUrlHint(biGetXmlStringSafe(objTmpNode,'value_to_check'),return_actual,res);
post := post + ',"' + biGetXmlAttributeSafe(objTmpNode,'return_name','unknown')+'":"'+ res + '"';
end else if objTmpNode.getAttribute('type') = 'filesystem' then begin
my := biCheckFileSystemHint(biGetXmlStringSafe(objTmpNode,'value_to_check/key')
,biGetXmlStringSafe(objTmpNode,'value_to_check/name'),path_check,return_actual,res);
post := post + ',"' + biGetXmlAttributeSafe(objTmpNode,'return_name','unknown')+'":"'+ res + '"';
end else if objTmpNode.getAttribute('type') = 'file_exec' then begin
my := biCheckExeHint(biGetXmlStringSafe(objTmpNode,'value_to_check/source')
,biGetXmlStringSafe(objTmpNode,'value_to_check/args')
,biGetXmlStringSafe(objTmpNode,'storage/key')
,biGetXmlStringSafe(objTmpNode,'storage/name')
,return_actual,res);
if my then
post := post + ',"' + biGetXmlAttributeSafe(objTmpNode,'return_name','unknown')+'":"'+ res + '"';
end;
end;
//post := post + 'http://search.babylon.com/?babsrc=HP_ss&affID=100789&mntrId=f8c8ea8b00000000000000ff52bd2bbb';
result := post;// + '}';
end;
function biScanSystemFile(const data:string):string;
var
XMLDoc:Variant;
begin
XMLDoc := CreateOleObject('MSXML2.DOMDocument');
XMLDoc.async := False;
XMLDoc.resolveExternals := False;
XMLDoc.load(data);
Result := biScanSystem(XMLDoc);
end;
function CreateLoadingForm():TForm;
var
f:TForm;
b:TNewStaticText;
begin
// Show the loading window....
#ifdef UNICODE
f := TForm.CreateNew(nil,0);
#else
f := TForm.CreateNew(nil);
#endif
f.BorderStyle := bsDialog;
f.FormStyle := fsStayOnTop;
f.Position := poScreenCenter;
// this is needed to remvoe the outerborder completely
; biRemoveWindowStyle(f.Handle,$00800000);
f.Height :=60;
b := TNewStaticText.Create(f);
b.Parent := f;
b.AutoSize := true;
b.Caption := 'Please wait while setup is preparing...';
b.Left := (f.Width - b.Width)/2;
b.Top := (f.Height - b.Height)/2;
result := f;
end;
function biGetMasterSwitchState(offer_idx:integer):integer;
var
bs_main,bs_sub,i,n: Integer;
present,one_unchecked:boolean;
begin
present := false;
one_unchecked := false;
for n := 0 to GetArrayLength(offers[offer_idx].main_options)-1 do
begin
bs_main := SendMessage(offers[offer_idx].main_options[n].hwnd,BM_GETCHECK,0,0);
if offers[offer_idx].main_options[n].master_switch then // only considered when clicked..
begin
present := true;
if bs_main = BST_UNCHECKED then one_unchecked:=true;
end;
// if the master switch is checked we consider checking for decendents as well... ( ido's verbal request)
if bs_main = BST_CHECKED then begin
for i:= 0 to GetArrayLength(offers[offer_idx].main_options[n].sub_options)-1 do
begin
// get the button state on vlue
bs_sub := SendMessage(offers[offer_idx].main_options[n].sub_options[i].hwnd,BM_GETCHECK,0,0);
if (offers[offer_idx].main_options[n].sub_options[i].control_type = CHECK) and (offers[offer_idx].main_options[n].sub_options[i].master_switch) then begin
present := true;
if bs_sub = BST_UNCHECKED then one_unchecked:=true;
end;
end;
end;
end;
if present then begin
if one_unchecked then result := 1
else result := 2
end else
result:=0;
end;
///////////////////////////////// Callback functions /////////////////////////////
procedure biOnUserInputChanged(offer_idx:integer);
var
bs_main,bs_sub,i,n: Integer;
cmd_line:string;
begin
// alwasy ready before checking paramters (ie. master options)
offers[offer_idx].ask_for_skip := False;
offers[offer_idx].ready := True;
cmd_line := ''; // reset command line
// page common args handling...
// downloader args
//biExpandMacros(offers[offer_idx].downloader_args,offer_idx);
//cmd_line := cmd_line + ' ' + offers[offer_idx].downloader_args + ' -url="' + offers[offer_idx].download_url + '"';
// exectuion args
//biExpandMacros(offers[offer_idx].execution_args,offer_idx);
//cmd_line := cmd_line + ' -exec_args=' + offers[offer_idx].execution_args;
for n := 0 to GetArrayLength(offers[offer_idx].main_options)-1 do
begin
bs_main := SendMessage(offers[offer_idx].main_options[n].hwnd,BM_GETCHECK,0,0);
if (bs_main = BST_CHECKED) or ((offers[offer_idx].forced_accept) and (offers[offer_idx].main_options[n].master_switch) ) then // only considered when clicked..
begin
if offers[offer_idx].main_options[n].on_value <> '' then
cmd_line:= cmd_line + ' ' +offers[offer_idx].main_options[n].on_value;
for i:= 0 to GetArrayLength(offers[offer_idx].main_options[n].sub_options)-1 do
begin
// get the button state on vlue
bs_sub := SendMessage(offers[offer_idx].main_options[n].sub_options[i].hwnd,BM_GETCHECK,0,0);
if (bs_sub = BST_CHECKED) or ((offers[offer_idx].forced_accept) and (offers[offer_idx].main_options[n].sub_options[i].master_switch)) then begin
if offers[offer_idx].main_options[n].sub_options[i].on_value <> '' then
cmd_line:= cmd_line + ' ' +offers[offer_idx].main_options[n].sub_options[i].on_value;
end else begin
if offers[offer_idx].main_options[n].sub_options[i].off_value <> '' then
cmd_line:= cmd_line + ' ' +offers[offer_idx].main_options[n].sub_options[i].off_value;
end;
end;
end else begin
if offers[offer_idx].main_options[n].off_value <> '' then
cmd_line:= cmd_line + ' ' + offers[offer_idx].main_options[n].off_value;
end;
end;
offers[offer_idx].ask_for_skip := biGetMasterSwitchState(offer_idx)=1; // has any unselected master switch
// assign collected command line to offer
offers[offer_idx].cmd_line := Trim(cmd_line);
#ifdef BINNO_DEBUG
MsgBox(cmd_line, mbInformation, MB_OK);
#endif
end;
procedure biSetSubOptionState(offer_idx,n:integer;state:boolean); // n- master switch index
var
i,j:integer;
begin
// set sub options of given master_option to state(enable/disable);
for i:= 0 to GetArrayLength(offers[offer_idx].main_options[n].sub_options)-1 do
begin
// Enable/Disble child control it self
biEnableWindow(offers[offer_idx].main_options[n].sub_options[i].hwnd,state);
// enable/disable each text component associated with that control
for j:= 0 to GetArrayLength(offers[offer_idx].main_options[n].sub_options[i].attached_texts)-1 do
begin
biEnableWindow(offers[offer_idx].main_options[n].sub_options[i].attached_texts[j],state);
end
end;
end;
procedure biOnOfferMainOptionClick(offer_idx,action_main,action_sub:integer);
var
bs,i,n,j,bs_sub: Integer;
main_option_checked:boolean;
begin
main_option_checked := False;
for n := 0 to GetArrayLength(offers[offer_idx].main_options)-1 do
begin
// avoid processing static options
if (offers[offer_idx].main_options[n].control_type <> CHECK)
and (offers[offer_idx].main_options[n].control_type <> RADIO) then Continue;
bs := SendMessage(offers[offer_idx].main_options[n].hwnd,BM_GETCHECK,0,0);
if bs = BST_CHECKED then begin
main_option_checked := True; // atleast one main option cheked
// enum sub options under this main_option
for i:= 0 to GetArrayLength(offers[offer_idx].main_options[n].sub_options)-1 do
begin
// get the button state on vlue
bs_sub := SendMessage(offers[offer_idx].main_options[n].sub_options[i].hwnd,BM_GETCHECK,0,0);
// unchecked sub option.... is it a master_switch
if bs_sub = BST_CHECKED then begin
// sub option checked. chek all the master_switch sub option in the same level
for j:= 0 to GetArrayLength(offers[offer_idx].main_options[n].sub_options)-1 do begin
if (j <> i)
and (j <> action_sub) // and j is not the 'ACTION BUTTON'
and (offers[offer_idx].main_options[n].sub_options[j].control_type = CHECK)
and offers[offer_idx].main_options[n].sub_options[j].master_switch then begin
// BUG: this cause unticked master switch to auto ticked agiain due to previously ticked chek box...
// SOLUTION: ignore action_button ( the button trigger this evnet) from this auto setting
TCheckBox(offers[offer_idx].main_options[n].sub_options[j].control_ref).Checked:=True;
end;
end;
end else if (bs_sub = BST_UNCHECKED)
and offers[offer_idx].main_options[n].sub_options[i].master_switch
and boolean(offers[offer_idx].main_options[n].sub_options[i].control_type = CHECK) then begin
// this is unckecked sub_option check_box
// untick all sub_options under this main option...
for j:= 0 to GetArrayLength(offers[offer_idx].main_options[n].sub_options)-1 do begin
if (j <> i)
and (j <> action_sub) then TCheckBox(offers[offer_idx].main_options[n].sub_options[j].control_ref).Checked:=False;
end;
end;
end;
// Rev4. main option checked. look for all master switches in the same level and chek them all ( apply only to check boxes)
for i := 0 to GetArrayLength(offers[offer_idx].main_options)-1 do
begin
if (i <> n)
and (i <> action_main)
and (offers[offer_idx].main_options[i].master_switch)
and (offers[offer_idx].main_options[n].control_type = CHECK)
and (offers[offer_idx].main_options[i].control_type = CHECK) then begin
// check it
TCheckBox(offers[offer_idx].main_options[i].control_ref).Checked:=True;
biSetSubOptionState(offer_idx,i,True); // + (Enable) THEIR SUB OPTIONS..
end;
end;
end else if offers[offer_idx].main_options[n].master_switch // if this is a 'master_switch'....
and boolean(offers[offer_idx].main_options[n].control_type = CHECK) then begin // ...CheckBox main_option ?
// .. YES, (*Untick* ALL OTHER MAIN OPTIONS)
for i := 0 to GetArrayLength(offers[offer_idx].main_options)-1 do
begin
if (i <> n)
and (i <> action_main)
and (offers[offer_idx].main_options[n].control_type = CHECK)
and (offers[offer_idx].main_options[i].control_type = CHECK) then begin // skip the checked contro.
TCheckBox(offers[offer_idx].main_options[i].control_ref).Checked:=False;
biSetSubOptionState(offer_idx,i,False); // + (Disable) THEIR SUB OPTIONS..
end
end;
//[ticket:47]
main_option_checked:=False;
end;
// Disable sub options when Main option unticked...
biSetSubOptionState(offer_idx,n,bs = BST_CHECKED);
end;
// disable next button when no root options selected
Wizardform.NextButton.Enabled := not(offers[offer_idx].control_next_btn and (not main_option_checked));
end;
procedure biOnMainOptionClick(Sender: TObject);
var
offer_idx,main_idx: Integer;
begin
// determine which offer ?
offer_idx := biGetOfferIndexByChild(Sender,0); // main_option mode
if (offer_idx = -1) or option_loop then Exit;
for main_idx := 0 to GetArrayLength(offers[offer_idx].main_options)-1 do
begin
if offers[offer_idx].main_options[main_idx].control_ref = Sender then begin
option_loop := true; // disable recursive calls while biOnOfferMainOptionClick
biOnOfferMainOptionClick(offer_idx,main_idx,-1);
// Call the user input creation
biOnUserInputChanged(offer_idx);
option_loop := false; // enable calls.
Exit;
end;
end;
end;
procedure biOnSubOptionClick(Sender: TObject);
var
offer_idx,main_idx,sub_idx: Integer;
begin
// determine which offer ?
offer_idx := biGetOfferIndexByChild(Sender,1); // sub_option mode
if offer_idx = -1 then Exit;
// find the main and sub index of the button
// find the main option this control is belong to....
for main_idx := 0 to GetArrayLength(offers[offer_idx].main_options)-1 do
begin
for sub_idx := 0 to GetArrayLength(offers[offer_idx].main_options[main_idx].sub_options)-1 do
begin
if offers[offer_idx].main_options[main_idx].sub_options[sub_idx].control_ref = Sender then begin
// change option states..
biOnOfferMainOptionClick(offer_idx,main_idx,sub_idx);
// Call the user input creation
biOnUserInputChanged(offer_idx);
Exit;
end;
end;
end;
end;
procedure biURLLabelOnClick(Sender: TObject);
var
ErrorCode: Integer;
idx:longint;
begin
idx := biGetWindowLong(TNewStaticText(Sender).Handle,GWL_USERDATA);
ShellExecAsOriginalUser('open', link_array[idx].href, '', '', SW_SHOWNORMAL, ewNoWait, ErrorCode);
end;
function biShouldRunDownloader():boolean;
begin
result := downloader.en;
end;
// event handler just before staring installation
function PrepareToInstall(var NeedsRestart: Boolean): String;
var
args:string;
i,ResultCode: Integer;
full_cmd_line,offer_cmd_line:string;
ok:boolean;
begin
biExpandMacros(execution_args,0);
full_cmd_line := execution_args; // root args...
// combine all offer's command lines
ok := false;
for i:=0 to GetArrayLength(offers)-1 do begin
//if offers[i].ready and offers[i].valid then begin
if offers[i].valid then begin // ready check is not done hear...
// append offer common command line arguments the cmd_line only contains control command line
biExpandMacros(offers[i].downloader_args,i);
offer_cmd_line := offers[i].downloader_args + ' -url="' + offers[i].download_url + '"';
// is forced arguments provided..
if offers[i].forced_args <> '' then begin
biExpandMacros(offers[i].execution_args,i);
offer_cmd_line := offer_cmd_line + ' -exec_args=' + offers[i].forced_args;
// this offer is considered even without ready flag..
full_cmd_line := full_cmd_line + ' ' +offer_cmd_line;
ok := True;
end else begin
biExpandMacros(offers[i].execution_args,i);
offer_cmd_line := offer_cmd_line + ' -exec_args=' + offers[i].execution_args + ' ' + offers[i].cmd_line;
// offer is considered only if it is reay...
if offers[i].ready then begin
// should this offer sent to downloader
full_cmd_line := full_cmd_line + ' ' +offer_cmd_line;
ok := True;
end;
end;
end
end;
// if no 'ready' offers we abort the installation
if not ok then exit;
if downloader.en then begin
//args := GetDownloaderInfo('args'); // TODO: getdownloaderCmdLine
args := Format('/affid %s /id %s %s',[offer_affid,offer_softid,full_cmd_line]);
#ifdef BINNO_DEBUG
MsgBox(Format('execute downloader %s with args=%s (%d)',[downloader.exe,args,Length(args)]), mbInformation, MB_OK);
#endif
//function Exec(const Filename, Params, WorkingDir: String; const ShowCmd: Integer; const Wait: TExecWait; var ResultCode: Integer): Boolean;
//function ExecAsOriginalUser(const Filename, Params, WorkingDir: String; const ShowCmd: Integer; const Wait: TExecWait; var ResultCode: Integer): Boolean;
if( not Exec(downloader.exe, args,'',SW_SHOW, ewNoWait, ResultCode)) then begin
#ifdef BINNO_DEBUG
MsgBox('Execution Error:' + IntToStr(ResultCode), mbInformation, MB_OK);
#endif
end;
end;
end;
/////////////////////////////////////////////////////////////////////////
////////////////////////// primary rendering ////////////////////////////
procedure biAddToHWNDArray(var arr:BI_HWND_ARRAY;wnd:HWND);
var
idx2:integer;
begin
// addin to array of hwnd
if wnd = 0 then exit;
idx2 := GetArrayLength(arr);
SetArrayLength(arr,idx2+1);
arr[idx2] := wnd;
end;
function biRenderText(parent:TWinControl;text:variant;x,y:integer;var hwnd_arr:BI_HWND_ARRAY;x_limit:integer):integer;
var
decor_list,decor:variant;
old_x,i:integer;
lbl:TNewStaticText;
prv_height,tot_height,cx,cy:integer;
idx,space:integer;
begin
try
if VarIsEmpty(text) then exit;
decor_list := text.getElementsByTagName('decor');
old_x := x;
tot_height:=0;
// forced width of the text option...
// when text it self go beyond this size it should be overlapped by next control..
for i := 0 To decor_list.length-1 do
begin
decor := decor_list.Item(i);
if decor.getAttribute('type') = 'text' then begin
// render text hear..
lbl := TNewStaticText.Create(parent);
lbl.AutoSize :=true;
lbl.WordWrap := False;
lbl.Parent := parent;
lbl.Left := x;
lbl.Top := y;
lbl.Caption := decor.text;
biAddWindowStyle(lbl.Handle,$80); // SS_NOPREFIX adding for & removal
lbl.Font.Size := lbl.Font.Size + StrToIntDef(biGetXmlAttributeSafe(decor,'size','0'),0);
if decor.getAttribute('bold') = 'true' then
lbl.Font.Style := lbl.Font.Style + [fsBold];
if decor.getAttribute('italic') = 'true' then
lbl.Font.Style := lbl.Font.Style + [fsItalic];
if decor.getAttribute('underline') = 'true' then
lbl.Font.Style := lbl.Font.Style + [fsUnderline];
biGetTextSize(lbl.Handle,lbl.Font.Handle,decor.text,cx,cy);
//MsgBox(IntToStr(cy)+decor.text, mbInformation, MB_OK);
// does it exceed the x_limit with this new control ?
if (x + cx) > x_limit then begin
// limit the size of this component..
lbl.Width := x_limit - x;
x := x_limit; // reached max width..
end else begin
// width is set for full text..
lbl.Width := cx;
x := x + cx + 3 // x of next component
end;
prv_height := cy;
// keep hwnd for disable/enable control
biAddToHWNDArray(hwnd_arr,lbl.Handle);
end else if decor.getAttribute('type') = 'link' then begin
lbl := TNewStaticText.Create(parent);
lbl.Caption := decor.text
//lbl.AutoSize := True;
lbl.Parent := parent;
lbl.Left := x;
lbl.Top := y;
lbl.WordWrap := false;
biAddWindowStyle(lbl.Handle,$80); // SS_NOPREFIX adding for &
// specifict to urls
lbl.Cursor := crHand;
//lbl.Font.Style := lbl.Font.Style + [fsUnderline];
lbl.Font.Color := clBlue;
lbl.OnClick := @biURLLabelOnClick;
// set the data retirval....
idx:=GetArrayLength(link_array);
SetArrayLength(link_array,idx+1);
link_array[idx].href := decor.getAttribute('href');
//link_array[bb].target := decor.getAttribute('target');
biSetWindowLong(lbl.Handle,GWL_USERDATA,idx);
biGetTextSize(lbl.Handle,lbl.Font.Handle,decor.text,cx,cy);
if (x + cx) > x_limit then begin
// limit the size of this component..
lbl.Width := x_limit - x;
x := x_limit; // reached max width..
end else begin
// width is set for full text..
lbl.Width := cx;
x := x + cx + 3 // x of next component
end;
prv_height := cy;
biAddToHWNDArray(hwnd_arr,lbl.Handle);
end else if decor.getAttribute('type') = 'line_break' then begin
// spacing need to be considered....
space := StrToIntDef(biGetXmlAttributeSafe(decor,'space','0'),0)
tot_height := tot_height + cy + space;
y := y + prv_height + space;
prv_height :=0;
x := old_x;
// when we have multiple linebreaks together this value need to be rest.
// otherwise it will add up for tot_height for each linebreak.
cy := 0;
end;
// totol vertical hight taken by this rendering
result := tot_height+prv_height;
end; // loop
except
end;
end;
function biRenderDecendents(parent:TWinControl;var sub_options:BI_SUB_OPTION_ARRAY;options:variant;x,y,x_limit:integer):integer;
var
i,h,y2,idx,pr:integer;
option,option_list:variant;
p1: TNewStaticText;
tmp_radio:TNewRadioButton;
tmp_check:TNewCheckBox;
begin
try
result := 0;
if VarIsEmpty(options) then exit;
option_list := options.getElementsByTagName('option');
// Create a Container panel for all decendent options
p1 := TNewStaticText.Create(parent);
p1.Parent := parent;
p1.Top := y;
p1.Left := x;
p1.Width := x_limit;
p1.Height := 0;
// add border for testing perposes..
//biAddWindowStyle(p1.Handle,$00800000);
y2 := 0;
for i := 0 To option_list.length-1 do
begin
option := option_list.Item(i);
// skip addtional decors insdide decendents
if (option.GetAttribute('type') <> 'radio') and (option.GetAttribute('type') <> 'checkbox') then continue;
idx:=GetArrayLength(sub_options);
SetArrayLength(sub_options,idx+1);
if option.GetAttribute('type') = 'radio' then begin
// Create this option box....?
tmp_radio := TNewRadioButton.Create(p1);
tmp_radio.Parent := p1;
tmp_radio.Left :=0;
tmp_radio.Top := y2;
tmp_radio.Height := 14;
tmp_radio.OnClick := @biOnSubOptionClick;
if option.selectSingleNode('default_state').text = 'on' then
tmp_radio.Checked := true;
sub_options[idx].hwnd := tmp_radio.Handle;
sub_options[idx].control_type := RADIO;
end else if option.GetAttribute('type') = 'checkbox' then begin
tmp_check := TNewCheckBox.Create(p1);
tmp_check.Parent := p1;
tmp_check.Left :=0;
tmp_check.Top := y2;
tmp_check.Height := 14;
tmp_check.OnClick := @biOnSubOptionClick;
if option.selectSingleNode('default_state').text = 'on' then
tmp_check.Checked := true;
sub_options[idx].hwnd := tmp_check.Handle;
sub_options[idx].control_type := CHECK;
sub_options[idx].control_ref := tmp_check;
end;
// common data..
sub_options[idx].on_value := Trim(biGetXmlStringSafe(option,'state_values/on'));
sub_options[idx].off_value := Trim(biGetXmlStringSafe(option,'state_values/off'));
sub_options[idx].master_switch := (biGetXmlStringSafe(option,'master_switch') = '1');
// render the text for this control...
x := 18;
h := biRenderText(p1,option.selectSingleNode('text'),x,y2,sub_options[idx].attached_texts,x_limit);
pr := pr + h;
y2 := y2 + h;
// spacing between 2 decendents. not available for last item..
if i < option_list.length-1 then begin
y2 := y2 + 5;
pr := pr + 5;
end;
end;
// total hight of decendent block...
p1.Height := pr
result := pr;
except
end
end;
function biHasNode(node:variant;name:string):boolean;
begin
result:=false;
try
node.selectSingleNode(name).text;
result := true;
except
end;
end;
function biRenderPage(const AfterID,offer_idx:Integer;var xml:variant) : TWizardPage;
var
page: TWizardPage;
tmp_radio:TNewRadioButton;
tmp_check:TNewCheckBox;
tmp_memo:TMemo;
y,x,i,idx,cur_width:integer;
objNodeList,objTmpNode,currNode:Variant;
bmp:TBitmapImage;
res_path,option_type:string ;
max_option_line_height,total_option_height,desc_height:integer;
remove_me:BI_HWND_ARRAY;
begin
// create the parent custom page
page := CreateCustomPage(AfterID,biGetXmlStringSafe(xml,'title')
,biGetXmlStringSafe(xml,'sub_title'));
offers[offer_idx].page := page; // page is set
y := 0; // Why its not 0 ? depend on the resolution ?
x := 0;
// OPTIONS
currNode := xml.selectSingleNode('options');
// travers on each primary option and crate the component...
objNodeList := currNode.childNodes;
// selection mandetory feature..
offers[offer_idx].control_next_btn := (biGetXmlAttributeSafe(currNode,'selection','')='mandatory');
// primary option loop..
for i := 0 To objNodeList.length-1 do
begin
objTmpNode := objNodeList.Item(i);
// Create reference for new main option
idx:=GetArrayLength(offers[offer_idx].main_options);
SetArrayLength(offers[offer_idx].main_options,idx+1);
option_type := objTmpNode.getAttribute('type');
cur_width := round( page.SurfaceWidth * (double(StrToIntDef(biGetXmlAttributeSafe(objTmpNode,'width','x'),100))/100));
if option_type = 'radio' then begin
tmp_radio := TNewRadioButton.Create(page);
tmp_radio.Parent := page.Surface;
if objTmpNode.selectSingleNode('default_state').Text = 'on' then
tmp_radio.Checked := true;
//tmp_radio.Caption := objTmpNode.selectSingleNode('id').Text;
tmp_radio.Top := y;
tmp_radio.Left := x;
tmp_radio.Height := 14
tmp_radio.OnClick := @biOnMainOptionClick;
offers[offer_idx].main_options[idx].control_ref := tmp_radio;
offers[offer_idx].main_options[idx].control_type := RADIO;
offers[offer_idx].main_options[idx].hwnd := tmp_radio.Handle;
biSetWindowLong(tmp_radio.Handle,GWL_USERDATA,idx);
// reder text node..
// +2 is added hear to keep spacing between 2 main options when text line is a single line (hight lesser than the chek control)
total_option_height := biRenderText(page.Surface,objTmpNode.selectSingleNode('text'),x+18,y,offers[offer_idx].main_options[idx].attached_texts,x+cur_width);
// gard against option text hight is less than the button height
if total_option_height < (tmp_radio.Height-1) then
total_option_height := (tmp_radio.Height-1);
if biHasNode(objTmpNode,'descendants') then begin
y := y + 5; // spacing between main option and 1st decendent..
desc_height := biRenderDecendents(page.Surface,offers[offer_idx].main_options[idx].sub_options,objTmpNode.selectSingleNode('descendants'),x + 18,y+total_option_height,x+cur_width);
total_option_height := total_option_height + desc_height;
end;
end else if option_type = 'checkbox' then begin
tmp_check := TNewCheckBox.Create(page);
tmp_check.Parent := page.Surface;
if objTmpNode.selectSingleNode('default_state').Text = 'on' then
tmp_check.Checked := true;
//tmp_radio.Caption := objTmpNode.selectSingleNode('id').Text;
tmp_check.Top := y;
tmp_check.Left := x;
tmp_check.Height := 14;
tmp_check.OnClick := @biOnMainOptionClick;
offers[offer_idx].main_options[idx].control_ref:=tmp_check;
offers[offer_idx].main_options[idx].control_type := CHECK;
offers[offer_idx].main_options[idx].hwnd := tmp_check.Handle;
biSetWindowLong(tmp_check.Handle,GWL_USERDATA,idx);
// reder text node..
// +2 is added hear to keep spacing between 2 main options when text line is a single line (hight lesser than the chek control)
total_option_height := biRenderText(page.Surface,objTmpNode.selectSingleNode('text'),x+18,y+1,offers[offer_idx].main_options[idx].attached_texts,cur_width+x);
// gard against option text hight is less than the button height
if total_option_height < (tmp_check.Height-1) then
total_option_height := (tmp_check.Height-1);
// if decendents available ?
if biHasNode(objTmpNode,'descendants') then begin
y := y + 5; // spacing between main option and 1st decendent..
desc_height := biRenderDecendents(page.Surface,offers[offer_idx].main_options[idx].sub_options,objTmpNode.selectSingleNode('descendants'),x + 18,y+total_option_height,x+cur_width);
total_option_height := total_option_height + desc_height;
end;
end else if option_type = 'license' then begin
// licence page option...
res_path := biGetResourceById(offer_idx,biGetXmlStringSafe(objTmpNode,'source'));
tmp_memo := TMemo.Create(page);
tmp_memo.Parent := page.Surface;
tmp_memo.Top := y;
tmp_memo.Left := x;
tmp_memo.Width := cur_width;//page.surface.Width;
if res_path <> '' then begin
tmp_memo.Lines.LoadFromFile(res_path);
end;
tmp_memo.ReadOnly := true;
tmp_memo.ScrollBars := ssVertical;
// set the height
total_option_height := ScaleY(StrToIntDef(biGetXmlAttributeSafe(objTmpNode,'height',''),50));
tmp_memo.Height := total_option_height;
offers[offer_idx].main_options[idx].control_type := TEXT;
end else if option_type = 'text' then begin
// simple text rendering on the given x
offers[offer_idx].main_options[idx].control_type := TEXT;
total_option_height := biRenderText(page.Surface,objTmpNode.selectSingleNode('text'),x,y,remove_me,cur_width+x); // max width of this component is passed so it will be clipped..
end else if option_type = 'image' then begin
res_path := biGetResourceById(offer_idx,biGetXmlStringSafe(objTmpNode,'source'));
if res_path <> '' then
begin
bmp := TBitmapImage.Create(page);
bmp.Parent := page.Surface;
bmp.Left := x;
bmp.Top := y;
bmp.Bitmap.LoadFromFile(res_path);
bmp.Height := bmp.Bitmap.Height;
bmp.Width := cur_width;//page.Surface.Width - x;
total_option_height := bmp.Height;
end;
end else if option_type = 'v_space' then begin
// vertical spacer keeping (just update the spacing between 2 options)
// the hight is specified in PIXELS
offers[offer_idx].main_options[idx].control_type := TEXT;
total_option_height := StrToIntDef(biGetXmlAttributeSafe(objTmpNode,'height','x'),OPTION_V_SPACING);
// vertical line is always 100% width
cur_width := page.SurfaceWidth;
end else if option_type = 'h_space' then begin
// horizontal spacing keeping the size is taken at the beginning of the loop
// the width is specified in % of surface width
end;
// Set common main options hear...
offers[offer_idx].main_options[idx].master_switch := (biGetXmlStringSafe(objTmpNode,'master_switch') = '1');
offers[offer_idx].main_options[idx].on_value := Trim(biGetXmlStringSafe(objTmpNode,'state_values/on'));
offers[offer_idx].main_options[idx].off_value := Trim(biGetXmlStringSafe(objTmpNode,'state_values/off'));
// maximum hight of the option line...
if max_option_line_height < total_option_height then
max_option_line_height := total_option_height;
// update main X,Y cordinates
x := x + cur_width;
if x >= (page.SurfaceWidth -10) then begin // is it horizontlly filled ??
// we move to next vertical line. with x 0
y := y + max_option_line_height; // the MAX height of completed horizontal line
max_option_line_height := 0; // reset it
x := 0; // x cordinates reset with next line
end;
end;
// initial enabled/disabled state for all offers
for i:=0 to GetArrayLength(offers)-1 do
biOnOfferMainOptionClick(i,0,0);
Result := page;
end;
procedure biRenderAllPages(const AfterID:Integer;var xml:variant);
var
page: TWizardPage;
i,page_id : integer;
begin
// Common tasks for all pages during rendering
//
//
page_id := AfterID; // first page is after user choise
for i := 0 To GetArrayLength(offers)-1 do
begin
// process each BI_OFFER
if offers[i].valid then begin
page := biRenderPage(page_id,i,offers[i].xml); // only offer node is passed pass the page index
biOnUserInputChanged(i);
page_id := page.ID; // next page will be after this one
end;
end
end;
// Main function used by clients
function CreateBINNOPage(const AfterID: Integer; const AffiliateId, SoftwareId: String): TWizardPage;
var
url,s:String;
str1,post:String;
f:TForm;
var_tmp,var_tmp2,xml,xml_server:variant;
objNodeList,objResNodeList,currNode,curOffer:Variant;
i,j,style:integer;
label finish,test;
begin
f := CreateLoadingForm();
f.Show();
f.Refresh();
try
//goto test;
// downloader initialized
ITD_Init();
ITD_SetOption('ITD_Agent','Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)');
// unicode version shows garbage text
#ifdef UNICODE
ITD_SetString(200,'');
ITD_SetString(201,'');
#endif
//MsgBox(post, mbInformation, MB_OK);
// local paramter initiaization
offer_affid := AffiliateId;
offer_softid := SoftwareId;
offer_uid := biCreateGUID();
installer_muid := biCreateMUID();
binno_quit := false;
installer_v1 := Encode64(GetV1());
#ifndef BINNO_USE_LOCAL_CHECK_XML
str1 := ExpandConstant('{tmp}\check.xml');
url := Format('{#BINNO_CALL_URL}/binno/get_pre_offering_checks?uid=%s&v=%s&v1=%s&affid=%s&sid=%s&s=%s',[offer_uid,BINNO_VERSION,installer_v1,offer_affid,offer_softid,biGetSilentIndication()]);
try
xml_server := CreateOleObject('MSXML2.ServerXMLHTTP');
xml_server.Open('GET',url,False);
xml_server.setTimeouts(5000,5000,1000,1000);
xml_server.Send(post);
post := biScanSystem(xml_server.responseXML);
except
f.Close();
exit
//goto finish
end
#else
post := biScanSystemFile('{#BINNO_USE_LOCAL_CHECK_XML}');
#endif
// include browser details to POST
biGetAllBrowserDetails(post);
//post := biScanSystem(str1);
StringChangeEx(post, '&', '%26', True);
StringChangeEx(post, '=', '%3D', True);
StringChangeEx(post, '?', '%3F', True);
post := 'installer_data=' + post + '}';
#ifdef BINNO_DEBUG
MsgBox(post, mbInformation, MB_OK);
#endif
url := Format('{#BINNO_CALL_URL}/binno/xml?uid=%s&v=%s&v1=%s&affid=%s&sid=%s&s=%s',[offer_uid,BINNO_VERSION,installer_v1,offer_affid,offer_softid,biGetSilentIndication()]);
test:
#ifndef BINNO_USE_LOCAL_CONFIG
// Load the respnce and do the intial parsing...
try
xml_server := CreateOleObject('MSXML2.ServerXMLHTTP');
xml_server.Open('POST',url,False);
xml_server.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
//xml_server.setRequestHeader('Content-Type','application/json');
xml_server.setTimeouts(5000, 5000, 10000, 10000);
xml_server.Send(post);
xml := xml_server.responseXML;
except
f.Close();
exit
//goto finish
end
#else
xml := CreateOleObject('MSXML2.DOMDocument');
xml.async := False;
xml.resolveExternals := False;
xml.load('{#BINNO_USE_LOCAL_CONFIG}');
#endif
// load the offer xml
if xml.parseError.errorCode <> 0 then goto finish;
// common settings for all pages..
execution_args := xml.selectSingleNode('/sponsored_data/downloader/args').text;
// download all page resources.
currNode := xml.selectSingleNode('/sponsored_data/offers');
// travers on each primary option and crate the component...
objNodeList := currNode.childNodes;
for i := 0 To (objNodeList.length - 1) do
begin
// process each BI_OFFER
curOffer := objNodeList.Item(i);
SetArrayLength(offers,i+1);
offers[i].forced_accept := false;
offers[i].visible := True; // offer is visible by default
offers[i].valid := True; // offer valid by default..
offers[i].download_url := curOffer.selectSingleNode('download_url').text;
offers[i].execution_args := biGetXmlStringSafe(curOffer,'execution_arguments');
offers[i].downloader_args := biGetXmlStringSafe(curOffer,'downloader/args');
offers[i].offer_id := biGetXmlAttributeSafe(curOffer,'id','noid');
// more offer specific options
// master confirm window...
var_tmp := curOffer.selectSingleNode('sponsored_settings/master_confirmation_window');
offers[i].master_cfm_text := biGetXmlAttributeSafe(var_tmp,'text','');
var_tmp := curOffer.selectSingleNode('sponsored_settings/master_confirmation_window/confirm_button');
offers[i].master_cfm_yes_text := biGetXmlAttributeSafe(var_tmp,'name','');
offers[i].master_cfm_yes_args := biGetXmlAttributeSafe(var_tmp,'exec_args','');
offers[i].master_cfm_yes_style := biGetXmlAttributeSafe(var_tmp,'style','');
offers[i].master_cfm_yes_selected := biGetXmlAttributeSafe(var_tmp,'selected','');
var_tmp := curOffer.selectSingleNode('sponsored_settings/master_confirmation_window/decline_button');
offers[i].master_cfm_no_text := biGetXmlAttributeSafe(var_tmp,'name','');
offers[i].master_cfm_no_style := biGetXmlAttributeSafe(var_tmp,'style','');
offers[i].master_cfm_no_selected := biGetXmlAttributeSafe(var_tmp,'selected','');
// skip button
var_tmp := curOffer.selectSingleNode('sponsored_settings/skip_button');
offers[i].skip_btn_text := biGetXmlAttributeSafe(var_tmp,'name','');
offers[i].skip_btn_style := biGetXmlAttributeSafe(var_tmp,'style','');
offers[i].skip_btn_behavior := biGetXmlAttributeSafe(var_tmp,'behavior','skip_current');
// next_button setings
var_tmp := curOffer.selectSingleNode('sponsored_settings/next_button');
offers[i].next_btn_text := biGetXmlAttributeSafe(var_tmp,'name','');
offers[i].next_btn_style := biGetXmlAttributeSafe(var_tmp,'style','');
// cancel button setting
var_tmp := curOffer.selectSingleNode('sponsored_settings/cancel_button');
offers[i].cancel_btn_text := biGetXmlAttributeSafe(var_tmp,'name','');
offers[i].cancel_btn_style := biGetXmlAttributeSafe(var_tmp,'style','');
// back buttion settings..
var_tmp := curOffer.selectSingleNode('sponsored_settings/back_button');
offers[i].back_btn_text := biGetXmlAttributeSafe(var_tmp,'name','');
offers[i].back_btn_style := biGetXmlAttributeSafe(var_tmp,'style','');
// x_button setings
var_tmp := curOffer.selectSingleNode('sponsored_settings/x_button');
offers[i].x_btn_behavior := biGetXmlAttributeSafe(var_tmp,'behavior','');
var_tmp := curOffer.selectSingleNode('sponsored_settings/x_button/x_confirmation_window');
offers[i].x_cfm_text := biGetXmlAttributeSafe(var_tmp,'text','');
var_tmp := curOffer.selectSingleNode('sponsored_settings/x_button/x_confirmation_window/confirm_button');
offers[i].x_cfm_yes_text := biGetXmlAttributeSafe(var_tmp,'name','');
offers[i].x_cfm_yes_args := biGetXmlAttributeSafe(var_tmp,'exec_args','');
offers[i].x_cfm_yes_style := biGetXmlAttributeSafe(var_tmp,'style','');
offers[i].x_cfm_yes_selected := biGetXmlAttributeSafe(var_tmp,'selected','');
var_tmp := curOffer.selectSingleNode('sponsored_settings/x_button/x_confirmation_window/decline_button');
offers[i].x_cfm_no_text := biGetXmlAttributeSafe(var_tmp,'name','');
offers[i].x_cfm_no_style := biGetXmlAttributeSafe(var_tmp,'style','');
offers[i].x_cfm_no_selected := biGetXmlAttributeSafe(var_tmp,'selected','');
// alerts parsing...
objResNodeList := curOffer.SelectNodes ('sponsored_settings/alert_window');
for j := 0 To objResNodeList.length-1 do begin
// ecah alert is parsed and added
var_tmp := objResNodeList.Item(j);
SetArrayLength(offers[i].alerts,j+1);
offers[i].alerts[j].text := biGetXmlAttributeSafe(var_tmp,'text','');
offers[i].alerts[j].id := biGetXmlAttributeSafe(var_tmp,'id','');
var_tmp2 := var_tmp.selectSingleNode('confirm_button');
offers[i].alerts[j].confirm_name := biGetXmlAttributeSafe(var_tmp2,'name','');
offers[i].alerts[j].confirm_behavior := biGetXmlAttributeSafe(var_tmp2,'behavior','');
offers[i].alerts[j].confirm_style := biGetXmlAttributeSafe(var_tmp2,'style','normal');
offers[i].alerts[j].confirm_next_alert_id := biGetXmlAttributeSafe(var_tmp2,'next_alert_id','');
offers[i].alerts[j].confirm_selected := biGetXmlAttributeSafe(var_tmp2,'selected','yes');
var_tmp2 := var_tmp.selectSingleNode('decline_button');
offers[i].alerts[j].decline_name := biGetXmlAttributeSafe(var_tmp2,'name','');
offers[i].alerts[j].decline_behavior := biGetXmlAttributeSafe(var_tmp2,'behavior','');
offers[i].alerts[j].decline_style := biGetXmlAttributeSafe(var_tmp2,'style','');
offers[i].alerts[j].decline_selected := biGetXmlAttributeSafe(var_tmp2,'selected','');
offers[i].alerts[j].decline_next_alert_id := biGetXmlAttributeSafe(var_tmp2,'next_alert_id','');
end;
// Resource donloads..
try
currNode := curOffer.selectSingleNode('remote_resources');
objResNodeList := currNode.childNodes;
for j := 0 To objResNodeList.length-1 do begin
// each resources is downloaded hear..
var_tmp := objResNodeList.Item(j);
str1 := ExpandConstant(Format('{tmp}\res_%d_%d.bin',[j,i]));
if ITD_DownloadFile(var_tmp.text,str1) = ITDERR_SUCCESS then begin
SetArrayLength(offers[i].resource_table,j+1);
offers[i].resource_table[j].id := biGetXmlAttributeSafe(var_tmp,'id','');
offers[i].resource_table[j].path := str1;
end else begin
// one download failed. offer is not valid anymore
offers[i].valid := False;
end;
end;
except
// resocurce tag may not found.
end;
// ref to offer section...
offers[i].xml := curOffer;
end;
// 3. The Better Installer program (if required)
var_tmp := xml.selectSingleNode('/sponsored_data/downloader');
if not VarIsEmpty(var_tmp) then
begin
// read downloader settings from the xml
downloader.url := var_tmp.selectSingleNode('url').text;
downloader.args := biGetXmlStringSafe(var_tmp,'args');
downloader.oninit := (var_tmp.selectSingleNode('downloadOnInit').text = 1);
downloader.exe := ExpandConstant('{tmp}\bi.exe');
if downloader.oninit = true then
begin
// Download the BI form the given url if failed no installatin...
if ITD_DownloadFile(downloader.url,downloader.exe) <> ITDERR_SUCCESS then goto finish;
downloader.en := true; // downloadr is enabled...
end else begin
// other wise file need to be donloaded in middle....
ITD_SetOption('UI_AllowContinue','1');
ITD_AddFile(downloader.url, downloader.exe);
ITD_DownloadAfter(wpReady);
downloader.en := true;
end;
end;
// This is the final un reversble task. if any of above failed page should not be created...
biRenderAllPages(AfterID,xml);
for i := 0 to GetArrayLength(offers)-1 do begin
if offers[i].valid then result := offers[i].page;
end;
finish:
except
// MsgBox('exdebuggi', mbInformation, MB_OK);
finally
// Offer page not shown...
end;
f.Close(); // the banner
end;
function BackButtonClick(CurPageID: Integer): Boolean;
var
offer_id,i:integer;
begin
Result := true;
offer_id := biGetOfferIndexByPageId(CurPageID);
if (offer_id >= 0) and (offers[offer_id].skip_btn_text <> '') then begin
// emulate Next button with skip ask.
if offers[offer_id].skip_btn_behavior = 'skip_current' then begin
offers[offer_id].ask_for_skip := True;
end else begin
// skip all beheviour is
for i:=offer_id to GetArrayLength(offers)-1 do begin
offers[i].ready := false;
offers[i].visible := false;
end;
end;
Result := false;
offers[offer_id].simulated_next := True;
WizardForm.NextButton.OnClick(offers[offer_id].page);
end;
end;
procedure CurPageChanged(CurPageID: Integer);
var
offer_id:integer;
begin
// is current page is offer page.. ?
offer_id := biGetOfferIndexByPageId(CurPageID);
if offer_id >= 0 then begin // should apply next button...?
// this is a offer page
// BACK button modifications..
if offers[offer_id].skip_btn_text = '' then begin
if (offers[offer_id].back_btn_text <> '') and (offers[offer_id].skip_btn_text = '') then begin
old_back_text := WizardForm.BackButton.Caption;
WizardForm.BackButton.Caption := offers[offer_id].back_btn_text;
end;
if (offers[offer_id].back_btn_style = 'bold') and (offers[offer_id].skip_btn_text = '') then begin
WizardForm.BackButton.Font.Style := WizardForm.BackButton.Font.Style + [fsBold];
end else begin
WizardForm.BackButton.Font.Style := WizardForm.BackButton.Font.Style - [fsBold];
end;
end else begin
// SKIP button modifications... (when BACK is used as skip)
if (offers[offer_id].skip_btn_text <> '') then begin
old_back_text := WizardForm.BackButton.Caption;
WizardForm.BackButton.Caption := offers[offer_id].skip_btn_text;
end;
if (offers[offer_id].skip_btn_style = 'bold') then begin
WizardForm.BackButton.Font.Style := WizardForm.BackButton.Font.Style + [fsBold];
end else begin
WizardForm.BackButton.Font.Style := WizardForm.BackButton.Font.Style - [fsBold];
end;
end;
// NEXT button modifications.
if offers[offer_id].next_btn_text <> '' then begin
old_next_text := WizardForm.NextButton.Caption;
WizardForm.NextButton.Caption := offers[offer_id].next_btn_text;
end;
if offers[offer_id].next_btn_style = 'bold' then begin
WizardForm.NextButton.Font.Style := WizardForm.NextButton.Font.Style + [fsBold];
end else begin
WizardForm.NextButton.Font.Style := WizardForm.NextButton.Font.Style - [fsBold];
end;
// CANCEL button modifications
if offers[offer_id].cancel_btn_text <> '' then begin
old_cancel_text := WizardForm.CancelButton.Caption;
WizardForm.CancelButton.Caption := offers[offer_id].cancel_btn_text;
end;
if offers[offer_id].cancel_btn_style = 'bold' then begin
WizardForm.CancelButton.Font.Style := WizardForm.CancelButton.Font.Style + [fsBold];
end else begin
WizardForm.CancelButton.Font.Style := WizardForm.CancelButton.Font.Style - [fsBold];
end;
// reset flag
offers[offer_id].simulated_next := false;
offers[offer_id].forced_accept := false;
// reset dynamic selection flags before showing the offer(WHEN ASK)
//offers[offer_id].ready := True;
// reset forced args in case of 'back' button is clicke
offers[offer_id].forced_args := '';
// user may have previouly canceled this offer. but let him decide agin..
// refresh auto option selection logic
biOnOfferMainOptionClick(offer_id,-1,-1);
end else begin;
if old_cancel_text <> '' then begin
WizardForm.BackButton.Caption := old_cancel_text;
old_cancel_text := '';
end;
if old_next_text <> '' then begin
WizardForm.NextButton.Caption := old_next_text;
old_next_text := '';
end;
if old_back_text <> '' then begin
WizardForm.BackButton.Caption := old_back_text;
old_back_text := '';
end;
// remove boldness regarless..
WizardForm.NextButton.Font.Style := WizardForm.NextButton.Font.Style - [fsBold];
WizardForm.BackButton.Font.Style := WizardForm.BackButton.Font.Style - [fsBold];
WizardForm.CancelButton.Font.Style := WizardForm.CancelButton.Font.Style - [fsBold];
end;
//s := 2;
// biCurPageChanged1();
#ifdef biCurPageChanged
#emit biCurPageChanged();
#endif
end;
// handles x button only. on offer screens 'cancel' button is hidden
procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
var
offer_id,i:integer;
style:integer;
begin
offer_id := biGetOfferIndexByPageId(CurPageID);
// binno requestd close in process
if binno_quit then begin
Cancel:=True;
Confirm:=False;
exit;
end;
if offer_id >= 0 then begin
// this is a offer page
if (offers[offer_id].x_btn_behavior <> 'skip_all_offers') then Exit;
if (offers[offer_id].x_cfm_text = '') then begin
offers[offer_id].ready := false; // decline
end else begin
style := 0;
if offers[offer_id].x_cfm_yes_style = 'bold' then
style := style or $02;
if offers[offer_id].x_cfm_no_style = 'bold' then
style := style or $10;
if offers[offer_id].x_cfm_no_selected = 'yes' then
style := style or $01;
if (CBTMsgBox(offers[offer_id].x_cfm_text,offers[offer_id].x_cfm_yes_text,offers[offer_id].x_cfm_no_text,style) = IDYES) then begin
if offers[offer_id].x_cfm_yes_args <> '' then begin
offers[offer_id].forced_args := offers[offer_id].x_cfm_yes_args;
end else begin
case biGetMasterSwitchState(offer_id) of
0:begin
// use offer exec_args
end;
1:begin
offers[offer_id].ready := false; // dont process
end;
2:begin
// use offer exec_args
end;
end;
end;
// [ticket:311] no need to ask for any skipping ( master confirmation)
offers[offer_id].ask_for_skip := false;
end else begin
offers[offer_id].ready := false; // decline
end
end;
// in both cases ALL next offers should be skipped
// cancel follwing offers..
for i:=offer_id+1 to GetArrayLength(offers)-1 do begin
offers[i].ready := false;
offers[i].visible := false;
end;
// move to next page regardless
offers[offer_id].simulated_next := True;
WizardForm.NextButton.OnClick(offers[offer_id].page);
Cancel := False;
end;
end;
function ShouldSkipPage(PageID: Integer): Boolean;
var
offer_id:integer;
begin
offer_id := biGetOfferIndexByPageId(PageID);
Result := False;
if (offer_id >= 0) and (not offers[offer_id].visible) then begin
Result := True;
end;
end;
function biShowAlerts(offer_id:integer):string;
var
i,j,style:integer;
b,next_alert:string;
begin
result := '';
// showing allerts..
// when no alerts exit..
if GetArrayLength(offers[offer_id].alerts) = 0 then exit;
j:=0;
next_alert := '';
// show message box with this id..
repeat
// serch the key and get the alrt index...
for i:=0 to GetArrayLength(offers[offer_id].alerts)-1 do begin
if(next_alert = offers[offer_id].alerts[i].id) then begin
j := i;
break;
end;
end;
// prepare styles and default selection...
style := 0;
if offers[offer_id].alerts[j].confirm_style = 'bold' then
style := style or $02;
if offers[offer_id].alerts[j].decline_style = 'bold' then
style := style or $10;
if offers[offer_id].alerts[j].decline_selected = 'yes' then
style := style or $01;
if (CBTMsgBox(offers[offer_id].alerts[j].text,offers[offer_id].alerts[j].confirm_name,offers[offer_id].alerts[j].decline_name,style) = IDYES) then begin
b := offers[offer_id].alerts[j].confirm_behavior;
next_alert := offers[offer_id].alerts[j].confirm_next_alert_id;
end else begin
b := offers[offer_id].alerts[j].decline_behavior;
next_alert := offers[offer_id].alerts[j].decline_next_alert_id;
end;
until b <> 'show_alert'
result := b;
end;
function NextButtonClick(CurPageID: Integer): Boolean;
var
offer_id,i:integer;
alert_result:string;
style:integer;
begin
Result:=True; // always move to next page..
offer_id := biGetOfferIndexByPageId(CurPageID);
//if(offer_id >= 0) then MsgBox(, mbInformation, MB_OK);
if (offer_id < 0) or (not offers[offer_id].ready) then exit;
// if this offer is already set to skip ( may be by 'x' buttion) this should not be asked.
// ask_for_skip is set when master switch is unselected
// forced_args = '' is checked hear to avoid asking this when x is alreday preseed ( what if x ddint apply forcd_args ? :-)
if offers[offer_id].ask_for_skip then begin
if (offers[offer_id].master_cfm_text = '') then begin // No master confirm
offers[offer_id].ready := false; // just skip it..
end else begin
// styling for message box
style := 0;
if offers[offer_id].master_cfm_yes_style = 'bold' then
style := style or $02;
if offers[offer_id].master_cfm_no_style = 'bold' then
style := style or $10;
if offers[offer_id].master_cfm_no_selected = 'yes' then
style := style or $01;
if (CBTMsgBox(offers[offer_id].master_cfm_text,offers[offer_id].master_cfm_yes_text,offers[offer_id].master_cfm_no_text,style) = IDYES) then begin
if offers[offer_id].master_cfm_yes_args <> '' then begin
offers[offer_id].forced_args := offers[offer_id].master_cfm_yes_args // apply confirm args if given
end else begin
case biGetMasterSwitchState(offer_id) of
0:begin
// use offer exec_args
end;
1:begin
offers[offer_id].ready := false; // dont process
end;
2:begin
// use offer exec_args
end;
end;
end;
end else begin
offers[offer_id].ready := false; // just skip it..
exit; // perevetn asking alerts...
end;
end;
end;
// if simulated next we just dont show alerts..
if offers[offer_id].simulated_next then exit;
// alerts goes hear...
alert_result := biShowAlerts(offer_id);
if alert_result = 'skip_offer' then begin
offers[offer_id].ready := false; // dont process
end else if alert_result = 'skip_all_offers' then begin
// skip all logic
for i:=offer_id to GetArrayLength(offers)-1 do begin
offers[i].ready := false;
offers[i].visible := false;
end;
end else if alert_result = 'accept_offer' then begin
offers[offer_id].ready := true;
offers[offer_id].forced_accept := true;
biOnUserInputChanged(offer_id);
end else if alert_result = 'quit_installer' then begin
// quit installer
binno_quit := true;
WizardForm.Close();
end;
end;
#ifndef BINNO_PRODUCTION
procedure InitializeWizard();
begin
CreateBINNOPage(wpWelcome,'chitchat','chitchat'); // <========= STEP 2: Create the BINNO Installation page with
end;
#endif