Browse Source

Merge branch 'develop'

Unknown 6 years ago
parent
commit
12aaa23194

+ 145 - 0
Quick.CloudStorage.Provider.Amazon.pas

@@ -0,0 +1,145 @@
+unit Quick.CloudStorage.Provider.Amazon;
+
+interface
+
+uses
+  Classes,
+  System.SysUtils,
+  Quick.Commons,
+  Quick.CloudStorage,
+  Quick.Amazon;
+
+type
+
+  TCloudStorageAmazonProvider = class(TCloudStorageProvider)
+  private
+    fAmazon : TQuickAmazon;
+    fAmazonID : string;
+    fAmazonKey: string;
+    fAmazonRegion : string;
+    fSecure : Boolean;
+    fCurrentBuckeet: string;
+    procedure SetSecure(const Value: Boolean);
+  public
+    constructor Create; overload;
+    constructor Create(const aAccountID, aAccountKey, aAWSRegion : string); overload;
+    destructor Destroy; override;
+    property Secure : Boolean read fSecure write SetSecure;
+    procedure OpenDir(const aPath : string); override;
+    function GetFile(const aPath: string; out stream : TStream) : Boolean; override;
+  end;
+
+implementation
+
+{ TCloudExplorerProvider }
+
+constructor TCloudStorageAmazonProvider.Create;
+begin
+  fAmazon := TQuickAmazon.Create;
+  fAmazon.AmazonProtocol := amHTTPS;
+end;
+
+constructor TCloudStorageAmazonProvider.Create(const aAccountID, aAccountKey, aAWSRegion : string);
+begin
+  Create;
+  fAmazonID := aAccountID;
+  fAmazonKey := aAccountKey;
+  fAmazonRegion := aAWSRegion;
+  fAmazon.AccountName := fAmazonID;
+  fAmazon.AccountKey := fAmazonKey;
+  fAmazon.AWSRegion := TQuickAmazon.GetAWSRegion(fAmazonRegion);
+end;
+
+destructor TCloudStorageAmazonProvider.Destroy;
+begin
+  if Assigned(fAmazon) then fAmazon.Free;
+  inherited;
+end;
+
+function TCloudStorageAmazonProvider.GetFile(const aPath: string; out stream : TStream) : Boolean;
+begin
+
+end;
+
+procedure TCloudStorageAmazonProvider.OpenDir(const aPath : string);
+var
+  lista : TAmazonObjects;
+  Blob : TAmazonObject;
+  i : Integer;
+  azurefilter : string;
+  DirItem : TCloudItem;
+  respinfo : TAmazonResponseInfo;
+begin
+  if aPath = '..' then
+  begin
+    CurrentPath := RemoveLastPathSegment(CurrentPath);
+  end
+  else
+  begin
+    if CurrentPath = '' then CurrentPath := aPath
+      else CurrentPath := CurrentPath + aPath;
+  end;
+  if Assigned(OnBeginReadDir) then OnBeginReadDir(CurrentPath);
+  if CurrentPath.StartsWith('/') then CurrentPath := Copy(CurrentPath,2,CurrentPath.Length);
+  if (not CurrentPath.IsEmpty) and (not CurrentPath.EndsWith('/')) then CurrentPath := CurrentPath + '/';
+
+  Status := stRetrieving;
+  lista := fAmazon.ListObjects(RootFolder,CurrentPath,fAmazon.AWSRegion,respinfo);
+  try
+    if CurrentPath <> '' then
+    begin
+      if Assigned(OnGetListItem) then
+      begin
+        DirItem := TCloudItem.Create;
+        try
+          DirItem.Name := '..';
+          DirItem.IsDir := True;
+          DirItem.Date := 0;
+          OnGetListItem(DirItem);
+        finally
+          DirItem.Free;
+        end;
+      end;
+    end;
+
+    if respinfo.StatusCode = 200 then
+    begin
+      for Blob in lista do
+      begin
+        DirItem := TCloudItem.Create;
+        try
+          if Blob.Name.StartsWith(CurrentPath) then Blob.Name := StringReplace(Blob.Name,CurrentPath,'',[]);
+          if Blob.Name.Contains('/') then
+          begin
+            DirItem.IsDir := True;
+            DirItem.Name := Copy(Blob.Name,1,Blob.Name.IndexOf('/'));
+          end
+          else
+          begin
+            DirItem.IsDir := False;
+            DirItem.Name := Blob.Name;
+            DirItem.Size := Blob.Size;
+            DirItem.Date := Blob.Modified;
+          end;
+          if Assigned(OnGetListItem) then OnGetListItem(DirItem);
+        finally
+          DirItem.Free;
+        end;
+      end;
+      Status := stDone;
+    end
+    else Status := stFailed;
+  finally
+    lista.Free;
+    ResponseInfo.Get(respinfo.StatusCode,respinfo.StatusMsg);
+  end;
+end;
+
+procedure TCloudStorageAmazonProvider.SetSecure(const Value: Boolean);
+begin
+  fSecure := Value;
+  if Value then fAmazon.AmazonProtocol := TAmazonProtocol.amHTTPS
+    else fAmazon.AmazonProtocol := TAmazonProtocol.amHTTP;
+end;
+
+end.

+ 340 - 0
Quick.CloudStorage.Provider.Azure.pas

@@ -0,0 +1,340 @@
+unit Quick.CloudStorage.Provider.Azure;
+
+interface
+
+uses
+  Classes,
+  System.SysUtils,
+  System.Generics.Collections,
+  Quick.Commons,
+  Quick.CloudStorage,
+  IPPeerClient,
+  Data.Cloud.CloudAPI,
+  Data.Cloud.AzureAPI;
+
+type
+
+  TCloudStorageAzureProvider = class(TCloudStorageProvider)
+  private
+    fAzureConnection : TAzureConnectionInfo;
+    fAzureID : string;
+    fAzureKey : string;
+    procedure SetSecure(aValue: Boolean); override;
+    function ListContainers(azContainersStartWith : string; azResponseInfo : TResponseInfo) : TStrings;
+  public
+    constructor Create; overload; override;
+    constructor Create(const aAccountName, aAccountKey : string); overload;
+    destructor Destroy; override;
+    function GetRootFolders : TStrings; override;
+    procedure OpenDir(const aPath : string); override;
+    function GetFile(const aPath: string; out stream : TStream) : Boolean; override;
+    function GetURL(const aPath : string) : string; override;
+  end;
+
+implementation
+
+{ TCloudExplorerProvider }
+
+constructor TCloudStorageAzureProvider.Create;
+begin
+  fAzureConnection := TAzureConnectionInfo.Create(nil);
+end;
+
+constructor TCloudStorageAzureProvider.Create(const aAccountName, aAccountKey : string);
+begin
+  inherited Create;
+  Create;
+  fAzureID := aAccountName;
+  fAzureKey := aAccountKey;
+  fAzureConnection.AccountName := aAccountName;
+  fAzureConnection.AccountKey := aAccountKey;
+end;
+
+destructor TCloudStorageAzureProvider.Destroy;
+begin
+  if Assigned(fAzureConnection) then fAzureConnection.Free;
+  inherited;
+end;
+
+function TCloudStorageAzureProvider.GetFile(const aPath: string; out stream : TStream) : Boolean;
+var
+  BlobService : TAzureBlobService;
+  CloudResponseInfo : TCloudResponseInfo;
+begin
+  BlobService := TAzureBlobService.Create(fAzureConnection);
+  try
+    CloudResponseInfo := TCloudResponseInfo.Create;
+    try
+      Result := BlobService.GetBlob(RootFolder,aPath,stream,'',CloudResponseInfo);
+      if not Result then raise Exception.CreateFmt('Cloud error %d : %s',[CloudResponseInfo.StatusCode,CloudResponseInfo.StatusMessage]);
+    finally
+      CloudResponseInfo.Free;
+    end;
+  finally
+    BlobService.Free;
+  end;
+end;
+
+function TCloudStorageAzureProvider.GetRootFolders: TStrings;
+var
+  respinfo : TResponseInfo;
+begin
+  Result := ListContainers('',respinfo);
+end;
+
+function TCloudStorageAzureProvider.GetURL(const aPath: string): string;
+begin
+  Result := Format('https://%s.blob.core.windows.net/%s/%s',[fAzureConnection.AccountName,RootFolder,aPath]);
+end;
+
+function TCloudStorageAzureProvider.ListContainers(azContainersStartWith : string; azResponseInfo : TResponseInfo) : TStrings;
+var
+  BlobService : TAzureBlobService;
+  CloudResponseInfo : TCloudResponseInfo;
+  cNextMarker : string;
+  AzParams : TStrings;
+  AzContainer : TAzureContainer;
+  AzContainers : TList<TAzureContainer>;
+begin
+  Result := TStringList.Create;
+  cNextMarker := '';
+  BlobService := TAzureBlobService.Create(fAzureConnection);
+  CloudResponseInfo := TCloudResponseInfo.Create;
+  try
+    BlobService.Timeout := Timeout;
+    repeat
+      AzParams := TStringList.Create;
+      try
+        if azContainersStartWith <> '' then AzParams.Values['prefix'] := azContainersStartWith;
+        if cNextMarker <> '' then AzParams.Values['marker'] := cNextMarker;
+        AzContainers := BlobService.ListContainers(cNextMarker,AzParams,CloudResponseInfo);
+        try
+          azResponseInfo.Get(CloudResponseInfo);
+          if (azResponseInfo.StatusCode = 200) and (Assigned(AzContainers)) then
+          begin
+            for AzContainer in AzContainers do
+            begin
+              Result.Add(AzContainer.Name);
+            end;
+          end;
+        finally
+          if Assigned(AzContainer) then
+          begin
+            //frees ContainerList objects
+            for AzContainer in AzContainers do AzContainer.Free;
+            AzContainers.Free;
+          end;
+        end;
+      finally
+        AzParams.Free;
+      end;
+    until (cNextMarker = '') or (azResponseInfo.StatusCode <> 200);
+  finally
+    BlobService.Free;
+    CloudResponseInfo.Free;
+  end;
+end;
+
+procedure TCloudStorageAzureProvider.OpenDir(const aPath: string);
+var
+  BlobService : TAzureBlobService;
+  azBlob : TAzureBlob;
+  azBlobList : TList<TAzureBlob>;
+  DirItem : TCloudItem;
+  CloudResponseInfo : TCloudResponseInfo;
+  cNextMarker : string;
+  AzParams : TStrings;
+  azResponseInfo : TResponseInfo;
+  azContainer : string;
+begin
+  Status := stSearching;
+  cNextMarker := '';
+  if aPath = '..' then
+  begin
+    CurrentPath := RemoveLastPathSegment(CurrentPath);
+  end
+  else
+  begin
+    if (CurrentPath = '') or (aPath.StartsWith('/')) then CurrentPath := aPath
+      else CurrentPath := CurrentPath + aPath;
+  end;
+  if Assigned(OnBeginReadDir) then OnBeginReadDir(CurrentPath);
+  if CurrentPath.StartsWith('/') then CurrentPath := Copy(CurrentPath,2,CurrentPath.Length);
+  if (not CurrentPath.IsEmpty) and (not CurrentPath.EndsWith('/')) then CurrentPath := CurrentPath + '/';
+
+  azContainer := RootFolder;
+  if azContainer = '' then azContainer := '$root';
+  BlobService := TAzureBlobService.Create(fAzureConnection);
+  try
+    BlobService.Timeout := Timeout;
+    Status := stRetrieving;
+    if Assigned(OnGetListItem) then
+    begin
+      DirItem := TCloudItem.Create;
+      try
+        DirItem.Name := '..';
+        DirItem.IsDir := True;
+        DirItem.Date := 0;
+        OnGetListItem(DirItem);
+      finally
+        DirItem.Free;
+      end;
+    end;
+    repeat
+      if not (Status in [stSearching,stRetrieving]) then Exit;
+      AzParams := TStringList.Create;
+      try
+        if fCancelOperation then
+        begin
+          fCancelOperation := False;
+          Exit;
+        end;
+        AzParams.Values['prefix'] := CurrentPath;
+        //if not Recursive then
+        AzParams.Values['delimiter'] := '/';
+        AzParams.Values['maxresults'] := '100';
+        if cNextMarker <> '' then AzParams.Values['marker'] := cNextMarker;
+        CloudResponseInfo := TCloudResponseInfo.Create;
+        try
+          azBlobList := BlobService.ListBlobs(azContainer,cNextMarker,AzParams,CloudResponseInfo);
+          azResponseInfo.Get(CloudResponseInfo);
+          if azResponseInfo.StatusCode = 200 then
+          begin
+            try
+              for azBlob in azBlobList do
+              begin
+                if not (Status in [stSearching,stRetrieving]) then Exit;
+                if fCancelOperation then
+                begin
+                  fCancelOperation := False;
+                  Exit;
+                end;
+                DirItem := TCloudItem.Create;
+                try
+                  DirItem.Name := azBlob.Name;
+                  if DirItem.Name.StartsWith(CurrentPath) then DirItem.Name := StringReplace(DirItem.Name,CurrentPath,'',[]);
+                  if DirItem.Name.Contains('/') then
+                  begin
+                    DirItem.IsDir := True;
+                    DirItem.Name := Copy(DirItem.Name,1,DirItem.Name.IndexOf('/'));
+                  end
+                  else
+                  begin
+                    DirItem.IsDir := False;
+                    DirItem.Size := StrToInt64Def(azBlob.Properties.Values['Content-Length'],0);
+                    DirItem.Date := GMT2DateTime(azBlob.Properties.Values['Last-Modified']);
+                  end;
+                  if Assigned(OnGetListItem) then OnGetListItem(DirItem);
+                finally
+                  DirItem.Free;
+                end;
+                azBlob.Free;
+              end;
+            finally
+              //frees azbloblist objects
+              //for azBlob in azBlobList do azBlob.Free;
+              azBlobList.Free;
+            end;
+          end
+          else
+          begin
+            Status := stFailed;
+            Exit;
+          end;
+        finally
+          CloudResponseInfo.Free;
+        end;
+      finally
+        FreeAndNil(AzParams);
+      end;
+      if Assigned(OnRefreshReadDir) then OnRefreshReadDir(CurrentPath);
+    until (cNextMarker = '') or (azResponseInfo.StatusCode <> 200);
+    Status := stDone;
+  finally
+    BlobService.Free;
+    if Assigned(OnEndReadDir) then OnEndReadDir(CurrentPath);
+  end;
+end;
+
+{procedure TCloudStorageAzureProvider.OpenDir(const aPath : string);
+var
+  lista : TBlobList;
+  Blob : TAzureBlobObject;
+  i : Integer;
+  azurefilter : string;
+  DirItem : TCloudItem;
+  respinfo : TAzureResponseInfo;
+begin
+  if aPath = '..' then
+  begin
+    CurrentPath := RemoveLastPathSegment(CurrentPath);
+  end
+  else
+  begin
+    if CurrentPath = '' then CurrentPath := aPath
+      else CurrentPath := CurrentPath + aPath;
+  end;
+  if Assigned(OnBeginReadDir) then OnBeginReadDir(CurrentPath);
+  if CurrentPath.StartsWith('/') then CurrentPath := Copy(CurrentPath,2,CurrentPath.Length);
+  if (not CurrentPath.IsEmpty) and (not CurrentPath.EndsWith('/')) then CurrentPath := CurrentPath + '/';
+
+  Status := stRetrieving;
+  lista := fAzure.ListBlobs(RootFolder,CurrentPath,False,respinfo);
+  try
+    if Assigned(lista) then
+    begin
+      if Assigned(OnGetListItem) then
+      begin
+        DirItem := TCloudItem.Create;
+        try
+          DirItem.Name := '..';
+          DirItem.IsDir := True;
+          DirItem.Date := 0;
+          OnGetListItem(DirItem);
+        finally
+          DirItem.Free;
+        end;
+      end;
+    end;
+
+    if respinfo.StatusCode = 200 then
+    begin
+      for Blob in lista do
+      begin
+        DirItem := TCloudItem.Create;
+        try
+          if Blob.Name.StartsWith(CurrentPath) then Blob.Name := StringReplace(Blob.Name,CurrentPath,'',[]);
+          if Blob.Name.Contains('/') then
+          begin
+            DirItem.IsDir := True;
+            DirItem.Name := Copy(Blob.Name,1,Blob.Name.IndexOf('/'));
+          end
+          else
+          begin
+            DirItem.IsDir := False;
+            DirItem.Name := Blob.Name;
+            DirItem.Size := Blob.Size;
+            DirItem.Date := Blob.LastModified;
+          end;
+          if Assigned(OnGetListItem) then OnGetListItem(DirItem);
+        finally
+          DirItem.Free;
+        end;
+      end;
+      Status := stDone;
+    end
+    else Status := stFailed;
+  finally
+    lista.Free;
+    ResponseInfo.Get(respinfo.StatusCode,respinfo.StatusMsg);
+  end;
+end;}
+
+procedure TCloudStorageAzureProvider.SetSecure(aValue: Boolean);
+begin
+  inherited;
+  if aValue then fAzureConnection.Protocol := 'HTTPS'
+    else fAzureConnection.Protocol := 'HTTP';
+end;
+
+end.

