project64/Source/Installer/binno/utility.iss

772 lines
18 KiB
Plaintext

// ;#define UNIT_TEST
#ifdef UNIT_TEST
[Setup]
AppName=My Program
AppVersion=1.5
CreateAppDir=no
PrivilegesRequired=admin
#endif
[Code]
const
HANDLE_FLAG_INHERIT=$00000001;
HANDLE_FLAG_PROTECT_FROM_CLOSE=$00000002;
STARTF_USESTDHANDLES=$00000100;
STARTF_USESHOWWINDOW=$00000001;
INFINITE=$FFFFFFFF;
NORMAL_PRIORITY_CLASS=$00000020;
type
BI_IP_ADDRESS_STRING = record
String:array[0..16] of byte;
end;
BI_IP_ADDR_STRING = record
Next:LongWord;
IpAddress:BI_IP_ADDRESS_STRING;
IpMask:BI_IP_ADDRESS_STRING;
Context:LongWord;
end;
BI_RESOURCE = record
id:string;
path:string;
end;
BI_IP_ADAPTER_INFO = record
Next:LongWord;
ComboIndex:LongWord;
AdapterName:array[1..260] of byte;
Description:array[1..132] of byte;
AddressLength:integer;
Address:array[0..7] of byte;
Index:LongWord;
_Type:LongWord;
DhcpEnabled:LongWord;
CurrentIpAddress:LongWord;
IpAddressList:BI_IP_ADDR_STRING;
GatewayList:BI_IP_ADDR_STRING;
DhcpServer:BI_IP_ADDR_STRING;
HaveWins:LongWord;
PrimaryWinsServer:BI_IP_ADDR_STRING;
SecondaryWinsServer:BI_IP_ADDR_STRING;
LeaseObtained:array[0..8]of byte;
LeaseExpires:array[0..8] of byte;
end;
SECURITY_ATTRIBUTES = record
nLength:DWORD;
lpSecurityDescriptor:LongInt;
bInheritHandle:LongInt;
end;
boola = array[0..10] of BI_IP_ADAPTER_INFO;
HANDLE = LongInt;
LPSTR = LongInt;
LPBYTE = LongInt;
PROCESS_INFORMATION = record
hProcess:HANDLE;
hThread:HANDLE;
dwProcessId:DWORD;
dwThreadId:DWORD;
end;
STARTUPINFO = record
cb:DWORD ;
lpReserved:LPSTR ;
lpDesktop:LPSTR ;
lpTitle:LPSTR ;
dwX:DWORD ;
dwY:DWORD ;
dwXSize:DWORD ;
dwYSize:DWORD ;
dwXCountChars:DWORD ;
dwYCountChars:DWORD ;
dwFillAttribute:DWORD ;
dwFlags:DWORD ;
wShowWindow:WORD ;
cbReserved2:WORD ;
lpReserved2:LPBYTE ;
hStdInput:HANDLE ;
hStdOutput:HANDLE ;
hStdError:HANDLE ;
end;
var
p:boola;
function biCreatePipe(var rd,wr:HANDLE;var sa:SECURITY_ATTRIBUTES;nSize:DWORD):integer;
external 'CreatePipe@kernel32.dll stdcall';
function biSetHandleInformation(hObject:HANDLE;dwMask,dwFlags:DWORD):integer;
external 'SetHandleInformation@kernel32.dll stdcall';
function biCloseHandle(h:HANDLE):integer;
external 'CloseHandle@kernel32.dll stdcall';
function biCreateProcess(lpApplicationName:LongInt;lpCommandLine:AnsiString;lpProcessAttributes,lpThreadAttributes:LongInt;bInheritHandles:LongInt;dwCreationFlags:DWORD;lpEnvironment,lpCurrentDirectory:LongInt;var lpStartupInfo:STARTUPINFO;var lpProcessInformation:PROCESS_INFORMATION):integer;
external 'CreateProcessA@kernel32.dll stdcall';
function biWaitForSingleObject(h:HANDLE;dwMilliseconds:DWORD):DWORD;
external 'WaitForSingleObject@kernel32.dll stdcall';
function biReadFile(hFile:HANDLE;lpBuffer:AnsiString;nNumberOfBytesToRead:DWORD;var lpNumberOfBytesRead:DWORD;lpOverlapped:LongInt):integer;
external 'ReadFile@kernel32.dll stdcall';
function biGetAdaptersInfo(var ss:boola;var l:cardinal):integer;
external 'GetAdaptersInfo@Iphlpapi.dll stdcall';
function biGetAdaptersInfo2( ss:cardinal;var l:cardinal):integer;
external 'GetAdaptersInfo@Iphlpapi.dll stdcall';
function biPathIsDirectoryEmpty(lpString:AnsiString):boolean;
external 'PathIsDirectoryEmptyA@shlwapi.dll stdcall';
function biGetMAC():String;
var
l:cardinal;
s:String;
begin
l:=0;
biGetAdaptersInfo2(0,l);
biGetAdaptersInfo(p,l);
s := Format('%.2x%.2x%.2x%.2x%.2x%.2x',[p[0].Address[0],p[0].Address[1],p[0].Address[2],p[0].Address[3],p[0].Address[4],p[0].Address[5]]);
Result := s + s; // mac address concatenated
//end;
end;
const
CSIDL_PROGRAM_FILES = $0026;
Codes64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
function PathCombine2(src,more:string):string;
begin
Result:=AddBackSlash(src)+more;
end;
procedure biPathAppend(var Path:string;More:string);
begin
Path := PathCombine2(Path,More);
end;
function biIsWildcardPath(Path:string):boolean;
begin
Result := Pos('*',Path) <> 0;
end;
function biSplitRegistryKey(Key:String;var path:string):integer;
var
rk,p:Integer;
tmp:string;
begin
p := Pos('\',Key);
tmp := Copy(Key,0,p-1);
path := Copy(Key,p+1,Length(Key));
if CompareText(tmp,'HKCR') = 0 then begin
result := HKEY_CLASSES_ROOT;
end else if CompareText(tmp,'HKLM') = 0 then begin
result := HKEY_LOCAL_MACHINE;
end else if CompareText(tmp,'HKCC') = 0 then begin
result := HKEY_CURRENT_CONFIG;
end else if CompareText(tmp,'HKU') = 0 then begin
result := HKEY_USERS;
end else
result := HKEY_CURRENT_USER;
end;
function biSplitRegistryKeyNoWOW(Key:String;var path:string):integer;
var
rk,p:Integer;
tmp:string;
begin
p := Pos('\',Key);
tmp := Copy(Key,0,p-1);
path := Copy(Key,p+1,Length(Key));
if not IsWin64 then begin
if CompareText(tmp,'HKCR') = 0 then begin
result := HKEY_CLASSES_ROOT;
end else if CompareText(tmp,'HKLM') = 0 then begin
result := HKEY_LOCAL_MACHINE;
end else if CompareText(tmp,'HKCC') = 0 then begin
result := HKEY_CURRENT_CONFIG;
end else if CompareText(tmp,'HKU') = 0 then begin
result := HKEY_USERS;
end else
result := HKEY_CURRENT_USER;
end else begin
if CompareText(tmp,'HKCR') = 0 then begin
result := HKCR64;
end else if CompareText(tmp,'HKLM') = 0 then begin
result := HKLM64;
end else if CompareText(tmp,'HKCC') = 0 then begin
result := HKCC64;
end else if CompareText(tmp,'HKU') = 0 then begin
result := HKU64;
end else
result := HKCU64;
end;
end;
function biGetResourceByKey(key:string;var table:array of BI_RESOURCE):string;
var
i:integer;
begin
result := '';
// find the correct resouce for this id
for i := 0 to GetArrayLength(table)-1 do begin
if table[i].id = key then begin
result := table[i].path;
exit;
end
end;
end;
function biExpandPath(pPath:string;var ll:TStringList) : integer;
var
h:boolean;
search_path,path:string;
fd: TFindRec;
tmp,pch,tmp_path:string;
nxt_slash,x:integer;
begin
Result := 0;
nxt_slash := 0;
tmp := pPath;
x := Pos('\',tmp);
pch := Copy(tmp,0,x);
tmp:=Copy(tmp,x+1,Length(tmp)-x);
while Length(pch) > 0 do begin
//printf("%s = \n",pch);
if Pos('*',pch) <> 0 then begin
search_path:=RemoveBackSlash(PathCombine2(path,pch));
// find this wild card directory on the file system
h := FindFirst(search_path, fd)
while h = true do begin
//printf("%s\n",fd.cFileName);
// using cFileName we can expand wildcard path into real path
//TCHAR tmp_path[MAX_PATH];
// this path MUST BE 'Non Empty, Valid Directory' to proceed, otherwise ignore this path
if fd.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0 then begin
tmp_path:=PathCombine2(path,fd.Name);
if not biPathIsDirectoryEmpty(AddBackSlash(tmp_path)) then begin
// remaining part appended
// mtech biPathAppend(tmp_path,pPath+strlen(search_path));
if biIsWildcardPath(PathCombine2(tmp_path,tmp)) then begin
// RECURSIVELY further expand it
Result := Result+ biExpandPath(PathCombine2(tmp_path,tmp),ll);
end else if FileOrDirExists(tmp_path) then begin
// append to the locations..
ll.Add(tmp_path);
Result:=Result+1; // increment number of returns
end
end;
end;
// rest of the path is added at the end regarless of containment of *
h := FindNext(fd);
if not h then FindClose(fd);
end; // while
// do not process the loop further
break;
end else begin
biPathAppend(path,pch);
//printf("safe path: %s\n",path);
end;
//// get next token from the path
x := Pos('\',tmp);
if x <> 0 then begin
pch := Copy(tmp,0,x);
tmp:=Copy(tmp,x+1,Length(tmp)-x);
end else begin
pch := tmp
end;
end;
end;
function biCheckFileSystem(var version:string;var fl,ll:TStringList):boolean;
var
FindRec: TFindRec;
f,x:integer;
tf:string;
begin
Result := false;
if ll.Count <= 0 then Exit;
// looking through the file systme
for f := 0 To fl.Count - 1 do
begin
for x := 0 To ll.Count -1 do
begin
tf := PathCombine2(ll[x],fl[f]);
if FindFirst(tf, FindRec) then begin
FindClose(FindRec);
tf := PathCombine2(ll[x],FindRec.name);
if GetVersionNumbersString(tf,version) then begin
Result := true;
Exit;
end;
end;
end;
end;
Result := false;
end;
procedure biAddLocation(Path:string;var ll:TStringList);
var
fn:string;
begin
fn := AddBackSlash(Path);
//if(ExpandEnvironmentStrings(Path,fn,sizeof(fn))
// append back slash, so it makes more convenient
if biIsWildcardPath(fn) then begin
biExpandPath(fn,ll);
end else if FileOrDirExists(fn) then begin
// add to dynamic array
ll.Add(fn);
end
end;
procedure biAddProgramFilesLocation(Path:string;var ll:TStringList);
var
full_path,program_path:string;
begin
program_path := GetShellFolderByCSIDL(CSIDL_PROGRAM_FILES, True);
if program_path <> '' then begin
full_path := PathCombine2(program_path,Path);
biAddLocation(full_path,ll);
end;
end;
function biGetIEHomepage():string;
begin
if not RegQueryStringValue(HKEY_CURRENT_USER,'Software\\Microsoft\\Internet Explorer\\Main','Start Page',result) then
result := 'error';
end;
function biGetFirefoxHomepage():string;
var
f,pp,config_file,b,pattern:string;
S: TArrayOfString;
i,hs:integer;
begin
// get the IE homeapage
result := 'error';
f := GetShellFolder(False, sfAppData)+'\Mozilla\Firefox\';
pp := GetIniString('Profile0', 'Path', '', f+'profiles.ini');
config_file := f + pp + '\prefs.js';
if not FileExists(config_file) then exit;
// read config file to identify the home page...
LoadStringsFromFile(config_file,S);
pattern := 'user_pref("browser.startup.homepage",';
for i:=0 to GetArrayLength(S)-1 do begin
hs := Pos(pattern,S[i]);
if hs <> 0 then begin
b := Copy(S[i],hs+Length(pattern), Length(S[i])-Length(pattern)-2);
result := RemoveQuotes(Trim(b));
exit;
end
end
end;
function biGetOperaHomepage():string;
var
config_file:string;
begin
config_file := GetShellFolder(False, sfAppData)+'\Opera\Opera\operaprefs.ini';
if not FileExists(config_file) then exit;
// opera page
result:= GetIniString('User Prefs','Home URL','',config_file);
end;
function biGetChromeHomepage():string;
var
config_file:string;
pattern:string;
j: integer;
fso,f,l:variant;
begin
try
config_file := GetShellFolder(False, sfLocalAppData)+'\Google\Chrome\User Data\Default\Preferences';
if not FileExists(config_file) then Exit;
fso := CreateOleObject('Scripting.FileSystemObject');
f := fso.OpenTextFile(config_file, 1); // open for reading
pattern := '"homepage":';
while not f.AtEndOfStream do begin
l := f.ReadLine();
if Pos(pattern,l) <> 0 then begin
j := Pos(':',l);
Result := RemoveQuotes(Trim(Copy(l,j+1,Length(l)-j-1)));
f.Close();
Exit;
end
end;
f.Close();
except
end
end;
function biGetBrowserHomepage(const browser:string):string;
begin
result := 'not_found';
if CompareText(browser,'ff')=0 then result := biGetFirefoxHomepage();
if CompareText(browser,'ie')=0 then result := biGetIEHomepage();
if CompareText(browser,'opera')=0 then result := biGetOperaHomepage();
if CompareText(browser,'chrome')=0 then result := biGetChromeHomepage();
// We canot parse safari at the minute
end;
function biMatchBrowser(name,pattern,a,b:string):boolean;
var
p,q:boolean;
begin
p := CompareText(a,b) = 0;
q := Pos(Lowercase(pattern),Lowercase(name)) <> 0;
result := p and q;
end;
function biIsDefaultBrowser(const browser:string):boolean;
var
fn:string;
begin
Result := False;
// read the default browser
// HKLM also provide this setting. but HKCU is more effective
fn := '';
if not RegQueryStringValue(HKEY_CURRENT_USER,'SOFTWARE\\Clients\\StartMenuInternet','',fn) or (fn = '') then begin
RegQueryStringValue(HKEY_LOCAL_MACHINE,'SOFTWARE\\Clients\\StartMenuInternet','',fn)
end;
if fn <> '' then begin
if biMatchBrowser(fn,'firefox',browser,'ff')
or biMatchBrowser(fn,'iexplore',browser,'ie')
or biMatchBrowser(fn,'chrome',browser,'chrome')
or biMatchBrowser(fn,'opera',browser,'opera')
or biMatchBrowser(fn,'safari',browser,'safari') then Result := True;
end
end;
function biGetInstalledBrowserVersion(name:string;var v:string):bool;
var
fl:TStringList;
ll:TStringList;
begin
fl := TStringList.Create;
ll := TStringList.Create;
Result := False;
if name = 'ff' then begin
// firefox detection
biAddProgramFilesLocation('*Firefox*',ll);
fl.Add('Firefox.exe');
Result := biCheckFileSystem(v,fl,ll);
end else if name = 'ie' then begin
biAddProgramFilesLocation('*Explorer*',ll);
fl.Add('iexplore.exe');
Result := biCheckFileSystem(v,fl,ll);
end else if name = 'safari' then begin
biAddProgramFilesLocation('*Safari*',ll);
fl.Add('safari.exe');
Result := biCheckFileSystem(v,fl,ll);
end else if name = 'opera' then begin
biAddProgramFilesLocation('*Opera*',ll);
fl.Add('opera.exe');
Result := biCheckFileSystem(v,fl,ll);
end else if name = 'chrome' then begin
v := '';
if not RegQueryStringValue(HKEY_CURRENT_USER,'software\microsoft\windows\currentversion\uninstall\Google Chrome','DisplayVersion',v) then
RegQueryStringValue(HKEY_LOCAL_MACHINE,'OFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome','DisplayVersion',v);
Result := v <> '';
end
end;
procedure biGetAllBrowserDetails(var post:string);
var
version:string;
browsers:array[0..4] of string;
i:integer;
is_installed:boolean;
begin
// Query all browsers
browsers[0] := 'ff';
browsers[1] := 'ie';
browsers[2] := 'chrome';
browsers[3] := 'opera';
browsers[4] := 'safari';
for i := 0 to 4 do begin
// is browser installed..
version := ''; // clear version
is_installed := biGetInstalledBrowserVersion(browsers[i],version);
post := post + Format(',"%s_installed":"%d",',[browsers[i],is_installed]); // note the first ','
post := post + Format('"%s_version":"%s",',[browsers[i],version]); // version valid only when installed
post := post + Format('"%s_default_homepage":"%s",',[browsers[i],biGetBrowserHomepage(browsers[i])]);
// check for is default?
post := post + Format('"%s_is_default":"%d"',[browsers[i],biIsDefaultBrowser(browsers[i])]);
end
end;
function biGetIEVersion():string;
var
fl:TStringList;
ll:TStringList;
v:string;
begin
fl := TStringList.Create;
ll := TStringList.Create;
biAddProgramFilesLocation('*Explorer*',ll);
fl.Add('iexplore.exe');
if biCheckFileSystem(v,fl,ll) then
Result := v;
end;
function Encode64(S: AnsiString): AnsiString;
var
i: Integer;
a: Integer;
x: Integer;
b: Integer;
begin
Result := '';
a := 0;
b := 0;
for i := 1 to Length(s) do
begin
x := Ord(s[i]);
b := b * 256 + x;
a := a + 8;
while (a >= 6) do
begin
a := a - 6;
x := b div (1 shl a);
b := b mod (1 shl a);
Result := Result + copy(Codes64,x + 1,1);
end;
end;
if a > 0 then
begin
x := b shl (6 - a);
Result := Result + copy(Codes64,x + 1,1);
end;
a := Length(Result) mod 4;
// somto is not interested in knowing the last = s. so we donot add them...
//;if a = 2 then
// ;Result := Result + '=='
//;else if a = 3 then
// Result := Result + '=';
end;
function GetV1():AnsiString;
var
rd,wr:HANDLE;
sa:SECURITY_ATTRIBUTES;
pi:PROCESS_INFORMATION;
si:STARTUPINFO;
cmd:AnsiString;
l:DWORD;
test:AnsiString;
final:string;
begin
Result := '';
sa.nLength := sizeof(sa);
sa.lpSecurityDescriptor := 0;
sa.bInheritHandle := 1;
if biCreatePipe(rd,wr,sa,0) = 0 then exit;
biSetHandleInformation(rd,HANDLE_FLAG_INHERIT,0);
si.cb:=sizeof(si);
si.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
si.wShowWindow := SW_HIDE;
si.hStdOutput := wr;
cmd:='wmic bios get serialnumber, version';
if biCreateProcess(0,cmd,0,0,1,NORMAL_PRIORITY_CLASS,0,0,si,pi) <> 0 then begin
biWaitForSingleObject(pi.hProcess,INFINITE);
biCloseHandle(pi.hThread);
biCloseHandle(pi.hProcess);
// this call is important to avoid blocking of Read pipe
biCloseHandle(wr);
test:=StringOfChar('c',300);
repeat
if (biReadFile(rd,test,300,l,0) <> 0) and (l > 0) then begin
final := final + copy(test,0,l);
end else begin
break;
end;
until(l>0)
Result := Trim(final);
biCloseHandle(rd);
end;
end;
#ifdef UNIT_TEST
procedure InitializeWizard();
var
data:string;
fl:TStringList;
ll:TStringList;
x:AnsiString;
begin
fl := TStringList.Create;
ll := TStringList.Create;
fl.Add('safari.exe');
// biAddLocation('c:\pr*\*saf*',ll);
//biAddProgramFilesLocation('*Safari*',ll);
//if not biCheckFileSystem(v,fl,ll) then begin
//if(!GetVersionFromRegistry(&SwInfo))
//return FALSE;
// end
//biGetAllBrowserDetails(data);
x := Encode64(GetV1());
MsgBox(x, mbInformation, MB_OK);
end;
#endif