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: