Wonderland
  • README.md
  • Notebook
    • Crypto
      • Solana
        • Troubleshooting
          • BPF SDK path does not exist
    • Language
      • Rust
        • Reference
          • Capturing the Environment with Closures
          • Understanding &mut &mut Reference
      • C++
        • Reference
          • Code for MS rand() and srand() in VC++ 6.0
  • Textbook
    • Serials
      • A Real-Time Cryptocurrency Ticker Dashboard
        • 0 - Some Preparation
    • Frontend
      • A Simple Progress Bar
      • A React Ribbon Component
      • An Easy to Use React DnD Sortable Component
      • Sticky Header, Sticky Footer and Fluid Content
      • How To Set Same Height As Width In CSS
  • dictionary
    • Alphabet
      • MySQL
      • FFmpeg
    • Algorithm
      • Diary
        • 2022
          • 07
            • 2022-07-02
            • 2022-07-01
          • 06
            • 2022-06-30
            • 2022-06-29
            • 2022-06-28
            • 2022-06-27
            • 2022-06-26
            • 2022-06-25
            • 2022-06-24
            • 2022-06-23
            • 2022-06-22
            • 2022-06-21
            • 2022-06-20
            • 2022-06-19
            • 2022-06-18
            • 2022-06-17
            • 2022-06-16
            • 2022-06-15
            • 2022-06-14
            • 2022-06-13
            • 2022-06-12
            • 2022-06-11
            • 2022-06-10
            • 2022-06-09
            • 2022-06-08
            • 2022-06-07
            • 2022-06-06
            • 2022-06-05
            • 2022-06-04
            • 2022-06-03
            • 2022-06-02
            • 2022-06-01
          • 05
            • 2022-05-31
            • 2022-05-30
            • 2022-05-29
            • 2022-05-28
            • 2022-05-27
            • 2022-05-26
            • 2022-05-25
            • 2022-05-24
            • 2022-05-23
            • 2022-05-22
            • 2022-05-21
            • 2022-05-20
            • 2022-05-19
            • 2022-05-18
            • 2022-05-17
            • 2022-05-16
            • 2022-05-15
    • Troubleshooting
      • A Weird Python Command Not Found Problem
Powered by GitBook
On this page
  • The different results on Windows and Linux
  • Digging the source code
  • Reference
  1. Notebook
  2. Language
  3. C++
  4. Reference

Code for MS rand() and srand() in VC++ 6.0

Last updated 2 years ago

My friend created a registration code generator for his software on Windows, and he wanted to transplant it into a web app.

He asked for my help. I think it seems really easy, so I agreed without hesitation. Then a long story began...

The different results on Windows and Linux

As we know, srand will set the current number stored in the memory which is known as seed, and rand will use the seed to calculate and return a new number.

The source code of the registration code generator looks like this:

for(int i=0; i<5; i++) {    
    srand(seed[i]);
    strKey.Format(strKey+_T("%c"), _T('A')+rand()%26);
}

The seed in the code above is generated from the user's machine id. Now it seems evident that we combine the usages of rand of srand to generate a static registration code.

I use cgo to wrap the origin C++ code, however, the result is not as expected. After some debugging, I found the executing result of rand on Linux is different from the one on Windows.

Digging the source code

is easy to find:

/* If we are using the trivial TYPE_0 R.N.G., just do the old linear
   congruential bit.  Otherwise, we do our fancy trinomial stuff, which is the
   same in all the other cases due to all the global variables that have been
   set up.  The basic operation is to add the number at the rear pointer into
   the one at the front pointer.  Then both pointers are advanced to the next
   location cyclically in the table.  The value returned is the sum generated,
   reduced to 31 bits by throwing away the "least random" low bit.
   Note: The code takes advantage of the fact that both the front and
   rear pointers can't wrap on the same call by not testing the rear
   pointer if the front one has wrapped.  Returns a 31-bit random number.  */

int
__random_r (buf, result)
     struct random_data *buf;
     int32_t *result;
{
  int32_t *state;

  if (buf == NULL || result == NULL)
    goto fail;

  state = buf->state;

  if (buf->rand_type == TYPE_0)
    {
      int32_t val = state[0];
      val = ((state[0] * 1103515245) + 12345) & 0x7fffffff;
      state[0] = val;
      *result = val;
    }
  else
    {
      int32_t *fptr = buf->fptr;
      int32_t *rptr = buf->rptr;
      int32_t *end_ptr = buf->end_ptr;
      int32_t val;

      val = *fptr += *rptr;
      /* Chucking least random bit.  */
      *result = (val >> 1) & 0x7fffffff;
      ++fptr;
      if (fptr >= end_ptr)
    {
      fptr = state;
      ++rptr;
    }
      else
    {
      ++rptr;
      if (rptr >= end_ptr)
        rptr = state;
    }
      buf->fptr = fptr;
      buf->rptr = rptr;
    }
  return 0;

 fail:
  __set_errno (EINVAL);
  return -1;
}

Here is the source code of rand in VC++ 6.0(or still the same as the one today in Visual Studio 2022...):

static long holdrand = 1L;
int __cdecl rand (void)
{
    return(((holdrand = holdrand * 214013L + 2531011L)>>16) & 0x7fff);
}
void __cdecl srand (unsigned int seed)
{
    holdrand = (long)seed;
}

and the functions are finally implemented into Typescript:

class WinRandom {
  next: number;
  rand(this: WinRandom): number {
    this.next = this.next * 214013 + 2531011;
    return (this.next >> 16) & 0x7fff;
  }
  srand(this: WinRandom, seed: number) {
    this.next = seed;
  }
}

Reference

The source code of Windows rand really took me a lot of time to discover the truth, and here let's skip my three-hour search and experimentation. The source code is finally found in ...

The source code of Linux rand
an ancient discussion in a forum which is posted in 2003
How can I get the sourcecode for rand() (C++)?
Code for MS rand() and srand()