Re: c>c++ code translation
- From: Joseph M. Newcomer <newcomer@xxxxxxxxxxxx>
- Date: Sun, 12 Nov 2006 12:58:42 -0500
See below...
On Fri, 10 Nov 2006 15:42:01 -0800, segue <segue@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote:
****
Can someone explain what this class could be doing I don't know C++.
Thanks
void CRequest::OnSpawn() {
CString str;
SelectTransactionProcessor(""); // Selects default transaction processor
srand((unsigned)time(NULL));
This is seeding the random number generator with the current time so that you get a
"random" pattern to what is happening
****
for (int i=0; i<47; i++,rand()) {};****
This statement is nonsensical and should be removed; it was written by someone who is
totally clueless. It generates 47 random numbers. This serves no useful purpose.
****
KeyL=(rand()<<16)+rand();****
KeyM=(rand()<<16)+rand();
This is a pathethic attempt to create 32-bit "random" numbers. It is crap. It is based
on some erroneous premises about the rand() generator and will not really generate good
32-bit random numbers. I'm appending my 32-bit random number generator at the end.
****
str.Format("220****
%08x%08x%04x%04x%04x%04x%04x%04x%04x%04x\r\n",KeyL,KeyM,rand(),rand(),rand(),rand(),rand(),rand(),rand(),rand());
(*this) << str.GetBuffer(0);
This was written by someone totally clueless. It pretends to format some kind of "random"
key, but it is nonsense because it still uses a crappy random number generator. Then it
calls GetBuffer() and fails to release the buffer. I would say that the author of this
whole piece of code is deeply clueless about both random numbers and MFC. And judging from
the "(*this)<<" it suggests the person might be clueless about C++ and modularization as
well. So it is not surprising it is hard to read. The correct solution in this case is
to throw it out and rewrite it. The goal is to generate (if I've counted right) a
192-bit (24-byte) random number. This will not actually do that. It will generate a
192-bit value, but its randomness is problematic.
****
TicksTillDisconnect=600;****
Seems unrelated to generating a random number. So either the random number generator
should have been a separate method called from this code or this code should not be doing
other things.
****
}
*****
Here's my 32-bit random number generator. See the comment below; it trivially generalizes
to handle wider values, you just need to tweak the code a bit.
This is essentially implemented as a singleton class, and to get a random number I call
int n = Rand32::rand32();
The reason I did my own GetLastError handler had to do with meeting some existing
contraints; I would be more likely to ::SetLastError myself if I reused this code.
*****
//========================= RAND32.H ===========================
#pragma once
#include <WinCrypt.h>
class Rand32 {
public:
typedef enum {None, Crypto, Fake} RandType;
static RandType GetRandType();
static int rand32();
static GetLastError() { return error; }
protected:
static HCRYPTPROV provider;
static __declspec(thread) DWORD error;
};
//======================== RAND32.CPP ==========================
#include "stdafx.h"
#include "rand32.h"
#include <WinCrypt.h>
// This is not really a "random" number, and this code should ideally never
// be executed. I put it in as a fallback in case something really screws up
#define RAND32() ((int)(((DWORD)rand() << 17) ^ ((DWORD)rand() << 9) ^ rand()))
/* protected: static */ HCRYPTPROV Rand32::provider = NULL;
__declspec(thread) DWORD Rand32::error = 0;
/****************************************************************************
* rand32
* Result: int
* A 32-bit random number
* Notes:
* Sets ERROR_SUCCESS if successful
****************************************************************************/
/* static */ int Rand32::rand32()
{
error = ERROR_SUCCESS;
if(provider == NULL)
{ /* get provider */
if(!::CryptAcquireContext(&provider,
NULL, // use default cryptographic container
NULL, // use default cryptographic provider
PROV_RSA_FULL, // as good a choice as any
CRYPT_NEWKEYSET | CRYPT_SILENT))
{ /* failed */
error = ::GetLastError();
provider = (HCRYPTPROV)INVALID_HANDLE_VALUE;
} /* failed */
} /* get provider */
if(provider != (HCRYPTPROV)INVALID_HANDLE_VALUE)
{ /* get number */
int result;
if(::CryptGenRandom(provider, sizeof(int), (LPBYTE)&result))
return result;
// *****************
// Note here that if you define
// #define RAND_BYTES 24
// then you can use this same code to generate the entire
// 24-byte random number in a single call!
// if(::CryptGenRandom(provider, RAND_BYTES, (LPBYTE)buffer)
// where buffer is
// BYTE buffer[RAND_BYTES];
// and making other suitable changes in the code as needed, then
// you will have very good random number generator
//
// I forget who first pointed me at this solution, but thanks to whomever that was
..//*******************
error = ::GetLastError();
::CryptReleaseContext(provider, 0); // failed, why?
provider = (HCRYPTPROV)INVALID_HANDLE_VALUE;
} /* get number */
return RAND32();
} // rand32
/****************************************************************************
* GetRandType
* Result: RandType
* Type of random number returned
****************************************************************************/
/* static */ Rand32::RandType Rand32::GetRandType()
{
if(provider == NULL)
return None;
if(provider == (HCRYPTPROV)INVALID_HANDLE_VALUE)
return Fake;
return Crypto;
} // GetRandType
Joseph M. Newcomer [MVP]
email: newcomer@xxxxxxxxxxxx
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
.
- Prev by Date: Re: File length problem
- Next by Date: Re: location of groupbox
- Previous by thread: Re: c>c++ code translation
- Next by thread: Complier Help Program only runs on single Computer
- Index(es):
Relevant Pages
|