; 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