Subject: | [Win32] Dependency upon Win32::API is not ideal |
Hi Dana, Dave,
I'd prefer to see CryptGenRandom and RtlGenRandom called via XSubs - thereby removing the Win32::API dependency.
Win32::API certainly filled a role back in the day when Windows machines typically were missing a C compiler. But now that those days have gone, I don't see why one would prefer to build and install Win32::API in preference to compiling XSubs.
While Win32-API-0.77 (current stable) builds straight out of the box on Strawberry Perls, it won't do so on those 64-bit perls built using a mingw64 cross-compiler.
This is not actually the fault of Win32::API. I think it's that EU::MM doesn't realize that "as.exe" is actually named "x86_64-w64-mingw32-as.exe" - and I'll file a bug report against EU::MM for that when I've worked out the patch.
It is, of course, quite easy to work around this problem - one simply creates a copy of "x86_64-w64-mingw32-as.exe" named "as.exe" and Win32-API-0.77 then builds fine.
In the interests of advancing the replacement of Win32::API, I'm attaching 'random2.pl' which contains 2 XSubs - one that wraps RtlGenRandom and one that wraps CryptGenRandom.
For your convenience, they come in the form of an Inline::C script.
I'm rating this bug report as "wishlist" - which, to my mind, implies that you are quite free to ignore it completely ;-)
Cheers,
Rob
Subject: | random2.pl |
use strict;
use warnings;
use Devel::Peek;
use Inline C => Config =>
BUILD_NOISY => 1,
USING => 'ParseRegExp';
use Inline C => <<'EOC';
#include <wincrypt.h> /* needed for crypt_gen_random()
but not for rtl_gen_random() */
SV * crypt_gen_random(unsigned long len) {
SV * ret;
char * buff;
HCRYPTPROV prov = 0;
if(!CryptAcquireContextA(&prov, 0, 0, PROV_RSA_FULL, CRYPT_SILENT | CRYPT_VERIFYCONTEXT))
croak("Call to CryptAcquireContextA() failed");
Newx(buff, len, char);
if(buff == NULL) {
CryptReleaseContext(&prov, 0);
croak ("Failed to allocate memory for buffer");
}
if(!CryptGenRandom(prov, len, buff)) {
Safefree(buff);
CryptReleaseContext(&prov, 0);
croak("Call to CryptGenRandom() failed");
}
ret = newSVpv(buff, len);
Safefree(buff);
CryptReleaseContext(&prov, 0);
return ret;
}
SV * rtl_gen_random(unsigned long len) {
SV * ret;
unsigned long i;
char * buff;
Newx(buff, len, char);
if(buff == 0) croak ("Failed to allocate memory for 'buff'");
HMODULE hLib=LoadLibrary("ADVAPI32.DLL");
if (hLib) {
BOOLEAN (APIENTRY *pfn)(void*, ULONG) =
(BOOLEAN (APIENTRY *)(void*,ULONG))GetProcAddress(hLib,"SystemFunction036");
if(pfn(buff,len)) ret = newSVpv(buff, len);
else {
FreeLibrary(hLib);
croak("Call to 'SystemFunction036' failed");
}
FreeLibrary(hLib);
}
else {
croak("Failed to load ADVAPI32.dll");
}
Safefree(buff);
return ret;
}
EOC
my $c = crypt_gen_random(100);
print "$c\n", length($c), "\n";
Dump($c);
my $r = rtl_gen_random(100);
print "\n$r\n", length($r), "\n";
Dump($r);