From 770ba0b9f3e3d3e87dd72fe9daafedcda3c03d48 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Fri, 29 Sep 2006 14:45:28 +0000 Subject: [PATCH] Fixed random number generation on Windows. On 9x/ME UuidCreate returns the same value in UUID.Data4 on each call meaning that the numbers generated are always the same, too. In such cases srand() and rand() is used instead of UuidCreate. The loop for the "UuidCreate failed" case was broken as well. --- ChangeLog | 7 +++++ src/common/random.cpp | 69 ++++++++++++++++++++++++++++++------------- src/common/random.h | 2 ++ 3 files changed, 58 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index f16a5762e..21894ea36 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2006-09-29 Moritz Bunkus + + * mkvmerge: bug fix: Fixed the random number generation on + Windows. On Windows 9x/ME mkvmerge would simply hang. On newer + versions the function was accessing invalid memory and was + generally buggy. + 2006-09-26 Moritz Bunkus * mkvmerge: bug fix: SSA/ASS subtitles with comments before the diff --git a/src/common/random.cpp b/src/common/random.cpp index 4f24b90b8..7f0e4a044 100644 --- a/src/common/random.cpp +++ b/src/common/random.cpp @@ -29,34 +29,63 @@ bool random_c::m_seeded = false; #if defined(SYS_WINDOWS) +bool random_c::m_tried_uuidcreate = false; +bool random_c::m_use_uuidcreate = false; + void random_c::generate_bytes(void *destination, int num_bytes) { - int i, num_left; + int num_written, num_left; + UUID uuid; + RPC_STATUS status; - i = 0; - while (num_bytes > 0) { - UUID uuid; - RPC_STATUS status; + if (!m_seeded) { + srand(GetTickCount()); + m_seeded = true; + } - status = UuidCreate(&uuid); - if ((RPC_S_OK != status) && (RPC_S_UUID_LOCAL_ONLY != status)) { - if (!m_seeded) { - srand(GetTickCount()); - m_seeded = true; + if (!m_tried_uuidcreate) { + // Find out whether UuidCreate returns different + // data in Data4 on each call by comparing up to five + // results. If not use srand() and rand(). + UUID first_uuid; + int i; + + m_use_uuidcreate = true; + status = UuidCreate(&first_uuid); + if ((RPC_S_OK == status) || (RPC_S_UUID_LOCAL_ONLY == status)) { + for (i = 0; i < 5; ++i) { + status = UuidCreate(&uuid); + if (((RPC_S_OK != status) && (RPC_S_UUID_LOCAL_ONLY != status)) || + !memcmp(first_uuid.Data4, uuid.Data4, sizeof(uuid.Data4))) { + m_use_uuidcreate = false; + break; + } + } + } else + m_use_uuidcreate = false; + + m_tried_uuidcreate = true; + } + + num_written = 0; + while (num_written < num_bytes) { + if (m_use_uuidcreate) { + status = UuidCreate(&uuid); + if ((RPC_S_OK != status) && (RPC_S_UUID_LOCAL_ONLY != status)) { + m_use_uuidcreate = false; + continue; } - while (0 > num_bytes) { - ((unsigned char *)destination)[i + num_bytes] = + num_left = (num_bytes - num_written) > 8 ? 8 : + (num_written - num_bytes); + memcpy((unsigned char *)destination + num_written, &uuid.Data4, num_left); + num_written += num_left; + + } else + for (; num_written < num_bytes; ++num_written) + ((unsigned char *)destination)[num_written] = (unsigned char)(256.0 * rand() / (RAND_MAX + 1.0)); - --num_bytes; - } - } - - num_left = num_bytes > 8 ? 8 : num_bytes; - memcpy((unsigned char *)destination + i, &uuid.Data4, num_left); - num_bytes -= num_left; - i += num_left; } } diff --git a/src/common/random.h b/src/common/random.h index fc06f1fe1..9238d8baf 100644 --- a/src/common/random.h +++ b/src/common/random.h @@ -28,6 +28,8 @@ private: #if !defined(SYS_WINDOWS) static auto_ptr m_dev_urandom; static bool m_tried_dev_urandom; +#else + static bool m_tried_uuidcreate, m_use_uuidcreate; #endif public: