• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "core/fxcrt/extension.h"
8 
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12 
13 #include "core/fxcrt/fx_basic.h"
14 #include "core/fxcrt/fx_ext.h"
15 
16 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
17 #include <wincrypt.h>
18 #else
19 #include <ctime>
20 #endif
21 
22 namespace {
23 
24 #ifdef PDF_ENABLE_XFA
25 
26 class CFX_CRTFileAccess : public IFX_FileAccess {
27  public:
28   template <typename T, typename... Args>
29   friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
30 
31   // IFX_FileAccess
32   void GetPath(CFX_WideString& wsPath) override;
33   CFX_RetainPtr<IFX_SeekableStream> CreateFileStream(uint32_t dwModes) override;
34 
35   bool Init(const CFX_WideStringC& wsPath);
36 
37  private:
38   CFX_CRTFileAccess();
39   ~CFX_CRTFileAccess() override;
40 
41   CFX_WideString m_path;
42 };
43 
CFX_CRTFileAccess()44 CFX_CRTFileAccess::CFX_CRTFileAccess() {}
45 
~CFX_CRTFileAccess()46 CFX_CRTFileAccess::~CFX_CRTFileAccess() {}
47 
GetPath(CFX_WideString & wsPath)48 void CFX_CRTFileAccess::GetPath(CFX_WideString& wsPath) {
49   wsPath = m_path;
50 }
51 
CreateFileStream(uint32_t dwModes)52 CFX_RetainPtr<IFX_SeekableStream> CFX_CRTFileAccess::CreateFileStream(
53     uint32_t dwModes) {
54   return IFX_SeekableStream::CreateFromFilename(m_path.c_str(), dwModes);
55 }
56 
Init(const CFX_WideStringC & wsPath)57 bool CFX_CRTFileAccess::Init(const CFX_WideStringC& wsPath) {
58   m_path = wsPath;
59   return true;
60 }
61 
62 #endif  // PDF_ENABLE_XFA
63 
64 class CFX_CRTFileStream final : public IFX_SeekableStream {
65  public:
66   template <typename T, typename... Args>
67   friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
68 
69   // IFX_SeekableStream:
70   FX_FILESIZE GetSize() override;
71   bool IsEOF() override;
72   FX_FILESIZE GetPosition() override;
73   bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
74   size_t ReadBlock(void* buffer, size_t size) override;
75   bool WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override;
76   bool Flush() override;
77 
78  private:
79   explicit CFX_CRTFileStream(std::unique_ptr<IFXCRT_FileAccess> pFA);
80   ~CFX_CRTFileStream() override;
81 
82   std::unique_ptr<IFXCRT_FileAccess> m_pFile;
83 };
84 
CFX_CRTFileStream(std::unique_ptr<IFXCRT_FileAccess> pFA)85 CFX_CRTFileStream::CFX_CRTFileStream(std::unique_ptr<IFXCRT_FileAccess> pFA)
86     : m_pFile(std::move(pFA)) {}
87 
~CFX_CRTFileStream()88 CFX_CRTFileStream::~CFX_CRTFileStream() {}
89 
GetSize()90 FX_FILESIZE CFX_CRTFileStream::GetSize() {
91   return m_pFile->GetSize();
92 }
93 
IsEOF()94 bool CFX_CRTFileStream::IsEOF() {
95   return GetPosition() >= GetSize();
96 }
97 
GetPosition()98 FX_FILESIZE CFX_CRTFileStream::GetPosition() {
99   return m_pFile->GetPosition();
100 }
101 
ReadBlock(void * buffer,FX_FILESIZE offset,size_t size)102 bool CFX_CRTFileStream::ReadBlock(void* buffer,
103                                   FX_FILESIZE offset,
104                                   size_t size) {
105   return m_pFile->ReadPos(buffer, size, offset) > 0;
106 }
107 
ReadBlock(void * buffer,size_t size)108 size_t CFX_CRTFileStream::ReadBlock(void* buffer, size_t size) {
109   return m_pFile->Read(buffer, size);
110 }
111 
WriteBlock(const void * buffer,FX_FILESIZE offset,size_t size)112 bool CFX_CRTFileStream::WriteBlock(const void* buffer,
113                                    FX_FILESIZE offset,
114                                    size_t size) {
115   return !!m_pFile->WritePos(buffer, size, offset);
116 }
117 
Flush()118 bool CFX_CRTFileStream::Flush() {
119   return m_pFile->Flush();
120 }
121 
122 #define FX_MEMSTREAM_BlockSize (64 * 1024)
123 #define FX_MEMSTREAM_Consecutive 0x01
124 #define FX_MEMSTREAM_TakeOver 0x02
125 
126 class CFX_MemoryStream final : public IFX_MemoryStream {
127  public:
128   template <typename T, typename... Args>
129   friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
130 
131   // IFX_MemoryStream
132   FX_FILESIZE GetSize() override;
133   bool IsEOF() override;
134   FX_FILESIZE GetPosition() override;
135   bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
136   size_t ReadBlock(void* buffer, size_t size) override;
137   bool WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override;
138   bool Flush() override;
139   bool IsConsecutive() const override;
140   void EstimateSize(size_t nInitSize, size_t nGrowSize) override;
141   uint8_t* GetBuffer() const override;
142   void AttachBuffer(uint8_t* pBuffer,
143                     size_t nSize,
144                     bool bTakeOver = false) override;
145   void DetachBuffer() override;
146 
147  private:
148   explicit CFX_MemoryStream(bool bConsecutive);
149   CFX_MemoryStream(uint8_t* pBuffer, size_t nSize, bool bTakeOver);
150   ~CFX_MemoryStream() override;
151 
152   bool ExpandBlocks(size_t size);
153 
154   CFX_ArrayTemplate<uint8_t*> m_Blocks;
155   size_t m_nTotalSize;
156   size_t m_nCurSize;
157   size_t m_nCurPos;
158   size_t m_nGrowSize;
159   uint32_t m_dwFlags;
160 };
161 
CFX_MemoryStream(bool bConsecutive)162 CFX_MemoryStream::CFX_MemoryStream(bool bConsecutive)
163     : m_nTotalSize(0),
164       m_nCurSize(0),
165       m_nCurPos(0),
166       m_nGrowSize(FX_MEMSTREAM_BlockSize) {
167   m_dwFlags =
168       FX_MEMSTREAM_TakeOver | (bConsecutive ? FX_MEMSTREAM_Consecutive : 0);
169 }
170 
CFX_MemoryStream(uint8_t * pBuffer,size_t nSize,bool bTakeOver)171 CFX_MemoryStream::CFX_MemoryStream(uint8_t* pBuffer,
172                                    size_t nSize,
173                                    bool bTakeOver)
174     : m_nTotalSize(nSize),
175       m_nCurSize(nSize),
176       m_nCurPos(0),
177       m_nGrowSize(FX_MEMSTREAM_BlockSize) {
178   m_Blocks.Add(pBuffer);
179   m_dwFlags =
180       FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
181 }
182 
~CFX_MemoryStream()183 CFX_MemoryStream::~CFX_MemoryStream() {
184   if (m_dwFlags & FX_MEMSTREAM_TakeOver) {
185     for (int32_t i = 0; i < m_Blocks.GetSize(); i++) {
186       FX_Free(m_Blocks[i]);
187     }
188   }
189   m_Blocks.RemoveAll();
190 }
191 
GetSize()192 FX_FILESIZE CFX_MemoryStream::GetSize() {
193   return (FX_FILESIZE)m_nCurSize;
194 }
195 
IsEOF()196 bool CFX_MemoryStream::IsEOF() {
197   return m_nCurPos >= (size_t)GetSize();
198 }
199 
GetPosition()200 FX_FILESIZE CFX_MemoryStream::GetPosition() {
201   return (FX_FILESIZE)m_nCurPos;
202 }
203 
ReadBlock(void * buffer,FX_FILESIZE offset,size_t size)204 bool CFX_MemoryStream::ReadBlock(void* buffer,
205                                  FX_FILESIZE offset,
206                                  size_t size) {
207   if (!buffer || !size || offset < 0)
208     return false;
209 
210   FX_SAFE_SIZE_T newPos = size;
211   newPos += offset;
212   if (!newPos.IsValid() || newPos.ValueOrDefault(0) == 0 ||
213       newPos.ValueOrDie() > m_nCurSize) {
214     return false;
215   }
216 
217   m_nCurPos = newPos.ValueOrDie();
218   if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
219     FXSYS_memcpy(buffer, m_Blocks[0] + (size_t)offset, size);
220     return true;
221   }
222   size_t nStartBlock = (size_t)offset / m_nGrowSize;
223   offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
224   while (size) {
225     size_t nRead = m_nGrowSize - (size_t)offset;
226     if (nRead > size) {
227       nRead = size;
228     }
229     FXSYS_memcpy(buffer, m_Blocks[(int)nStartBlock] + (size_t)offset, nRead);
230     buffer = ((uint8_t*)buffer) + nRead;
231     size -= nRead;
232     nStartBlock++;
233     offset = 0;
234   }
235   return true;
236 }
237 
ReadBlock(void * buffer,size_t size)238 size_t CFX_MemoryStream::ReadBlock(void* buffer, size_t size) {
239   if (m_nCurPos >= m_nCurSize) {
240     return 0;
241   }
242   size_t nRead = std::min(size, m_nCurSize - m_nCurPos);
243   if (!ReadBlock(buffer, (int32_t)m_nCurPos, nRead)) {
244     return 0;
245   }
246   return nRead;
247 }
248 
WriteBlock(const void * buffer,FX_FILESIZE offset,size_t size)249 bool CFX_MemoryStream::WriteBlock(const void* buffer,
250                                   FX_FILESIZE offset,
251                                   size_t size) {
252   if (!buffer || !size)
253     return false;
254 
255   if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
256     FX_SAFE_SIZE_T newPos = size;
257     newPos += offset;
258     if (!newPos.IsValid())
259       return false;
260 
261     m_nCurPos = newPos.ValueOrDie();
262     if (m_nCurPos > m_nTotalSize) {
263       m_nTotalSize = (m_nCurPos + m_nGrowSize - 1) / m_nGrowSize * m_nGrowSize;
264       if (m_Blocks.GetSize() < 1) {
265         uint8_t* block = FX_Alloc(uint8_t, m_nTotalSize);
266         m_Blocks.Add(block);
267       } else {
268         m_Blocks[0] = FX_Realloc(uint8_t, m_Blocks[0], m_nTotalSize);
269       }
270       if (!m_Blocks[0]) {
271         m_Blocks.RemoveAll();
272         return false;
273       }
274     }
275     FXSYS_memcpy(m_Blocks[0] + (size_t)offset, buffer, size);
276     if (m_nCurSize < m_nCurPos) {
277       m_nCurSize = m_nCurPos;
278     }
279     return true;
280   }
281 
282   FX_SAFE_SIZE_T newPos = size;
283   newPos += offset;
284   if (!newPos.IsValid()) {
285     return false;
286   }
287 
288   if (!ExpandBlocks(newPos.ValueOrDie())) {
289     return false;
290   }
291   m_nCurPos = newPos.ValueOrDie();
292   size_t nStartBlock = (size_t)offset / m_nGrowSize;
293   offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
294   while (size) {
295     size_t nWrite = m_nGrowSize - (size_t)offset;
296     if (nWrite > size) {
297       nWrite = size;
298     }
299     FXSYS_memcpy(m_Blocks[(int)nStartBlock] + (size_t)offset, buffer, nWrite);
300     buffer = ((uint8_t*)buffer) + nWrite;
301     size -= nWrite;
302     nStartBlock++;
303     offset = 0;
304   }
305   return true;
306 }
307 
Flush()308 bool CFX_MemoryStream::Flush() {
309   return true;
310 }
311 
IsConsecutive() const312 bool CFX_MemoryStream::IsConsecutive() const {
313   return !!(m_dwFlags & FX_MEMSTREAM_Consecutive);
314 }
315 
EstimateSize(size_t nInitSize,size_t nGrowSize)316 void CFX_MemoryStream::EstimateSize(size_t nInitSize, size_t nGrowSize) {
317   if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
318     if (m_Blocks.GetSize() < 1) {
319       uint8_t* pBlock =
320           FX_Alloc(uint8_t, std::max(nInitSize, static_cast<size_t>(4096)));
321       m_Blocks.Add(pBlock);
322     }
323     m_nGrowSize = std::max(nGrowSize, static_cast<size_t>(4096));
324   } else if (m_Blocks.GetSize() < 1) {
325     m_nGrowSize = std::max(nGrowSize, static_cast<size_t>(4096));
326   }
327 }
328 
GetBuffer() const329 uint8_t* CFX_MemoryStream::GetBuffer() const {
330   return m_Blocks.GetSize() ? m_Blocks[0] : nullptr;
331 }
332 
AttachBuffer(uint8_t * pBuffer,size_t nSize,bool bTakeOver)333 void CFX_MemoryStream::AttachBuffer(uint8_t* pBuffer,
334                                     size_t nSize,
335                                     bool bTakeOver) {
336   if (!(m_dwFlags & FX_MEMSTREAM_Consecutive))
337     return;
338 
339   m_Blocks.RemoveAll();
340   m_Blocks.Add(pBuffer);
341   m_nTotalSize = m_nCurSize = nSize;
342   m_nCurPos = 0;
343   m_dwFlags =
344       FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
345 }
346 
DetachBuffer()347 void CFX_MemoryStream::DetachBuffer() {
348   if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
349     return;
350   }
351   m_Blocks.RemoveAll();
352   m_nTotalSize = m_nCurSize = m_nCurPos = 0;
353   m_dwFlags = FX_MEMSTREAM_TakeOver;
354 }
355 
ExpandBlocks(size_t size)356 bool CFX_MemoryStream::ExpandBlocks(size_t size) {
357   if (m_nCurSize < size) {
358     m_nCurSize = size;
359   }
360   if (size <= m_nTotalSize) {
361     return true;
362   }
363   int32_t iCount = m_Blocks.GetSize();
364   size = (size - m_nTotalSize + m_nGrowSize - 1) / m_nGrowSize;
365   m_Blocks.SetSize(m_Blocks.GetSize() + (int32_t)size);
366   while (size--) {
367     uint8_t* pBlock = FX_Alloc(uint8_t, m_nGrowSize);
368     m_Blocks.SetAt(iCount++, pBlock);
369     m_nTotalSize += m_nGrowSize;
370   }
371   return true;
372 }
373 
374 }  // namespace
375 
376 #ifdef PDF_ENABLE_XFA
CreateDefault(const CFX_WideStringC & wsPath)377 CFX_RetainPtr<IFX_FileAccess> IFX_FileAccess::CreateDefault(
378     const CFX_WideStringC& wsPath) {
379   if (wsPath.GetLength() == 0)
380     return nullptr;
381 
382   auto pFA = pdfium::MakeRetain<CFX_CRTFileAccess>();
383   pFA->Init(wsPath);
384   return pFA;
385 }
386 #endif  // PDF_ENABLE_XFA
387 
388 // static
CreateFromFilename(const FX_CHAR * filename,uint32_t dwModes)389 CFX_RetainPtr<IFX_SeekableStream> IFX_SeekableStream::CreateFromFilename(
390     const FX_CHAR* filename,
391     uint32_t dwModes) {
392   std::unique_ptr<IFXCRT_FileAccess> pFA(IFXCRT_FileAccess::Create());
393   if (!pFA->Open(filename, dwModes))
394     return nullptr;
395   return pdfium::MakeRetain<CFX_CRTFileStream>(std::move(pFA));
396 }
397 
398 // static
CreateFromFilename(const FX_WCHAR * filename,uint32_t dwModes)399 CFX_RetainPtr<IFX_SeekableStream> IFX_SeekableStream::CreateFromFilename(
400     const FX_WCHAR* filename,
401     uint32_t dwModes) {
402   std::unique_ptr<IFXCRT_FileAccess> pFA(IFXCRT_FileAccess::Create());
403   if (!pFA->Open(filename, dwModes))
404     return nullptr;
405   return pdfium::MakeRetain<CFX_CRTFileStream>(std::move(pFA));
406 }
407 
408 // static
409 CFX_RetainPtr<IFX_SeekableReadStream>
CreateFromFilename(const FX_CHAR * filename)410 IFX_SeekableReadStream::CreateFromFilename(const FX_CHAR* filename) {
411   return IFX_SeekableStream::CreateFromFilename(filename, FX_FILEMODE_ReadOnly);
412 }
413 
414 // static
Create(uint8_t * pBuffer,size_t dwSize,bool bTakeOver)415 CFX_RetainPtr<IFX_MemoryStream> IFX_MemoryStream::Create(uint8_t* pBuffer,
416                                                          size_t dwSize,
417                                                          bool bTakeOver) {
418   return pdfium::MakeRetain<CFX_MemoryStream>(pBuffer, dwSize, bTakeOver);
419 }
420 
421 // static
Create(bool bConsecutive)422 CFX_RetainPtr<IFX_MemoryStream> IFX_MemoryStream::Create(bool bConsecutive) {
423   return pdfium::MakeRetain<CFX_MemoryStream>(bConsecutive);
424 }
425 
FXSYS_tan(FX_FLOAT a)426 FX_FLOAT FXSYS_tan(FX_FLOAT a) {
427   return (FX_FLOAT)tan(a);
428 }
FXSYS_logb(FX_FLOAT b,FX_FLOAT x)429 FX_FLOAT FXSYS_logb(FX_FLOAT b, FX_FLOAT x) {
430   return FXSYS_log(x) / FXSYS_log(b);
431 }
FXSYS_strtof(const FX_CHAR * pcsStr,int32_t iLength,int32_t * pUsedLen)432 FX_FLOAT FXSYS_strtof(const FX_CHAR* pcsStr,
433                       int32_t iLength,
434                       int32_t* pUsedLen) {
435   ASSERT(pcsStr);
436   if (iLength < 0) {
437     iLength = (int32_t)FXSYS_strlen(pcsStr);
438   }
439   CFX_WideString ws =
440       CFX_WideString::FromLocal(CFX_ByteStringC(pcsStr, iLength));
441   return FXSYS_wcstof(ws.c_str(), iLength, pUsedLen);
442 }
FXSYS_wcstof(const FX_WCHAR * pwsStr,int32_t iLength,int32_t * pUsedLen)443 FX_FLOAT FXSYS_wcstof(const FX_WCHAR* pwsStr,
444                       int32_t iLength,
445                       int32_t* pUsedLen) {
446   ASSERT(pwsStr);
447   if (iLength < 0) {
448     iLength = (int32_t)FXSYS_wcslen(pwsStr);
449   }
450   if (iLength == 0) {
451     return 0.0f;
452   }
453   int32_t iUsedLen = 0;
454   bool bNegtive = false;
455   switch (pwsStr[iUsedLen]) {
456     case '-':
457       bNegtive = true;
458     case '+':
459       iUsedLen++;
460       break;
461   }
462   FX_FLOAT fValue = 0.0f;
463   while (iUsedLen < iLength) {
464     FX_WCHAR wch = pwsStr[iUsedLen];
465     if (wch >= L'0' && wch <= L'9') {
466       fValue = fValue * 10.0f + (wch - L'0');
467     } else {
468       break;
469     }
470     iUsedLen++;
471   }
472   if (iUsedLen < iLength && pwsStr[iUsedLen] == L'.') {
473     FX_FLOAT fPrecise = 0.1f;
474     while (++iUsedLen < iLength) {
475       FX_WCHAR wch = pwsStr[iUsedLen];
476       if (wch >= L'0' && wch <= L'9') {
477         fValue += (wch - L'0') * fPrecise;
478         fPrecise *= 0.1f;
479       } else {
480         break;
481       }
482     }
483   }
484   if (pUsedLen) {
485     *pUsedLen = iUsedLen;
486   }
487   return bNegtive ? -fValue : fValue;
488 }
FXSYS_wcsncpy(FX_WCHAR * dstStr,const FX_WCHAR * srcStr,size_t count)489 FX_WCHAR* FXSYS_wcsncpy(FX_WCHAR* dstStr,
490                         const FX_WCHAR* srcStr,
491                         size_t count) {
492   ASSERT(dstStr && srcStr && count > 0);
493   for (size_t i = 0; i < count; ++i)
494     if ((dstStr[i] = srcStr[i]) == L'\0') {
495       break;
496     }
497   return dstStr;
498 }
FXSYS_wcsnicmp(const FX_WCHAR * s1,const FX_WCHAR * s2,size_t count)499 int32_t FXSYS_wcsnicmp(const FX_WCHAR* s1, const FX_WCHAR* s2, size_t count) {
500   ASSERT(s1 && s2 && count > 0);
501   FX_WCHAR wch1 = 0, wch2 = 0;
502   while (count-- > 0) {
503     wch1 = (FX_WCHAR)FXSYS_tolower(*s1++);
504     wch2 = (FX_WCHAR)FXSYS_tolower(*s2++);
505     if (wch1 != wch2) {
506       break;
507     }
508   }
509   return wch1 - wch2;
510 }
FXSYS_strnicmp(const FX_CHAR * s1,const FX_CHAR * s2,size_t count)511 int32_t FXSYS_strnicmp(const FX_CHAR* s1, const FX_CHAR* s2, size_t count) {
512   ASSERT(s1 && s2 && count > 0);
513   FX_CHAR ch1 = 0, ch2 = 0;
514   while (count-- > 0) {
515     ch1 = (FX_CHAR)FXSYS_tolower(*s1++);
516     ch2 = (FX_CHAR)FXSYS_tolower(*s2++);
517     if (ch1 != ch2) {
518       break;
519     }
520   }
521   return ch1 - ch2;
522 }
523 
FX_HashCode_GetA(const CFX_ByteStringC & str,bool bIgnoreCase)524 uint32_t FX_HashCode_GetA(const CFX_ByteStringC& str, bool bIgnoreCase) {
525   uint32_t dwHashCode = 0;
526   if (bIgnoreCase) {
527     for (FX_STRSIZE i = 0; i < str.GetLength(); ++i)
528       dwHashCode = 31 * dwHashCode + FXSYS_tolower(str.CharAt(i));
529   } else {
530     for (FX_STRSIZE i = 0; i < str.GetLength(); ++i)
531       dwHashCode = 31 * dwHashCode + str.CharAt(i);
532   }
533   return dwHashCode;
534 }
535 
FX_HashCode_GetW(const CFX_WideStringC & str,bool bIgnoreCase)536 uint32_t FX_HashCode_GetW(const CFX_WideStringC& str, bool bIgnoreCase) {
537   uint32_t dwHashCode = 0;
538   if (bIgnoreCase) {
539     for (FX_STRSIZE i = 0; i < str.GetLength(); ++i)
540       dwHashCode = 1313 * dwHashCode + FXSYS_tolower(str.CharAt(i));
541   } else {
542     for (FX_STRSIZE i = 0; i < str.GetLength(); ++i)
543       dwHashCode = 1313 * dwHashCode + str.CharAt(i);
544   }
545   return dwHashCode;
546 }
547 
FX_Random_MT_Start(uint32_t dwSeed)548 void* FX_Random_MT_Start(uint32_t dwSeed) {
549   FX_MTRANDOMCONTEXT* pContext = FX_Alloc(FX_MTRANDOMCONTEXT, 1);
550   pContext->mt[0] = dwSeed;
551   uint32_t& i = pContext->mti;
552   uint32_t* pBuf = pContext->mt;
553   for (i = 1; i < MT_N; i++) {
554     pBuf[i] = (1812433253UL * (pBuf[i - 1] ^ (pBuf[i - 1] >> 30)) + i);
555   }
556   pContext->bHaveSeed = true;
557   return pContext;
558 }
FX_Random_MT_Generate(void * pContext)559 uint32_t FX_Random_MT_Generate(void* pContext) {
560   ASSERT(pContext);
561   FX_MTRANDOMCONTEXT* pMTC = static_cast<FX_MTRANDOMCONTEXT*>(pContext);
562   uint32_t v;
563   static uint32_t mag[2] = {0, MT_Matrix_A};
564   uint32_t& mti = pMTC->mti;
565   uint32_t* pBuf = pMTC->mt;
566   if ((int)mti < 0 || mti >= MT_N) {
567     if (mti > MT_N && !pMTC->bHaveSeed) {
568       return 0;
569     }
570     uint32_t kk;
571     for (kk = 0; kk < MT_N - MT_M; kk++) {
572       v = (pBuf[kk] & MT_Upper_Mask) | (pBuf[kk + 1] & MT_Lower_Mask);
573       pBuf[kk] = pBuf[kk + MT_M] ^ (v >> 1) ^ mag[v & 1];
574     }
575     for (; kk < MT_N - 1; kk++) {
576       v = (pBuf[kk] & MT_Upper_Mask) | (pBuf[kk + 1] & MT_Lower_Mask);
577       pBuf[kk] = pBuf[kk + (MT_M - MT_N)] ^ (v >> 1) ^ mag[v & 1];
578     }
579     v = (pBuf[MT_N - 1] & MT_Upper_Mask) | (pBuf[0] & MT_Lower_Mask);
580     pBuf[MT_N - 1] = pBuf[MT_M - 1] ^ (v >> 1) ^ mag[v & 1];
581     mti = 0;
582   }
583   v = pBuf[mti++];
584   v ^= (v >> 11);
585   v ^= (v << 7) & 0x9d2c5680UL;
586   v ^= (v << 15) & 0xefc60000UL;
587   v ^= (v >> 18);
588   return v;
589 }
FX_Random_MT_Close(void * pContext)590 void FX_Random_MT_Close(void* pContext) {
591   ASSERT(pContext);
592   FX_Free(pContext);
593 }
FX_Random_GenerateMT(uint32_t * pBuffer,int32_t iCount)594 void FX_Random_GenerateMT(uint32_t* pBuffer, int32_t iCount) {
595   uint32_t dwSeed;
596 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
597   if (!FX_GenerateCryptoRandom(&dwSeed, 1)) {
598     FX_Random_GenerateBase(&dwSeed, 1);
599   }
600 #else
601   FX_Random_GenerateBase(&dwSeed, 1);
602 #endif
603   void* pContext = FX_Random_MT_Start(dwSeed);
604   while (iCount-- > 0) {
605     *pBuffer++ = FX_Random_MT_Generate(pContext);
606   }
607   FX_Random_MT_Close(pContext);
608 }
FX_Random_GenerateBase(uint32_t * pBuffer,int32_t iCount)609 void FX_Random_GenerateBase(uint32_t* pBuffer, int32_t iCount) {
610 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
611   SYSTEMTIME st1, st2;
612   ::GetSystemTime(&st1);
613   do {
614     ::GetSystemTime(&st2);
615   } while (FXSYS_memcmp(&st1, &st2, sizeof(SYSTEMTIME)) == 0);
616   uint32_t dwHash1 =
617       FX_HashCode_GetA(CFX_ByteStringC((uint8_t*)&st1, sizeof(st1)), true);
618   uint32_t dwHash2 =
619       FX_HashCode_GetA(CFX_ByteStringC((uint8_t*)&st2, sizeof(st2)), true);
620   ::srand((dwHash1 << 16) | (uint32_t)dwHash2);
621 #else
622   time_t tmLast = time(nullptr);
623   time_t tmCur;
624   while ((tmCur = time(nullptr)) == tmLast) {
625     continue;
626   }
627 
628   ::srand((tmCur << 16) | (tmLast & 0xFFFF));
629 #endif
630   while (iCount-- > 0) {
631     *pBuffer++ = (uint32_t)((::rand() << 16) | (::rand() & 0xFFFF));
632   }
633 }
634 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
FX_GenerateCryptoRandom(uint32_t * pBuffer,int32_t iCount)635 bool FX_GenerateCryptoRandom(uint32_t* pBuffer, int32_t iCount) {
636   HCRYPTPROV hCP = 0;
637   if (!::CryptAcquireContext(&hCP, nullptr, nullptr, PROV_RSA_FULL, 0) ||
638       !hCP) {
639     return false;
640   }
641   ::CryptGenRandom(hCP, iCount * sizeof(uint32_t), (uint8_t*)pBuffer);
642   ::CryptReleaseContext(hCP, 0);
643   return true;
644 }
645 #endif
FX_Random_GenerateCrypto(uint32_t * pBuffer,int32_t iCount)646 void FX_Random_GenerateCrypto(uint32_t* pBuffer, int32_t iCount) {
647 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
648   FX_GenerateCryptoRandom(pBuffer, iCount);
649 #else
650   FX_Random_GenerateBase(pBuffer, iCount);
651 #endif
652 }
653 
654 #ifdef PDF_ENABLE_XFA
655 static const FX_CHAR gs_FX_pHexChars[] = "0123456789ABCDEF";
FX_GUID_CreateV4(FX_GUID * pGUID)656 void FX_GUID_CreateV4(FX_GUID* pGUID) {
657   FX_Random_GenerateMT((uint32_t*)pGUID, 4);
658   uint8_t& b = ((uint8_t*)pGUID)[6];
659   b = (b & 0x0F) | 0x40;
660 }
FX_GUID_ToString(const FX_GUID * pGUID,CFX_ByteString & bsStr,bool bSeparator)661 void FX_GUID_ToString(const FX_GUID* pGUID,
662                       CFX_ByteString& bsStr,
663                       bool bSeparator) {
664   FX_CHAR* pBuf = bsStr.GetBuffer(40);
665   uint8_t b;
666   for (int32_t i = 0; i < 16; i++) {
667     b = ((const uint8_t*)pGUID)[i];
668     *pBuf++ = gs_FX_pHexChars[b >> 4];
669     *pBuf++ = gs_FX_pHexChars[b & 0x0F];
670     if (bSeparator && (i == 3 || i == 5 || i == 7 || i == 9)) {
671       *pBuf++ = L'-';
672     }
673   }
674   bsStr.ReleaseBuffer(bSeparator ? 36 : 32);
675 }
676 #endif  // PDF_ENABLE_XFA
677