Subversion Repositories autosfx

Rev

Blame | Last modification | View Log | RSS feed

  1. unit Unit1;    { ViewZip - Demo4 of Delphi Zip }
  2. { This is a Delphi example of how a small self-installing program
  3.   might be written.  If it runs with an argument of /INSTALL, it automatically
  4.   brings up the install menu.  If it runs with an argument of /UNINSTALL
  5.   (such as when running from the Control Panel Uninstall option), it
  6.   does the uninstall and exits.  If the argument is anything else, then
  7.   it assumes it's a zip file and tries to open it.
  8.  
  9.   IMPORTANT!!!  The "InstUnit" is designed for Win95 Registry keys.  It
  10.   should work on Win98, but it will likely require some tweaks for WinNT.
  11.   YOU HAVE BEEN WARNED!
  12. }
  13. (************************************************************************
  14.  Copyright (C) 2009, 2010  by Russell J. Peters, Roger Aelbrecht,
  15.       Eric W. Engler and Chris Vleghert.
  16.  
  17.    This file is part of TZipMaster Version 1.9.
  18.  
  19.     TZipMaster is free software: you can redistribute it and/or modify
  20.     it under the terms of the GNU Lesser General Public License as published by
  21.     the Free Software Foundation, either version 3 of the License, or
  22.     (at your option) any later version.
  23.  
  24.     TZipMaster is distributed in the hope that it will be useful,
  25.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.     GNU Lesser General Public License for more details.
  28.  
  29.     You should have received a copy of the GNU Lesser General Public License
  30.     along with TZipMaster.  If not, see <http://www.gnu.org/licenses/>.
  31.  
  32.     contact: problems@delphizip.org (include ZipMaster in the subject).
  33.     updates: http://www.delphizip.org
  34.     DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip
  35. ************************************************************************)
  36.  
  37. interface
  38.  
  39. uses
  40.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  41.   StdCtrls, Grids, ExtCtrls, SortGrid, InstUnit, ZipMstr19, ImgList;
  42.  
  43. //{$IfDef VER90} // Delphi 2 is a special case
  44. //   type LPCTSTR = PChar;
  45. //{$EndIf}
  46.  
  47. // Prototypes for functions that we explicitly import from Kernel32.DLL
  48. type PROCFREELIBRARY     = function( hInst: THandle ): Boolean; stdcall;
  49. type PROCDELETEFILE      = function ( aFile: LPCTSTR ): Boolean; stdcall;
  50. type PROCREMOVEDIRECTORY = function( aDir: LPCTSTR ): Boolean; stdcall;
  51. type PROCEXITPROCESS     = procedure( aVal: DWORD ); stdcall;
  52.  
  53. // Data structure containing all the information we need to delete ourself,
  54. // remove our containing directory, and terminate ourself.
  55. type DELEXEINFO = packed record
  56.    hInstExe:           THandle;
  57.    pfnFreeLibrary:     PROCFREELIBRARY;
  58.    pfnDeleteFile:      PROCDELETEFILE;
  59.    FileName:           Array [0..MAX_PATH] of Char;
  60.    pfnRemoveDirectory: PROCREMOVEDIRECTORY;
  61.    Dir:                Array [0..MAX_PATH] of Char;
  62.    pfnExitProcess:     PROCEXITPROCESS;
  63.    ExitCode:           DWORD;
  64.  end;
  65. type pDELEXEINFO = ^DELEXEINFO;
  66.  
  67. type PROCDELEXE = procedure( pDEI: pDELEXEINFO ); stdcall;
  68.  
  69. type
  70.   TForm1 = class( TForm )
  71.     Panel1:      TPanel;
  72.     OpenBut:     TButton;
  73.     CancelBut:   TButton;
  74.     InstBut:     TButton;
  75.     Label1:      TLabel;
  76.     Label2:      TLabel;
  77.     ZipFName:    TLabel;
  78.     Label4:      TLabel;
  79.     OpenDialog1: TOpenDialog;
  80.     ImageList1:  TImageList;
  81.     ZipDir1: TZipMaster19;
  82.  
  83.     procedure FormCreate( Sender: TObject );
  84.     procedure FormActivate( Sender: TObject );
  85.     procedure OpenButClick( Sender: TObject );
  86.     procedure CancelButClick( Sender: TObject );
  87.     procedure InstButClick( Sender: TObject );
  88.     procedure SortGrid1DrawCell( Sender: TObject; ACol, ARow: LongInt; Rect: TRect; State: TGridDrawState );
  89.     procedure SortGrid1ClickSort( Sender: TObject; Col, Row: Longint; var SortOptions: TSortOptions );
  90.  
  91.   private
  92.     { Private declarations }
  93.  
  94.   public
  95.     { Public declarations }    
  96.     SortGrid1:   TSortGrid;
  97.     GSortOptions:  TSortOptions;
  98.     GSortCol:      Integer;
  99.     AutoUninstall: Boolean;
  100.  
  101.     procedure FillGrid;
  102.   end;
  103.  
  104. const
  105.   HEAP_ZERO_MEMORY = $00000008;  
  106.  
  107. var
  108.   Form1: TForm1;
  109.  
  110. //  procedure DelExeInjCode( pdei: PDELEXEINFO ); stdcall;
  111. //  procedure AfterDelExeInjCode; stdcall;
  112. //  procedure KillMySelf( exitcode: Integer; fRemoveDir: Boolean ); stdcall;
  113.  
  114. implementation
  115.  
  116. {$R *.DFM}
  117. uses
  118.   printers;
  119.  
  120. procedure TForm1.FormCreate( Sender: TObject );
  121. begin
  122.    SortGrid1 := TSortGrid.Create(self);
  123.    SortGrid1.Parent := Self;
  124.    with SortGrid1 do
  125.    begin
  126.     Left := 0;
  127.     Top := 89;
  128.     Width := 572;
  129.     Height := 224;
  130.     Align := alClient;
  131.     ColCount := 4;
  132.     DefaultRowHeight := 18;
  133.     FixedCols := 0;
  134.     RowCount := 2;
  135.     Options := [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goColSizing, goRowSelect];
  136.     TabOrder := 1;
  137.     OnDrawCell := SortGrid1DrawCell;
  138.     CaseSensitive := False;
  139.     AlignmentHorz := taLeftJustify;
  140.     AlignmentVert := taTopJustify;
  141.     ProportionalScrollBars := True;
  142.     ExtendedKeys := False;
  143.     SortOnClick := True;
  144.     FooterFont.Charset := DEFAULT_CHARSET;
  145.     FooterFont.Color := clWindowText;
  146.     FooterFont.Height := -11;
  147.     FooterFont.Name := 'MS Sans Serif';
  148.     FooterFont.Style := [];
  149.     PrintOptions.Orientation := poPortrait;
  150.     PrintOptions.PageTitleMargin := 0;
  151.     PrintOptions.PageFooter := 'date|time|page';
  152.     PrintOptions.HeaderSize := 10;
  153.     PrintOptions.FooterSize := 7;
  154.     PrintOptions.DateFormat := 'd-mmm-yyyy';
  155.     PrintOptions.TimeFormat := 'h:nn';
  156.     PrintOptions.FromRow := 0;
  157.     PrintOptions.ToRow := 0;
  158.     PrintOptions.BorderStyle := bsNone;
  159.     PrintOptions.MarginBottom := 0;
  160.     PrintOptions.MarginLeft := 0;
  161.     PrintOptions.MarginTop := 0;
  162.     PrintOptions.MarginRight := 0;
  163.     WordWrap := False;
  164.     OnClickSort := SortGrid1ClickSort;
  165.     ColWidths[0] := 306;
  166.     ColWidths[1] := 94;
  167.     ColWidths[2] := 100;
  168.     ColWidths[3] := 120;
  169.       Cells[0, 0]  := 'File Name';
  170.       Cells[1, 0]  := 'Compr Size';
  171.       Cells[2, 0]  := 'Uncmpr Size';
  172.       Cells[3, 0]  := 'Date/Time';
  173.    end;
  174.  
  175.    { Allowable Command Line parameters:
  176.        a zip filename = display it's contents
  177.        /install = bring up install menu automatically
  178.        /uninstall = do the uninstall and quit (no menu)
  179.    }
  180.    if ParamCount > 0 then
  181.    begin
  182.       if UpperCase( ParamStr( 1 ) ) = '/INSTALL' then
  183.       begin
  184.          AutoUnInstall := False;
  185.          InstButClick( Self );   { show install menu }
  186.       end
  187.       else if UpperCase( ParamStr( 1 ) ) = '/UNINSTALL' then
  188.       begin
  189.          AutoUnInstall := True;
  190.          InstButClick( Self );  { do the un-install }
  191.       end
  192.       else
  193.       begin
  194.          { someone passed us an argument that is most likely
  195.          the name of a zip file }
  196.          if FileExists( ParamStr( 1 ) ) then
  197.          begin
  198.             ZipFName.Caption := ParamStr( 1 );
  199.             { This assignment causes zipfile to be read: }
  200.             ZipDir1.ZipFileName := ZipFName.Caption;
  201.             FillGrid;
  202.          end
  203.          else
  204.             ShowMessage( 'File Not Found: ' + ParamStr( 1 ) );
  205.       end;
  206.    end;
  207. end;
  208.  
  209. procedure TForm1.FormActivate( Sender: TObject );
  210. begin
  211.    if AutoUnInstall then
  212.       { The user just un-installed us: either from the Control Panel, or
  213.         from our Install Menu.  Either way, he obviously doesn't want
  214.         us to continue running now. }
  215.       Close;
  216. end;
  217.  
  218. procedure TForm1.OpenButClick( Sender: TObject );
  219. begin
  220.    if OpenDialog1.Execute then
  221.    begin
  222.       ZipFName.Caption := OpenDialog1.Filename;
  223.       { This assignment causes zipfile to be read: }
  224.       ZipDir1.ZipFileName := ZipFName.Caption;
  225.       FillGrid;
  226.    end;
  227. end;
  228.  
  229. procedure TForm1.CancelButClick( Sender: TObject );
  230. begin
  231.    Close;
  232. end;
  233.  
  234. procedure TForm1.InstButClick( Sender: TObject );
  235. var
  236.    InstForm: TInstForm;
  237. begin
  238.    InstForm := TInstForm.Create( Self );
  239.    InstForm.ShowModal;
  240.    InstForm.Destroy;
  241. end;
  242.  
  243.  
  244. //---------------------------------------------------------------------------
  245. procedure TForm1.FillGrid;
  246. var
  247.   i: Integer;
  248. begin
  249.   with SortGrid1 do
  250.   begin
  251.     { Empty data from string grid }
  252.     RowCount  := 2; { remove everything from grid except col titles }
  253.     Rows[1].Clear();
  254.     if ZipDir1.Count = 0 then
  255.        Exit;
  256.  
  257.     RowCount := ZipDir1.Count + 1;
  258.     for i := 1 to ZipDir1.Count do
  259.     begin
  260.   //     with ZipDirEntry( ZipDir1.ZipContents[i - 1]^ ) do  // old way
  261.            with ZipDir1.DirEntry[i - 1]{^} do    // new
  262.        begin
  263.           { The "-1" below is an offset for the row titles }
  264.           Cells[0, i] := FileName;
  265.           Cells[1, i] := IntToStr( CompressedSize );
  266.           Cells[2, i] := IntToStr( UncompressedSize );
  267.           Cells[3, i] := FormatDateTime( 'ddddd  t', FileDateToDateTime( DateTime ) );
  268.        end; // end with
  269.     end; // end for
  270.     SortByColumn( GSortCol, GSortOptions );
  271.   end; // end with
  272. end;
  273.  
  274. procedure TForm1.SortGrid1ClickSort( Sender: TObject; Col, Row: LongInt; var SortOptions: TSortOptions );
  275. begin
  276.    if GSortOptions.SortDirection = sdAscending then
  277.       GSortOptions.SortDirection := sdDescending
  278.    else
  279.       GSortOptions.SortDirection := sdAscending;
  280.    GSortCol    := Col;
  281.    SortOptions := GSortOptions;
  282. end;
  283.  
  284. procedure TForm1.SortGrid1DrawCell( Sender: TObject; ACol, ARow: LongInt; Rect: TRect; State: TGridDrawState );
  285. var
  286.   direction: Integer;
  287. begin
  288.    if (ARow = 0) and (ACol = GSortCol) then
  289.    begin
  290.       if GSortOptions.SortDirection = sdAscending then
  291.          direction := 0
  292.       else
  293.          direction := 1;
  294.       ImageList1.Draw( SortGrid1.Canvas, Rect.Right - 18, 0, direction );
  295.    end;
  296. end;
  297.  
  298. {$ifdef NEVER}
  299. //---------------------------------------------------------------------------
  300. // Code to be injected into our own address space.
  301. procedure DelExeInjCode( pdei: pDELEXEINFO ); stdcall;
  302. begin
  303.   // Remove the EXE file from our address space
  304.   pdei.pfnFreeLibrary( pdei.hinstExe );
  305.  
  306.   // Delete the EXE file now that it is no longer in use
  307.   pdei.pfnDeleteFile( pdei.FileName );
  308.  
  309.   if @pdei.pfnRemoveDirectory <> nil then // Remove the directory (which is now empty)
  310.      pdei.pfnRemoveDirectory( pdei.Dir );
  311.  
  312.   // Terminate our process
  313.   pdei.pfnExitProcess( pdei.ExitCode );
  314. end;
  315.  
  316. // This function just marks the end of the previous function.
  317. procedure AfterDelExeInjCode; stdcall
  318. begin
  319. end;
  320.  
  321. // I'm showing you here how to delete an .exe file from within itself.
  322. // This is not protable accross Windows versions.
  323. // This is just "For your info...".
  324. procedure KillMySelf( exitcode: Integer; fRemoveDir: Boolean ); stdcall
  325. var
  326.   dei:       DELEXEINFO;
  327.   hinstKrnl: THandle;
  328.   hheap:     THandle;
  329.   FuncSize:  Integer;
  330.   pfnDelExe: PROCDELEXE;
  331.   P:         PChar;
  332. begin
  333.   if Win32Platform = VER_PLATFORM_WIN32_NT then
  334.      Exit;
  335.  
  336.   hinstKrnl := GetModuleHandle( 'KERNEL32' );
  337.   hheap     := GetProcessHeap();
  338.  
  339.   // Calculate the number of bytes in the DelExeInjCode function.
  340.   FuncSize := Integer(DWord(@AfterDelExeInjCode) - DWord(@DelExeInjCode));
  341.  
  342.   // From our process's default heap, allocate memory where we can inject our own function.
  343.   @pfnDelExe := HeapAlloc( hheap, HEAP_ZERO_MEMORY, FuncSize );
  344.  
  345.   // Inject the DelExeInjCode function into the memory block
  346.   CopyMemory( @pfnDelExe, @DelExeInjCode, FuncSize );
  347.  
  348.   // Initialize the DELEXEINFO structure.
  349.   dei.hinstExe := GetModuleHandle( nil );
  350.   @dei.pfnFreeLibrary := GetProcAddress( hinstKrnl, 'FreeLibrary' );
  351.  
  352.   // Assume that the subdirectory is NOT to be removed.
  353.   dei.pfnRemoveDirectory := nil;
  354.   @dei.pfnDeleteFile := GetProcAddress( hinstKrnl, 'DeleteFileA' );
  355.   GetModuleFileName( dei.hinstExe, dei.FileName, MAX_PATH );
  356.  
  357.   if fRemoveDir then
  358.   begin // The subdirectory should be removed.
  359.     @dei.pfnRemoveDirectory := GetProcAddress( hinstKrnl, 'RemoveDirectoryA' );
  360.     StrCopy( dei.Dir, dei.FileName );
  361.     P := StrRScan( dei.Dir, '\' );
  362.     if P <> nil then
  363.        P^ := #0;
  364.   end;
  365.  
  366.   @dei.pfnExitProcess := GetProcAddress( hinstKrnl, 'ExitProcess' );
  367.   dei.ExitCode := exitcode;
  368.  
  369.   pfnDelExe( @dei );
  370.   // We never get here because pfnDelExe never returns.
  371. end;
  372. {$endif}
  373.  
  374. end.
  375.