+ 256 - 0
Quick.CloudStorage.pas

@@ -0,0 +1,256 @@
+unit Quick.CloudStorage;
+
+interface
+
+uses
+  Classes,
+  System.SysUtils,
+  System.Generics.Collections,
+  Data.Cloud.CloudAPI;
+
+type
+
+  TCloudActionStatus = (stNone, stSearching, stRetrieving, stDone, stFailed);
+
+  TCloudProtocol = (cpHTTP,cpHTTPS);
+
+  TResponseInfo = record
+    StatusCode : Integer;
+    StatusMsg : string;
+    procedure Get(aStatusCode : Integer; const aStatusMsg : string); overload;
+    procedure Get(aCloudResponseInfo : TCloudResponseInfo); overload;
+  end;
+
+  TCloudItem = class
+  private
+    fName : string;
+    fIsDir : Boolean;
+    fSize : Int64;
+    fDate : TDateTime;
+  public
+    property Name : string read fName write fName;
+    property IsDir : Boolean read fIsDir write fIsDir;
+    property Size : Int64 read fSize write fSize;
+    property Date : TDateTime read fDate write fDate;
+  end;
+
+  TCloudItemList = TObjectList<TCloudItem>;
+
+  TReadDirEvent = procedure(const aDir : string) of object;
+  TGetListItemEvent = procedure(aItem : TCloudItem) of object;
+  TChangeStatusEvent = procedure(aStatus : TCloudActionStatus) of object;
+
+  ICloudStorage = interface
+  ['{5F36CD88-405F-45C1-89E0-9114146CA8D9}']
+  function GetName : string;
+  function GetRootFolders : TStrings;
+  procedure OpenDir(const aPath : string);
+  function GetFile(const aSourcePath: string; out stream : TStream) : Boolean; overload;
+  function GetFile(const aSourcePath, aTargetLocalFile : string) : Boolean; overload;
+  function GetURL(const aPath : string) : string;
+  end;
+
+  TCloudPermissions = class
+  private
+    fCanList : Boolean;
+    fCanRead : Boolean;
+    fCanWrite : Boolean;
+    fCanDelete : Boolean;
+  public
+    property CanList : Boolean read fCanList write fCanList;
+    property CanRead : Boolean read fCanRead write fCanRead;
+    property CanWrite : Boolean read fCanWrite write fCanWrite;
+    property CanDelete : Boolean read fCanDelete write fCanDelete;
+  end;
+
+  TCloudStorageProvider = class(TInterfacedObject,ICloudStorage)
+  private
+    fName : string;
+    fResponseInfo : TResponseInfo;
+    fCurrentPath : string;
+    fOnGetListItem : TGetListItemEvent;
+    fOnBeginReadDir : TReadDirEvent;
+    fOnRefresReadDir : TReadDirEvent;
+    fOnEndReadDir : TReadDirEvent;
+    fOnChangeStatus : TChangeStatusEvent;
+    fStatus: TCloudActionStatus;
+    fRootFolder : string;
+    fTimeout : Integer;
+    fSecure : Boolean;
+    fPermissions : TCloudPermissions;
+    procedure SetStatus(aStatus : TCloudActionStatus);
+  protected
+    fCancelOperation : Boolean;
+    procedure SetSecure(aValue : Boolean); virtual;
+    function GMT2DateTime(const gmtdate : string):TDateTime;
+  public
+    constructor Create; virtual;
+    destructor Destroy; override;
+    property Name : string read fName write fName;
+    property ResponseInfo : TResponseInfo read fResponseInfo write fResponseInfo;
+    property Timeout : Integer read fTimeout write fTimeout;
+    property CurrentPath : string read fCurrentPath write fCurrentPath;
+    property RootFolder : string read fRootFolder write fRootFolder;
+    property OnBeginReadDir : TReadDirEvent read fOnBeginReadDir write fOnBeginReadDir;
+    property OnRefreshReadDir : TReadDirEvent read fOnRefresReadDir write fOnRefresReadDir;
+    property OnEndReadDir : TReadDirEvent read fOnEndReadDir write fOnEndReadDir;
+    property OnGetListItem : TGetListItemEvent read fOnGetListItem write fOnGetListItem;
+    property Status : TCloudActionStatus read fStatus write SetStatus;
+    property Secure : Boolean read fSecure write SetSecure;
+    property OnChangeStatus : TChangeStatusEvent read fOnChangeStatus write fOnChangeStatus;
+    property Permissions : TCloudPermissions read fPermissions write fPermissions;
+    class function GetStatusStr(aStatus : TCloudActionStatus) : string;
+    function GetName : string;
+    function GetRootFolders : TStrings; virtual; abstract;
+    procedure OpenDir(const aPath : string); virtual; abstract;
+    function GetFile(const aPath: string; out stream : TStream) : Boolean; overload; virtual; abstract;
+    function GetFile(const aSourcePath, aTargetLocalFile : string) : Boolean; overload; virtual;
+    function GetURL(const aPath : string) : string; virtual; abstract;
+  end;
+
+implementation
+
+const
+  CloudActionStatusStr : array of string = ['','Searching...','Retrieving...','Done','Failed'];
+
+constructor TCloudStorageProvider.Create;
+begin
+  fCancelOperation := False;
+  fPermissions := TCloudPermissions.Create;
+  fTimeout := 30;
+  fSecure := True;
+  fPermissions.CanList := True;
+  fPermissions.CanRead := True;
+  fPermissions.CanWrite := True;
+  fPermissions.CanDelete := True;
+end;
+
+destructor TCloudStorageProvider.Destroy;
+begin
+  if Assigned(fPermissions) then fPermissions.Free;
+  inherited;
+end;
+
+function TCloudStorageProvider.GetFile(const aSourcePath, aTargetLocalFile: string): Boolean;
+var
+  stream : TStream;
+begin
+  stream := TFileStream.Create(aTargetLocalFile,fmCreate);
+  try
+    Result := GetFile(aSourcePath,stream);
+  finally
+    stream.Free;
+  end;
+end;
+
+function TCloudStorageProvider.GetName: string;
+begin
+  Result := fName;
+end;
+
+class function TCloudStorageProvider.GetStatusStr(aStatus: TCloudActionStatus): string;
+begin
+  Result := CloudActionStatusStr[Integer(aStatus)];
+end;
+
+function TCloudStorageProvider.GMT2DateTime(const gmtdate: string): TDateTime;
+  function GetMonthDig(Value : string):Integer;
+  const
+    aMonth : array[1..12] of string = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
+  var
+    idx : Integer;
+  begin
+    Result := 0;
+    for idx := 1 to 12 do
+    begin
+      if CompareText(Value,aMonth[idx]) = 0 then
+      begin
+        Result := idx;
+        Break;
+      end;
+     end;
+  end;
+var
+  i : Integer;
+  Len : Integer;
+  wDay, wMonth, wYear,
+  wHour, wMinute, wSec : Word;
+begin
+  //GMT Format: 'Mon, 12 Jan 2014 16:20:35 GMT'
+  Result := 0;
+  Len := 0;
+  if gmtdate = '' then Exit;
+
+  try
+    for i := 0 to Length(gmtdate) do
+    begin
+      if gmtdate[i] in ['0'..'9'] then
+      begin
+        Len := i;
+        Break;
+      end;
+    end;
+
+    //Day
+    wDay := StrToIntDef(Copy(gmtdate,Len,2),0);
+    if wDay = 0 then Exit;
+
+    Inc(Len,3);
+
+    //Month
+    wMonth := GetMonthDig(Copy(gmtdate,Len,3));
+    if wMonth = 0 then Exit;
+    Inc(Len,4);
+
+    //Year
+    wYear := StrToIntDef(Copy(gmtdate,Len,4),0);
+    if wYear = 0 then Exit;
+    Inc(Len,5);
+
+    //Hour
+    wHour := StrToIntDef(Copy(gmtdate,Len,2),99);
+    if wHour = 99 then Exit;
+    Inc(Len,3);
+
+    //Min
+    wMinute := StrToIntDef(Copy(gmtdate,Len,2),99);
+    if wMinute = 99 then Exit;
+    Inc(Len,3);
+
+    //Sec
+    wSec := StrToIntDef(Copy(gmtdate,Len,2),99);
+    if wSec = 99 then Exit;
+
+    Result := EncodeDate(wYear,wMonth,wDay) + EncodeTime(wHour,wMinute,wSec,0);
+  except
+    Result := 0;
+  end;
+end;
+
+procedure TCloudStorageProvider.SetSecure(aValue: Boolean);
+begin
+  fSecure := aValue;
+end;
+
+procedure TCloudStorageProvider.SetStatus(aStatus: TCloudActionStatus);
+begin
+  fStatus := aStatus;
+  if Assigned(fOnChangeStatus) then fOnChangeStatus(aStatus);
+end;
+
+
+{ TResponseInfo }
+
+procedure TResponseInfo.Get(aStatusCode: Integer; const aStatusMsg: string);
+begin
+  Self.StatusCode := aStatusCode;
+  Self.StatusMsg := aStatusMsg;
+end;
+
+procedure TResponseInfo.Get(aCloudResponseInfo : TCloudResponseInfo);
+begin
+  Self.StatusCode := aCloudResponseInfo.StatusCode;
+  Self.StatusMsg := aCloudResponseInfo.StatusMessage;
+end;
+
+end.

