2452 lines
78 KiB
Plaintext
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
|
|
|
|
|
|
|
|
|
|
|
|
|