/////////////////////////////// // Check version // Current e5685457 function CheckNumVer(ScolVer: String): Boolean; var Version: Integer; begin Result := True; Version := StrToIntDef('$' + ScolVer, 0); if Version < $e5685457 then begin Result := False; end; end; //////////////// // info de debug procedure DBG(Msg: String); begin // mettre la ligne suivante en commentaire pour ne plus avoir les infos de debug //MsgBox(Msg, mbInformation, MB_OK); end; ///////////////////////// // affichage d'un message function AffMsg(NumMsg: Integer): Integer; begin if CompareStr(ActiveLanguage(), 'Francais') = 0 then begin Result := MsgBox(InternalMsgs[NumMsg].TextFR, InternalMsgs[NumMsg].Typ, InternalMsgs[NumMsg].Buttons); end else begin Result := MsgBox(InternalMsgs[NumMsg].TextEN, InternalMsgs[NumMsg].Typ, InternalMsgs[NumMsg].Buttons); end; end; function GetLastDir(s: String): String; var Idx: Integer; begin Idx := Pos('\', s); while (Idx > 0) do begin s := Copy(s, Idx + 1, Length(s) - (Idx)); Idx := Pos('\', s); end; Result := s; end; //////////////////////////////////// // Charge des lignes dans un tableau // (la fct Inno LoadStringsFromFile ne marche pas tjrs) procedure Strings2Array(Str: String; var arr: array of String); var Idx1: Integer; Idx2: Integer; begin Idx1 := Pos(#13#10, Str); Idx2 := Pos(#10, Str); if (Idx1 > 0) and ((Idx2 = 0) or (Idx1 < Idx2)) then begin SetArrayLength(arr, GetArrayLength(arr)+1); arr[GetArrayLength(arr)-1] := Copy(Str, 1, Idx1-1); Strings2Array(Copy(Str, Idx1+2, Length(Str)), arr); end else begin if (Idx2 > 0) and ((Idx1 = 0) or (Idx2 < Idx1)) then begin SetArrayLength(arr, GetArrayLength(arr)+1); arr[GetArrayLength(arr)-1] := Copy(Str, 1, Idx2-1); Strings2Array(Copy(Str, Idx2+1, Length(Str)), arr); end else begin if Length(Str) > 0 then begin SetArrayLength(arr, GetArrayLength(arr)+1); arr[GetArrayLength(arr)-1] := Copy(Str, 1, Length(Str)); end; end; end; end; /////////////////////////////////////// // Transforme une chaine au format scol // '\' devient '\\' et ' ' devient '\ ' function Str2Scol(Str: String): String; var Idx: Integer; Car: Char; begin Result := ''; Idx := 1; while Idx <= Length(Str) do begin Car := StrGet(Str, Idx); if Car = '\' then begin Result := Result + '\\'; end else if Car = ' ' then begin Result := Result + '\ '; end else begin Result := Result + Car; end; Idx := Idx + 1; end; end; //////////////////////////////////////////////////////// // Recupere le 1er mot d'une chaine (sans saut de ligne) // NextIdx est la position la suite // Si Trans=True on transforme les '/' en '\', les '\\' en '\' et les '\ ' en ' ' function GetFirstWord(Str: String; Trans: Boolean; var NextIdx: Integer): String; var Fin: Boolean; Idx: Integer; Car: Char; begin Result := ''; Fin := False; Idx := 1; while Fin = False do begin if Idx > Length(Str) then begin Fin := True; end else begin Car := StrGet(Str, Idx); Idx := Idx + 1; if Car = '/' then begin if Trans then begin Result := Result + '\'; end else begin Result := Result + '/'; end; end else if Car = '\' then begin if Idx > Length(Str) then begin // error de syntaxe Result := ''; Fin := True; end else begin Car := StrGet(Str, Idx); Idx := Idx + 1; if Car = '\' then begin if Trans then begin Result := Result + '\'; end else begin Result := Result + '\\'; end; end else if Car = ' ' then begin if Trans then begin Result := Result + ' '; end else begin Result := Result + '\ '; end; end else begin // error de syntaxe Result := ''; Fin := True; Idx := Length(Str) + 1; end; end; end else if Car = ' ' then begin Fin := True; end else begin Result := Result + Car; end; end; end; NextIdx := Idx; DBG('firstWord='+Result); DBG('nextIdx='+IntToStr(NextIdx)); end; ///////////////////////////////////////////////// // Recupere la 1ere ligne d'un tableau de chaines // qui commence par First // StartIdx est la position où commencer // Compact à True pour ne pas tenir compte des blancs au début // Renvoie l'indice si trouvé ou -1 sinon function SearchFirstLine(Arr: array of String; First: String; StartIdx: Integer; Compact: Boolean): Integer; var Idx: Integer; Fin: Boolean; Str: String; begin Result := -1; Fin := False; Idx := StartIdx; while (Fin = False) and (Idx < GetArrayLength(Arr)) do begin if Compact = True then begin Str := Copy(TrimLeft(Arr[Idx]), 1, Length(First)); end else begin Str := Copy(Arr[Idx], 1, Length(First)); end; if CompareStr(First, Str) = 0 then begin Fin := True; end else begin Idx := Idx + 1; end; end; if Fin = True then begin Result := Idx; end; end; /////////////////////////////////////////// // 1ere partition de scol (à part le cache) function GetScolPart(ScolDir: String; isUser: Boolean): String; var UsmIni: String; ArrUsmIni: array of String; Disk: String; Part: String; ScolMain: String; PartType: String; Idx: Integer; NextIdx: Integer; begin Result := ''; if (isUser = True) then begin PartType := 'disku'; end else begin PartType := 'diska'; end; if (LoadStringFromFile(ScolDir + '\usm.ini', UsmIni) = True) then begin // chargement en tableau SetArrayLength(ArrUsmIni, 0); Strings2Array(UsmIni, ArrUsmIni); // looking for last partition Idx := SearchFirstLine(ArrUsmIni, PartType + ' ', 0, True); if ((Idx < 0) and (CompareStr(PartType, 'disku') = 0)) then begin PartType := 'diska'; Idx := SearchFirstLine(ArrUsmIni, PartType + ' ', 0, True); end; if (isUser) then begin Disk := TrimLeft(ArrUsmIni[Idx]); // on enlève le mot diska Disk := Copy(Disk, Length(PartType + ' '), Length(Disk)); Disk := TrimLeft(Disk); // on récupère la partition Part := GetFirstWord(Disk, True, NextIdx); if (CompareStr(PartType, 'disku') = 0) then begin // get Scol dir ScolMain := GetLastDir(ScolDir); ScolDir := ExpandConstant('{userdocs}'); end // on remplace '.\' par '\' if Pos('.\', Part) = 1 then begin Part := ScolDir + Copy(Part, 2, Length(Part)); end // on n'ajoute pas ScolDir s'il s'agit d'une unité de lecteur else if (Length(Part) > 0) and ((Length(Part) = 1) or (StrGet(Part, 2) <> ':')) then begin Part := ScolDir + '\' + Part; end; Result := Part; end else begin while Idx >= 0 do begin Disk := TrimLeft(ArrUsmIni[Idx]); // on enlève le mot diska Disk := Copy(Disk, Length(PartType + ' '), Length(Disk)); Disk := TrimLeft(Disk); // on récupère la partition Part := GetFirstWord(Disk, True, NextIdx); if (CompareStr(PartType, 'disku') = 0) then begin // get Scol dir ScolMain := GetLastDir(ScolDir); ScolDir := ExpandConstant('{userdocs}') + '\'; end // on remplace '.\' par '\' if Pos('.\', Part) = 1 then begin Part := ScolDir + Copy(Part, 2, Length(Part)); end // on n'ajoute pas ScolDir s'il s'agit d'une unité de lecteur else if (Length(Part) > 0) and ((Length(Part) = 1) or (StrGet(Part, 2) <> ':')) then begin Part := ScolDir + '\' + Part; end; Result := Part; Idx := SearchFirstLine(ArrUsmIni, PartType + ' ', Idx+1, True); end; end; end; DBG('ScolPart='+Result); end; /////////////////////////////// // Scol install directory function GetScolDir(Default: String): String; var Value: String; begin if RegQueryStringValue(HKEY_CLASSES_ROOT, 'scm_auto_file\shell\open\command', '', Value) then begin // get file directory Value := ExtractFilePath(Copy(Value, 2, Length(Value) -7)); // remove last "\" Value := Copy(Value, 0, Length(Value) -1); end else begin Value := Default; end; DBG('ScolDir='+Value); Result := Value; end; function GetScolUserPartitionDir(ScolDir: String; Default: String): String; var Value: String; begin Value := GetScolPart(ScolDir, True); if Length(Value) = 0 then begin Value := Default; end; DBG('User Partition='+Value); Result := Value; end; function GetScolLockedPartitionDir(ScolDir: String; Default: String): String; var Value: String; begin Value := GetScolPart(ScolDir, False); if Length(Value) = 0 then begin Value := Default; end; DBG('Locked Partition='+Value); Result := Value; end; /////////////////////////////// // Scolexe name function GetScolExe(): String; var Value: String; begin if RegQueryStringValue(HKEY_CLASSES_ROOT, 'scm_auto_file\shell\open\command', '', Value) then begin // get file directory Value := ExtractFileName(Copy(Value, 2, Length(Value) -7)); end; DBG('ScolExe='+Value); Result := Value; end; /////////////////////////////////////////// // Check Scol version function CheckScolVer(scolpath: String): Boolean; var ScolPart: String; ScolVer: String; ArrScolVer: array of String; Idx: Integer; begin Result := False; ScolPart := GetScolPart(scolpath, False); if Length(ScolPart) = 0 then begin // partition error Result := False; end else if LoadStringFromFile(ScolPart + '\locked\etc\version.txt', ScolVer) = True then begin SetArrayLength(ArrScolVer, 0); Strings2Array(ScolVer, ArrScolVer); Idx := SearchFirstLine(ArrScolVer, 'version ', 0, True); if Idx >= 0 then begin ScolVer := TrimLeft(ArrScolVer[Idx]); ScolVer := Copy(ScolVer, Length('version '), Length(ScolVer)); ScolVer := Trim(ScolVer); Result := CheckNumVer(ScolVer); end; end; end; ///////////////////////////////// // Recherche si scol est installé function isScolInstalled(): Boolean; var ScolDir: String; begin Result := False; ScolDir := GetScolDir(''); if Length(ScolDir) > 0 then begin if FileExists(ScolDir + (GetScolExe())) then begin Result := FileExists(ScolDir + '\' + GetScolExe()); end else begin Result := FileExists(ScolDir + '\' + GetScolExe()); end; end; end; ////////////////////////////////////// // Argument /FORCE pour install forcée function isForced(): Boolean; var Idx: Integer; begin Result := False; Idx := 0; while (Length(ParamStr(Idx)) > 0) and (Result = False) do begin if CompareText(ParamStr(Idx), '/FORCE') = 0 then begin Result := True; end else begin Idx := Idx + 1; end; end; if (Result) then DBG('isForced=True') else DBG('isForced=False'); end; //////////////////////////////////////// // Construction du custom.txt en tableau procedure BuildCustom(customtxt: array of String; var custom: TCustom); var FirstLine: String; Idx: Integer; Car: Char; currIdx: Integer; levelIdx: Integer; lastIdx: Integer; tabIdx: array of Integer; Key: String; ValIdx: Integer; Val: String; begin currIdx := 0; levelIdx := 0; lastIdx := 0; SetArrayLength(tabIdx, 1); tabIdx[0] := 0; Idx := 0; while Idx < GetArrayLength(customtxt) do begin FirstLine := Trim(customtxt[Idx]); Car := StrGet(FirstLine, 1); // nouveau bloc if Car = '>' then begin SetArrayLength(custom[currIdx].Childs, GetArrayLength(custom[currIdx].Childs)+1); custom[currIdx].Childs[GetArrayLength(custom[currIdx].Childs)-1] := lastIdx + 1; if levelIdx+2 > GetArrayLength(tabIdx) then SetArrayLength(tabIdx, GetArrayLength(tabIdx) + 1); lastIdx := lastIdx + 1; levelIdx := levelIdx + 1; tabIdx[levelIdx] := lastIdx; currIdx := lastIdx; SetArrayLength(custom, GetArrayLength(custom) + 1); custom[lastIdx].BlocName := FirstLine; custom[lastIdx].Fathers := custom[tabIdx[levelIdx-1]].Fathers + custom[tabIdx[levelIdx-1]].BlocName; SetArrayLength(custom[lastIdx].Lines, 0); end // fin d'un bloc else if Car = '<' then begin currIdx := tabIdx[levelIdx-1]; levelIdx := levelIdx - 1; end // ligne normale else begin Key := GetFirstWord(FirstLine, False, ValIdx); Val := GetFirstWord(Copy(FirstLine, ValIdx, Length(FirstLine)), False, ValIdx); SetArrayLength(custom[currIdx].Lines, GetArrayLength(custom[currIdx].Lines) + 1); custom[currIdx].Lines[GetArrayLength(custom[currIdx].Lines)-1].Key := Key; custom[currIdx].Lines[GetArrayLength(custom[currIdx].Lines)-1].Val := Val; end; Idx := Idx + 1; end; end; ///////////////////// // Debugage du custom procedure printcust(custom: TCustom); var i, j: Integer; begin i := 0; while i < GetArrayLength(custom) do begin DBG('BLOCNAME='+custom[i].BlocName); DBG('fathers='+custom[i].Fathers); j := 0; while j < GetArrayLength(custom[i].Childs) do begin DBG('child'+IntToStr(j)+'='+IntToStr(custom[i].Childs[j])); j := j + 1; end; j := 0; while j < GetArrayLength(custom[i].Lines) do begin DBG('key'+IntToStr(j)+'='+custom[i].Lines[j].Key); j := j + 1; end; i := i + 1; end; end; ////////////////////// // Recherche d'un bloc // (même nom, mêmes pères) // -1 si non trouvé function FindCustBloc(currcustom: TCustom; custBloc: TBloc): Integer; var i: Integer; begin Result := -1; i := 0; while (i < GetArrayLength(currcustom)) and (Result = -1) do begin if (CompareStr(currcustom[i].BlocName, custBloc.BlocName) = 0) and (CompareStr(currcustom[i].Fathers, custBloc.Fathers) = 0) then begin Result := i; end else i := i + 1; end; end; ////////////////////// // Recherche d'une clé // -1 si non trouvé function FindCustKey(currcustlines: array of TLine; Key: String): Integer; var i: Integer; begin Result := -1; i := 0; while (i < GetArrayLength(currcustlines)) and (Result = -1) do begin if CompareStr(currcustlines[i].Key, Key) = 0 then begin Result := i; end else i := i + 1; end; end; //////////////////////////////// // Merge de deux tableaux custom procedure MergeCustomBloc(var currcustom: TCustom; custom: TCustom); var i, j: Integer; IdxBloc: Integer; IdxLine: Integer; Father: TBloc; begin i := 0; while i < GetArrayLength(custom) do begin // recherche du bloc IdxBloc := FindCustBloc(currcustom, custom[i]); // si bloc trouvé, on cherche les clés if IdxBloc >= 0 then begin j := 0 while j < GetArrayLength(custom[i].Lines) do begin IdxLine := FindCustKey(currcustom[IdxBloc].Lines, custom[i].Lines[j].Key); // si clé non trouvée, on l'ajoute if IdxLine < 0 then begin SetArrayLength(currcustom[IdxBloc].Lines, GetArrayLength(currcustom[IdxBloc].Lines)+1); currcustom[IdxBloc].Lines[GetArrayLength(currcustom[IdxBloc].Lines)-1].Key := custom[i].Lines[j].Key; currcustom[IdxBloc].Lines[GetArrayLength(currcustom[IdxBloc].Lines)-1].Val := custom[i].Lines[j].Val; end else j := j + 1; end; end // si bloc non trouvé else begin // on l'ajoute SetArrayLength(currcustom, GetArrayLength(currcustom)+1); currcustom[GetArrayLength(currcustom)-1].BlocName := custom[i].BlocName; currcustom[GetArrayLength(currcustom)-1].Fathers := custom[i].Fathers; SetArrayLength(currcustom[GetArrayLength(currcustom)-1].Childs, 0); SetArrayLength(currcustom[GetArrayLength(currcustom)-1].Lines, GetArrayLength(custom[i].Lines)); j := 0; while j < GetArrayLength(custom[i].Lines) do begin currcustom[GetArrayLength(currcustom)-1].Lines[j].Key := custom[i].Lines[j].Key; currcustom[GetArrayLength(currcustom)-1].Lines[j].Val := custom[i].Lines[j].Val; j := j + 1; end; // on s'ajoute dans la liste des fils de son père j := Length(custom[i].Fathers); while (j > 0) and (StrGet(custom[i].Fathers, j) <> '>') do j := j - 1; Father.BlocName := Copy(custom[i].Fathers, j, Length(custom[i].Fathers)); Father.Fathers := Copy(custom[i].Fathers, 1, j-1); IdxBloc := FindCustBloc(currcustom, Father); SetArrayLength(currcustom[IdxBloc].Childs, GetArrayLength(currcustom[IdxBloc].Childs)+1); currcustom[IdxBloc].Childs[GetArrayLength(currcustom[IdxBloc].Childs)-1] := GetArrayLength(currcustom)-1; end; i := i + 1; end; end; ///////////////////////////////////////////// // Transformation du tableau custom en string function BlocToString(custom: TCustom; idx: Integer): String; var i: Integer; begin if Length(custom[idx].BlocName) > 0 then begin Result := custom[idx].BlocName + #13#10; end else begin Result := ''; end; i := 0; while i < GetArrayLength(custom[idx].Childs) do begin Result := Result + BlocToString(custom, custom[idx].Childs[i]); i := i + 1; end; i := 0; while i < GetArrayLength(custom[idx].Lines) do begin Result := Result + custom[idx].Lines[i].Key + ' ' + custom[idx].Lines[i].Val + #13#10; i := i + 1; end; if Length(custom[idx].BlocName) > 0 then begin Result := Result + '<' + #13#10; end; end; ////////////////////////////////////////////////////////// // Ajoute une dll plugin dans usm.ini si version le permet // Retourne True si dll ajoutée function InstallPluginDll(var ArrUsmIni: array of String; Dll: String; IniFuncs: String): Boolean; var Idx: Integer; LastIdx: Integer; Fin: Boolean; Plugin: String; DllIdx: Integer; begin Result := False; Fin := False; Idx := -1; while Fin = False do begin // recherche des plugins Idx := SearchFirstLine(ArrUsmIni, 'plugin ', Idx+1, True); if Idx >= 0 then begin LastIdx := Idx; DllIdx := Pos(Uppercase(Dll), Uppercase(ArrUsmIni[Idx])); // dll trouvée if DllIdx > 0 then begin Fin := True; Plugin := GetFirstWord(Copy(ArrUsmIni[Idx], DllIdx, Length(ArrUsmIni[Idx])), False, DllIdx); // on remplace dans usm.ini par nouvelle dll ArrUsmIni[Idx] := 'plugin plugins/' + Dll + ' ' + IniFuncs; Result := True; end; end else Fin := True; end; // si dll non trouvée, on l'ajoute if Idx < 0 then begin SetArrayLength(ArrUsmIni, GetArrayLength(ArrUsmIni)+1); Idx := GetArrayLength(ArrUsmIni)-1; while Idx > LastIdx do begin ArrUsmIni[Idx] := ArrUsmIni[Idx-1]; Idx := Idx - 1; end; ArrUsmIni[LastIdx+1] := 'plugin plugins/' + Dll + ' ' + IniFuncs; Result := True; end; If Result then DBG('InstallPluginDll '+Dll+' True') else DBG('InstallPluginDll '+Dll+' False'); end; ////////////////////////////////////////////////////////// // Ajoute une partition dans usm.ini // Retourne True si la partition est ajoutée function InstallPartition(var ArrUsmIni: array of String; Part: String; isUser: Boolean): Boolean; var Idx: Integer; LastIdx: Integer; FirstIdx: Integer; Fin: Boolean; Partition: String; PartIdx: Integer; PartType: String; begin Result := False; Fin := False; Idx := -1; FirstIdx := SearchFirstLine(ArrUsmIni, 'disk', 0, True); DBG('InstallPartition found disk at ' + IntToStr(FirstIdx)); if (isUser = True) then begin PartType := 'disku '; end else PartType := 'diska '; while Fin = False do begin // recherche des partitions Idx := SearchFirstLine(ArrUsmIni, PartType, Idx+1, True); if Idx >= 0 then begin LastIdx := Idx; PartIdx := Pos(Uppercase(Part), Uppercase(ArrUsmIni[Idx])); // partition trouvée if PartIdx > 0 then begin Fin := True; Partition := GetFirstWord(Copy(ArrUsmIni[Idx], PartIdx, Length(ArrUsmIni[Idx])), False, PartIdx); // on remplace dans usm.ini par nouvelle dll ArrUsmIni[Idx] := PartType + Part + ' 0'; Result := True; end; end else Fin := True; end; // si partition non trouvée, on l'ajoute if Idx < 0 then begin SetArrayLength(ArrUsmIni, GetArrayLength(ArrUsmIni)+1); Idx := GetArrayLength(ArrUsmIni)-1; while Idx >= FirstIdx do begin ArrUsmIni[Idx] := ArrUsmIni[Idx-1]; Idx := Idx - 1; end; ArrUsmIni[FirstIdx] := PartType + Part + ' 0'; Result := True; end; If Result then DBG('InstallPartition '+Part+' True') else DBG('InstallPartition '+Part+' False'); end; function ReplacePartition(var ArrUsmIni: array of String; Part: String; toPart: String; isUser: Boolean): Boolean; var Idx: Integer; LastIdx: Integer; Fin: Boolean; Partition: String; PartIdx: Integer; PartType: String; begin Result := False; Fin := False; Idx := -1; if (isUser = True) then begin PartType := 'disku '; end else PartType := 'diska '; while Fin = False do begin // recherche des partitions Idx := SearchFirstLine(ArrUsmIni, PartType, Idx+1, True); if Idx >= 0 then begin LastIdx := Idx; PartIdx := Pos(Uppercase(Part), Uppercase(ArrUsmIni[Idx])); // partition trouvée if PartIdx > 0 then begin Fin := True; Partition := GetFirstWord(Copy(ArrUsmIni[Idx], PartIdx, Length(ArrUsmIni[Idx])), False, PartIdx); // on remplace dans usm.ini par nouvelle dll ArrUsmIni[Idx] := PartType + toPart + ' 0'; Result := True; end; end else Fin := True; end; If Result then DBG('InstallPartition '+Part+' True') else DBG('InstallPartition '+Part+' False'); end;