+ 198 - 0
Quick.Crypto.pas

@@ -0,0 +1,198 @@
+{ ***************************************************************************
+
+  Copyright (c) 2016-2017 Kike Pérez
+
+  Unit        : Quick.Crypto
+  Description : Cryptography utils
+  Author      : Kike Pérez
+  Version     : 1.19
+  Created     : 15/10/2017
+  Modified    : 08/11/2017
+
+  This file is part of QuickLib: https://github.com/exilon/QuickLib
+
+ ***************************************************************************
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+ *************************************************************************** }
+unit Quick.Crypto;
+
+interface
+
+uses
+
+function AES128_Encrypt(Value, Password: string): string;
+function AES128_Decrypt(Value, Password: string): string;
+
+implementation
+
+uses
+  SysUtils, Windows, IdCoderMIME, IdGlobal;
+
+//-------------------------------------------------------------------------------------------------------------------------
+//    Base64 Encode/Decode
+//-------------------------------------------------------------------------------------------------------------------------
+
+function Base64_Encode(Value: TBytes): string;
+var
+  Encoder: TIdEncoderMIME;
+begin
+  Encoder := TIdEncoderMIME.Create(nil);
+  try
+    Result := Encoder.EncodeBytes(TIdBytes(Value));
+  finally
+    Encoder.Free;
+  end;
+end;
+
+function Base64_Decode(Value: string): TBytes;
+var
+  Encoder: TIdDecoderMIME;
+begin
+  Encoder := TIdDecoderMIME.Create(nil);
+  try
+    Result := TBytes(Encoder.DecodeBytes(Value));
+  finally
+    Encoder.Free;
+  end;
+end;
+
+//-------------------------------------------------------------------------------------------------------------------------
+//    WinCrypt.h
+//-------------------------------------------------------------------------------------------------------------------------
+
+type
+  HCRYPTPROV  = Cardinal;
+  HCRYPTKEY   = Cardinal;
+  ALG_ID      = Cardinal;
+  HCRYPTHASH  = Cardinal;
+
+const
+  _lib_ADVAPI32    = 'ADVAPI32.dll';
+  CALG_SHA_256     = 32780;
+  CALG_AES_128     = 26126;
+  CRYPT_NEWKEYSET  = $00000008;
+  PROV_RSA_AES     = 24;
+  KP_MODE          = 4;
+  CRYPT_MODE_CBC   = 1;
+
+function CryptAcquireContext(var Prov: HCRYPTPROV; Container: PChar; Provider: PChar; ProvType: LongWord; Flags: LongWord): LongBool; stdcall; external _lib_ADVAPI32 name 'CryptAcquireContextW';
+function CryptDeriveKey(Prov: HCRYPTPROV; Algid: ALG_ID; BaseData: HCRYPTHASH; Flags: LongWord; var Key: HCRYPTKEY): LongBool; stdcall; external _lib_ADVAPI32 name 'CryptDeriveKey';
+function CryptSetKeyParam(hKey: HCRYPTKEY; dwParam: LongInt; pbData: PBYTE; dwFlags: LongInt): LongBool stdcall; stdcall; external _lib_ADVAPI32 name 'CryptSetKeyParam';
+function CryptEncrypt(Key: HCRYPTKEY; Hash: HCRYPTHASH; Final: LongBool; Flags: LongWord; pbData: PBYTE; var Len: LongInt; BufLen: LongInt): LongBool;stdcall;external _lib_ADVAPI32 name 'CryptEncrypt';
+function CryptDecrypt(Key: HCRYPTKEY; Hash: HCRYPTHASH; Final: LongBool; Flags: LongWord; pbData: PBYTE; var Len: LongInt): LongBool; stdcall; external _lib_ADVAPI32 name 'CryptDecrypt';
+function CryptCreateHash(Prov: HCRYPTPROV; Algid: ALG_ID; Key: HCRYPTKEY; Flags: LongWord; var Hash: HCRYPTHASH): LongBool; stdcall; external _lib_ADVAPI32 name 'CryptCreateHash';
+function CryptHashData(Hash: HCRYPTHASH; Data: PChar; DataLen: LongWord; Flags: LongWord): LongBool; stdcall; external _lib_ADVAPI32 name 'CryptHashData';
+function CryptReleaseContext(hProv: HCRYPTPROV; dwFlags: LongWord): LongBool; stdcall; external _lib_ADVAPI32 name 'CryptReleaseContext';
+function CryptDestroyHash(hHash: HCRYPTHASH): LongBool; stdcall; external _lib_ADVAPI32 name 'CryptDestroyHash';
+function CryptDestroyKey(hKey: HCRYPTKEY): LongBool; stdcall; external _lib_ADVAPI32 name 'CryptDestroyKey';
+
+//-------------------------------------------------------------------------------------------------------------------------
+
+{$WARN SYMBOL_PLATFORM OFF}
+
+function __CryptAcquireContext(ProviderType: Integer): HCRYPTPROV;
+begin
+  if (not CryptAcquireContext(Result, nil, nil, ProviderType, 0)) then
+  begin
+    if HRESULT(GetLastError) = NTE_BAD_KEYSET then
+      Win32Check(CryptAcquireContext(Result, nil, nil, ProviderType, CRYPT_NEWKEYSET))
+    else
+      RaiseLastOSError;
+  end;
+end;
+
+function __AES128_DeriveKeyFromPassword(m_hProv: HCRYPTPROV; Password: string): HCRYPTKEY;
+var
+  hHash: HCRYPTHASH;
+  Mode: DWORD;
+begin
+  Win32Check(CryptCreateHash(m_hProv, CALG_SHA_256, 0, 0, hHash));
+  try
+    Win32Check(CryptHashData(hHash, PChar(Password), Length(Password) * SizeOf(Char), 0));
+    Win32Check(CryptDeriveKey(m_hProv, CALG_AES_128, hHash, 0, Result));
+    // Wine uses a different default mode of CRYPT_MODE_EBC
+    Mode := CRYPT_MODE_CBC;
+    Win32Check(CryptSetKeyParam(Result, KP_MODE, Pointer(@Mode), 0));
+  finally
+    CryptDestroyHash(hHash);
+  end;
+end;
+
+function AES128_Encrypt(Value, Password: string): string;
+var
+  hCProv: HCRYPTPROV;
+  hKey: HCRYPTKEY;
+  lul_datalen: Integer;
+  lul_buflen: Integer;
+  Buffer: TBytes;
+begin
+  Assert(Password <> '');
+  if (Value = '') then
+    Result := ''
+  else begin
+    hCProv := __CryptAcquireContext(PROV_RSA_AES);
+    try
+      hKey := __AES128_DeriveKeyFromPassword(hCProv, Password);
+      try
+        // allocate buffer space
+        lul_datalen := Length(Value) * SizeOf(Char);
+        Buffer := TEncoding.Unicode.GetBytes(Value + '        ');
+        lul_buflen := Length(Buffer);
+        // encrypt to buffer
+        Win32Check(CryptEncrypt(hKey, 0, True, 0, @Buffer[0], lul_datalen, lul_buflen));
+        SetLength(Buffer, lul_datalen);
+        // base 64 result
+        Result := Base64_Encode(Buffer);
+      finally
+        CryptDestroyKey(hKey);
+      end;
+    finally
+      CryptReleaseContext(hCProv, 0);
+    end;
+  end;
+end;
+
+function AES128_Decrypt(Value, Password: string): string;
+var
+  hCProv: HCRYPTPROV;
+  hKey: HCRYPTKEY;
+  lul_datalen: Integer;
+  Buffer: TBytes;
+begin
+  Assert(Password <> '');
+  if Value = '' then
+    Result := ''
+  else begin
+    hCProv := __CryptAcquireContext(PROV_RSA_AES);
+    try
+      hKey := __AES128_DeriveKeyFromPassword(hCProv, Password);
+      try
+        // decode base64
+        Buffer := Base64_Decode(Value);
+        // allocate buffer space
+        lul_datalen := Length(Buffer);
+        // decrypt buffer to to string
+        Win32Check(CryptDecrypt(hKey, 0, True, 0, @Buffer[0], lul_datalen));
+        Result := TEncoding.Unicode.GetString(Buffer, 0, lul_datalen);
+      finally
+        CryptDestroyKey(hKey);
+      end;
+    finally
+      CryptReleaseContext(hCProv, 0);
+    end;
+  end;
+end;
+
+end.

+ 53 - 3
Quick.Threads.pas

@@ -7,7 +7,7 @@
   Author      : Kike Pérez
   Version     : 1.2
   Created     : 09/03/2018
-  Modified    : 07/04/2018
+  Modified    : 19/12/2018
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -36,6 +36,7 @@ interface
 uses
   Classes,
   Types,
+  SysUtils,
   //Quick.Chrono,
   {$IFNDEF FPC}
   System.RTLConsts,
@@ -44,8 +45,7 @@ uses
   {$ELSE}
   RtlConsts,
   Generics.Collections,
-  syncobjs,
-  SysUtils;
+  syncobjs;
   {$ENDIF}
 
 type
@@ -157,6 +157,27 @@ type
   end;
   {$ENDIF}
 
+  {$IFDEF FPC}
+  TProc = procedure of object;
+  {$ENDIF}
+
+  IAnonymousThread = interface
+    procedure Start;
+    function OnTerminate(aProc : TProc) : IAnonymousThread;
+  end;
+
+  TAnonymousThread = class(TInterfacedObject,IAnonymousThread)
+  private
+    fThread : TThread;
+    fTerminateProc : TProc;
+    constructor Create(aProc : TProc);
+    procedure NotifyTerminate(Sender : TObject);
+  public
+    class function Execute(aProc : TProc) : IAnonymousThread;
+    procedure Start;
+    function OnTerminate(aProc : TProc) : IAnonymousThread;
+  end;
+
 implementation
 
 { TThreadedQueueCS<T> }
@@ -634,4 +655,33 @@ begin
 end;
 {$ENDIF}
 
+{ TThreadEx }
+
+constructor TAnonymousThread.Create(aProc : TProc);
+begin
+  fThread := TThread.CreateAnonymousThread(@aProc);
+end;
+
+class function TAnonymousThread.Execute(aProc: TProc): IAnonymousThread;
+begin
+  Result := TAnonymousThread.Create(aProc);
+end;
+
+procedure TAnonymousThread.NotifyTerminate(Sender: TObject);
+begin
+  fTerminateProc;
+end;
+
+function TAnonymousThread.OnTerminate(aProc: TProc): IAnonymousThread;
+begin
+  Result := Self;
+  fTerminateProc := aProc;
+  fThread.OnTerminate := Self.NotifyTerminate;
+end;
+
+procedure TAnonymousThread.Start;
+begin
+  fThread.Start;
+end;
+
 end.

+ 21 - 1
README.md

@@ -4,7 +4,8 @@
 **QuickLib**
 --------
 
-Small delphi/fpc library containing interesting and quick to implement functions, created to simplify application development and crossplatform support.
+Small delphi/fpc library containing interesting and quick to implement functions, created to simplify application development and crossplatform support and improve productivity.
+* NEW: TAnonymousThread simplified
 * NEW: TIndexedObjectList & TSearchObjectList.
 * NEW: RTTIUtils.
 * NEW: Improved firemonkey android compatibility.
@@ -249,6 +250,25 @@ SMTP.SendMail;
 - TThreadedQueueCS: Version of TThreadedQueue with Critical Section.
 - TThreadObjectList: Thread safe Object List.
 - TThreadedQueueList: Thread safe Queue List. Autogrow and with Critical Section.
+- TAnonymousThread: Creates anonymous thread defining unchained Execute and OnTerminate methods.
+```delphi
+//simple anonymousthread
+TAnonymousThread.Execute(
+      procedure
+      var
+        i : Integer;
+      begin
+        for i := 0 to 10 do cout('Working %d',[i],etTrace);
+        cout('executed thread',etSuccess);
+      end)
+    .OnTerminate(
+      procedure
+      begin
+        cout('terminated thread',etSuccess);
+        cout('PRESS <ENTER> TO EXIT',etInfo);
+      end)
+    .Start;
+```
 
 **Quick.Process:** Manages windows processes.
 ```delphi

+ 39 - 0
samples/delphi/QuickThreads/AnonymousThread.dpr

@@ -0,0 +1,39 @@
+program AnonymousThread;
+
+{$APPTYPE CONSOLE}
+
+{$R *.res}
+
+uses
+  Classes,
+  Quick.Commons,
+  Quick.Console,
+  System.SysUtils,
+  Quick.Threads;
+
+begin
+  try
+    ReportMemoryLeaksOnShutdown := True;
+
+    TAnonymousThread.Execute(
+      procedure
+      var
+        i : Integer;
+      begin
+        for i := 0 to 10 do cout('Working %d',[i],etTrace);
+        cout('executed thread',etSuccess);
+      end)
+    .OnTerminate(
+      procedure
+      begin
+        cout('terminated thread',etSuccess);
+        cout('PRESS <ENTER> TO EXIT',etInfo);
+      end)
+    .Start;
+
+    ConsoleWaitForEnterKey;
+  except
+    on E: Exception do
+      Writeln(E.ClassName, ': ', E.Message);
+  end;
+end.

+ 678 - 0
samples/delphi/QuickThreads/AnonymousThread.dproj

@@ -0,0 +1,678 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <PropertyGroup>
+        <ProjectGuid>{4A1D6777-4DA7-4BD7-A82F-1FB652041985}</ProjectGuid>
+        <ProjectVersion>18.5</ProjectVersion>
+        <FrameworkType>None</FrameworkType>
+        <MainSource>AnonymousThread.dpr</MainSource>
+        <Base>True</Base>
+        <Config Condition="'$(Config)'==''">Debug</Config>
+        <Platform Condition="'$(Platform)'==''">Win32</Platform>
+        <TargetedPlatforms>1</TargetedPlatforms>
+        <AppType>Console</AppType>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Android' and '$(Base)'=='true') or '$(Base_Android)'!=''">
+        <Base_Android>true</Base_Android>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='iOSDevice32' and '$(Base)'=='true') or '$(Base_iOSDevice32)'!=''">
+        <Base_iOSDevice32>true</Base_iOSDevice32>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='iOSDevice64' and '$(Base)'=='true') or '$(Base_iOSDevice64)'!=''">
+        <Base_iOSDevice64>true</Base_iOSDevice64>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='iOSSimulator' and '$(Base)'=='true') or '$(Base_iOSSimulator)'!=''">
+        <Base_iOSSimulator>true</Base_iOSSimulator>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='OSX32' and '$(Base)'=='true') or '$(Base_OSX32)'!=''">
+        <Base_OSX32>true</Base_OSX32>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
+        <Base_Win32>true</Base_Win32>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
+        <Base_Win64>true</Base_Win64>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
+        <Cfg_1>true</Cfg_1>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
+        <Cfg_1_Win32>true</Cfg_1_Win32>
+        <CfgParent>Cfg_1</CfgParent>
+        <Cfg_1>true</Cfg_1>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
+        <Cfg_2>true</Cfg_2>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base)'!=''">
+        <DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
+        <DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
+        <DCC_E>false</DCC_E>
+        <DCC_N>false</DCC_N>
+        <DCC_S>false</DCC_S>
+        <DCC_F>false</DCC_F>
+        <DCC_K>false</DCC_K>
+        <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
+        <SanitizedProjectName>AnonymousThread</SanitizedProjectName>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_Android)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;RESTComponents;DBXInterBaseDriver;emsclientfiredac;DataSnapFireDAC;tethering;bindcompfmx;FmxTeeUI;FireDACIBDriver;fmx;FlatButtonSet;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;soapserver;bindengine;CloudService;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;FireDAC;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;ibxpress;xmlrtl;soapmidas;DataSnapNativeClient;ibxbindings;rtl;DbxClientDriver;FireDACDSDriver;CustomIPTransport;bindcomp;CoolTrayIcon_D210_XE7;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage)</DCC_UsePackage>
+        <Android_LauncherIcon36>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png</Android_LauncherIcon36>
+        <Android_LauncherIcon48>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png</Android_LauncherIcon48>
+        <Android_LauncherIcon72>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png</Android_LauncherIcon72>
+        <Android_LauncherIcon96>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png</Android_LauncherIcon96>
+        <Android_LauncherIcon144>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png</Android_LauncherIcon144>
+        <Android_SplashImage426>$(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png</Android_SplashImage426>
+        <Android_SplashImage470>$(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png</Android_SplashImage470>
+        <Android_SplashImage640>$(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png</Android_SplashImage640>
+        <Android_SplashImage960>$(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png</Android_SplashImage960>
+        <EnabledSysJars>android-support-v4.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services-ads-7.0.0.dex.jar;google-play-services-analytics-7.0.0.dex.jar;google-play-services-base-7.0.0.dex.jar;google-play-services-gcm-7.0.0.dex.jar;google-play-services-identity-7.0.0.dex.jar;google-play-services-maps-7.0.0.dex.jar;google-play-services-panorama-7.0.0.dex.jar;google-play-services-plus-7.0.0.dex.jar;google-play-services-wallet-7.0.0.dex.jar</EnabledSysJars>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_iOSDevice32)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;RESTComponents;DBXInterBaseDriver;emsclientfiredac;DataSnapFireDAC;tethering;bindcompfmx;FmxTeeUI;FireDACIBDriver;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;soapserver;bindengine;CloudService;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;FireDAC;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;ibxpress;xmlrtl;soapmidas;DataSnapNativeClient;ibxbindings;rtl;DbxClientDriver;FireDACDSDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_iOSDevice64)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;RESTComponents;DBXInterBaseDriver;emsclientfiredac;DataSnapFireDAC;tethering;bindcompfmx;FmxTeeUI;FireDACIBDriver;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;soapserver;bindengine;CloudService;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;FireDAC;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;ibxpress;xmlrtl;soapmidas;DataSnapNativeClient;ibxbindings;rtl;DbxClientDriver;FireDACDSDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_iOSSimulator)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;RESTComponents;DBXInterBaseDriver;emsclientfiredac;DataSnapFireDAC;tethering;bindcompfmx;FmxTeeUI;FireDACIBDriver;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;soapserver;bindengine;CloudService;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;FireDAC;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;ibxpress;xmlrtl;soapmidas;DataSnapNativeClient;ibxbindings;rtl;DbxClientDriver;FireDACDSDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_OSX32)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXInterBaseDriver;emsclientfiredac;DataSnapFireDAC;tethering;FireDACMSSQLDriver;bindcompfmx;DBXOracleDriver;inetdb;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;soapserver;bindengine;DBXMySQLDriver;FireDACOracleDriver;CloudService;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;FireDAC;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;ibxbindings;rtl;DbxClientDriver;FireDACDSDriver;DBXSybaseASADriver;CustomIPTransport;bindcomp;DBXInformixDriver;IndyIPClient;dbxcds;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
+        <DCC_ConsoleTarget>true</DCC_ConsoleTarget>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_Win32)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;UbuntuProgressPackage;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;svnui;tethering;JvGlobus;FireDACADSDriver;JvPluginSystem;DBXMSSQLDriver;JvMM;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;JvBands;vcldb;bindcompfmx;svn;Intraweb;DBXOracleDriver;JvJans;JvNet;inetdb;JvAppFrm;FmxTeeUI;emsedge;JvDotNetCtrls;FireDACIBDriver;fmx;fmxdae;vclib;FlatButtonSet;JvWizards;FireDACDBXDriver;dbexpress;IndyCore;vclx;JvPageComps;dsnap;DataSnapCommon;emsclient;FireDACCommon;JvDB;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;JclDeveloperTools;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;CloudService;FireDACMySQLDriver;DBXFirebirdDriver;JvCmp;JvHMI;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;GR32_D;JvCustom;vcl;IndyIPServer;DBXSybaseASEDriver;JvXPCtrls;PngComponents;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;FireDAC;Jcl;JvCore;emshosting;JvCrypt;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;FireDACTDataDriver;DBXOdbcDriver;FMXTee;soaprtl;DbxCommonDriver;JvDlgs;JvRuntimeDesign;ibxpress;Tee;JvManagedThreads;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;emsserverresource;DbxClientDriver;FireDACDSDriver;DBXSybaseASADriver;GR32_R;CustomIPTransport;vcldsnap;JvTimeFramework;JvSystem;JvStdCtrls;bindcomp;appanalytics;CoolTrayIcon_D210_XE7;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;JvDocking;dbxcds;VclSmp;KernowSoftwareFMX;adortl;FireDACODBCDriver;JvPascalInterpreter;JclVcl;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;JvControls;JvPrintPreview;Analog_XE7;JclContainers;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
+        <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
+        <BT_BuildType>Debug</BT_BuildType>
+        <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
+        <VerInfo_Locale>1033</VerInfo_Locale>
+        <DCC_ConsoleTarget>true</DCC_ConsoleTarget>
+        <UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
+        <UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_Win64)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;FireDACIBDriver;fmx;fmxdae;vclib;FlatButtonSet;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;CloudService;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;IndyIPServer;DBXSybaseASEDriver;PngComponents;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;FireDACTDataDriver;DBXOdbcDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;emsserverresource;DbxClientDriver;FireDACDSDriver;DBXSybaseASADriver;GR32_R;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
+        <DCC_ConsoleTarget>true</DCC_ConsoleTarget>
+        <UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
+        <UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_1)'!=''">
+        <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
+        <DCC_DebugDCUs>true</DCC_DebugDCUs>
+        <DCC_Optimize>false</DCC_Optimize>
+        <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
+        <DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
+        <DCC_RemoteDebug>true</DCC_RemoteDebug>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
+        <DCC_RemoteDebug>false</DCC_RemoteDebug>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2)'!=''">
+        <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
+        <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
+        <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
+        <DCC_DebugInformation>0</DCC_DebugInformation>
+    </PropertyGroup>
+    <ItemGroup>
+        <DelphiCompile Include="$(MainSource)">
+            <MainSource>MainSource</MainSource>
+        </DelphiCompile>
+        <BuildConfiguration Include="Release">
+            <Key>Cfg_2</Key>
+            <CfgParent>Base</CfgParent>
+        </BuildConfiguration>
+        <BuildConfiguration Include="Base">
+            <Key>Base</Key>
+        </BuildConfiguration>
+        <BuildConfiguration Include="Debug">
+            <Key>Cfg_1</Key>
+            <CfgParent>Base</CfgParent>
+        </BuildConfiguration>
+    </ItemGroup>
+    <ProjectExtensions>
+        <Borland.Personality>Delphi.Personality.12</Borland.Personality>
+        <Borland.ProjectType>Application</Borland.ProjectType>
+        <BorlandProject>
+            <Delphi.Personality>
+                <Source>
+                    <Source Name="MainSource">AnonymousThread.dpr</Source>
+                </Source>
+            </Delphi.Personality>
+            <Deployment Version="3">
+                <DeployFile LocalName="$(BDS)\Redist\osx64\libcgsqlite3.dylib" Class="DependencyModule">
+                    <Platform Name="OSX64">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
+                    <Platform Name="OSX32">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule">
+                    <Platform Name="iOSSimulator">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="$(BDS)\Redist\iossimulator\libpcre.dylib" Class="DependencyModule">
+                    <Platform Name="iOSSimulator">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="$(BDS)\Redist\osx32\libcgsqlite3.dylib" Class="DependencyModule">
+                    <Platform Name="OSX32">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="Win32\Debug\AnonymousThread.exe" Configuration="Debug" Class="ProjectOutput">
+                    <Platform Name="Win32">
+                        <RemoteName>AnonymousThread.exe</RemoteName>
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployClass Name="AdditionalDebugSymbols">
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidClassesDexFile">
+                    <Platform Name="Android">
+                        <RemoteDir>classes</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidFileProvider">
+                    <Platform Name="Android">
+                        <RemoteDir>res\xml</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidGDBServer">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidLibnativeArmeabiFile">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidLibnativeMipsFile">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\mips</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidServiceOutput">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidSplashImageDef">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidSplashStyles">
+                    <Platform Name="Android">
+                        <RemoteDir>res\values</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidSplashStylesV21">
+                    <Platform Name="Android">
+                        <RemoteDir>res\values-v21</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_DefaultAppIcon">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon144">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xxhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon36">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-ldpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon48">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-mdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon72">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-hdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon96">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage426">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-small</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage470">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-normal</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage640">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-large</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage960">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xlarge</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="DebugSymbols">
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="DependencyFramework">
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.framework</Extensions>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.framework</Extensions>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="DependencyModule">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                        <Extensions>.dll;.bpl</Extensions>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Required="true" Name="DependencyPackage">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                        <Extensions>.bpl</Extensions>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="File">
+                    <Platform Name="Android">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice32">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch1024">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch1536">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch2048">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch768">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Launch320">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Launch640">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Launch640x1136">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectAndroidManifest">
+                    <Platform Name="Android">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSDeviceDebug">
+                    <Platform Name="iOSDevice32">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSDeviceResourceRules">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSEntitlements">
+                    <Platform Name="iOSDevice32">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSInfoPList">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSResource">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXDebug">
+                    <Platform Name="OSX64">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXEntitlements">
+                    <Platform Name="OSX32">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXInfoPList">
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXResource">
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\Resources</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\Resources</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Required="true" Name="ProjectOutput">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Linux64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectUWPManifest">
+                    <Platform Name="Win32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="UWP_DelphiLogo150">
+                    <Platform Name="Win32">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="UWP_DelphiLogo44">
+                    <Platform Name="Win32">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="OSX64" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
+            </Deployment>
+            <Platforms>
+                <Platform value="Android">False</Platform>
+                <Platform value="iOSDevice32">False</Platform>
+                <Platform value="iOSDevice64">False</Platform>
+                <Platform value="iOSSimulator">False</Platform>
+                <Platform value="OSX32">False</Platform>
+                <Platform value="Win32">True</Platform>
+                <Platform value="Win64">False</Platform>
+            </Platforms>
+        </BorlandProject>
+        <ProjectFileVersion>12</ProjectFileVersion>
+    </ProjectExtensions>
+    <Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
+    <Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
+    <Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
+</Project>

BIN
samples/delphi/QuickThreads/AnonymousThread.res


BIN
samples/firemonkey/QuickAutoMapper/Android/Debug/AutoMapperObjects/library/lib/armeabi-v7a/gdbserver


+ 42 - 0
samples/firemonkey/QuickAutoMapper/AndroidManifest.template.xml

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- BEGIN_INCLUDE(manifest) -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="%package%"
+        android:versionCode="%versionCode%"
+        android:versionName="%versionName%"
+        android:installLocation="%installLocation%">
+
+    <!-- This is the platform API where NativeActivity was introduced. -->
+    <uses-sdk android:minSdkVersion="%minSdkVersion%" android:targetSdkVersion="%targetSdkVersion%" />
+<%uses-permission%>
+    <uses-feature android:glEsVersion="0x00020000" android:required="True"/>
+    <application android:persistent="%persistent%" 
+        android:restoreAnyVersion="%restoreAnyVersion%" 
+        android:label="%label%" 
+        android:debuggable="%debuggable%" 
+        android:largeHeap="%largeHeap%"
+        android:icon="%icon%"
+        android:theme="%theme%"
+        android:hardwareAccelerated="%hardwareAccelerated%">
+
+<%application-meta-data%>
+		<%services%>
+        <!-- Our activity is a subclass of the built-in NativeActivity framework class.
+             This will take care of integrating with our NDK code. -->
+        <activity android:name="com.embarcadero.firemonkey.FMXNativeActivity"
+                android:label="%activityLabel%"
+                android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
+                android:launchMode="singleTask">
+            <!-- Tell NativeActivity the name of our .so -->
+            <meta-data android:name="android.app.lib_name"
+                android:value="%libNameValue%" />
+            <intent-filter>  
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter> 
+        </activity>
+        <%activity%>
+        <%receivers%>
+    </application>
+</manifest>
+<!-- END_INCLUDE(manifest) -->

+ 241 - 0
samples/firemonkey/QuickAutoMapper/AutoMapperObjects.deployproj

@@ -0,0 +1,241 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <Import Condition="Exists('$(BDS)\bin\CodeGear.Deployment.targets')" Project="$(BDS)\bin\CodeGear.Deployment.targets"/>
+    <ProjectExtensions>
+        <ProjectFileVersion>12</ProjectFileVersion>
+    </ProjectExtensions>
+    <PropertyGroup>
+        <DeviceId Condition="'$(Platform)'=='Android'">emulator-5554</DeviceId>
+        <DeviceId Condition="'$(Platform)'=='iOSDevice32'"/>
+        <DeviceId Condition="'$(Platform)'=='iOSDevice64'"/>
+        <DeviceId Condition="'$(Platform)'=='iOSSimulator'">iPhone5</DeviceId>
+    </PropertyGroup>
+    <ItemGroup Condition="'$(Platform)'=='iOSDevice64'"/>
+    <ItemGroup Condition="'$(Platform)'=='Win64'"/>
+    <ItemGroup Condition="'$(Platform)'=='iOSDevice32'"/>
+    <ItemGroup Condition="'$(Platform)'=='Win32'">
+        <DeployFile Include="Win32\Debug\AutoMapperObjects.exe" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\</RemoteDir>
+            <RemoteName>AutoMapperObjects.exe</RemoteName>
+            <DeployClass>ProjectOutput</DeployClass>
+            <Operation>0</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+            <Required>True</Required>
+        </DeployFile>
+    </ItemGroup>
+    <ItemGroup Condition="'$(Platform)'=='OSX32'">
+        <DeployFile Include="$(BDS)\Redist\osx32\libcgsqlite3.dylib">
+            <RemoteDir>AutoMapperObjects.app\Contents\MacOS\</RemoteDir>
+            <RemoteName>libcgsqlite3.dylib</RemoteName>
+            <DeployClass>DependencyModule</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib">
+            <RemoteDir>AutoMapperObjects.app\Contents\MacOS\</RemoteDir>
+            <RemoteName>libcgunwind.1.0.dylib</RemoteName>
+            <DeployClass>DependencyModule</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+    </ItemGroup>
+    <ItemGroup Condition="'$(Platform)'=='Android'">
+        <DeployFile Include="$(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\res\drawable-ldpi\</RemoteDir>
+            <RemoteName>ic_launcher.png</RemoteName>
+            <DeployClass>Android_LauncherIcon36</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="$(BDS)\lib\android\release\armeabi\libnative-activity.so" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\library\lib\armeabi\</RemoteDir>
+            <RemoteName>libAutoMapperObjects.so</RemoteName>
+            <DeployClass>AndroidLibnativeArmeabiFile</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="Android\Debug\AndroidManifest.xml" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\</RemoteDir>
+            <RemoteName>AndroidManifest.xml</RemoteName>
+            <DeployClass>ProjectAndroidManifest</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="$(BDS)\lib\android\debug\armeabi\libnative-activity.so" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\library\lib\armeabi\</RemoteDir>
+            <RemoteName>libAutoMapperObjects.so</RemoteName>
+            <DeployClass>AndroidLibnativeArmeabiFile</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="$(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\res\drawable-hdpi\</RemoteDir>
+            <RemoteName>ic_launcher.png</RemoteName>
+            <DeployClass>Android_LauncherIcon72</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="$(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\res\drawable-xxhdpi\</RemoteDir>
+            <RemoteName>ic_launcher.png</RemoteName>
+            <DeployClass>Android_LauncherIcon144</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="$(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\res\drawable-xlarge\</RemoteDir>
+            <RemoteName>splash_image.png</RemoteName>
+            <DeployClass>Android_SplashImage960</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="$(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\res\drawable-normal\</RemoteDir>
+            <RemoteName>splash_image.png</RemoteName>
+            <DeployClass>Android_SplashImage470</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="$(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\res\drawable-small\</RemoteDir>
+            <RemoteName>splash_image.png</RemoteName>
+            <DeployClass>Android_SplashImage426</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="$(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\res\drawable-large\</RemoteDir>
+            <RemoteName>splash_image.png</RemoteName>
+            <DeployClass>Android_SplashImage640</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="$(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\res\drawable-xhdpi\</RemoteDir>
+            <RemoteName>ic_launcher.png</RemoteName>
+            <DeployClass>Android_LauncherIcon96</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="$(BDS)\lib\android\release\mips\libnative-activity.so" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\library\lib\mips\</RemoteDir>
+            <RemoteName>libAutoMapperObjects.so</RemoteName>
+            <DeployClass>AndroidLibnativeMipsFile</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="$(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\res\drawable-mdpi\</RemoteDir>
+            <RemoteName>ic_launcher.png</RemoteName>
+            <DeployClass>Android_LauncherIcon48</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="$(BDS)\lib\android\debug\mips\libnative-activity.so" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\library\lib\mips\</RemoteDir>
+            <RemoteName>libAutoMapperObjects.so</RemoteName>
+            <DeployClass>AndroidLibnativeMipsFile</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="Android\Debug\classes.dex" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\classes\</RemoteDir>
+            <RemoteName>classes.dex</RemoteName>
+            <DeployClass>AndroidClassesDexFile</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="Android\Debug\libAutoMapperObjects.so" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\library\lib\armeabi-v7a\</RemoteDir>
+            <RemoteName>libAutoMapperObjects.so</RemoteName>
+            <DeployClass>ProjectOutput</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+            <Required>True</Required>
+        </DeployFile>
+        <DeployFile Include="Android\Debug\splash_image_def.xml" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\res\drawable\</RemoteDir>
+            <RemoteName>splash_image_def.xml</RemoteName>
+            <DeployClass>AndroidSplashImageDef</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="Android\Debug\styles.xml" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\res\values\</RemoteDir>
+            <RemoteName>styles.xml</RemoteName>
+            <DeployClass>AndroidSplashStyles</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="$(NDKBasePath)\prebuilt\android-arm\gdbserver\gdbserver" Condition="'$(Config)'=='Debug'">
+            <RemoteDir>AutoMapperObjects\library\lib\armeabi-v7a\</RemoteDir>
+            <RemoteName>gdbserver</RemoteName>
+            <DeployClass>AndroidGDBServer</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+    </ItemGroup>
+    <ItemGroup Condition="'$(Platform)'=='iOSSimulator'">
+        <DeployFile Include="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib">
+            <RemoteDir>AutoMapperObjects.app\</RemoteDir>
+            <RemoteName>libcgunwind.1.0.dylib</RemoteName>
+            <DeployClass>DependencyModule</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+        <DeployFile Include="$(BDS)\Redist\iossimulator\libPCRE.dylib">
+            <RemoteDir>AutoMapperObjects.app\</RemoteDir>
+            <RemoteName>libPCRE.dylib</RemoteName>
+            <DeployClass>DependencyModule</DeployClass>
+            <Operation>1</Operation>
+            <LocalCommand/>
+            <RemoteCommand/>
+            <Overwrite>True</Overwrite>
+        </DeployFile>
+    </ItemGroup>
+</Project>

+ 60 - 0
samples/fpc/QuickThreads/AnonymousThreads.lpi

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+        <MainUnitHasScaledStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="AnonymousThreads"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0"/>
+    </RunParams>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="AnonymousThreads.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="AnonymousThreads"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <OtherUnitFiles Value="..\..\.."/>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 44 - 0
samples/fpc/QuickThreads/AnonymousThreads.lpr

@@ -0,0 +1,44 @@
+program AnonymousThreads;
+
+{$APPTYPE CONSOLE}
+
+{$MODE DELPHI}
+
+uses
+  Classes,
+  Quick.Commons,
+  Quick.Console,
+  SysUtils,
+  Quick.Threads;
+
+type
+  TMyProcs = class
+    class procedure DoWork;
+    class procedure DoTerminate;
+  end;
+
+  class procedure TMyProcs.DoWork;
+  var
+    i : Integer;
+  begin
+    for i := 0 to 10 do cout('Working %d',[i],etTrace);
+    cout('executed thread',etSuccess);
+  end;
+
+  class procedure TMyProcs.DoTerminate;
+  begin
+    cout('terminated thread',etSuccess);
+    cout('PRESS <ENTER> TO EXIT',TLogEventType.etInfo);
+  end;
+
+begin
+  try
+    TAnonymousThread.Execute(TMyProcs.DoWork)
+    .OnTerminate(TMyProcs.DoTerminate).Start;
+
+    ConsoleWaitForEnterKey;
+  except
+    on E: Exception do
+      Writeln(E.ClassName, ': ', E.Message);
+  end;
+end.