Mmmemmap.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:14k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Tel.: +0351-8012255                   =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/mmtools.html             =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 20.01.1998 - 18:00:00 $                                      =}
  24. {========================================================================}
  25. unit MMMemMap;
  26. {$I COMPILER.INC}
  27. {.$DEFINE _MMDEBUG}
  28. interface
  29. uses
  30.     Windows,
  31.     Messages,
  32.     SysUtils,
  33.     Classes,
  34.     Graphics,
  35.     Controls,
  36.     Forms,
  37.     Dialogs,
  38.     MMObj,
  39.     MMUtils,
  40.     MMString;
  41. type
  42.     EMMMemMapFileError = class(Exception);
  43.     TMMAccessMode = (amRead, amReadWrite);
  44.     TMMShareMode  = (smNone, smRead, smWrite, smReadWrite);
  45.     TMMCreateMode = (cmCreateNew, cmCreateAlways, cmOpenExisting,
  46.                      cmOpenAlways, cmTruncateExisting );
  47.     {-- TMMMemMapFile ---------------------------------------------------}
  48.     TMMMemMapFile = class(TMMNonVisualComponent)
  49.     private
  50.        FAccessMode : TMMAccessMode;
  51.        FShareMode  : TMMShareMode;
  52.        FCreateMode : TMMCreateMode;
  53.        FActive     : Boolean;
  54.        FFileData   : Pointer;
  55.        FFileName   : TFileName;
  56.        FFileSize   : Longint;
  57.        HFile       : THandle;
  58.        HFileMapping: THandle;
  59.        FProtect    : Longint;
  60.        FMapAccess  : Longint;
  61.        FHighSize   : Longint;
  62.        FMapOffset  : LongInt;
  63.        FMapSize    : LongInt;
  64.        FDataPtr    : Pointer;
  65.        procedure CreateFileHandle;
  66.        procedure CloseFileHandle;
  67.        procedure CreateFileView;
  68.        procedure CloseFileView;
  69.        procedure SetActive(aValue: Boolean);
  70.        procedure SetFileName(aValue: TFileName);
  71.        procedure SetFileSize(aValue: Longint);
  72.        procedure SetMapOffset(Value: LongInt);
  73.        procedure SetMapSize(Value: LongInt);
  74.        function  GetFileData : Pointer;
  75.        function  GetHandle : THandle;
  76.        function  GetMapSize : LongInt;
  77.     public
  78.        constructor Create(AOwner: TComponent); override;
  79.        destructor Destroy; override;
  80.        procedure  OpenFile;
  81.        procedure  FlushFile;
  82.        procedure  CloseFile;
  83.        property   Handle: THandle read GetHandle;
  84.        property   Active: Boolean read FActive write SetActive;
  85.        property   FileData: Pointer read GetFileData;
  86.     published
  87.        property CreateMode: TMMCreateMode read FCreateMode write FCreateMode default cmOpenAlways;
  88.        property AccessMode: TMMAccessMode read FAccessMode write FAccessMode default amReadWrite;
  89.        property ShareMode: TMMShareMode read FShareMode write FShareMode default smReadWrite;
  90.        property FileName: TFileName read FFileName write SetFileName;
  91.        property FileSize: Longint read FFileSize write SetFileSize;
  92.        property MapOffset: LongInt read FMapOffset write SetMapOffset;
  93.        property MapSize  : LongInt read GetMapSize write SetMapSize;
  94.     end;
  95. implementation
  96. var
  97.    AllocationGranularity: LongInt = 0;
  98. {------------------------------------------------------------------------}
  99. function FormatError(Text: String): String;
  100. begin
  101.    Result := Text+' '+IntToStr(GetLastError)+',  '+SysErrorMessage(GetLastError);
  102. end;
  103. {-- TMMMemMapFile -------------------------------------------------------}
  104. constructor TMMMemMapFile.Create(AOwner: TComponent);
  105. begin
  106.    inherited Create(AOwner);
  107.    HFile := INVALID_HANDLE_VALUE;
  108.    FAccessMode := amReadWrite;
  109.    FShareMode := smReadWrite;
  110.    FCreateMode := cmOpenAlways;
  111.    FActive := False;
  112.    ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  113.    if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  114. end;
  115. {-- TMMMemMapFile -------------------------------------------------------}
  116. destructor TMMMemMapFile.Destroy;
  117. begin
  118.    CloseFile;
  119.    inherited Destroy;
  120. end;
  121. {-- TMMMemMapFile -------------------------------------------------------}
  122. { Open and Close methods are another way of changing the Active property.}
  123. procedure TMMMemMapFile.CloseFile;
  124. begin
  125.    Active := False;
  126. end;
  127. {-- TMMMemMapFile -------------------------------------------------------}
  128. procedure TMMMemMapFile.OpenFile;
  129. begin
  130.    Active := True;
  131. end;
  132. {-- TMMMemMapFile -------------------------------------------------------}
  133. {  NOTE: if the file not exits, set new fileName and then the req. size  }
  134. procedure TMMMemMapFile.SetFileName(aValue: TFileName);
  135. begin
  136.    if (aValue <> FFileName) then
  137.    begin
  138.       if Active then CloseFile;
  139.       FFileName := aValue;
  140.       if (FFileName <> '') and FileExists(FFileName) then
  141.       begin
  142.          { look if the file is OK. }
  143.          CreateFileHandle;
  144.          { Get the size of the file and make this the default value for }
  145.          { the mapped file                                              }
  146.          FFileSize := Windows.GetFileSize(HFile, @FHighSize);
  147.       end
  148.       else FFileSize := 0;
  149.       FMapOffset := 0 ;
  150.       FMapSize   := 0 ; { Map all file }
  151.       CloseFileHandle;
  152.       { Don't allow use of files larger than 4gig ... for now }
  153.       if FHighSize <> 0 then
  154.       begin
  155.          FFileName := '';
  156.          FFileSize := 0;
  157.          raise EMMMemMapFileError.Create(LoadResStr(IDS_MMTOBIG));
  158.       end;
  159.    end;
  160.    {$IFDEF TRIAL}
  161.    {$DEFINE _HACK1}
  162.    {$I MMHACK.INC}
  163.    {$ENDIF}
  164. end;
  165. {-- TMMMemMapFile -------------------------------------------------------}
  166. procedure TMMMemMapFile.SetFileSize(aValue: Longint);
  167. begin
  168.    if (aValue <> FFileSize) then
  169.    begin
  170.       FFileSize := Max(aValue,0);
  171.       if Active then
  172.       begin
  173.          { set the new FileSize }
  174.          Active := False;
  175.          Active := True;
  176.       end;
  177.    end;
  178. end;
  179. {-- TMMMemMapFile -------------------------------------------------------}
  180. { This routine creates the file kernal object.                           }
  181. procedure TMMMemMapFile.CreateFileHandle;
  182. const
  183.   AccessFlags : array[TMMAccessMode] of LongInt =
  184.                       (GENERIC_READ,GENERIC_READ or GENERIC_WRITE);
  185.   ShareFlags  : array[TMMShareMode] of LongInt =
  186.                       (0,FILE_SHARE_READ,FILE_SHARE_WRITE,
  187.                       FILE_SHARE_READ or FILE_SHARE_WRITE);
  188.   CreateFlags : array[TMMCreateMode] of LongInt =
  189.                       (CREATE_NEW,CREATE_ALWAYS,OPEN_EXISTING,
  190.                       OPEN_ALWAYS,TRUNCATE_EXISTING);
  191. Var
  192.   dwAccess, dwShare, dwCreate: Longint;
  193. begin
  194.    { If a handle is open, make sure to close it }
  195.    CloseFileHandle;
  196.    // FFileSize := 0;
  197.    { Determine settings for CreateFile call }
  198.    case FAccessMode of
  199.         amRead:
  200.         begin
  201.            FProtect   := PAGE_READONLY;
  202.            FMapAccess := FILE_MAP_READ;
  203.         end;
  204.         amReadWrite:
  205.         begin
  206.            FProtect   := PAGE_READWRITE;
  207.            FMapAccess := FILE_MAP_ALL_ACCESS;
  208.         end;
  209.    end;
  210.    dwAccess := AccessFlags[FAccessMode];
  211.    dwShare  := ShareFlags[FShareMode];
  212.    dwCreate := CreateFlags[FCreateMode];
  213.    {$IFDEF _MMDEBUG}
  214.    DB_WriteStrLn(0,'Filename: ' + FFileName) ;
  215.    DB_FormatLn(0,'AccessMode: %x ShareMode: %x CreateMode: %x', [dwAccess, dwShare, dwCreate]);
  216.    {$ENDIF}
  217.    { Call CreateFile, and check for success }
  218.    HFile := CreateFile(PChar(FFileName), dwAccess, dwShare, nil, dwCreate,
  219.                        FILE_ATTRIBUTE_NORMAL, 0);
  220.    if HFile = INVALID_HANDLE_VALUE then
  221.    begin
  222.       { Removed to avoid file name lost when sharing violation occured }
  223.       { FFileName := '';}
  224.       FFileSize := 0;
  225.       raise EMMMemMapFileError.Create(FormatError('CreateFile failed with Error Code:'));
  226.    end;
  227. end;
  228. {-- TMMMemMapFile -------------------------------------------------------}
  229. procedure TMMMemMapFile.CloseFileHandle;
  230. begin
  231.    if HFile <> INVALID_HANDLE_VALUE then
  232.    begin
  233.       CloseHandle(HFile);
  234.       HFile := INVALID_HANDLE_VALUE;
  235.    end;
  236. end;
  237. {-- TMMMemMapFile -------------------------------------------------------}
  238. procedure TMMMemMapFile.CreateFileView;
  239. var
  240.     ActualOffs, ActualSize : LongInt ;
  241. begin
  242.    if (HFile <> INVALID_HANDLE_VALUE) and (HFileMapping = 0) then
  243.    begin
  244.       {$IFDEF _MMDEBUG}
  245.       DB_WriteStrLn('FFileSize = ' + IntToStr(FFileSize));
  246.       {$ENDIF}
  247.       HFileMapping := CreateFileMapping(HFile, nil, FProtect, 0, FFileSize, nil);
  248.       if (HFileMapping = 0) then
  249.           raise EMMMemMapFileError.Create(FormatError('CreateFileMapping failed with Error Code:'));
  250.       {$IFDEF _MMDEBUG}
  251.       DB_FormatLn('Offs: %d Size: %d', [FMapOffset,FMapSize]);
  252.       {$ENDIF}
  253.       if FMapOffset >= FFileSize then
  254.          raise  EMMMemMapFileError.Create(LoadResStr(IDS_MMBEYOND));
  255.       if FMapOffset + FMapSize > FFileSize then
  256.          raise  EMMMemMapFileError.Create(LoadResStr(IDS_MMEXCEED));
  257.       ActualOffs := FMapOffset - FMapOffset mod AllocationGranularity ;
  258.       ActualSize := FMapOffset - ActualOffs + FMapSize ;
  259.       FDataPtr   := nil ;
  260.       FFileData  := MapViewOfFile(HFileMapping, FMapAccess, 0, ActualOffs, ActualSize);
  261.       if FFileData = nil then
  262.          raise EMMMemMapFileError.Create(FormatError('MapViewOfFile failed with Error Code:'));
  263.       FDataPtr   := FFileData ;
  264.       Inc(PChar(FDataPtr),FMapOffset-ActualOffs);
  265.    end;
  266. end;
  267. {-- TMMMemMapFile -------------------------------------------------------}
  268. procedure TMMMemMapFile.CloseFileView;
  269. begin
  270.    if (FFileData <> nil) then
  271.    begin
  272.       UnmapViewOfFile(FFileData);
  273.       FFileData := nil;
  274.    end;
  275.    if (HFileMapping <> 0) then
  276.    begin
  277.       CloseHandle(HFileMapping);
  278.       HFileMapping := 0;
  279.    end;
  280. end;
  281. {-- TMMMemMapFile -------------------------------------------------------}
  282. { Setting Active to true establishes the mapping and commits physical    }
  283. { storage to the region.                                                 }
  284. procedure TMMMemMapFile.SetActive(aValue: Boolean);
  285. begin
  286.    if FActive <> aValue then
  287.    begin
  288.       if Not (csDesigning in ComponentState) then
  289.       begin
  290.          if aValue then
  291.          begin
  292.             try
  293.                CreateFileHandle;
  294.                CreateFileView;
  295.             except
  296.                CloseFileView;
  297.                CloseFileHandle;
  298.                raise;
  299.             end;
  300.          end
  301.          else
  302.          begin
  303.             CloseFileView;
  304.             CloseFileHandle;
  305.          end;
  306.       end;
  307.       FActive := aValue;
  308.    end;
  309. end;
  310. {-- TMMMemMapFile -------------------------------------------------------}
  311. { Allow the user to flush the data if desired.                           }
  312. procedure TMMMemMapFile.FlushFile;
  313. begin
  314.    if FActive then FlushViewOfFile(FFileData, FFileSize);
  315. end;
  316. {-- TMMMemMapFile -------------------------------------------------------}
  317. procedure TMMMemMapFile.SetMapOffset(Value: LongInt);
  318. begin
  319.    if (Value < 0) or ((FFileSize <> 0) and (Value >= FFileSize)) then
  320.        raise EMMMemMapFileError.Create(LoadResStr(IDS_MMINVALIDOFFSET));
  321.     if Value <> FMapOffset then
  322.     begin
  323.        FMapOffset := Value;
  324.        if Active then
  325.        begin
  326.           Active := False;
  327.           Active := True;
  328.        end;
  329.     end;
  330.    {$IFDEF TRIAL}
  331.    {$DEFINE _HACK2}
  332.    {$I MMHACK.INC}
  333.    {$ENDIF}
  334. end;
  335. {-- TMMMemMapFile -------------------------------------------------------}
  336. procedure TMMMemMapFile.SetMapSize(Value: LongInt);
  337. begin
  338.    if (Value < 0) or (Value + FMapOffset > FFileSize) then
  339.       raise EMMMemMapFileError.Create(LoadResStr(IDS_MMINVALIDSIZE));
  340.    if (Value <> FMapSize) then
  341.    begin
  342.       FMapSize := Value;
  343.       if Active then
  344.       begin
  345.          Active := False;
  346.          Active := True;
  347.       end;
  348.    end;
  349.    {$IFDEF TRIAL}
  350.    {$DEFINE _HACK3}
  351.    {$I MMHACK.INC}
  352.    {$ENDIF}
  353. end;
  354. {-- TMMMemMapFile -------------------------------------------------------}
  355. function TMMMemMapFile.GetFileData: Pointer;
  356. begin
  357.    if not Active then OpenFile;
  358.    Result := FDataPtr;
  359. end;
  360. {-- TMMMemMapFile -------------------------------------------------------}
  361. function TMMMemMapFile.GetHandle: THandle;
  362. begin
  363.    if not Active then OpenFile;
  364.    Result := HFile;
  365. end;
  366. {-- TMMMemMapFile -------------------------------------------------------}
  367. function TMMMemMapFile.GetMapSize: LongInt;
  368. begin
  369.    if (FMapSize <> 0) then
  370.       Result := FMapSize
  371.    else
  372.       Result := FFileSize - FMapOffset;
  373. end;
  374. {------------------------------------------------------------------------}
  375. procedure InitAllocGran;
  376. var
  377.     SI: TSYSTEMINFO;
  378. begin
  379.    GetSystemInfo(SI);
  380.    AllocationGranularity := SI.dwAllocationGranularity;
  381. end;
  382. initialization
  383.    InitAllocGran;
  384. end.