@@ -228,7 +228,7 @@ extern int lstat(const char *, struct stat *);
228228#include <io.h>
229229#include <process.h>
230230#include "osdefs.h"
231- #define WIN32_LEAN_AND_MEAN
231+ #define _WIN32_WINNT 0x0400 /* Needed for CryptoAPI on some systems */
232232#include <windows.h>
233233#include <shellapi.h> /* for ShellExecute() */
234234#define popen _popen
@@ -7221,6 +7221,74 @@ posix_getloadavg(PyObject *self, PyObject *noargs)
72217221}
72227222#endif
72237223
7224+ #ifdef MS_WINDOWS
7225+
7226+ PyDoc_STRVAR (win32_urandom__doc__ ,
7227+ "urandom(n) -> str\n\n\
7228+ Return a string of n random bytes suitable for cryptographic use." );
7229+
7230+ typedef BOOL (WINAPI * CRYPTACQUIRECONTEXTA )(HCRYPTPROV * phProv ,\
7231+ LPCSTR pszContainer , LPCSTR pszProvider , DWORD dwProvType ,\
7232+ DWORD dwFlags );
7233+ typedef BOOL (WINAPI * CRYPTGENRANDOM )(HCRYPTPROV hProv , DWORD dwLen ,\
7234+ BYTE * pbBuffer );
7235+
7236+ static CRYPTGENRANDOM pCryptGenRandom = NULL ;
7237+ static HCRYPTPROV hCryptProv = 0 ;
7238+
7239+ static PyObject * win32_urandom (PyObject * self , PyObject * args )
7240+ {
7241+ int howMany = 0 ;
7242+ unsigned char * bytes = NULL ;
7243+ PyObject * returnVal = NULL ;
7244+
7245+ /* Read arguments */
7246+ if (!PyArg_ParseTuple (args , "i" , & howMany ))
7247+ return (NULL );
7248+
7249+ if (hCryptProv == 0 ) {
7250+ HINSTANCE hAdvAPI32 = NULL ;
7251+ CRYPTACQUIRECONTEXTA pCryptAcquireContext = NULL ;
7252+
7253+ /* Obtain handle to the DLL containing CryptoAPI
7254+ This should not fail */
7255+ if ( (hAdvAPI32 = GetModuleHandle ("advapi32.dll" )) == NULL )
7256+ return win32_error ("GetModuleHandle" , NULL );
7257+
7258+ /* Obtain pointers to the CryptoAPI functions
7259+ This will fail on some early versions of Win95 */
7260+ pCryptAcquireContext = (CRYPTACQUIRECONTEXTA )GetProcAddress (hAdvAPI32 ,\
7261+ "CryptAcquireContextA" );
7262+ pCryptGenRandom = (CRYPTGENRANDOM )GetProcAddress (hAdvAPI32 ,\
7263+ "CryptGenRandom" );
7264+
7265+ if (pCryptAcquireContext == NULL || pCryptGenRandom == NULL )
7266+ return PyErr_Format (PyExc_NotImplementedError ,\
7267+ "CryptGenRandom not found" );
7268+
7269+ /* Acquire context */
7270+ if (!pCryptAcquireContext (& hCryptProv , NULL , NULL , PROV_RSA_FULL ,
7271+ CRYPT_VERIFYCONTEXT ))
7272+ return win32_error ("CryptAcquireContext" , NULL );
7273+ }
7274+
7275+ /* Allocate bytes */
7276+ if ((bytes = (unsigned char * )PyMem_Malloc (howMany )) == NULL )
7277+ return PyErr_NoMemory ();
7278+
7279+ /* Get random data */
7280+ if (!pCryptGenRandom (hCryptProv , howMany , bytes )) {
7281+ PyMem_Free (bytes );
7282+ return win32_error ("CryptGenRandom" , NULL );
7283+ }
7284+
7285+ /* Build return value */
7286+ returnVal = PyString_FromStringAndSize (bytes , howMany );
7287+ PyMem_Free (bytes );
7288+
7289+ return returnVal ;
7290+ }
7291+ #endif
72247292
72257293static PyMethodDef posix_methods [] = {
72267294 {"access" , posix_access , METH_VARARGS , posix_access__doc__ },
@@ -7506,6 +7574,9 @@ static PyMethodDef posix_methods[] = {
75067574#ifdef HAVE_GETLOADAVG
75077575 {"getloadavg" , posix_getloadavg , METH_NOARGS , posix_getloadavg__doc__ },
75087576#endif
7577+ #ifdef MS_WINDOWS
7578+ {"urandom" , win32_urandom , METH_VARARGS , win32_urandom__doc__ },
7579+ #endif
75097580 {NULL , NULL } /* Sentinel */
75107581};
75117582
0 commit comments