include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / crypt32 / unixlib.c
blob5a255442fdffe5516928df5d6e9429039f236d3d
1 /*
2 * Copyright 2019 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #if 0
20 #pragma makedep unix
21 #endif
23 #include "config.h"
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <dirent.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <dlfcn.h>
31 #include <sys/stat.h>
32 #ifdef __APPLE__
33 #include <Security/Security.h>
34 #endif
35 #ifdef SONAME_LIBGNUTLS
36 #include <gnutls/pkcs12.h>
37 #endif
39 #include "ntstatus.h"
40 #define WIN32_NO_STATUS
41 #include "windef.h"
42 #include "winbase.h"
43 #include "winternl.h"
44 #include "wincrypt.h"
45 #include "crypt32_private.h"
46 #include "wine/debug.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
50 #ifdef SONAME_LIBGNUTLS
52 WINE_DECLARE_DEBUG_CHANNEL(winediag);
54 /* Not present in gnutls version < 3.0 */
55 int gnutls_pkcs12_simple_parse(gnutls_pkcs12_t p12, const char *password,
56 gnutls_x509_privkey_t *key, gnutls_x509_crt_t **chain, unsigned int *chain_len,
57 gnutls_x509_crt_t **extra_certs, unsigned int *extra_certs_len,
58 gnutls_x509_crl_t * crl, unsigned int flags);
60 int gnutls_x509_privkey_get_pk_algorithm2(gnutls_x509_privkey_t, unsigned int*);
62 static void *libgnutls_handle;
63 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
64 MAKE_FUNCPTR(gnutls_global_deinit);
65 MAKE_FUNCPTR(gnutls_global_init);
66 MAKE_FUNCPTR(gnutls_global_set_log_function);
67 MAKE_FUNCPTR(gnutls_global_set_log_level);
68 MAKE_FUNCPTR(gnutls_perror);
69 MAKE_FUNCPTR(gnutls_pkcs12_deinit);
70 MAKE_FUNCPTR(gnutls_pkcs12_import);
71 MAKE_FUNCPTR(gnutls_pkcs12_init);
72 MAKE_FUNCPTR(gnutls_pkcs12_simple_parse);
73 MAKE_FUNCPTR(gnutls_x509_crt_export);
74 MAKE_FUNCPTR(gnutls_x509_privkey_export_rsa_raw2);
75 MAKE_FUNCPTR(gnutls_x509_privkey_get_pk_algorithm2);
76 #undef MAKE_FUNCPTR
78 static void gnutls_log( int level, const char *msg )
80 TRACE( "<%d> %s", level, msg );
83 static NTSTATUS process_attach( void *args )
85 const char *env_str;
86 int ret;
88 if ((env_str = getenv("GNUTLS_SYSTEM_PRIORITY_FILE")))
90 WARN("GNUTLS_SYSTEM_PRIORITY_FILE is %s.\n", debugstr_a(env_str));
92 else
94 WARN("Setting GNUTLS_SYSTEM_PRIORITY_FILE to \"/dev/null\".\n");
95 setenv("GNUTLS_SYSTEM_PRIORITY_FILE", "/dev/null", 0);
98 if (!(libgnutls_handle = dlopen( SONAME_LIBGNUTLS, RTLD_NOW )))
100 ERR_(winediag)( "failed to load libgnutls, no support for pfx import/export\n" );
101 return STATUS_DLL_NOT_FOUND;
104 #define LOAD_FUNCPTR(f) \
105 if (!(p##f = dlsym( libgnutls_handle, #f ))) \
107 ERR( "failed to load %s\n", #f ); \
108 goto fail; \
111 LOAD_FUNCPTR(gnutls_global_deinit)
112 LOAD_FUNCPTR(gnutls_global_init)
113 LOAD_FUNCPTR(gnutls_global_set_log_function)
114 LOAD_FUNCPTR(gnutls_global_set_log_level)
115 LOAD_FUNCPTR(gnutls_perror)
116 LOAD_FUNCPTR(gnutls_pkcs12_deinit)
117 LOAD_FUNCPTR(gnutls_pkcs12_import)
118 LOAD_FUNCPTR(gnutls_pkcs12_init)
119 LOAD_FUNCPTR(gnutls_pkcs12_simple_parse)
120 LOAD_FUNCPTR(gnutls_x509_crt_export)
121 LOAD_FUNCPTR(gnutls_x509_privkey_export_rsa_raw2)
122 LOAD_FUNCPTR(gnutls_x509_privkey_get_pk_algorithm2)
123 #undef LOAD_FUNCPTR
125 if ((ret = pgnutls_global_init()) != GNUTLS_E_SUCCESS)
127 pgnutls_perror( ret );
128 goto fail;
131 if (TRACE_ON( crypt ))
133 char *env = getenv("GNUTLS_DEBUG_LEVEL");
134 int level = env ? atoi(env) : 4;
135 pgnutls_global_set_log_level(level);
136 pgnutls_global_set_log_function( gnutls_log );
139 return TRUE;
141 fail:
142 dlclose( libgnutls_handle );
143 libgnutls_handle = NULL;
144 return STATUS_DLL_INIT_FAILED;
147 static NTSTATUS process_detach( void *args )
149 pgnutls_global_deinit();
150 dlclose( libgnutls_handle );
151 libgnutls_handle = NULL;
152 return STATUS_SUCCESS;
154 #define RSA_MAGIC_KEY ('R' | ('S' << 8) | ('A' << 16) | ('2' << 24))
155 #define RSA_PUBEXP 65537
157 struct cert_store_data
159 gnutls_pkcs12_t p12;
160 gnutls_x509_privkey_t key;
161 gnutls_x509_crt_t *chain;
162 unsigned int key_bitlen;
163 unsigned int chain_len;
166 static struct cert_store_data *get_store_data( cert_store_data_t data )
168 return (struct cert_store_data *)(ULONG_PTR)data;
171 static NTSTATUS import_store_key( void *args )
173 struct import_store_key_params *params = args;
174 struct cert_store_data *data = get_store_data( params->data );
175 int i, ret;
176 unsigned int bitlen = data->key_bitlen;
177 gnutls_datum_t m, e, d, p, q, u, e1, e2;
178 BLOBHEADER *hdr;
179 RSAPUBKEY *rsakey;
180 BYTE *src, *dst;
181 DWORD size;
183 size = sizeof(*hdr) + sizeof(*rsakey) + (bitlen * 9 / 16);
184 if (!params->buf || *params->buf_size < size)
186 *params->buf_size = size;
187 return STATUS_BUFFER_TOO_SMALL;
190 if ((ret = pgnutls_x509_privkey_export_rsa_raw2( data->key, &m, &e, &d, &p, &q, &u, &e1, &e2 )) < 0)
192 pgnutls_perror( ret );
193 return STATUS_INVALID_PARAMETER;
196 hdr = params->buf;
197 hdr->bType = PRIVATEKEYBLOB;
198 hdr->bVersion = CUR_BLOB_VERSION;
199 hdr->reserved = 0;
200 hdr->aiKeyAlg = CALG_RSA_KEYX;
202 rsakey = (RSAPUBKEY *)(hdr + 1);
203 rsakey->magic = RSA_MAGIC_KEY;
204 rsakey->bitlen = bitlen;
205 rsakey->pubexp = RSA_PUBEXP;
207 dst = (BYTE *)(rsakey + 1);
208 if (m.size == bitlen / 8 + 1 && !m.data[0]) src = m.data + 1;
209 else if (m.size != bitlen / 8) goto done;
210 else src = m.data;
211 for (i = bitlen / 8 - 1; i >= 0; i--) *dst++ = src[i];
213 if (p.size == bitlen / 16 + 1 && !p.data[0]) src = p.data + 1;
214 else if (p.size != bitlen / 16) goto done;
215 else src = p.data;
216 for (i = bitlen / 16 - 1; i >= 0; i--) *dst++ = src[i];
218 if (q.size == bitlen / 16 + 1 && !q.data[0]) src = q.data + 1;
219 else if (q.size != bitlen / 16) goto done;
220 else src = q.data;
221 for (i = bitlen / 16 - 1; i >= 0; i--) *dst++ = src[i];
223 if (e1.size == bitlen / 16 + 1 && !e1.data[0]) src = e1.data + 1;
224 else if (e1.size != bitlen / 16) goto done;
225 else src = e1.data;
226 for (i = bitlen / 16 - 1; i >= 0; i--) *dst++ = src[i];
228 if (e2.size == bitlen / 16 + 1 && !e2.data[0]) src = e2.data + 1;
229 else if (e2.size != bitlen / 16) goto done;
230 else src = e2.data;
231 for (i = bitlen / 16 - 1; i >= 0; i--) *dst++ = src[i];
233 if (u.size == bitlen / 16 + 1 && !u.data[0]) src = u.data + 1;
234 else if (u.size != bitlen / 16) goto done;
235 else src = u.data;
236 for (i = bitlen / 16 - 1; i >= 0; i--) *dst++ = src[i];
238 if (d.size == bitlen / 8 + 1 && !d.data[0]) src = d.data + 1;
239 else if (d.size != bitlen / 8) goto done;
240 else src = d.data;
241 for (i = bitlen / 8 - 1; i >= 0; i--) *dst++ = src[i];
243 done:
244 free( m.data );
245 free( e.data );
246 free( d.data );
247 free( p.data );
248 free( q.data );
249 free( u.data );
250 free( e1.data );
251 free( e2.data );
252 return STATUS_SUCCESS;
255 static char *password_to_ascii( const WCHAR *str )
257 char *ret;
258 unsigned int i = 0;
260 if (!(ret = malloc( (lstrlenW(str) + 1) * sizeof(*ret) ))) return NULL;
261 while (*str)
263 if (*str > 0x7f) WARN( "password contains non-ascii characters\n" );
264 ret[i++] = *str++;
266 ret[i] = 0;
267 return ret;
270 static NTSTATUS open_cert_store( void *args )
272 struct open_cert_store_params *params = args;
273 gnutls_pkcs12_t p12;
274 gnutls_datum_t pfx_data;
275 gnutls_x509_privkey_t key;
276 gnutls_x509_crt_t *chain;
277 unsigned int chain_len;
278 unsigned int bitlen;
279 char *pwd = NULL;
280 int ret;
281 struct cert_store_data *store_data;
283 if (!libgnutls_handle) return STATUS_DLL_NOT_FOUND;
284 if (params->password && !(pwd = password_to_ascii( params->password ))) return STATUS_NO_MEMORY;
286 if ((ret = pgnutls_pkcs12_init( &p12 )) < 0) goto error;
288 pfx_data.data = params->pfx->pbData;
289 pfx_data.size = params->pfx->cbData;
290 if ((ret = pgnutls_pkcs12_import( p12, &pfx_data, GNUTLS_X509_FMT_DER, 0 )) < 0) goto error;
292 if ((ret = pgnutls_pkcs12_simple_parse( p12, pwd ? pwd : "", &key, &chain, &chain_len, NULL, NULL, NULL, 0 )) < 0)
293 goto error;
295 if ((ret = pgnutls_x509_privkey_get_pk_algorithm2( key, &bitlen )) < 0)
296 goto error;
298 free( pwd );
300 if (ret != GNUTLS_PK_RSA)
302 FIXME( "key algorithm %u not supported\n", ret );
303 pgnutls_pkcs12_deinit( p12 );
304 return STATUS_INVALID_PARAMETER;
307 store_data = malloc( sizeof(*store_data) );
308 store_data->p12 = p12;
309 store_data->key = key;
310 store_data->chain = chain;
311 store_data->key_bitlen = bitlen;
312 store_data->chain_len = chain_len;
313 *params->data_ret = (ULONG_PTR)store_data;
314 return STATUS_SUCCESS;
316 error:
317 pgnutls_perror( ret );
318 pgnutls_pkcs12_deinit( p12 );
319 free( pwd );
320 return STATUS_INVALID_PARAMETER;
323 static NTSTATUS import_store_cert( void *args )
325 struct import_store_cert_params *params = args;
326 struct cert_store_data *data = get_store_data( params->data );
327 size_t size = 0;
328 int ret;
330 if (params->index >= data->chain_len) return STATUS_NO_MORE_ENTRIES;
332 if ((ret = pgnutls_x509_crt_export( data->chain[params->index], GNUTLS_X509_FMT_DER, NULL, &size )) != GNUTLS_E_SHORT_MEMORY_BUFFER)
333 return STATUS_INVALID_PARAMETER;
335 if (!params->buf || *params->buf_size < size)
337 *params->buf_size = size;
338 return STATUS_BUFFER_TOO_SMALL;
340 if ((ret = pgnutls_x509_crt_export( data->chain[params->index], GNUTLS_X509_FMT_DER, params->buf, &size )) < 0)
341 return STATUS_INVALID_PARAMETER;
343 return STATUS_SUCCESS;
346 static NTSTATUS close_cert_store( void *args )
348 struct close_cert_store_params *params = args;
349 struct cert_store_data *data = get_store_data( params->data );
351 if (params->data)
353 pgnutls_pkcs12_deinit( data->p12 );
354 free( data );
356 return STATUS_SUCCESS;
359 #else /* SONAME_LIBGNUTLS */
361 static NTSTATUS process_attach( void *args ) { return STATUS_SUCCESS; }
362 static NTSTATUS process_detach( void *args ) { return STATUS_SUCCESS; }
363 static NTSTATUS open_cert_store( void *args ) { return STATUS_DLL_NOT_FOUND; }
364 static NTSTATUS import_store_key( void *args ) { return STATUS_DLL_NOT_FOUND; }
365 static NTSTATUS import_store_cert( void *args ) { return STATUS_DLL_NOT_FOUND; }
366 static NTSTATUS close_cert_store( void *args ) { return STATUS_DLL_NOT_FOUND; }
368 #endif /* SONAME_LIBGNUTLS */
370 struct root_cert
372 struct list entry;
373 SIZE_T size;
374 BYTE data[1];
377 static struct list root_cert_list = LIST_INIT(root_cert_list);
379 static BYTE *add_cert( SIZE_T size )
381 struct root_cert *cert = malloc( offsetof( struct root_cert, data[size] ));
383 if (!cert) return NULL;
384 cert->size = size;
385 list_add_tail( &root_cert_list, &cert->entry );
386 return cert->data;
389 struct DynamicBuffer
391 DWORD allocated;
392 DWORD used;
393 char *data;
396 static inline void reset_buffer(struct DynamicBuffer *buffer)
398 buffer->used = 0;
399 if (buffer->data) buffer->data[0] = 0;
402 static void add_line_to_buffer(struct DynamicBuffer *buffer, LPCSTR line)
404 if (buffer->used + strlen(line) + 1 > buffer->allocated)
406 DWORD new_size = max( max( buffer->allocated * 2, 1024 ), buffer->used + strlen(line) + 1 );
407 void *ptr = realloc( buffer->data, new_size );
408 if (!ptr) return;
409 buffer->data = ptr;
410 buffer->allocated = new_size;
411 if (!buffer->used) buffer->data[0] = 0;
413 strcpy( buffer->data + buffer->used, line );
414 buffer->used += strlen(line);
417 #define BASE64_DECODE_PADDING 0x100
418 #define BASE64_DECODE_WHITESPACE 0x200
419 #define BASE64_DECODE_INVALID 0x300
421 static inline int decodeBase64Byte(char c)
423 int ret = BASE64_DECODE_INVALID;
425 if (c >= 'A' && c <= 'Z')
426 ret = c - 'A';
427 else if (c >= 'a' && c <= 'z')
428 ret = c - 'a' + 26;
429 else if (c >= '0' && c <= '9')
430 ret = c - '0' + 52;
431 else if (c == '+')
432 ret = 62;
433 else if (c == '/')
434 ret = 63;
435 else if (c == '=')
436 ret = BASE64_DECODE_PADDING;
437 else if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
438 ret = BASE64_DECODE_WHITESPACE;
439 return ret;
442 static BOOL base64_to_cert( const char *str )
444 DWORD i, valid, out, hasPadding;
445 BYTE block[4], *data;
447 for (i = valid = out = hasPadding = 0; str[i]; i++)
449 int d = decodeBase64Byte( str[i] );
450 if (d == BASE64_DECODE_INVALID) return FALSE;
451 if (d == BASE64_DECODE_WHITESPACE) continue;
453 /* When padding starts, data is not acceptable */
454 if (hasPadding && d != BASE64_DECODE_PADDING) return FALSE;
456 /* Padding after a full block (like "VVVV=") is ok and stops decoding */
457 if (d == BASE64_DECODE_PADDING && (valid & 3) == 0) break;
459 valid++;
460 if (d == BASE64_DECODE_PADDING)
462 hasPadding = 1;
463 /* When padding reaches a full block, stop decoding */
464 if ((valid & 3) == 0) break;
465 continue;
468 /* out is incremented in the 4-char block as follows: "1-23" */
469 if ((valid & 3) != 2) out++;
471 /* Fail if the block has bad padding; omitting padding is fine */
472 if ((valid & 3) != 0 && hasPadding) return FALSE;
474 if (!(data = add_cert( out ))) return FALSE;
475 for (i = valid = out = 0; str[i]; i++)
477 int d = decodeBase64Byte( str[i] );
478 if (d == BASE64_DECODE_WHITESPACE) continue;
479 if (d == BASE64_DECODE_PADDING) break;
480 block[valid & 3] = d;
481 valid += 1;
482 switch (valid & 3)
484 case 1:
485 data[out++] = (block[0] << 2);
486 break;
487 case 2:
488 data[out-1] = (block[0] << 2) | (block[1] >> 4);
489 break;
490 case 3:
491 data[out++] = (block[1] << 4) | (block[2] >> 2);
492 break;
493 case 0:
494 data[out++] = (block[2] << 6) | (block[3] >> 0);
495 break;
498 return TRUE;
501 /* Reads the file fd, and imports any certificates in it into store. */
502 static void import_certs_from_file( int fd )
504 FILE *fp = fdopen(fd, "r");
505 char line[1024];
506 BOOL in_cert = FALSE;
507 struct DynamicBuffer saved_cert = { 0, 0, NULL };
508 int num_certs = 0;
510 if (!fp) return;
511 TRACE("\n");
512 while (fgets(line, sizeof(line), fp))
514 static const char header[] = "-----BEGIN CERTIFICATE-----";
515 static const char trailer[] = "-----END CERTIFICATE-----";
517 if (!strncmp(line, header, strlen(header)))
519 TRACE("begin new certificate\n");
520 in_cert = TRUE;
521 reset_buffer(&saved_cert);
523 else if (!strncmp(line, trailer, strlen(trailer)))
525 TRACE("end of certificate, adding cert\n");
526 in_cert = FALSE;
527 if (base64_to_cert( saved_cert.data )) num_certs++;
529 else if (in_cert) add_line_to_buffer(&saved_cert, line);
531 free( saved_cert.data );
532 TRACE("Read %d certs\n", num_certs);
533 fclose(fp);
536 static void import_certs_from_path(LPCSTR path, BOOL allow_dir);
538 static BOOL check_buffer_resize(char **ptr_buf, size_t *buf_size, size_t check_size)
540 if (check_size > *buf_size)
542 void *ptr = realloc(*ptr_buf, check_size);
544 if (!ptr) return FALSE;
545 *buf_size = check_size;
546 *ptr_buf = ptr;
548 return TRUE;
551 /* Opens path, which must be a directory, and imports certificates from every
552 * file in the directory into store.
553 * Returns TRUE if any certificates were successfully imported.
555 static void import_certs_from_dir( LPCSTR path )
557 DIR *dir;
559 dir = opendir(path);
560 if (dir)
562 size_t path_len = strlen(path), bufsize = 0;
563 char *filebuf = NULL;
565 struct dirent *entry;
566 while ((entry = readdir(dir)))
568 if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
570 size_t name_len = strlen(entry->d_name);
572 if (!check_buffer_resize(&filebuf, &bufsize, path_len + 1 + name_len + 1)) break;
573 snprintf(filebuf, bufsize, "%s/%s", path, entry->d_name);
574 import_certs_from_path(filebuf, FALSE);
577 free(filebuf);
578 closedir(dir);
582 /* Opens path, which may be a file or a directory, and imports any certificates
583 * it finds into store.
584 * Returns TRUE if any certificates were successfully imported.
586 static void import_certs_from_path(LPCSTR path, BOOL allow_dir)
588 int fd;
590 TRACE("(%s, %d)\n", debugstr_a(path), allow_dir);
592 fd = open(path, O_RDONLY);
593 if (fd != -1)
595 struct stat st;
597 if (fstat(fd, &st) == 0)
599 if (S_ISREG(st.st_mode))
600 import_certs_from_file(fd);
601 else if (S_ISDIR(st.st_mode))
603 if (allow_dir)
604 import_certs_from_dir(path);
605 else
606 WARN("%s is a directory and directories are disallowed\n",
607 debugstr_a(path));
609 else
610 ERR("%s: invalid file type\n", path);
612 close(fd);
616 static const char * const CRYPT_knownLocations[] = {
617 "/etc/ssl/certs/ca-certificates.crt",
618 "/etc/ssl/certs",
619 "/etc/pki/tls/certs/ca-bundle.crt",
620 "/usr/share/ca-certificates/ca-bundle.crt",
621 "/usr/local/share/certs/",
622 "/etc/sfw/openssl/certs",
623 "/etc/security/cacerts", /* Android */
626 static void load_root_certs(void)
628 unsigned int i;
630 #ifdef __APPLE__
631 const SecTrustSettingsDomain domains[] = {
632 kSecTrustSettingsDomainSystem,
633 kSecTrustSettingsDomainAdmin,
634 kSecTrustSettingsDomainUser
636 OSStatus status;
637 CFArrayRef certs;
638 DWORD domain;
640 for (domain = 0; domain < ARRAY_SIZE(domains); domain++)
642 status = SecTrustSettingsCopyCertificates(domains[domain], &certs);
643 if (status == noErr)
645 for (i = 0; i < CFArrayGetCount(certs); i++)
647 SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
648 CFDataRef certData;
649 if ((status = SecItemExport(cert, kSecFormatX509Cert, 0, NULL, &certData)) == noErr)
651 BYTE *data = add_cert( CFDataGetLength(certData) );
652 if (data) memcpy( data, CFDataGetBytePtr(certData), CFDataGetLength(certData) );
653 CFRelease(certData);
655 else
656 WARN("could not export certificate %u to X509 format: 0x%08x\n", i, (unsigned int)status);
658 CFRelease(certs);
661 #endif
663 for (i = 0; i < ARRAY_SIZE(CRYPT_knownLocations) && list_empty(&root_cert_list); i++)
664 import_certs_from_path( CRYPT_knownLocations[i], TRUE );
667 static NTSTATUS enum_root_certs( void *args )
669 struct enum_root_certs_params *params = args;
670 static BOOL loaded;
671 struct list *ptr;
672 struct root_cert *cert;
674 if (!loaded) load_root_certs();
675 loaded = TRUE;
677 if (!(ptr = list_head( &root_cert_list ))) return STATUS_NO_MORE_ENTRIES;
678 cert = LIST_ENTRY( ptr, struct root_cert, entry );
679 *params->needed = cert->size;
680 if (cert->size <= params->size)
682 memcpy( params->buffer, cert->data, cert->size );
683 list_remove( &cert->entry );
684 free( cert );
686 return STATUS_SUCCESS;
689 const unixlib_entry_t __wine_unix_call_funcs[] =
691 process_attach,
692 process_detach,
693 open_cert_store,
694 import_store_key,
695 import_store_cert,
696 close_cert_store,
697 enum_root_certs,
700 C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count );
702 #ifdef _WIN64
704 typedef ULONG PTR32;
706 typedef struct
708 DWORD cbData;
709 PTR32 pbData;
710 } CRYPT_DATA_BLOB32;
712 static NTSTATUS wow64_open_cert_store( void *args )
714 struct
716 PTR32 pfx;
717 PTR32 password;
718 PTR32 data_ret;
719 } const *params32 = args;
721 const CRYPT_DATA_BLOB32 *pfx32 = ULongToPtr( params32->pfx );
722 CRYPT_DATA_BLOB pfx = { pfx32->cbData, ULongToPtr( pfx32->pbData ) };
723 struct open_cert_store_params params =
725 &pfx,
726 ULongToPtr( params32->password ),
727 ULongToPtr( params32->data_ret )
730 return open_cert_store( &params );
733 static NTSTATUS wow64_import_store_key( void *args )
735 struct
737 cert_store_data_t data;
738 PTR32 buf;
739 PTR32 buf_size;
740 } const *params32 = args;
742 struct import_store_key_params params =
744 params32->data,
745 ULongToPtr( params32->buf ),
746 ULongToPtr( params32->buf_size )
749 return import_store_key( &params );
752 static NTSTATUS wow64_import_store_cert( void *args )
754 struct
756 cert_store_data_t data;
757 unsigned int index;
758 PTR32 buf;
759 PTR32 buf_size;
760 } const *params32 = args;
762 struct import_store_cert_params params =
764 params32->data,
765 params32->index,
766 ULongToPtr( params32->buf ),
767 ULongToPtr( params32->buf_size )
770 return import_store_cert( &params );
773 static NTSTATUS wow64_enum_root_certs( void *args )
775 struct
777 PTR32 buffer;
778 DWORD size;
779 PTR32 needed;
780 } const *params32 = args;
782 struct enum_root_certs_params params =
784 ULongToPtr( params32->buffer ),
785 params32->size,
786 ULongToPtr( params32->needed )
789 return enum_root_certs( &params );
792 const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
794 process_attach,
795 process_detach,
796 wow64_open_cert_store,
797 wow64_import_store_key,
798 wow64_import_store_cert,
799 close_cert_store,
800 wow64_enum_root_certs,
803 C_ASSERT( ARRAYSIZE(__wine_unix_call_wow64_funcs) == unix_funcs_count );
805 #endif /* _WIN64 */