]> gitweb.factorcode.org Git - factor.git/blob - basis/random/windows/windows.factor
Updating code to use with-out-parameters
[factor.git] / basis / random / windows / windows.factor
1 USING: accessors alien.c-types alien.data byte-arrays
2 combinators.short-circuit continuations destructors init kernel
3 locals namespaces random windows.advapi32 windows.errors
4 windows.kernel32 windows.types math.bitwise sequences fry
5 literals ;
6 IN: random.windows
7
8 TUPLE: windows-rng provider type ;
9 C: <windows-rng> windows-rng
10
11 TUPLE: windows-crypto-context handle ;
12 C: <windows-crypto-context> windows-crypto-context
13
14 M: windows-crypto-context dispose ( tuple -- )
15     handle>> 0 CryptReleaseContext win32-error=0/f ;
16
17 CONSTANT: factor-crypto-container "FactorCryptoContainer"
18
19 :: (acquire-crypto-context) ( provider type flags -- handle )
20     { HCRYPTPROV } [
21         factor-crypto-container
22         provider
23         type
24         flags
25         CryptAcquireContextW
26     ] [ ] with-out-parameters ;
27
28 : acquire-crypto-context ( provider type -- handle )
29     CRYPT_MACHINE_KEYSET
30     (acquire-crypto-context)
31     swap 0 = [
32         GetLastError NTE_BAD_KEYSET =
33         [ drop f ] [ win32-error-string throw ] if
34     ] when ;
35
36 : create-crypto-context ( provider type -- handle )
37     flags{ CRYPT_MACHINE_KEYSET CRYPT_NEWKEYSET }
38     (acquire-crypto-context) win32-error=0/f *void* ;
39
40 ERROR: acquire-crypto-context-failed provider type ;
41
42 : attempt-crypto-context ( provider type -- handle )
43     {
44         [ acquire-crypto-context ] 
45         [ create-crypto-context ] 
46         [ acquire-crypto-context-failed ]
47     } 2|| ;
48
49 : windows-crypto-context ( provider type -- context )
50     attempt-crypto-context <windows-crypto-context> ;
51
52 M: windows-rng random-bytes* ( n tuple -- bytes )
53     [
54         [ provider>> ] [ type>> ] bi
55         windows-crypto-context &dispose
56         handle>> swap dup <byte-array>
57         [ CryptGenRandom win32-error=0/f ] keep
58     ] with-destructors ;
59
60 ERROR: no-windows-crypto-provider error ;
61
62 : try-crypto-providers ( seq -- windows-rng )
63     [ first2 <windows-rng> ] attempt-all
64     dup windows-rng? [ no-windows-crypto-provider ] unless ;
65
66 [
67     {
68         ${ MS_ENHANCED_PROV PROV_RSA_FULL }
69         ${ MS_DEF_PROV PROV_RSA_FULL }
70     } try-crypto-providers
71     system-random-generator set-global
72
73     {
74         ${ MS_STRONG_PROV PROV_RSA_FULL }
75         ${ MS_ENH_RSA_AES_PROV PROV_RSA_AES }
76     } try-crypto-providers secure-random-generator set-global
77 ] "random.windows" add-startup-hook
78
79 [
80     [
81         ! system-random-generator get-global &dispose drop
82         ! secure-random-generator get-global &dispose drop
83     ] with-destructors
84 ] "random.windows" add-shutdown-hook