1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #ifndef CORE_SRC_FXCRT_EXTENSION_H_
8 #define CORE_SRC_FXCRT_EXTENSION_H_
9 
10 #include "fx_safe_types.h"
11 
12 class IFXCRT_FileAccess
13 {
14 public:
~IFXCRT_FileAccess()15     virtual ~IFXCRT_FileAccess() {}
16     virtual FX_BOOL		Open(FX_BSTR fileName, FX_DWORD dwMode) = 0;
17     virtual FX_BOOL		Open(FX_WSTR fileName, FX_DWORD dwMode) = 0;
18     virtual void		Close() = 0;
19     virtual void		Release() = 0;
20     virtual FX_FILESIZE	GetSize() const = 0;
21     virtual FX_FILESIZE	GetPosition() const = 0;
22     virtual FX_FILESIZE	SetPosition(FX_FILESIZE pos) = 0;
23     virtual size_t		Read(void* pBuffer, size_t szBuffer) = 0;
24     virtual size_t		Write(const void* pBuffer, size_t szBuffer) = 0;
25     virtual size_t		ReadPos(void* pBuffer, size_t szBuffer, FX_FILESIZE pos) = 0;
26     virtual size_t		WritePos(const void* pBuffer, size_t szBuffer, FX_FILESIZE pos) = 0;
27     virtual FX_BOOL		Flush() = 0;
28     virtual FX_BOOL		Truncate(FX_FILESIZE szFile) = 0;
29 };
30 IFXCRT_FileAccess*	FXCRT_FileAccess_Create();
31 class CFX_CRTFileStream FX_FINAL : public IFX_FileStream
32 {
33 public:
CFX_CRTFileStream(IFXCRT_FileAccess * pFA)34     CFX_CRTFileStream(IFXCRT_FileAccess* pFA) : m_pFile(pFA), m_dwCount(1), m_bUseRange(FALSE), m_nOffset(0), m_nSize(0) {}
~CFX_CRTFileStream()35     ~CFX_CRTFileStream()
36     {
37         if (m_pFile) {
38             m_pFile->Release();
39         }
40     }
Retain()41     virtual IFX_FileStream*		Retain() FX_OVERRIDE
42     {
43         m_dwCount ++;
44         return this;
45     }
Release()46     virtual void				Release() FX_OVERRIDE
47     {
48         FX_DWORD nCount = -- m_dwCount;
49         if (!nCount) {
50             delete this;
51         }
52     }
GetSize()53     virtual FX_FILESIZE			GetSize() FX_OVERRIDE
54     {
55         return m_bUseRange ? m_nSize : m_pFile->GetSize();
56     }
IsEOF()57     virtual FX_BOOL				IsEOF() FX_OVERRIDE
58     {
59         return GetPosition() >= GetSize();
60     }
GetPosition()61     virtual FX_FILESIZE			GetPosition() FX_OVERRIDE
62     {
63         FX_FILESIZE pos = m_pFile->GetPosition();
64         if (m_bUseRange) {
65             pos -= m_nOffset;
66         }
67         return pos;
68     }
SetRange(FX_FILESIZE offset,FX_FILESIZE size)69     virtual FX_BOOL				SetRange(FX_FILESIZE offset, FX_FILESIZE size) FX_OVERRIDE
70     {
71         if (offset < 0 || size < 0) {
72             return FALSE;
73         }
74 
75         FX_SAFE_FILESIZE pos = size;
76         pos += offset;
77 
78         if (!pos.IsValid() || pos.ValueOrDie() > m_pFile->GetSize()) {
79             return FALSE;
80         }
81 
82         m_nOffset = offset, m_nSize = size;
83         m_bUseRange = TRUE;
84         m_pFile->SetPosition(m_nOffset);
85         return TRUE;
86     }
ClearRange()87     virtual void				ClearRange() FX_OVERRIDE
88     {
89         m_bUseRange = FALSE;
90     }
ReadBlock(void * buffer,FX_FILESIZE offset,size_t size)91     virtual FX_BOOL				ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) FX_OVERRIDE
92     {
93         if (m_bUseRange && offset < 0) {
94             return FALSE;
95         }
96         FX_SAFE_FILESIZE pos = offset;
97 
98         if (m_bUseRange) {
99             pos += m_nOffset;
100             if (!pos.IsValid() || pos.ValueOrDie() > (size_t)GetSize()) {
101                 return FALSE;
102             }
103         }
104         return (FX_BOOL)m_pFile->ReadPos(buffer, size, pos.ValueOrDie());
105     }
ReadBlock(void * buffer,size_t size)106     virtual size_t				ReadBlock(void* buffer, size_t size) FX_OVERRIDE
107     {
108         if (m_bUseRange) {
109             FX_FILESIZE availSize = m_nOffset + m_nSize - m_pFile->GetPosition();
110             if ((size_t)availSize < size) {
111                 size -= size - (size_t)availSize;
112             }
113         }
114         return m_pFile->Read(buffer, size);
115     }
WriteBlock(const void * buffer,FX_FILESIZE offset,size_t size)116     virtual	FX_BOOL				WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) FX_OVERRIDE
117     {
118         if (m_bUseRange) {
119             offset += m_nOffset;
120         }
121         return (FX_BOOL)m_pFile->WritePos(buffer, size, offset);
122     }
Flush()123     virtual FX_BOOL				Flush()  FX_OVERRIDE
124     {
125         return m_pFile->Flush();
126     }
127     IFXCRT_FileAccess*	m_pFile;
128     FX_DWORD			m_dwCount;
129     FX_BOOL				m_bUseRange;
130     FX_FILESIZE			m_nOffset;
131     FX_FILESIZE			m_nSize;
132 };
133 #define FX_MEMSTREAM_BlockSize		(64 * 1024)
134 #define FX_MEMSTREAM_Consecutive	0x01
135 #define FX_MEMSTREAM_TakeOver		0x02
136 class CFX_MemoryStream FX_FINAL : public IFX_MemoryStream
137 {
138 public:
CFX_MemoryStream(FX_BOOL bConsecutive)139     CFX_MemoryStream(FX_BOOL bConsecutive)
140         : m_dwCount(1)
141         , m_nTotalSize(0)
142         , m_nCurSize(0)
143         , m_nCurPos(0)
144         , m_nGrowSize(FX_MEMSTREAM_BlockSize)
145         , m_bUseRange(FALSE)
146     {
147         m_dwFlags = FX_MEMSTREAM_TakeOver | (bConsecutive ? FX_MEMSTREAM_Consecutive : 0);
148     }
CFX_MemoryStream(FX_LPBYTE pBuffer,size_t nSize,FX_BOOL bTakeOver)149     CFX_MemoryStream(FX_LPBYTE pBuffer, size_t nSize, FX_BOOL bTakeOver)
150         : m_dwCount(1)
151         , m_nTotalSize(nSize)
152         , m_nCurSize(nSize)
153         , m_nCurPos(0)
154         , m_nGrowSize(FX_MEMSTREAM_BlockSize)
155         , m_bUseRange(FALSE)
156     {
157         m_Blocks.Add(pBuffer);
158         m_dwFlags = FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
159     }
~CFX_MemoryStream()160     ~CFX_MemoryStream()
161     {
162         if (m_dwFlags & FX_MEMSTREAM_TakeOver) {
163             for (FX_INT32 i = 0; i < m_Blocks.GetSize(); i++) {
164                 FX_Free((FX_LPBYTE)m_Blocks[i]);
165             }
166         }
167         m_Blocks.RemoveAll();
168     }
Retain()169     virtual IFX_FileStream*		Retain()  FX_OVERRIDE
170     {
171         m_dwCount ++;
172         return this;
173     }
Release()174     virtual void				Release()  FX_OVERRIDE
175     {
176         FX_DWORD nCount = -- m_dwCount;
177         if (nCount) {
178             return;
179         }
180         delete this;
181     }
GetSize()182     virtual FX_FILESIZE			GetSize()  FX_OVERRIDE
183     {
184         return m_bUseRange ? (FX_FILESIZE) m_nSize : (FX_FILESIZE)m_nCurSize;
185     }
IsEOF()186     virtual FX_BOOL				IsEOF()  FX_OVERRIDE
187     {
188         return m_nCurPos >= (size_t)GetSize();
189     }
GetPosition()190     virtual FX_FILESIZE			GetPosition()  FX_OVERRIDE
191     {
192         FX_FILESIZE pos = (FX_FILESIZE)m_nCurPos;
193         if (m_bUseRange) {
194             pos -= (FX_FILESIZE)m_nOffset;
195         }
196         return pos;
197     }
SetRange(FX_FILESIZE offset,FX_FILESIZE size)198     virtual FX_BOOL				SetRange(FX_FILESIZE offset, FX_FILESIZE size)  FX_OVERRIDE
199     {
200         if (offset < 0 || size < 0) {
201             return FALSE;
202         }
203         FX_SAFE_FILESIZE range = size;
204         range += offset;
205         if (!range.IsValid() || range.ValueOrDie() > m_nCurSize) {
206             return FALSE;
207         }
208 
209         m_nOffset = (size_t)offset, m_nSize = (size_t)size;
210         m_bUseRange = TRUE;
211         m_nCurPos = m_nOffset;
212         return TRUE;
213     }
ClearRange()214     virtual void				ClearRange()  FX_OVERRIDE
215     {
216         m_bUseRange = FALSE;
217     }
ReadBlock(void * buffer,FX_FILESIZE offset,size_t size)218     virtual FX_BOOL				ReadBlock(void* buffer, FX_FILESIZE offset, size_t size)  FX_OVERRIDE
219     {
220         if (!buffer || !size) {
221             return FALSE;
222         }
223 
224         FX_SAFE_FILESIZE safeOffset = offset;
225         if (m_bUseRange) {
226             safeOffset += m_nOffset;
227         }
228 
229         if (!safeOffset.IsValid()) {
230             return FALSE;
231         }
232 
233         offset = safeOffset.ValueOrDie();
234 
235         FX_SAFE_SIZE_T newPos = size;
236         newPos += offset;
237         if (!newPos.IsValid() || newPos.ValueOrDefault(0) == 0 || newPos.ValueOrDie() > m_nCurSize) {
238             return FALSE;
239         }
240 
241         m_nCurPos = newPos.ValueOrDie();
242         if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
243             FXSYS_memcpy32(buffer, (FX_LPBYTE)m_Blocks[0] + (size_t)offset, size);
244             return TRUE;
245         }
246         size_t nStartBlock = (size_t)offset / m_nGrowSize;
247         offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
248         while (size) {
249             size_t nRead = m_nGrowSize - (size_t)offset;
250             if (nRead > size) {
251                 nRead = size;
252             }
253             FXSYS_memcpy32(buffer, (FX_LPBYTE)m_Blocks[(int)nStartBlock] + (size_t)offset, nRead);
254             buffer = ((FX_LPBYTE)buffer) + nRead;
255             size -= nRead;
256             nStartBlock ++;
257             offset = 0;
258         }
259         return TRUE;
260     }
ReadBlock(void * buffer,size_t size)261     virtual size_t				ReadBlock(void* buffer, size_t size)  FX_OVERRIDE
262     {
263         if (m_nCurPos >= m_nCurSize) {
264             return 0;
265         }
266         if (m_bUseRange) {
267             size_t availSize = m_nOffset + m_nSize - m_nCurPos;
268             if (availSize < size) {
269                 size -= size - (size_t)availSize;
270             }
271         }
272         size_t nRead = FX_MIN(size, m_nCurSize - m_nCurPos);
273         if (!ReadBlock(buffer, (FX_INT32)m_nCurPos, nRead)) {
274             return 0;
275         }
276         return nRead;
277     }
WriteBlock(const void * buffer,FX_FILESIZE offset,size_t size)278     virtual	FX_BOOL				WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size)  FX_OVERRIDE
279     {
280         if (!buffer || !size) {
281             return FALSE;
282         }
283         if (m_bUseRange) {
284             offset += (FX_FILESIZE)m_nOffset;
285         }
286         if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
287             FX_SAFE_SIZE_T newPos = size;
288             newPos += offset;
289             if (!newPos.IsValid())
290                 return FALSE;
291 
292             m_nCurPos = newPos.ValueOrDie();
293             if (m_nCurPos > m_nTotalSize) {
294                 m_nTotalSize = (m_nCurPos + m_nGrowSize - 1) / m_nGrowSize * m_nGrowSize;
295                 if (m_Blocks.GetSize() < 1) {
296                     void* block = FX_Alloc(FX_BYTE, m_nTotalSize);
297                     m_Blocks.Add(block);
298                 } else {
299                     m_Blocks[0] = FX_Realloc(FX_BYTE, m_Blocks[0], m_nTotalSize);
300                 }
301                 if (!m_Blocks[0]) {
302                     m_Blocks.RemoveAll();
303                     return FALSE;
304                 }
305             }
306             FXSYS_memcpy32((FX_LPBYTE)m_Blocks[0] + (size_t)offset, buffer, size);
307             if (m_nCurSize < m_nCurPos) {
308                 m_nCurSize = m_nCurPos;
309             }
310             return TRUE;
311         }
312 
313         FX_SAFE_SIZE_T newPos = size;
314         newPos += offset;
315         if (!newPos.IsValid()) {
316             return FALSE;
317         }
318 
319         if (!ExpandBlocks(newPos.ValueOrDie())) {
320             return FALSE;
321         }
322         m_nCurPos = newPos.ValueOrDie();
323         size_t nStartBlock = (size_t)offset / m_nGrowSize;
324         offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
325         while (size) {
326             size_t nWrite = m_nGrowSize - (size_t)offset;
327             if (nWrite > size) {
328                 nWrite = size;
329             }
330             FXSYS_memcpy32((FX_LPBYTE)m_Blocks[(int)nStartBlock] + (size_t)offset, buffer, nWrite);
331             buffer = ((FX_LPBYTE)buffer) + nWrite;
332             size -= nWrite;
333             nStartBlock ++;
334             offset = 0;
335         }
336         return TRUE;
337     }
Flush()338     virtual FX_BOOL				Flush()  FX_OVERRIDE
339     {
340         return TRUE;
341     }
IsConsecutive()342     virtual FX_BOOL				IsConsecutive() const  FX_OVERRIDE
343     {
344         return m_dwFlags & FX_MEMSTREAM_Consecutive;
345     }
EstimateSize(size_t nInitSize,size_t nGrowSize)346     virtual void				EstimateSize(size_t nInitSize, size_t nGrowSize)  FX_OVERRIDE
347     {
348         if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
349             if (m_Blocks.GetSize() < 1) {
350                 FX_LPBYTE pBlock = FX_Alloc(FX_BYTE, FX_MAX(nInitSize, 4096));
351                 m_Blocks.Add(pBlock);
352             }
353             m_nGrowSize = FX_MAX(nGrowSize, 4096);
354         } else if (m_Blocks.GetSize() < 1) {
355             m_nGrowSize = FX_MAX(nGrowSize, 4096);
356         }
357     }
GetBuffer()358     virtual FX_LPBYTE			GetBuffer() const  FX_OVERRIDE
359     {
360         return m_Blocks.GetSize() ? (FX_LPBYTE)m_Blocks[0] : NULL;
361     }
362     virtual void				AttachBuffer(FX_LPBYTE pBuffer, size_t nSize, FX_BOOL bTakeOver = FALSE)  FX_OVERRIDE
363     {
364         if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
365             return;
366         }
367         m_Blocks.RemoveAll();
368         m_Blocks.Add(pBuffer);
369         m_nTotalSize = m_nCurSize = nSize;
370         m_nCurPos = 0;
371         m_dwFlags = FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
372         ClearRange();
373     }
DetachBuffer()374     virtual void				DetachBuffer()  FX_OVERRIDE
375     {
376         if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
377             return;
378         }
379         m_Blocks.RemoveAll();
380         m_nTotalSize = m_nCurSize = m_nCurPos = 0;
381         m_dwFlags = FX_MEMSTREAM_TakeOver;
382         ClearRange();
383     }
384 protected:
385     CFX_PtrArray	m_Blocks;
386     FX_DWORD		m_dwCount;
387     size_t			m_nTotalSize;
388     size_t			m_nCurSize;
389     size_t			m_nCurPos;
390     size_t			m_nGrowSize;
391     FX_DWORD		m_dwFlags;
392     FX_BOOL			m_bUseRange;
393     size_t			m_nOffset;
394     size_t			m_nSize;
ExpandBlocks(size_t size)395     FX_BOOL	ExpandBlocks(size_t size)
396     {
397         if (m_nCurSize < size) {
398             m_nCurSize = size;
399         }
400         if (size <= m_nTotalSize) {
401             return TRUE;
402         }
403         FX_INT32 iCount = m_Blocks.GetSize();
404         size = (size - m_nTotalSize + m_nGrowSize - 1) / m_nGrowSize;
405         m_Blocks.SetSize(m_Blocks.GetSize() + (FX_INT32)size);
406         while (size --) {
407             FX_LPBYTE pBlock = FX_Alloc(FX_BYTE, m_nGrowSize);
408             m_Blocks.SetAt(iCount ++, pBlock);
409             m_nTotalSize += m_nGrowSize;
410         }
411         return TRUE;
412     }
413 };
414 #ifdef __cplusplus
415 extern "C" {
416 #endif
417 #define MT_N			848
418 #define MT_M			456
419 #define MT_Matrix_A		0x9908b0df
420 #define MT_Upper_Mask	0x80000000
421 #define MT_Lower_Mask	0x7fffffff
422 typedef struct _FX_MTRANDOMCONTEXT {
_FX_MTRANDOMCONTEXT_FX_MTRANDOMCONTEXT423     _FX_MTRANDOMCONTEXT()
424     {
425         mti = MT_N + 1;
426         bHaveSeed = FALSE;
427     }
428     FX_DWORD mti;
429     FX_BOOL	 bHaveSeed;
430     FX_DWORD mt[MT_N];
431 } FX_MTRANDOMCONTEXT, * FX_LPMTRANDOMCONTEXT;
432 typedef FX_MTRANDOMCONTEXT const * FX_LPCMTRANDOMCONTEXT;
433 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
434 FX_BOOL FX_GenerateCryptoRandom(FX_LPDWORD pBuffer, FX_INT32 iCount);
435 #endif
436 #ifdef __cplusplus
437 }
438 #endif
439 
440 #endif  // CORE_SRC_FXCRT_EXTENSION_H_
441