fx_extension.cpp revision 5ae9d0c6fd838a2967cca72aa5751b51dadc2769
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 22namespace { 23 24#ifdef PDF_ENABLE_XFA 25 26class 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 44CFX_CRTFileAccess::CFX_CRTFileAccess() {} 45 46CFX_CRTFileAccess::~CFX_CRTFileAccess() {} 47 48void CFX_CRTFileAccess::GetPath(CFX_WideString& wsPath) { 49 wsPath = m_path; 50} 51 52CFX_RetainPtr<IFX_SeekableStream> CFX_CRTFileAccess::CreateFileStream( 53 uint32_t dwModes) { 54 return IFX_SeekableStream::CreateFromFilename(m_path.c_str(), dwModes); 55} 56 57bool CFX_CRTFileAccess::Init(const CFX_WideStringC& wsPath) { 58 m_path = wsPath; 59 return true; 60} 61 62#endif // PDF_ENABLE_XFA 63 64class 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 85CFX_CRTFileStream::CFX_CRTFileStream(std::unique_ptr<IFXCRT_FileAccess> pFA) 86 : m_pFile(std::move(pFA)) {} 87 88CFX_CRTFileStream::~CFX_CRTFileStream() {} 89 90FX_FILESIZE CFX_CRTFileStream::GetSize() { 91 return m_pFile->GetSize(); 92} 93 94bool CFX_CRTFileStream::IsEOF() { 95 return GetPosition() >= GetSize(); 96} 97 98FX_FILESIZE CFX_CRTFileStream::GetPosition() { 99 return m_pFile->GetPosition(); 100} 101 102bool CFX_CRTFileStream::ReadBlock(void* buffer, 103 FX_FILESIZE offset, 104 size_t size) { 105 return m_pFile->ReadPos(buffer, size, offset) > 0; 106} 107 108size_t CFX_CRTFileStream::ReadBlock(void* buffer, size_t size) { 109 return m_pFile->Read(buffer, size); 110} 111 112bool CFX_CRTFileStream::WriteBlock(const void* buffer, 113 FX_FILESIZE offset, 114 size_t size) { 115 return !!m_pFile->WritePos(buffer, size, offset); 116} 117 118bool 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 126class 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 162CFX_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 171CFX_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 183CFX_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 192FX_FILESIZE CFX_MemoryStream::GetSize() { 193 return (FX_FILESIZE)m_nCurSize; 194} 195 196bool CFX_MemoryStream::IsEOF() { 197 return m_nCurPos >= (size_t)GetSize(); 198} 199 200FX_FILESIZE CFX_MemoryStream::GetPosition() { 201 return (FX_FILESIZE)m_nCurPos; 202} 203 204bool 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 238size_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 249bool 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 308bool CFX_MemoryStream::Flush() { 309 return true; 310} 311 312bool CFX_MemoryStream::IsConsecutive() const { 313 return !!(m_dwFlags & FX_MEMSTREAM_Consecutive); 314} 315 316void 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 329uint8_t* CFX_MemoryStream::GetBuffer() const { 330 return m_Blocks.GetSize() ? m_Blocks[0] : nullptr; 331} 332 333void 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 347void 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 356bool 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 377CFX_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 389CFX_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 399CFX_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 409CFX_RetainPtr<IFX_SeekableReadStream> 410IFX_SeekableReadStream::CreateFromFilename(const FX_CHAR* filename) { 411 return IFX_SeekableStream::CreateFromFilename(filename, FX_FILEMODE_ReadOnly); 412} 413 414// static 415CFX_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 422CFX_RetainPtr<IFX_MemoryStream> IFX_MemoryStream::Create(bool bConsecutive) { 423 return pdfium::MakeRetain<CFX_MemoryStream>(bConsecutive); 424} 425 426FX_FLOAT FXSYS_tan(FX_FLOAT a) { 427 return (FX_FLOAT)tan(a); 428} 429FX_FLOAT FXSYS_logb(FX_FLOAT b, FX_FLOAT x) { 430 return FXSYS_log(x) / FXSYS_log(b); 431} 432FX_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} 443FX_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} 489FX_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} 499int32_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} 511int32_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 524uint32_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 536uint32_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 548void* 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} 559uint32_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} 590void FX_Random_MT_Close(void* pContext) { 591 ASSERT(pContext); 592 FX_Free(pContext); 593} 594void 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} 609void 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_ 635bool 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 646void 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 655static const FX_CHAR gs_FX_pHexChars[] = "0123456789ABCDEF"; 656void 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} 661void 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