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.

This commit is contained in:
Moritz Bunkus 2006-09-29 14:45:28 +00:00
parent 528890fe47
commit 770ba0b9f3
3 changed files with 58 additions and 20 deletions

View File

@ -1,3 +1,10 @@
2006-09-29 Moritz Bunkus <moritz@bunkus.org>
* 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 <moritz@bunkus.org>
* mkvmerge: bug fix: SSA/ASS subtitles with comments before the

View File

@ -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;
}
}

View File

@ -28,6 +28,8 @@ private:
#if !defined(SYS_WINDOWS)
static auto_ptr<mm_file_io_c> m_dev_urandom;
static bool m_tried_dev_urandom;
#else
static bool m_tried_uuidcreate, m_use_uuidcreate;
#endif
public: