From 7f3497949a7a8a51ecb8a9f11a98e8a6b640a960 Mon Sep 17 00:00:00 2001
From: Constantin P <papizh.konstantin@demlabs.net>
Date: Wed, 23 Nov 2022 14:50:24 +0000
Subject: [PATCH] Features 6131

---
 3rdparty/crc32c_adler/crc32c_adler.c |   1 -
 3rdparty/crc32c_adler/crc32c_adler.h |   9 +
 modules/net/dap_chain_node_cli.c     |  11 +-
 modules/wallet/dap_chain_wallet.c    | 299 +++++++++++++++++++--------
 4 files changed, 227 insertions(+), 93 deletions(-)

diff --git a/3rdparty/crc32c_adler/crc32c_adler.c b/3rdparty/crc32c_adler/crc32c_adler.c
index ce23887e4f..68e90941aa 100755
--- a/3rdparty/crc32c_adler/crc32c_adler.c
+++ b/3rdparty/crc32c_adler/crc32c_adler.c
@@ -38,7 +38,6 @@
 */
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdint.h>
 #include <unistd.h>
 
 #include "crc32c_adler.h"
diff --git a/3rdparty/crc32c_adler/crc32c_adler.h b/3rdparty/crc32c_adler/crc32c_adler.h
index 32f3f81e6b..a983ecfbe1 100755
--- a/3rdparty/crc32c_adler/crc32c_adler.h
+++ b/3rdparty/crc32c_adler/crc32c_adler.h
@@ -39,6 +39,12 @@
 #ifndef CRC32C_ADLER_H
 #define CRC32C_ADLER_H
 
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 /* Compute CRC32C checksum using software algorithm (1). */
 uint32_t crc32c_sw(uint32_t crci, const void *buf, size_t len);
 
@@ -58,4 +64,7 @@ void crc32c_hw_disable();
    fall back on software algorithm otherwise. */
 uint32_t crc32c(uint32_t crc, const void *buf, size_t len);
 
+#if defined(__cplusplus)
+}
+#endif
 #endif // CRC32C_ADLER_H
diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c
index 11acd29739..71d482e51b 100644
--- a/modules/net/dap_chain_node_cli.c
+++ b/modules/net/dap_chain_node_cli.c
@@ -119,11 +119,12 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
                                         "\tObtain help for <command> or get the total list of the commands\n"
                                         );
     dap_cli_server_cmd_add ("wallet", com_tx_wallet, "Wallet operations",
-                "wallet list\n"
-                "wallet new -w <wallet_name> [-sign <sign_type>] [-restore <hex_value>] [-net <net_name>] [-force] [-password <password>] [-restore <hash>]\n"
-                "wallet info {-addr <addr> | -w <wallet_name>} -net <net_name>\n"
-                "wallet activate -w <wallet_name> -password <password> [-ttl <password_ttl_in_minutes>]\n"
-                "wallet deactivate -w <wallet_name> -password <password>\n");
+                            "wallet list\n"
+                            "wallet new -w <wallet_name> [-sign <sign_type>] [-restore <hex_value>] [-net <net_name>] [-force] [-password <password>] [-restore <hash>]\n"
+                            "wallet info {-addr <addr> | -w <wallet_name>} -net <net_name>\n"
+                            "wallet activate -w <wallet_name> -password <password> [-ttl <password_ttl_in_minutes>]\n"
+                            "wallet deactivate -w <wallet_name> -password <password>\n");
+
 
     // Token commands
     dap_cli_server_cmd_add ("token_update", com_token_update, "Token update",
diff --git a/modules/wallet/dap_chain_wallet.c b/modules/wallet/dap_chain_wallet.c
index 41978b18e4..adff4b947e 100644
--- a/modules/wallet/dap_chain_wallet.c
+++ b/modules/wallet/dap_chain_wallet.c
@@ -36,10 +36,9 @@
 #include <string.h>
 #include <dirent.h>
 #include <errno.h>
-
-#ifdef DAP_OS_UNIX
 #include <sys/types.h>
 #include <sys/stat.h>
+#ifdef DAP_OS_UNIX
 #include <sys/uio.h>
 #endif
 
@@ -52,35 +51,26 @@
 #endif
 
 #include <pthread.h>
-#include "crc32c_adler.h"
-
 
 #include "dap_common.h"
-#include "dap_strfuncs.h"
-#include "dap_string.h"
 #include "dap_cert_file.h"
 #include "dap_chain_wallet.h"
 #include "dap_chain_wallet_internal.h"
 #include "dap_enc_key.h"
+#include "crc32c_adler.h"
 
 #define LOG_TAG "dap_chain_wallet"
 
-#ifndef DAP_OS_WINDOWS
-                                                                            /* An argument for open()/create() */
+#ifndef DAP_OS_WINDOWS                                    /* An argument for open()/create() */
 static const mode_t s_fileprot =  ( S_IREAD | S_IWRITE) | (S_IREAD >> 3) | (S_IREAD >> 6) ;
 #endif
 static char s_wallet_ext [] = ".dwallet";
 
-
 static  pthread_rwlock_t s_wallet_n_pass_lock = PTHREAD_RWLOCK_INITIALIZER; /* Coordinate access to the hash-table */
 static  dap_chain_wallet_n_pass_t   *s_wallet_n_pass;                       /* A hash table to keep passwords for wallets */
 
-
-
-/*	CRC32-C	*/
 #define     CRC32C_INIT    0xEDB88320
 
-
 /*
  *  DESCRIPTION: Add/update a record for wallet into the internaly used table of name/password pair.
  *      Thhose records are supposed to be used for operations with the password-protected wallets.
@@ -115,10 +105,10 @@ char *c_wallets_path;
 
     /* Sanity checks ... */
     if ( a_name_len > DAP_WALLET$SZ_NAME )
-        return  log_it(L_ERROR, "Wallet's name is too long (%zd > %d)",  a_name_len, DAP_WALLET$SZ_NAME), -EINVAL;
+        return  log_it(L_ERROR, "Wallet's name is too long (%d > %d)",  (int) a_name_len, DAP_WALLET$SZ_NAME), -EINVAL;
 
     if ( a_pass_len > DAP_WALLET$SZ_PASS )
-        return  log_it(L_ERROR, "Wallet's password is too long (%zd > %d)",  a_pass_len, DAP_WALLET$SZ_PASS), -EINVAL;
+        return  log_it(L_ERROR, "Wallet's password is too long (%d > %d)",  (int) a_pass_len, DAP_WALLET$SZ_PASS), -EINVAL;
 
 
     memcpy(l_rec.name, a_name, l_rec.name_len = a_name_len);            /* Prefill local record fields */
@@ -165,8 +155,8 @@ char *c_wallets_path;
 
     if ( !(l_wallet = dap_chain_wallet_open (a_name, c_wallets_path)) )
     {
-        memset(l_prec->pass, 0, l_prec->pass_len), l_prec->pass_len = 0;
-        return  log_it(L_ERROR, "Wallet's password is invalid"), -EINVAL;
+        memset(l_prec->pass, 0, l_prec->pass_len), l_prec->pass_len = 0;    /* Say <what> again ?! */
+        return  log_it(L_ERROR, "Wallet's password is invalid, say <password> again"), -EAGAIN;
     }
 
     dap_chain_wallet_close( l_wallet);
@@ -208,10 +198,10 @@ struct timespec l_now;
 
     /* Sanity checks ... */
     if ( a_name_len > DAP_WALLET$SZ_NAME )
-        return  log_it(L_ERROR, "Wallet's name is too long (%zd > %d)",  a_name_len, DAP_WALLET$SZ_NAME), -EINVAL;
+        return  log_it(L_ERROR, "Wallet's name is too long (%d > %d)",  (int) a_name_len, DAP_WALLET$SZ_NAME), -EINVAL;
 
     if ( *a_pass_len < DAP_WALLET$SZ_PASS )
-        return  log_it(L_ERROR, "Wallet's buffer for password is too small (%zd < %d)",  *a_pass_len, DAP_WALLET$SZ_PASS), -EINVAL;
+        return  log_it(L_ERROR, "Wallet's buffer for password is too small (%d < %d)", (int) *a_pass_len, DAP_WALLET$SZ_PASS), -EINVAL;
 
 
     clock_gettime(CLOCK_REALTIME, &l_now);
@@ -270,7 +260,7 @@ int     l_rc, l_rc2;
 dap_chain_wallet_n_pass_t   *l_prec;
 
     if ( a_name_len > DAP_WALLET$SZ_NAME )
-        return  log_it(L_ERROR, "Wallet's name is too long (%zd > %d)",  a_name_len, DAP_WALLET$SZ_NAME), -EINVAL;
+        return  log_it(L_ERROR, "Wallet's name is too long (%d > %d)",  (int) a_name_len, DAP_WALLET$SZ_NAME), -EINVAL;
 
     if ( (l_rc = pthread_rwlock_wrlock(&s_wallet_n_pass_lock)) )        /* Lock for WR access */
         return  log_it(L_ERROR, "Error locking Wallet table, errno=%d", l_rc), -l_rc;
@@ -282,7 +272,7 @@ dap_chain_wallet_n_pass_t   *l_prec;
     if ( l_prec )
     {
         if ( !l_prec->pass_len )                                        /* Password is zero - has been reset probably */
-            log_it(L_WARNING, "The Wallet %.*s is not active", (int)a_name_len, a_name);
+            log_it(L_WARNING, "The Wallet %.*s is not active", (int) a_name_len, a_name);
 
         else if ( (l_prec->pass_len != a_pass_len)                      /* Check that passwords is equivalent */
              || memcmp(l_prec->pass, a_pass, l_prec->pass_len) )
@@ -559,7 +549,6 @@ dap_enc_key_t* dap_chain_wallet_get_key( dap_chain_wallet_t * a_wallet,uint32_t
     return 0;
 }
 
-
 /*
  *  DESCRIPTION: Save memory wallet's context into the protected by given password.
  *
@@ -578,15 +567,23 @@ dap_enc_key_t* dap_chain_wallet_get_key( dap_chain_wallet_t * a_wallet,uint32_t
 int dap_chain_wallet_save(dap_chain_wallet_t * a_wallet, const char *a_pass)
 {
 DAP_CHAIN_WALLET_INTERNAL_LOCAL (a_wallet);                                 /* Declare l_wallet_internal */
-#ifndef DAP_OS_WINDOWS
-int l_fd = -1, l_rc = 0, l_len = 0;
-dap_chain_wallet_file_hdr_t l_file_hdr = {0};
-dap_chain_wallet_cert_hdr_t l_wallet_cert_hdr = {0};
+#ifdef DAP_OS_WINDOWS
+HANDLE l_fh = INVALID_HANDLE_VALUE;
+#else
+int l_fd = -1;
+typedef struct iovec iovec_t;
+#endif
+size_t l_rc = 0;
+uint32_t l_len = 0;
 char *l_cp, *l_cert_raw, l_buf[32*1024];
 dap_enc_key_t *l_enc_key = NULL;
-uint32_t    csum = CRC32C_INIT;
-enum    { WALLET$K_IOV_HEADER = 0, WALLET$K_IOV_BODY, WALLET$SZ_IOV_NR};
-struct iovec l_iov [ WALLET$SZ_IOV_NR ];
+uint32_t l_csum = CRC32C_INIT;
+
+enum {
+    WALLET$K_IOV_HEADER = 0,
+    WALLET$K_IOV_BODY,
+    WALLET$SZ_IOV_NR
+};
 
     if ( !a_wallet )
         return  log_it(L_ERROR, "Wallet is null, can't save it to file!"), -EINVAL;
@@ -595,46 +592,65 @@ struct iovec l_iov [ WALLET$SZ_IOV_NR ];
         if ( !(l_enc_key = dap_enc_key_new_generate(DAP_ENC_KEY_TYPE_GOST_OFB, NULL, 0, a_pass, strlen(a_pass), 0)) )
             return  log_it(L_ERROR, "Error create key context"), -EINVAL;
 
+#ifdef DAP_OS_WINDOWS
+    DWORD l_err = 0;
+    if ((l_fh = CreateFile(l_wallet_internal->file_name, GENERIC_WRITE, /*FILE_SHARE_READ | FILE_SHARE_WRITE */ 0, NULL, CREATE_NEW,
+                          /*FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING*/ 0, NULL)) == INVALID_HANDLE_VALUE) {
+        l_err = GetLastError();
+        log_it(L_ERROR, "Cant open file %s for writing, err %lu", l_wallet_internal->file_name, l_err);
+        return -l_err;
+    }
+#else
     if ( 0 > (l_fd = open(l_wallet_internal->file_name , O_CREAT | O_WRONLY, s_fileprot)) )
-        return  log_it(L_ERROR,"Cant open file %s for writting, errno=%d", l_wallet_internal->file_name, errno), -errno;
-
-    l_file_hdr.signature = DAP_CHAIN_WALLETS_FILE_SIGNATURE;                /* Fill and write Wallet's file header */
-    l_file_hdr.type = a_pass ? DAP_WALLET$K_TYPE_GOST89 : DAP_WALLET$K_TYPE_PLAIN;
-    l_file_hdr.version = a_pass ? DAP_WALLET$K_VER_2 : DAP_WALLET$K_VER_1;
-
-    l_cp  = a_wallet->name ? a_wallet->name : "Bad-MotherFuqqer-Wallet";    /* What ?! */
-    l_file_hdr.wallet_len = strnlen(l_cp, DAP_WALLET$SZ_NAME);
-    l_file_hdr.wallet_len += 1;                                             /* Special ASCIZ for advanced programmers */
-
-    l_iov[WALLET$K_IOV_HEADER].iov_base = &l_file_hdr;
-    l_len = l_iov[WALLET$K_IOV_HEADER].iov_len = sizeof(l_file_hdr);
-
-    l_iov[WALLET$K_IOV_BODY].iov_base = l_cp;
-    l_len += l_iov[WALLET$K_IOV_BODY].iov_len = l_file_hdr.wallet_len;
+        return log_it(L_ERROR, "Cant open file %s for writing, errno=%d", l_wallet_internal->file_name, errno), -errno;
+#endif
 
+    l_cp = a_wallet->name[0] ? a_wallet->name : "DefaultWalletName";
+
+    dap_chain_wallet_file_hdr_t l_file_hdr = {
+        .signature  = DAP_CHAIN_WALLETS_FILE_SIGNATURE,
+        .version    = a_pass ? DAP_WALLET$K_VER_2 : DAP_WALLET$K_VER_1,
+        .type       = a_pass ? DAP_WALLET$K_TYPE_GOST89 : DAP_WALLET$K_TYPE_PLAIN,
+        .wallet_len = strnlen(l_cp, DAP_WALLET$SZ_NAME) + 1
+    };
+
+    iovec_t l_iov[] = {
+        { .iov_base = &l_file_hdr,  .iov_len = sizeof(l_file_hdr) },    /* WALLET$K_IOV_HEADER */
+        { .iov_base = l_cp,         .iov_len = l_file_hdr.wallet_len }  /* WALLET$K_IOV_BODY */
+    };
+
+#ifdef DAP_OS_WINDOWS
+    l_rc = dap_writev(l_fh, l_cp, l_iov, WALLET$SZ_IOV_NR, &l_err);
+    if (l_err) {
+        log_it(L_ERROR, "Error write Wallet header to file '%s', err %lu", l_wallet_internal->file_name, l_err);
+        CloseHandle(l_fh);
+        return -l_err;
+    }
+#else
     l_rc = writev (l_fd, l_iov, WALLET$SZ_IOV_NR );                         /* Performs writting vectorized buffer */
-    if ( l_len != l_rc )
+    if ((l_len = sizeof(l_file_hdr) + l_file_hdr.wallet_len) != l_rc)
     {
         close(l_fd);
         return  log_it(L_ERROR, "Error write Wallet header to file '%s', errno=%d", l_wallet_internal->file_name, errno), -EIO;
     }
+#endif
 
                                                                             /* CRC for file header part */
-    csum = crc32c (csum, l_iov[WALLET$K_IOV_HEADER].iov_base, l_iov[WALLET$K_IOV_HEADER].iov_len);
+    l_csum = crc32c(l_csum, l_iov[WALLET$K_IOV_HEADER].iov_base, l_iov[WALLET$K_IOV_HEADER].iov_len);
                                                                             /* CRC for file body part */
-    csum = crc32c (csum, l_iov[WALLET$K_IOV_BODY].iov_base, l_iov[WALLET$K_IOV_BODY].iov_len);
+    l_csum = crc32c(l_csum, l_iov[WALLET$K_IOV_BODY].iov_base, l_iov[WALLET$K_IOV_BODY].iov_len);
 
     /* Write certs */
     for ( size_t i = 0; i < l_wallet_internal->certs_count ; i++)
     {
                                                                             /* Get ceritificate body */
-        if ( !(l_cert_raw  = (char *) dap_cert_mem_save(l_wallet_internal->certs[i], (uint32_t *) &l_len)) )
+        if ( !(l_cert_raw  = (char *) dap_cert_mem_save(l_wallet_internal->certs[i], &l_len)) )
         {
             log_it(L_WARNING, "Certificate #%zu cannot be obtained, go next ...", i);
             continue;
         }
 
-        csum = crc32c (csum, l_cert_raw, l_len);                          /* CRC for every certificate */
+        l_csum = crc32c (l_csum, l_cert_raw, l_len);                          /* CRC for every certificate */
 
         if ( l_enc_key )
         {
@@ -645,9 +661,7 @@ struct iovec l_iov [ WALLET$SZ_IOV_NR ];
              */
             l_len = l_enc_key->enc_na(l_enc_key, l_cert_raw, l_len, l_buf, sizeof(l_buf) );
         }
-
-        l_wallet_cert_hdr.type = DAP_WALLET$K_CERT;                         /* Prepare on-disk cert record header */
-        l_wallet_cert_hdr.cert_raw_size = l_len;
+        dap_chain_wallet_cert_hdr_t l_wallet_cert_hdr = { .type = DAP_WALLET$K_CERT, .cert_raw_size = l_len };
 
         /*
          * Gather chunks for I/O
@@ -660,52 +674,73 @@ struct iovec l_iov [ WALLET$SZ_IOV_NR ];
         l_iov[WALLET$K_IOV_BODY].iov_base  = l_enc_key ? l_buf : l_cert_raw;/* Cert itself or buffer with has been encrypted cert */
         l_len += l_iov[WALLET$K_IOV_BODY].iov_len  = l_wallet_cert_hdr.cert_raw_size;
 
+#ifdef DAP_OS_WINDOWS
+        l_err = 0;
+        l_rc = dap_writev(l_fh, l_cp, l_iov, WALLET$SZ_IOV_NR, &l_err);
+        DAP_DEL_Z (l_cert_raw);
+        if (l_err) {
+            log_it(L_ERROR, "Error writing %d octets of cert to file '%s', err %lu", l_len, l_wallet_internal->file_name, l_err);
+            CloseHandle(l_fh);
+            return -l_err;
+        }
+#else
         l_rc = writev (l_fd, l_iov, WALLET$SZ_IOV_NR );                      /* Perform writting vectorized buffer */
         DAP_DEL_Z (l_cert_raw);                                             /* Free cert's memory */
         if ( l_rc != l_len )                                                /* Check a result of the I/O operation */
         {
             close (l_fd);
-            return  log_it(L_ERROR, "Error write %d octets of cert to  file '%s', errno=%d", l_len, l_wallet_internal->file_name, errno), errno;
+            return  log_it(L_ERROR, "Error write %d octets of cert to file '%s', errno=%d", l_len, l_wallet_internal->file_name, errno), errno;
         }
+#endif
     }
 
     if ( l_file_hdr.version == DAP_WALLET$K_VER_2 )
     {
-        l_wallet_cert_hdr.type = DAP_WALLET$K_MAGIC;
-        l_wallet_cert_hdr.cert_raw_size = sizeof(csum);
-
+        dap_chain_wallet_cert_hdr_t l_wallet_cert_hdr = { .type = DAP_WALLET$K_MAGIC, .cert_raw_size = sizeof(l_csum) };
         l_len = 0;                                                          /* Total octets to be writtent to disk */
-
         l_iov[WALLET$K_IOV_HEADER].iov_base  = &l_wallet_cert_hdr;
         l_len += l_iov[WALLET$K_IOV_HEADER].iov_len  = sizeof(l_wallet_cert_hdr);
 
-        l_iov[WALLET$K_IOV_BODY].iov_base  = &csum;
-        l_len += l_iov[WALLET$K_IOV_BODY].iov_len  = sizeof(csum);
+        l_iov[WALLET$K_IOV_BODY].iov_base  = &l_csum;
+        l_len += l_iov[WALLET$K_IOV_BODY].iov_len  = sizeof(l_csum);
+
+#ifdef DAP_OS_WINDOWS
+        l_err = 0;
+        l_rc = dap_writev(l_fh, l_cp, l_iov, WALLET$SZ_IOV_NR, &l_err);
+        if (l_err) {
+            log_it(L_ERROR, "Error writing %d octets of cert to file '%s', err %lu", l_len, l_wallet_internal->file_name, l_err);
+        }
+    }
+    CloseHandle(l_fh);
 
+#else
         l_rc = writev (l_fd, l_iov, WALLET$SZ_IOV_NR );                     /* Perform writting vectorized buffer */
         if ( l_rc != l_len )                                                /* Check a result of the I/O operation */
             log_it(L_ERROR, "Error write %d octets of cert to  file '%s', errno=%d", l_len, l_wallet_internal->file_name, errno);
+
     }
 
     /* Cleanup and exit ... */
     close (l_fd);
-
+#endif
     if ( l_enc_key )
         dap_enc_key_delete(l_enc_key);
-#endif
-
 
 #ifdef  DAP_SYS_DEBUG                                                       /* @RRL: For debug purpose only!!! */
     {
     dap_chain_wallet_t  *l_wallet;
 
-    if ( (l_wallet = dap_chain_wallet_open_file (l_wallet_internal->file_name, a_pass)) )
+    if ( l_wallet = dap_chain_wallet_open_file (l_wallet_internal->file_name, a_pass) )
         dap_chain_wallet_close(l_wallet);
 
     }
 #endif      /* DAP_SYS_DEBUG */
 
+#ifdef DAP_OS_WINDOWS
+    return  log_it(L_NOTICE, "Wallet '%s' has been saved into the '%s'", a_wallet->name, l_wallet_internal->file_name), l_err;
+#else
     return  log_it(L_NOTICE, "Wallet '%s' has been saved into the '%s'", a_wallet->name, l_wallet_internal->file_name), 0;
+#endif
 }
 
 
@@ -721,61 +756,136 @@ dap_chain_wallet_t *dap_chain_wallet_open_file (
                     )
 {
 dap_chain_wallet_t *l_wallet;
-int l_fd = -1, l_rc, l_certs_count, l_len;
+#ifdef DAP_OS_WINDOWS
+HANDLE l_fh = INVALID_HANDLE_VALUE;
+DWORD l_rc = 0;
+#else
+int l_fd = -1, l_rc;
+#endif
+int l_certs_count, l_len;
 dap_chain_wallet_file_hdr_t l_file_hdr = {0};
 dap_chain_wallet_cert_hdr_t l_cert_hdr = {0};
 char l_buf[32*1024], l_buf2[32*1024], *l_bufp, l_wallet_name [DAP_WALLET$SZ_NAME] = {0};
 dap_enc_key_t *l_enc_key = NULL;
 uint32_t    l_csum = CRC32C_INIT, l_csum2 = CRC32C_INIT;
 
+#ifdef DAP_OS_WINDOWS
+    if ((l_fh = CreateFile(a_file_name, GENERIC_READ, 0, 0,
+                           OPEN_EXISTING,
+                           FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, 0)) == INVALID_HANDLE_VALUE) {
+        return  log_it(L_ERROR,"Cant open file %s for read, err %lu", a_file_name, GetLastError()), NULL;
+    }
+
+#else
     if ( 0 > (l_fd = open(a_file_name , O_RDONLY)) )                        /* Open file for ReadOnly !!! */
         return  log_it(L_ERROR,"Cant open file %s for read, errno=%d", a_file_name, errno), NULL;
+#endif
 
+#ifdef DAP_OS_WINDOWS
+    if (ReadFile(l_fh, &l_file_hdr, sizeof(l_file_hdr), &l_rc, 0) == FALSE || l_rc != sizeof(l_file_hdr)) {
+        return  log_it(L_ERROR, "Error reading Wallet file (%s) header, err %lu", a_file_name, GetLastError()),
+                CloseHandle(l_fh), NULL;
+    }
+#else
     if ( sizeof(l_file_hdr) != read(l_fd, &l_file_hdr, sizeof(l_file_hdr)) )/* Get the file header record */
         return  log_it(L_ERROR, "Error read Wallet file (%s) header, errno=%d", a_file_name, errno), close(l_fd), NULL;
+#endif
 
-    if ( l_file_hdr.signature != DAP_CHAIN_WALLETS_FILE_SIGNATURE )         /* Check signature of the file */
-        return  log_it(L_ERROR, "Wallet (%s) signature mismatch (%#lx != %#lx", a_file_name, l_file_hdr.signature, DAP_CHAIN_WALLETS_FILE_SIGNATURE),
-                    close(l_fd), NULL;
+    if ( l_file_hdr.signature != DAP_CHAIN_WALLETS_FILE_SIGNATURE )  {       /* Check signature of the file */
+        log_it(L_ERROR, "Wallet (%s) signature mismatch (%llux != %ldx)", a_file_name, l_file_hdr.signature, DAP_CHAIN_WALLETS_FILE_SIGNATURE);
+#ifdef DAP_OS_WINDOWS
+        CloseHandle(l_fh);
+#else
+        close(l_fd);
+#endif
+        return NULL;
+    }
 
-    if ( (l_file_hdr.version == DAP_WALLET$K_VER_2) && (!l_pass) )
-        return  log_it(L_DEBUG, "Wallet (%s) version 2 cannot be processed w/o password", a_file_name), close(l_fd), NULL;
+    if ( (l_file_hdr.version == DAP_WALLET$K_VER_2) && (!l_pass) ) {
+        log_it(L_DEBUG, "Wallet (%s) version 2 cannot be processed w/o password", a_file_name);
+#ifdef DAP_OS_WINDOWS
+        CloseHandle(l_fh);
+#else
+        close(l_fd);
+#endif
+        return NULL;
+    }
 
-    if ( l_file_hdr.wallet_len > DAP_WALLET$SZ_NAME )
-        return  log_it(L_ERROR, "Invalid Wallet name (%s) length ( >%d)", a_file_name, DAP_WALLET$SZ_NAME),
-                    close(l_fd), NULL;
+    if ( l_file_hdr.wallet_len > DAP_WALLET$SZ_NAME ) {
+        log_it(L_ERROR, "Invalid Wallet name (%s) length ( >%d)", a_file_name, DAP_WALLET$SZ_NAME);
+#ifdef DAP_OS_WINDOWS
+        CloseHandle(l_fh);
+#else
+        close(l_fd);
+#endif
+        return NULL;
+    }
 
+#ifdef DAP_OS_WINDOWS
+    if (!ReadFile(l_fh, l_wallet_name, l_file_hdr.wallet_len, &l_rc, 0) || l_rc != l_file_hdr.wallet_len) {
+        return  log_it(L_ERROR, "Error reading Wallet name, err %lu", GetLastError()),
+                CloseHandle(l_fh), NULL;
+    }
+#else
     if ( l_file_hdr.wallet_len != read(l_fd, l_wallet_name, l_file_hdr.wallet_len) ) /* Read wallet's name */
         return  log_it(L_ERROR, "Error Wallet's name (%s), errno=%d", a_file_name, errno), close(l_fd), NULL;
+#endif
 
-
-    l_csum = crc32c (l_csum, &l_file_hdr, sizeof(l_file_hdr) );           /* Compute check sum of the Wallet file header */
-    l_csum = crc32c (l_csum, l_wallet_name,  l_file_hdr.wallet_len);
+    l_csum = crc32c(l_csum, &l_file_hdr, sizeof(l_file_hdr) );           /* Compute check sum of the Wallet file header */
+    l_csum = crc32c(l_csum, l_wallet_name,  l_file_hdr.wallet_len);
 
     log_it(L_DEBUG, "Wallet file: %s, Wallet[Version: %d, type: %d, name: '%.*s']",
            a_file_name, l_file_hdr.version, l_file_hdr.type, l_file_hdr.wallet_len, l_wallet_name);
 
     /* First run - count certs in file */
+
+#ifdef DAP_OS_WINDOWS
+    for ( l_certs_count = 0; ReadFile(l_fh, &l_cert_hdr, sizeof(l_cert_hdr), &l_rc, NULL) && l_rc; ++l_certs_count) {
+        if ( (l_file_hdr.version == DAP_WALLET$K_VER_2) && (l_cert_hdr.type == DAP_WALLET$K_MAGIC) )
+            break;
+        if (!ReadFile(l_fh, l_buf, l_cert_hdr.cert_raw_size, &l_rc, NULL) || l_rc != l_cert_hdr.cert_raw_size){
+            log_it(L_ERROR, "Error reading certificate body (%d != %lu), err %lu", l_cert_hdr.cert_raw_size, l_rc, GetLastError());
+            break;
+        }
+    }
+#else
     for ( l_certs_count = 0; sizeof(l_cert_hdr) == (l_rc = read (l_fd, &l_cert_hdr, sizeof(l_cert_hdr))); l_certs_count++ ) {
         if ( (l_file_hdr.version == DAP_WALLET$K_VER_2) && (l_cert_hdr.type == DAP_WALLET$K_MAGIC) )
             break;
 
-        if ( (int) l_cert_hdr.cert_raw_size != (l_rc = read(l_fd, l_buf, l_cert_hdr.cert_raw_size)) ) {
+        if ( (int)l_cert_hdr.cert_raw_size != (l_rc = read(l_fd, l_buf, l_cert_hdr.cert_raw_size)) ) {
             log_it(L_ERROR, "Error read certificate's body (%d != %d), errno=%d", l_cert_hdr.cert_raw_size, l_rc, errno);
             break;
         }
     }
+#endif
 
+#ifndef DAP_OS_WINDOWS
     if ( l_rc < 0 )
-        return  log_it(L_ERROR, "Wallet file (%s) I/O error, errno=%d", a_file_name, errno), close(l_fd), NULL;
+        return log_it(L_ERROR, "Wallet file (%s) I/O error, errno=%d", a_file_name, errno), close(l_fd), NULL;
+#endif
 
-    if ( !l_certs_count )
-        return  log_it(L_ERROR, "No certificate (-s) in the wallet file (%s)", a_file_name), close(l_fd), NULL;
+    if ( !l_certs_count ) {
+        log_it(L_ERROR, "No certificate (-s) in the wallet file (%s)", a_file_name);
+#ifdef DAP_OS_WINDOWS
+        CloseHandle(l_fh);
+#else
+        close(l_fd);
+#endif
+        return NULL;
+    }
 
 
     if ( (l_file_hdr.version == DAP_WALLET$K_VER_2) && l_pass )             /* Generate encryptor context  */
-        if ( !(l_enc_key = dap_enc_key_new_generate(DAP_ENC_KEY_TYPE_GOST_OFB, NULL, 0, l_pass, strlen(l_pass), 0)) )
-            return  log_it(L_ERROR, "Error create key context"), close(l_fd), NULL;
+        if ( !(l_enc_key = dap_enc_key_new_generate(DAP_ENC_KEY_TYPE_GOST_OFB, NULL, 0, l_pass, strlen(l_pass), 0)) ) {
+            log_it(L_ERROR, "Error create key context");
+#ifdef DAP_OS_WINDOWS
+            CloseHandle(l_fh);
+#else
+            close(l_fd);
+#endif
+            return NULL;
+    }
 
 
     /* Create local instance of wallet,
@@ -794,16 +904,27 @@ uint32_t    l_csum = CRC32C_INIT, l_csum2 = CRC32C_INIT;
     l_wallet_internal->certs = DAP_NEW_Z_SIZE(dap_cert_t *, l_wallet_internal->certs_count * sizeof(dap_cert_t *));
     assert(l_wallet_internal->certs);
 
-
-
+#ifdef DAP_OS_WINDOWS
+    LARGE_INTEGER l_offset;
+    l_offset.QuadPart = sizeof(l_file_hdr) + l_file_hdr.wallet_len;
+    if (SetFilePointerEx(l_fh, l_offset, &l_offset, FILE_BEGIN))
+#else
     lseek(l_fd,  sizeof(l_file_hdr) + l_file_hdr.wallet_len, SEEK_SET);     /* Set file pointer to first record after cert file header */
+#endif
 
-
-
+#ifdef DAP_OS_WINDOWS
+    for (size_t i = 0; (ReadFile(l_fh, &l_cert_hdr, sizeof(l_cert_hdr), &l_rc, NULL) == TRUE) && l_rc; ++i)
+#else
     for ( size_t i = 0; sizeof(l_cert_hdr) == (l_rc = read (l_fd, &l_cert_hdr, sizeof(l_cert_hdr))); i++ )           /* Read Cert/Record header */
+#endif
     {
-        if ( (int) l_cert_hdr.cert_raw_size != (l_rc = read(l_fd, l_buf, l_cert_hdr.cert_raw_size)) ) {
+#ifdef DAP_OS_WINDOWS
+        if (!ReadFile(l_fh, l_buf, l_cert_hdr.cert_raw_size, &l_rc, NULL) || l_rc != l_cert_hdr.cert_raw_size) {
+            log_it(L_ERROR, "Error reading certificate body (%lu != %lu), err %lu", l_cert_hdr.cert_raw_size, l_rc, GetLastError());
+#else
+        if ( (int)l_cert_hdr.cert_raw_size != (l_rc = read(l_fd, l_buf, l_cert_hdr.cert_raw_size)) ) {
             log_it(L_ERROR, "Error read certificate's body (%d != %d), errno=%d", l_cert_hdr.cert_raw_size, l_rc, errno);
+#endif
             break;
         }
 
@@ -819,7 +940,7 @@ uint32_t    l_csum = CRC32C_INIT, l_csum2 = CRC32C_INIT;
         {
             l_len = l_enc_key->dec_na(l_enc_key, l_buf, l_rc, l_buf2, sizeof(l_buf2) );
             l_bufp = l_buf2;
-            l_csum = crc32c (l_csum, l_bufp, l_len);                          /* CRC for every certificate */
+            l_csum = crc32c(l_csum, l_bufp, l_len);                          /* CRC for every certificate */
         }
 
         l_wallet_internal->certs[ i ] = dap_cert_mem_load(l_bufp, l_cert_hdr.cert_raw_size);
@@ -828,7 +949,11 @@ uint32_t    l_csum = CRC32C_INIT, l_csum2 = CRC32C_INIT;
 
 
     /* Cleanup and exit ... */
+#ifdef DAP_OS_WINDOWS
+    CloseHandle(l_fh);
+#else
     close (l_fd);
+#endif
 
     if ( l_enc_key )
     {
-- 
GitLab