00001
00010 #include "dkcSemiRealRandom.h"
00011 #include "dkcOS.h"
00012 #include "dkcStdio.h"
00013
00014 #ifdef _MSC_VER
00015 # pragma warning(disable:4055)
00016 #endif
00017
00018
00019
00020 #define dkcdSRR_PATH_SIZE (sizeof(wchar_t) * dkcdMAXPATH_BUFFER)
00021
00022 typedef
00023 DWORD (WINAPI *GetTempPathA_FT)(
00024 DWORD nBufferLength,
00025 LPSTR lpBuffer
00026 );
00027
00028 typedef
00029 DWORD (WINAPI *GetTempPathW_FT)(
00030 DWORD nBufferLength,
00031 LPWSTR lpBuffer
00032 );
00033
00034
00035 typedef
00036 UINT (WINAPI *GetTempFileNameA_FT)(
00037 LPCSTR lpPathName,
00038 LPCSTR lpPrefixString,
00039 UINT uUnique,
00040 LPSTR lpTempFileName
00041 );
00042
00043 typedef
00044 UINT (WINAPI *GetTempFileNameW_FT)(
00045 LPCWSTR lpPathName,
00046 LPCWSTR lpPrefixString,
00047 UINT uUnique,
00048 LPWSTR lpTempFileName
00049 );
00050
00051
00052 static DKC_INLINE int load_dll(DKC_SEMI_REAL_RANDOM *p,BOOL isNT){
00053 DKC_DLL *pdll = dkcLoadLibrary("kernel32.dll");
00054 if(NULL==pdll)
00055 return edk_FAILED;
00056
00057 if(isNT){
00058 p->fpGetTempFileName = dkcGetProcAddress(pdll,"GetTempFileNameW");
00059 p->fpGetTempPath = dkcGetProcAddress(pdll,"GetTempPathW");
00060 }else{
00061 p->fpGetTempFileName = dkcGetProcAddress(pdll,"GetTempFileNameA");
00062 p->fpGetTempPath = dkcGetProcAddress(pdll,"GetTempPathA");
00063 }
00064
00065 dkcmFORCE_NOT_ASSERT(
00066 p->fpGetTempFileName == NULL ||
00067 p->fpGetTempPath == NULL
00068 );
00069
00070 p->pDLL = pdll;
00071 return edk_SUCCEEDED;
00072 }
00073
00074 DKC_SEMI_REAL_RANDOM *WINAPI dkcAllocSemiRealRandomWin32()
00075 {
00076 DKC_SEMI_REAL_RANDOM *ptr;
00077 DKC_GENERIC_FILESYSTEM *pfs;
00078 BOOL isNT = dkcIsOSNT();
00079 if(isNT)
00080 {
00081 pfs = dkcAlloc_UNICODE_FileSystem();
00082 }else{
00083 pfs = dkcAlloc_SJIS_FileSystem();
00084 }
00085
00086 ptr = dkcAllocSemiRealRandomFromGFS(pfs);
00087 if(NULL==ptr){
00088 dkcFreeGenericFileSystem(&pfs);
00089 return NULL;
00090 }
00091
00092 ptr->pPath = dkcAllocate(dkcdSRR_PATH_SIZE);
00093 if(NULL==ptr->pPath){
00094 goto End;
00095 }
00096
00097 if(DKUTIL_FAILED(load_dll(ptr,isNT))){
00098 goto End;
00099 }
00100
00101 ptr->mIsNT = isNT;
00102
00103 return ptr;
00104 End:
00105 dkcFreeSemiRealRandom(&ptr);
00106 return NULL;
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 }
00120
00121
00122 DKC_SEMI_REAL_RANDOM *WINAPI dkcAllocSemiRealRandomFromGFS(DKC_GENERIC_FILESYSTEM *pa)
00123 {
00124 DKC_SEMI_REAL_RANDOM *p;
00125 if(NULL==pa){
00126 return NULL;
00127 }
00128 p = dkcAllocate(sizeof(DKC_SEMI_REAL_RANDOM));
00129 if(NULL==p){
00130 return NULL;
00131 }
00132 p->mpObj = pa;
00133 return p;
00134 }
00135
00136
00137 int WINAPI dkcFreeSemiRealRandom(DKC_SEMI_REAL_RANDOM **pp)
00138 {
00139 DKC_SEMI_REAL_RANDOM *p = *pp;
00140 if(NULL==pp || NULL==p)
00141 return edk_FAILED;
00142
00143 dkcFreeGenericFileSystem(&(p->mpObj));
00144 return dkcFree(pp);
00145 }
00146
00147 static DKC_INLINE int process(DKC_GENERIC_FILESYSTEM *gfs,const void *filename){
00148 size_t ws;
00149 char buff[1];
00150 int r = dkcGenericFileSystemOpen(gfs,edkcBinaryMode | edkcWriteMode,filename);
00151 if(DKUTIL_FAILED(r)) return r;
00152
00153 dkcGenericFileSystemWrite(gfs,buff,sizeof(buff),&ws);
00154
00155 dkcGenericFileSystemClose(gfs);
00156
00157 dkcGenericFileSystemDeleteFile(gfs,filename);
00158 return edk_SUCCEEDED;
00159 }
00160
00161 static BOOL generate(DKC_SEMI_REAL_RANDOM *ptr,uint32 *value32){
00162 #ifdef WIN32
00163 DKC_INT64_STRUCT hd;
00164 uint32 temp;
00165 QueryPerformanceCounter(&hd);
00166 temp = hd.u.LowPart;
00167
00168 if(DKUTIL_FAILED(process(ptr->mpObj,ptr->pPath))){
00169 return FALSE;
00170 }
00171
00172 QueryPerformanceCounter(&hd);
00173 *value32 = (hd.LowPart ^ temp);
00174 return TRUE;
00175 #else
00176
00177
00178 #endif
00179 }
00180
00182 static uint32 test(DKC_SEMI_REAL_RANDOM *ptr,size_t test_count,size_t min_,size_t max_)
00183 {
00184 uint8 bits[dkcdSEMI_REAL_RANDOM_BITS];
00185 uint8 prior_bits[dkcdSEMI_REAL_RANDOM_BITS];
00186 uint32 various[dkcdSEMI_REAL_RANDOM_BITS];
00187 uint32 val;
00188 int randRshift,randLshift;
00189 int i;
00190 size_t j;
00191
00192 memset(various,0,sizeof(uint32) * dkcdSEMI_REAL_RANDOM_BITS);
00193
00194 for(j=0;j<test_count;j++)
00195 {
00196 if(FALSE==generate(ptr,&val))
00197 return 0xFFFFFFFF;
00198
00199 for(i=0;i<dkcdSEMI_REAL_RANDOM_BITS;i++)
00200 {
00201 bits[i]=(uint8)(val & 1);
00202 val = val >> 1;
00203 various[i] += ( bits[i] != prior_bits[i] );
00204 prior_bits[i]=bits[i];
00205 }
00206 }
00207
00208 randRshift=255;
00209 randLshift=-1;
00210 for(i=0;i<dkcdSEMI_REAL_RANDOM_BITS;i++)
00211 {
00212 if((various[i]>=min_)&&(various[i]<=max_))
00213 {
00214 if(i < randRshift)
00215 randRshift=i;
00216
00217 if(i >= randLshift)
00218 randLshift=i-randRshift+1;
00219 }
00220 else break;
00221 }
00222 if(randRshift==255) return 0xFFFFFFFF;
00223 if(randLshift<=0) return 0xFFFFFFFF;
00224
00225 ptr->mLeftShift = randLshift;
00226 ptr->mRightShift = randRshift;
00227
00228 return (uint32)randLshift;
00229 }
00230
00231 int WINAPI dkcSemiRealRandomInit(DKC_SEMI_REAL_RANDOM *ptr)
00232 {
00233 #ifdef WIN32
00234
00235 GetTempPathA_FT pGTPA;
00236
00237
00238 GetTempPathW_FT pGTPW;
00239
00240
00241 if(ptr->mIsNT){
00242 pGTPW = (GetTempPathW_FT)ptr->fpGetTempPath;
00243 dkcmFORCE_NOT_ASSERT(dkcdMAXPATH < pGTPW(0,ptr->pPath));
00244
00245 if(pGTPW(dkcdMAXPATH,ptr->pPath)==0)
00246 return edk_FAILED;
00247
00248
00249 if(DKUTIL_FAILED(dkc_wcscat2(ptr->pPath,dkcdSRR_PATH_SIZE,dkcdSRR_TEMP_FILE_NAME_W)))
00250 {
00251 return edk_FAILED;
00252 }
00253
00254 }else{
00255 pGTPA = (GetTempPathA_FT)ptr->fpGetTempPath;
00256 dkcmFORCE_NOT_ASSERT(dkcdMAXPATH < pGTPA(0,ptr->pPath));
00257
00258 if(pGTPA(dkcdMAXPATH,ptr->pPath)==0)
00259 return edk_FAILED;
00260
00261
00262 if(DKUTIL_FAILED(dkc_strcat2(ptr->pPath,dkcdSRR_PATH_SIZE,dkcdSRR_TEMP_FILE_NAME)))
00263 {
00264 return edk_FAILED;
00265 }
00266 }
00267 {
00268 int i;
00269 for(i=0;i<dkcdSEMI_REAL_RANDOM_TRIAL_AND_ERROR_LIMIT;)
00270 {
00271 if(0xFFFFFFFF==test(ptr,128,40,60)){
00272 i++;
00273 }else{
00274 break;
00275 }
00276 }
00277 if(!(i<64))
00278 {
00279 return edk_FAILED;
00280 }
00281 }
00282
00283 return edk_SUCCEEDED;
00284 #else
00285
00286
00287 #endif
00288
00289 }
00290
00291
00292
00293 BOOL WINAPI dkcSemiRealRandomGet32(DKC_SEMI_REAL_RANDOM *ptr,uint32 *value32)
00294 {
00295 uint32 tmp=0;
00296 uint32 val;
00297 int totalbit=0;
00298 size_t i,j;
00299 for(j=0;j<dkcdSEMI_REAL_RANDOM_TRIAL_AND_ERROR_LIMIT;j++)
00300 {
00301 if(FALSE==generate(ptr,&val))
00302 return FALSE;
00303
00304 val = val >> ptr->mRightShift;
00305 for(i=0;i<ptr->mLeftShift;i++)
00306 {
00307 tmp+=val & 1;
00308 val=val >> 1;
00309 totalbit++;
00310 if(totalbit>=32){
00311 *value32 = tmp;
00312 goto End;
00313 }
00314 tmp=tmp<<1;
00315 }
00316 }
00317
00318 End:
00319 if(!(j<dkcdSEMI_REAL_RANDOM_TRIAL_AND_ERROR_LIMIT))
00320 {
00321 return FALSE;
00322 }
00323 return TRUE;
00324 }
00325
00326 uint8 WINAPI dkcSemiRealRandomGet1(DKC_SEMI_REAL_RANDOM *ptr)
00327 {
00328 #ifdef WIN32
00329 uint32 val;
00330 generate(ptr,&val);
00331 return (uint8) ( (val >> ptr->mRightShift ) & 1) ;
00332
00333 #else
00334
00335
00336 #endif
00337
00338
00339
00340 }
00341
00342
00343
00344 #ifdef _MSC_VER
00345 # pragma warning(default:4055)
00346 #endif
00347