~ubuntu-branches/ubuntu/utopic/mricron/utopic

1.1.2 by Michael Hanke
Import upstream version 0.20101102.1~dfsg.1
1
unit winmemmap;
2
{$H+}
3
interface
4
{ This Unit implements an interface to Win32 memory mapped files. It
5
  can be used to map data simply residing in memory or data residing
6
  in a file. The data can be fully mapped into the processes address
7
  space or chunks can be mapped. It also provides capabilities for
8
  processes to synchronize via mutexes. When mapping sections of the
9
  memory, you must be aware that the Win32 memory mapped file interface
10
  requires that when you are requesting an offset into the memory
11
  region, this offset must be a multiple of the system's memory
12
  allocation granularity (I've called it PageSize). At this point
13
  it is 64K. This is not a concern when you are mapping anything less
14
  than 64K. However, to map anything > 64K the total memory size
15
  mapped must be a multiple of 64K or you will not have access to
16
  the memorysize MOD 64K bytes left over. Basically there are five
17
  rules to be successful when using these routines:
18
           1. Mapname must be unique for each different case you use
19
              these objects (MyMap1 for case 1, MyMap2 for case 2
20
              etc.).However, each process using the same memory map
21
              MUST use the same MapName.
22
           2. Call MapExisting before CreateMemMap or FCreateMemMap.
23
              If another process has already started the mapping,
24
              all you want to do is map to the existing map. ie.
25
              If NOT MapExisting then CreateMemMap.
26
           3. If your processes are going to write to the mapped
27
              memory, it is suggested you use the mutex stuff.
28
           4. Pay heed to the warning above concerning seeking
29
              offsets into the mapped memory. Whenever you call
30
              the seek function, always check for an error. Errors
31
              in mapping to the file will result in the Memmap
32
              pointer being Nil.
33
           5. You MUST call LeaveCriticalSection after calling
34
              EnterCriticalSection or you will lock other processes wishing
35
              to use the map into an infinite wait state. Always use
36
              a Try..Finally block.
37
}
38
Uses
39
   Classes,Windows;
40
Const
41
     hMemMap = $FFFFFFFF;
42
Type
43
   //Map to memory
44
   TEMemMap = Class(TComponent)
45
   Private
46
      FhFile          : THandle;   //File handle, hMemMap when simple memory
47
      FhMap           : THandle;   //Mapping handle
48
      FMap            : Pointer;   //Memory Pointer
49
      FMapSize        : Cardinal;  //Mapping Page Size
50
      FMemSize        : Cardinal;  //Maximum size allocated, >=FileSize when a file
51
      FPageSize       : Cardinal;  //Minimum System allocation size
52
      FMaxSeeks       : Cardinal;  //Maximum seeks available,(FMemSize DIV PageSize)-1
53
      FMapError       : Integer;   //Error returned
54
      FhMutex         : THandle;   //Mutex handle for sharing
55
      FInMutex        : Boolean;   //Internal flag
56
      Function SetMapError : Boolean;
57
      Procedure SetMemSize(Size : Cardinal);
58
   Public
59
      Constructor Create(Aowner : TComponent); Override;
60
      Destructor Destroy; Override;
61
      //Create a mutex for sychronizing access
62
      Function CreateMutex(Const MutexName : String) : Boolean;
63
      //Use the mutex
64
      Procedure EnterCriticalSection;
65
      //Release the mutex
66
      Procedure LeaveCriticalSection;
67
      //Map to existing memory map
68
      Function MapExisting(Const MapName : String;
69
                           Const MapSize : Cardinal) : Boolean;Virtual;
70
      //Create a new memory map
71
      Function CreateMemMap(Const MapName : String;
72
                            Const MapSize : Cardinal;
73
                            Const MapData ) : Boolean;Virtual;
74
      //seek to an offset in the memory map
75
      Function Seek(Const OffSet : Cardinal) : Boolean;
76
      //duh?
77
      Procedure RaiseMappingException;Virtual;
78
79
      Property MemMap     : Pointer  Read FMap; //The mapped memory
80
      Property MapError   : Integer  Read FMapError Write FMapError;
81
      Property MemSize    : Cardinal Read FMemSize  Write SetMemSize; //Memory size to allocate
82
      Property PageSize : Cardinal Read FPageSize; //system returned page size
83
      Property MaxSeeks : Cardinal Read FMaxSeeks; //maximum seeks allowed
84
   end;
85
   //map to a file
86
   TEFileMap = Class(TEMemMap)
87
   Public
88
      Function FCreateMemMap(Const Filename : String;
89
                             Const MapName  : String;
90
                             Const MapSize  : Cardinal) : Boolean;
91
92
      Function FlushFileView : Boolean;
93
   end;
94
implementation
95
Uses
96
    SysUtils;
97
Type
98
   EMappingException = class(Exception);
99
Constructor TEMemMap.Create(AOwner : TComponent);
100
Var
101
    SysInfo : TSystemInfo;
102
begin
103
  Inherited Create(AOwner);
104
  FhFile:=hMemMap;
105
  GetSystemInfo(SysInfo);
106
  FPageSize:=SysInfo.dwAllocationGranularity;
107
end;
108
Destructor TEMemmap.Destroy;
109
begin
110
  LeaveCriticalSection;
111
  If FhMutex<>0 then
112
    CloseHandle(FhMutex);
113
  If FMap<>Nil then
114
    UnMapViewOfFile(FMap);
115
  If FHMap<>0 then
116
    CloseHandle(FHMap);
117
  Inherited Destroy;
118
end;
119
Function TEMemMap.CreateMutex(Const MutexName : String) : Boolean;
120
begin
121
  If FhMutex=0 then
122
    FhMutex:=Windows.CreateMutex(Nil,False,PChar(MutexName));
123
  If FhMutex=0 then
124
    Result:=SetMapError
125
  else
126
    Result:=True;
127
end;
128
Procedure TEMemMap.EnterCriticalSection;
129
begin
130
  If (NOT FInMutex) AND (FhMutex>0) then
131
  begin
132
    WaitForSingleObject(FhMutex,INFINITE);
133
    FInMutex:=True;
134
  end;
135
end;
136
Procedure TEMemMap.LeaveCriticalSection;
137
begin
138
  If FInMutex AND (FhMutex>0) then
139
  begin
140
    ReleaseMutex(FhMutex);
141
    FInMutex:=False;
142
  end;
143
end;
144
Function TEMemMap.SetMapError : Boolean;
145
begin
146
  FMapError:=GetLastError;
147
  Result:=False;
148
end;
149
Procedure TEMemMap.RaiseMappingException;
150
Var
151
    TError : Integer;
152
begin
153
  If FMapError<>0 then
154
  begin
155
    LeaveCriticalSection;
156
    TError:=FMapError;
157
    FMapError:=0;
158
    Raise EMappingException.Create('Memory Mapping Error #'+IntToStr(TError));
159
  end;
160
end;
161
Procedure TEMemMap.SetMemSize(Size : Cardinal);
162
begin
163
  FMemSize:=Size;
164
  If FMemSize>PageSize then
165
    FMaxSeeks:=(FMemSize DIV PageSize)-1
166
  else
167
    FMaxSeeks:=0;
168
end;
169
//map to an existing memory map described by MapName
170
Function TEMemMap.MapExisting(Const MapName : String;
171
                              Const MapSize : Cardinal) : Boolean;
172
begin
173
  FMapSize:=MapSize;
174
  FMap:=Nil;
175
  FhMap:=OpenFileMapping(FILE_MAP_WRITE,BOOL(True),PChar(MapName));
176
  If FhMap<>0 then
177
  begin
178
    FMap:=MapViewOfFile(FhMap,FILE_MAP_WRITE,0,0,MapSize);
179
    If FMap=Nil then
180
    begin
181
      CloseHandle(FHMap);
182
      FHMap:=0;
183
      SetMapError;
184
    end;
185
  end;
186
  Result:=FMap<>Nil;
187
end;
188
//Create a new memory mapping
189
Function TEMemMap.CreateMemMap(Const MapName : String;
190
                               Const MapSize : Cardinal;
191
                               Const MapData ) : Boolean;
192
begin
193
  If FMemSize=0 then
194
    FMemSize:=MapSize;
195
  FhMap:=CreateFileMapping(FhFile,nil,PAGE_READWRITE,0,FMemSize,PChar(MapName));
196
  If FhMap<>0 then
197
  begin
198
    FMap:=MapViewOfFile(FhMap,FILE_MAP_WRITE,0,0,MapSize);
199
    If FMap<>Nil then
200
    begin
201
      If fHFile=hMemMap then
202
      begin
203
        EnterCriticalSection;
204
        Try
205
          Move(MapData,FMap^,MapSize);
206
        Finally
207
          LeaveCriticalSection;
208
        end;
209
      end;
210
      Result:=True;
211
    end
212
    else
213
      Result:=SetMapError;
214
  end
215
  else
216
    Result:=SetMapError;
217
end;
218
//seek to a different position in map (0..MaxSeeks)
219
Function TEMemMap.Seek(Const OffSet : Cardinal) : Boolean;
220
begin
221
  Result:=True;
222
  If NOT UnMapViewOfFile(FMap) then
223
    Result:=SetMapError
224
  else
225
  begin
226
    FMap:=MapViewOfFile(FhMap,FILE_MAP_WRITE,0,OffSet*PageSize,FMapSize);
227
    If FMap=Nil then
228
      Result:=SetMapError;
229
  end;
230
end;
231
//Create a file mapping
232
Function TEFileMap.FCreateMemMap(Const Filename : String;
233
                                 Const MapName  : String;
234
                                 Const MapSize  : Cardinal) : Boolean;
235
Var
236
    TInt  : Cardinal;
237
begin
238
  FHFile:=CreateFile(PChar(FileName),GENERIC_READ OR GENERIC_WRITE,
239
                     FILE_SHARE_READ OR FILE_SHARE_WRITE,NIl,OPEN_EXISTING,
240
                     FILE_FLAG_RANDOM_ACCESS,0);
241
  If FhFile<>0 then
242
  begin
243
    Try
244
      Result:=CreateMemMap(MapName,MapSize,TInt);
245
    Finally
246
      CloseHandle(FhFile);
247
    end;
248
  end
249
  else
250
    Result:=SetMapError;
251
end;
252
253
Function TEFileMap.FlushFileView : Boolean;
254
begin
255
  EnterCriticalSection;
256
  Try
257
    Result:=FlushViewOfFile(FMap,FMapSize) OR SetMapError;
258
  Finally
259
    LeaveCriticalSection;
260
  end;
261
end;
262
end.