Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/SoftEtherVPN/SoftEtherVPN_Stable.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordnobori <da.git@softether.co.jp>2014-01-04 17:00:08 +0400
committerdnobori <da.git@softether.co.jp>2014-01-04 17:00:08 +0400
commit749497dde0a1dd08c434a73b9d4e93dc3e3326d9 (patch)
tree7c83a55919c0f1aa1267c4dbcd008f1644f961ee /src/Mayaqua
parentd433e567a561f8ae094a535025b02c7dc47026c6 (diff)
v4.03-9408-rtm
Diffstat (limited to 'src/Mayaqua')
-rw-r--r--src/Mayaqua/Cfg.c2306
-rw-r--r--src/Mayaqua/Cfg.h249
-rw-r--r--src/Mayaqua/Encrypt.c4691
-rw-r--r--src/Mayaqua/Encrypt.h486
-rw-r--r--src/Mayaqua/FileIO.c2738
-rw-r--r--src/Mayaqua/FileIO.h354
-rw-r--r--src/Mayaqua/Internat.c3483
-rw-r--r--src/Mayaqua/Internat.h227
-rw-r--r--src/Mayaqua/Kernel.c2172
-rw-r--r--src/Mayaqua/Kernel.h252
-rw-r--r--src/Mayaqua/MayaType.h553
-rw-r--r--src/Mayaqua/Mayaqua.c1200
-rw-r--r--src/Mayaqua/Mayaqua.h595
-rw-r--r--src/Mayaqua/Mayaqua.vcproj833
-rw-r--r--src/Mayaqua/Memory.c4124
-rw-r--r--src/Mayaqua/Memory.h429
-rw-r--r--src/Mayaqua/Microsoft.c14824
-rw-r--r--src/Mayaqua/Microsoft.h1155
-rw-r--r--src/Mayaqua/Network.c21774
-rw-r--r--src/Mayaqua/Network.h1582
-rw-r--r--src/Mayaqua/OS.c527
-rw-r--r--src/Mayaqua/OS.h220
-rw-r--r--src/Mayaqua/Object.c596
-rw-r--r--src/Mayaqua/Object.h189
-rw-r--r--src/Mayaqua/Pack.c1671
-rw-r--r--src/Mayaqua/Pack.h234
-rw-r--r--src/Mayaqua/Secure.c2197
-rw-r--r--src/Mayaqua/Secure.h297
-rw-r--r--src/Mayaqua/Str.c3391
-rw-r--r--src/Mayaqua/Str.h228
-rw-r--r--src/Mayaqua/Table.c1473
-rw-r--r--src/Mayaqua/Table.h186
-rw-r--r--src/Mayaqua/TcpIp.c3802
-rw-r--r--src/Mayaqua/TcpIp.h876
-rw-r--r--src/Mayaqua/Tick64.c378
-rw-r--r--src/Mayaqua/Tick64.h134
-rw-r--r--src/Mayaqua/Tracking.c975
-rw-r--r--src/Mayaqua/Tracking.h171
-rw-r--r--src/Mayaqua/TunTap.h306
-rw-r--r--src/Mayaqua/Unix.c2741
-rw-r--r--src/Mayaqua/Unix.h239
-rw-r--r--src/Mayaqua/Win32.c3463
-rw-r--r--src/Mayaqua/Win32.h204
-rw-r--r--src/Mayaqua/cryptoki.h66
-rw-r--r--src/Mayaqua/intelaes/iaesni.h147
-rw-r--r--src/Mayaqua/pkcs11.h299
-rw-r--r--src/Mayaqua/pkcs11f.h912
-rw-r--r--src/Mayaqua/pkcs11t.h1440
-rw-r--r--src/Mayaqua/win32_inc/openssl/aes.h148
-rw-r--r--src/Mayaqua/win32_inc/openssl/asn1.h1332
-rw-r--r--src/Mayaqua/win32_inc/openssl/asn1_mac.h571
-rw-r--r--src/Mayaqua/win32_inc/openssl/asn1t.h893
-rw-r--r--src/Mayaqua/win32_inc/openssl/bio.h791
-rw-r--r--src/Mayaqua/win32_inc/openssl/blowfish.h129
-rw-r--r--src/Mayaqua/win32_inc/openssl/bn.h855
-rw-r--r--src/Mayaqua/win32_inc/openssl/buffer.h118
-rw-r--r--src/Mayaqua/win32_inc/openssl/cast.h107
-rw-r--r--src/Mayaqua/win32_inc/openssl/comp.h80
-rw-r--r--src/Mayaqua/win32_inc/openssl/conf.h254
-rw-r--r--src/Mayaqua/win32_inc/openssl/conf_api.h89
-rw-r--r--src/Mayaqua/win32_inc/openssl/crypto.h619
-rw-r--r--src/Mayaqua/win32_inc/openssl/des.h245
-rw-r--r--src/Mayaqua/win32_inc/openssl/des_old.h446
-rw-r--r--src/Mayaqua/win32_inc/openssl/dh.h245
-rw-r--r--src/Mayaqua/win32_inc/openssl/dsa.h324
-rw-r--r--src/Mayaqua/win32_inc/openssl/dso.h368
-rw-r--r--src/Mayaqua/win32_inc/openssl/dtls1.h265
-rw-r--r--src/Mayaqua/win32_inc/openssl/e_os2.h279
-rw-r--r--src/Mayaqua/win32_inc/openssl/ebcdic.h19
-rw-r--r--src/Mayaqua/win32_inc/openssl/ec.h526
-rw-r--r--src/Mayaqua/win32_inc/openssl/ecdh.h123
-rw-r--r--src/Mayaqua/win32_inc/openssl/ecdsa.h271
-rw-r--r--src/Mayaqua/win32_inc/openssl/engine.h804
-rw-r--r--src/Mayaqua/win32_inc/openssl/err.h330
-rw-r--r--src/Mayaqua/win32_inc/openssl/evp.h1059
-rw-r--r--src/Mayaqua/win32_inc/openssl/fips.h126
-rw-r--r--src/Mayaqua/win32_inc/openssl/fips_rand.h74
-rw-r--r--src/Mayaqua/win32_inc/openssl/hmac.h109
-rw-r--r--src/Mayaqua/win32_inc/openssl/idea.h103
-rw-r--r--src/Mayaqua/win32_inc/openssl/krb5_asn.h256
-rw-r--r--src/Mayaqua/win32_inc/openssl/kssl.h179
-rw-r--r--src/Mayaqua/win32_inc/openssl/lhash.h200
-rw-r--r--src/Mayaqua/win32_inc/openssl/md2.h95
-rw-r--r--src/Mayaqua/win32_inc/openssl/md4.h120
-rw-r--r--src/Mayaqua/win32_inc/openssl/md5.h120
-rw-r--r--src/Mayaqua/win32_inc/openssl/mdc2.h98
-rw-r--r--src/Mayaqua/win32_inc/openssl/obj_mac.h3914
-rw-r--r--src/Mayaqua/win32_inc/openssl/objects.h1049
-rw-r--r--src/Mayaqua/win32_inc/openssl/ocsp.h623
-rw-r--r--src/Mayaqua/win32_inc/openssl/opensslconf.h259
-rw-r--r--src/Mayaqua/win32_inc/openssl/opensslv.h89
-rw-r--r--src/Mayaqua/win32_inc/openssl/ossl_typ.h183
-rw-r--r--src/Mayaqua/win32_inc/openssl/pem.h782
-rw-r--r--src/Mayaqua/win32_inc/openssl/pem2.h70
-rw-r--r--src/Mayaqua/win32_inc/openssl/pkcs12.h338
-rw-r--r--src/Mayaqua/win32_inc/openssl/pkcs7.h464
-rw-r--r--src/Mayaqua/win32_inc/openssl/pq_compat.h152
-rw-r--r--src/Mayaqua/win32_inc/openssl/pqueue.h96
-rw-r--r--src/Mayaqua/win32_inc/openssl/rand.h167
-rw-r--r--src/Mayaqua/win32_inc/openssl/rc2.h103
-rw-r--r--src/Mayaqua/win32_inc/openssl/rc4.h90
-rw-r--r--src/Mayaqua/win32_inc/openssl/rc5.h120
-rw-r--r--src/Mayaqua/win32_inc/openssl/ripemd.h106
-rw-r--r--src/Mayaqua/win32_inc/openssl/rsa.h496
-rw-r--r--src/Mayaqua/win32_inc/openssl/safestack.h1986
-rw-r--r--src/Mayaqua/win32_inc/openssl/sha.h203
-rw-r--r--src/Mayaqua/win32_inc/openssl/ssl.h2125
-rw-r--r--src/Mayaqua/win32_inc/openssl/ssl2.h268
-rw-r--r--src/Mayaqua/win32_inc/openssl/ssl23.h83
-rw-r--r--src/Mayaqua/win32_inc/openssl/ssl3.h585
-rw-r--r--src/Mayaqua/win32_inc/openssl/stack.h109
-rw-r--r--src/Mayaqua/win32_inc/openssl/store.h554
-rw-r--r--src/Mayaqua/win32_inc/openssl/symhacks.h429
-rw-r--r--src/Mayaqua/win32_inc/openssl/tls1.h410
-rw-r--r--src/Mayaqua/win32_inc/openssl/tmdiff.h93
-rw-r--r--src/Mayaqua/win32_inc/openssl/txt_db.h109
-rw-r--r--src/Mayaqua/win32_inc/openssl/ui.h381
-rw-r--r--src/Mayaqua/win32_inc/openssl/ui_compat.h83
-rw-r--r--src/Mayaqua/win32_inc/openssl/x509.h1357
-rw-r--r--src/Mayaqua/win32_inc/openssl/x509_vfy.h534
-rw-r--r--src/Mayaqua/win32_inc/openssl/x509v3.h922
-rw-r--r--src/Mayaqua/zlib/zconf.h332
-rw-r--r--src/Mayaqua/zlib/zlib.h1357
123 files changed, 125180 insertions, 0 deletions
diff --git a/src/Mayaqua/Cfg.c b/src/Mayaqua/Cfg.c
new file mode 100644
index 00000000..aa43eb84
--- /dev/null
+++ b/src/Mayaqua/Cfg.c
@@ -0,0 +1,2306 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Cfg.c
+// Configuration information manipulation module
+
+#include <GlobalConst.h>
+
+#define CFG_C
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// Create a backup of the configuration file
+void BackupCfgWEx(CFG_RW *rw, FOLDER *f, wchar_t *original, UINT revision_number)
+{
+ wchar_t dirname[MAX_PATH];
+ wchar_t filename[MAX_PATH];
+ wchar_t fullpath[MAX_PATH];
+ wchar_t datestr[MAX_PATH];
+ SYSTEMTIME st;
+ // Validate arguments
+ if (f == NULL || filename == NULL || rw == NULL)
+ {
+ return;
+ }
+
+ // Determine the directory name
+ UniFormat(dirname, sizeof(dirname), L"@backup.%s", original[0] == L'@' ? original + 1 : original);
+
+ // Determine the file name
+ LocalTime(&st);
+ UniFormat(datestr, sizeof(datestr), L"%04u%02u%02u%02u_%s",
+ st.wYear, st.wMonth, st.wDay, st.wHour, original[0] == L'@' ? original + 1 : original);
+
+ if (revision_number == INFINITE)
+ {
+ UniStrCpy(filename, sizeof(filename), datestr);
+ }
+ else
+ {
+ UniFormat(filename, sizeof(filename), L"%08u_%s",
+ revision_number, original[0] == L'@' ? original + 1 : original);
+ }
+
+ // Don't save if the date and time has not been changed
+ if (UniStrCmpi(datestr, rw->LastSavedDateStr) == 0)
+ {
+ return;
+ }
+
+ UniStrCpy(rw->LastSavedDateStr, sizeof(rw->LastSavedDateStr), datestr);
+
+ // Check the existence of file name
+ if (IsFileExistsW(filename))
+ {
+ return;
+ }
+
+ // Create the directory
+ MakeDirW(dirname);
+
+ // Save the file
+ UniFormat(fullpath, sizeof(fullpath), L"%s/%s", dirname, filename);
+ CfgSaveW(f, fullpath);
+}
+
+// Close the configuration file R/W
+void FreeCfgRw(CFG_RW *rw)
+{
+ // Validate arguments
+ if (rw == NULL)
+ {
+ return;
+ }
+
+ if (rw->Io != NULL)
+ {
+ FileClose(rw->Io);
+ }
+
+ DeleteLock(rw->lock);
+ Free(rw->FileNameW);
+ Free(rw->FileName);
+ Free(rw);
+}
+
+// Writing to the configuration file
+UINT SaveCfgRw(CFG_RW *rw, FOLDER *f)
+{
+ return SaveCfgRwEx(rw, f, INFINITE);
+}
+UINT SaveCfgRwEx(CFG_RW *rw, FOLDER *f, UINT revision_number)
+{
+ UINT ret = 0;
+ // Validate arguments
+ if (rw == NULL || f == NULL)
+ {
+ return 0;
+ }
+
+ Lock(rw->lock);
+ {
+ if (rw->Io != NULL)
+ {
+ FileClose(rw->Io);
+ rw->Io = NULL;
+ }
+
+ if (CfgSaveExW2(rw, f, rw->FileNameW, &ret))
+ {
+ if (rw->DontBackup == false)
+ {
+ BackupCfgWEx(rw, f, rw->FileNameW, revision_number);
+ }
+ }
+ else
+ {
+ ret = 0;
+ }
+
+ rw->Io = FileOpenW(rw->FileNameW, false);
+ }
+ Unlock(rw->lock);
+
+ return ret;
+}
+
+// Creating a configuration file R/W
+CFG_RW *NewCfgRw(FOLDER **root, char *cfg_name)
+{
+ return NewCfgRwEx(root, cfg_name, false);
+}
+CFG_RW *NewCfgRwW(FOLDER **root, wchar_t *cfg_name)
+{
+ return NewCfgRwExW(root, cfg_name, false);
+}
+CFG_RW *NewCfgRwEx(FOLDER **root, char *cfg_name, bool dont_backup)
+{
+ wchar_t *cfg_name_w = CopyStrToUni(cfg_name);
+ CFG_RW *ret = NewCfgRwExW(root, cfg_name_w, dont_backup);
+
+ Free(cfg_name_w);
+
+ return ret;
+}
+CFG_RW *NewCfgRwExW(FOLDER **root, wchar_t *cfg_name, bool dont_backup)
+{
+ CFG_RW *rw;
+ FOLDER *f;
+ // Validate arguments
+ if (cfg_name == NULL || root == NULL)
+ {
+ return NULL;
+ }
+
+ f = CfgReadW(cfg_name);
+ if (f == NULL)
+ {
+ rw = ZeroMalloc(sizeof(CFG_RW));
+ rw->lock = NewLock();
+ rw->FileNameW = CopyUniStr(cfg_name);
+ rw->FileName = CopyUniToStr(cfg_name);
+ rw->Io = FileCreateW(cfg_name);
+ *root = NULL;
+ rw->DontBackup = dont_backup;
+
+ return rw;
+ }
+
+ rw = ZeroMalloc(sizeof(CFG_RW));
+ rw->FileNameW = CopyUniStr(cfg_name);
+ rw->FileName = CopyUniToStr(cfg_name);
+ rw->Io = FileOpenW(cfg_name, false);
+ rw->lock = NewLock();
+
+ *root = f;
+
+ rw->DontBackup = dont_backup;
+
+ return rw;
+}
+
+// Copy a file
+bool FileCopy(char *src, char *dst)
+{
+ BUF *b;
+ bool ret = false;
+ // Validate arguments
+ if (src == NULL || dst == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDump(src);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ SeekBuf(b, 0, 0);
+
+ ret = DumpBuf(b, dst);
+
+ FreeBuf(b);
+
+ return ret;
+}
+bool FileCopyW(wchar_t *src, wchar_t *dst)
+{
+ return FileCopyExW(src, dst, true);
+}
+bool FileCopyExW(wchar_t *src, wchar_t *dst, bool read_lock)
+{
+ BUF *b;
+ bool ret = false;
+ // Validate arguments
+ if (src == NULL || dst == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDumpExW(src, false);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ SeekBuf(b, 0, 0);
+
+ ret = DumpBufW(b, dst);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Save the settings to a file
+void CfgSave(FOLDER *f, char *name)
+{
+ CfgSaveEx(NULL, f, name);
+}
+void CfgSaveW(FOLDER *f, wchar_t *name)
+{
+ CfgSaveExW(NULL, f, name);
+}
+bool CfgSaveEx(CFG_RW *rw, FOLDER *f, char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = CfgSaveExW(rw, f, name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool CfgSaveExW(CFG_RW *rw, FOLDER *f, wchar_t *name)
+{
+ return CfgSaveExW2(rw, f, name, NULL);
+}
+bool CfgSaveExW2(CFG_RW *rw, FOLDER *f, wchar_t *name, UINT *written_size)
+{
+ return CfgSaveExW3(rw, f, name, written_size, IsFileExistsW(SAVE_BINARY_FILE_NAME_SWITCH));
+}
+bool CfgSaveExW3(CFG_RW *rw, FOLDER *f, wchar_t *name, UINT *written_size, bool write_binary)
+{
+ wchar_t tmp[MAX_SIZE];
+ bool text = !write_binary;
+ UCHAR hash[SHA1_SIZE];
+ BUF *b;
+ IO *o;
+ bool ret = true;
+ UINT dummy_int = 0;
+ // Validate arguments
+ if (name == NULL || f == NULL)
+ {
+ return false;
+ }
+ if (written_size == NULL)
+ {
+ written_size = &dummy_int;
+ }
+
+ // Convert to buffer
+ b = CfgFolderToBuf(f, text);
+ if (b == NULL)
+ {
+ return false;
+ }
+ // Hash the contents
+ Hash(hash, b->Buf, b->Size, true);
+
+ // Compare the contents to be written with the content which was written last
+ if (rw != NULL)
+ {
+ if (Cmp(hash, rw->LashHash, SHA1_SIZE) == 0)
+ {
+ // Contents are not changed
+ ret = false;
+ }
+ else
+ {
+ Copy(rw->LashHash, hash, SHA1_SIZE);
+ }
+ }
+
+ if (ret || OS_IS_UNIX(GetOsInfo()->OsType))
+ {
+ // Generate a temporary file name
+ UniFormat(tmp, sizeof(tmp), L"%s.log", name);
+ // Copy the file that currently exist to a temporary file
+ FileCopyW(name, tmp);
+
+ // Save the new file
+ o = FileCreateW(name);
+ if (o != NULL)
+ {
+ if (FileWrite(o, b->Buf, b->Size) == false)
+ {
+ // File saving failure
+ FileClose(o);
+ FileDeleteW(name);
+ FileRenameW(tmp, name);
+
+ if (rw != NULL)
+ {
+ Zero(rw->LashHash, sizeof(rw->LashHash));
+ }
+ }
+ else
+ {
+ // Successful saving file
+ FileClose(o);
+ // Delete the temporary file
+ FileDeleteW(tmp);
+ }
+ }
+ else
+ {
+ // File saving failure
+ FileRenameW(tmp, name);
+
+ if (rw != NULL)
+ {
+ Zero(rw->LashHash, sizeof(rw->LashHash));
+ }
+ }
+ }
+
+ *written_size = b->Size;
+
+ // Release memory
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Read the settings from the file
+FOLDER *CfgRead(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ FOLDER *ret = CfgReadW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+FOLDER *CfgReadW(wchar_t *name)
+{
+ wchar_t tmp[MAX_SIZE];
+ wchar_t newfile[MAX_SIZE];
+ BUF *b;
+ IO *o;
+ UINT size;
+ void *buf;
+ FOLDER *f;
+ bool delete_new = false;
+ bool binary_file = false;
+ bool invalid_file = false;
+ UCHAR header[8];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ // Generate a new file name
+ UniFormat(newfile, sizeof(newfile), L"%s.new", name);
+ // Generate a temporary file name
+ UniFormat(tmp, sizeof(tmp), L"%s.log", name);
+
+ // Read the new file if it exists
+ o = FileOpenW(newfile, false);
+ if (o == NULL)
+ {
+ // Read the temporary file
+ o = FileOpenW(tmp, false);
+ }
+ else
+ {
+ delete_new = true;
+ }
+ if (o == NULL)
+ {
+ // Read the original file if there is no temporary file
+ o = FileOpenW(name, false);
+ }
+ else
+ {
+ // Read the original file too if the size of temporary file is 0
+ if (FileSize(o) == 0)
+ {
+ invalid_file = true;
+ }
+
+ if (invalid_file)
+ {
+ FileClose(o);
+ o = FileOpenW(name, false);
+ }
+ }
+ if (o == NULL)
+ {
+ // Failed to read
+ return NULL;
+ }
+
+ // Read into the buffer
+ size = FileSize(o);
+ buf = Malloc(size);
+ FileRead(o, buf, size);
+ b = NewBuf();
+ WriteBuf(b, buf, size);
+ SeekBuf(b, 0, 0);
+
+ // Close the file
+ FileClose(o);
+
+ if (delete_new)
+ {
+ // Delete the new file
+ FileDeleteW(newfile);
+ }
+
+ // If the beginning 8 character of the buffer is "SEVPN_DB", it is binary file
+ ReadBuf(b, header, sizeof(header));
+ if (Cmp(header, TAG_BINARY, 8) == 0)
+ {
+ UCHAR hash1[SHA1_SIZE], hash2[SHA1_SIZE];
+ binary_file = true;
+
+ // Check the hash
+ ReadBuf(b, hash1, sizeof(hash1));
+
+ Hash(hash2, ((UCHAR *)b->Buf) + 8 + SHA1_SIZE, b->Size - 8 - SHA1_SIZE, true);
+
+ if (Cmp(hash1, hash2, SHA1_SIZE) != 0)
+ {
+ // Corrupted file
+ invalid_file = true;
+ FreeBuf(b);
+ return NULL;
+ }
+ }
+
+ SeekBuf(b, 0, 0);
+
+ if (binary_file)
+ {
+ SeekBuf(b, 8 + SHA1_SIZE, 0);
+ }
+
+ // Convert the buffer into a folder
+ if (binary_file == false)
+ {
+ // Text mode
+ f = CfgBufTextToFolder(b);
+ }
+ else
+ {
+ // Binary mode
+ f = CfgBufBinToFolder(b);
+ }
+
+ // Memory release
+ Free(buf);
+ FreeBuf(b);
+
+ FileDeleteW(newfile);
+
+ return f;
+}
+
+// Test of Cfg
+void CfgTest2(FOLDER *f, UINT n)
+{
+}
+
+void CfgTest()
+{
+#if 0
+ FOLDER *root;
+ BUF *b;
+ Debug("\nCFG Test Begin\n");
+
+ root = CfgCreateFolder(NULL, TAG_ROOT);
+ CfgTest2(root, 5);
+
+ b = CfgFolderToBufText(root);
+ //Print("%s\n", b->Buf);
+ SeekBuf(b, 0, 0);
+
+ CfgDeleteFolder(root);
+
+ DumpBuf(b, "test1.config");
+
+ root = CfgBufTextToFolder(b);
+
+ FreeBuf(b);
+
+ b = CfgFolderToBufText(root);
+// Print("%s\n", b->Buf);
+ DumpBuf(b, "test2.config");
+ FreeBuf(b);
+
+ CfgSave(root, "test.txt");
+
+ CfgDeleteFolder(root);
+
+ Debug("\nCFG Test End\n");
+#endif
+}
+
+// Read one line
+char *CfgReadNextLine(BUF *b)
+{
+ char *tmp;
+ char *buf;
+ UINT len;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ // Examine the number of characters up to the next newline
+ tmp = (char *)b->Buf + b->Current;
+ if ((b->Size - b->Current) == 0)
+ {
+ // Read to the end
+ return NULL;
+ }
+ len = 0;
+ while (true)
+ {
+ if (tmp[len] == 13 || tmp[len] == 10)
+ {
+ if (tmp[len] == 13)
+ {
+ if (len < (b->Size - b->Current))
+ {
+ len++;
+ }
+ }
+ break;
+ }
+ len++;
+ if (len >= (b->Size - b->Current))
+ {
+ break;
+ }
+ }
+
+ // Read ahead only 'len' bytes
+ buf = ZeroMalloc(len + 1);
+ ReadBuf(b, buf, len);
+ SeekBuf(b, 1, 1);
+
+ if (StrLen(buf) >= 1)
+ {
+ if (buf[StrLen(buf) - 1] == 13)
+ {
+ buf[StrLen(buf) - 1] = 0;
+ }
+ }
+
+ return buf;
+}
+
+// Read the text stream
+bool CfgReadNextTextBUF(BUF *b, FOLDER *current)
+{
+ char *buf;
+ TOKEN_LIST *token;
+ char *name;
+ char *string;
+ char *data;
+ bool ret;
+ FOLDER *f;
+
+ // Validate arguments
+ if (b == NULL || current == NULL)
+ {
+ return false;
+ }
+
+ ret = true;
+
+ // Read one line
+ buf = CfgReadNextLine(b);
+ if (buf == NULL)
+ {
+ return false;
+ }
+
+ // Analyze this line
+ token = ParseToken(buf, "\t ");
+ if (token == NULL)
+ {
+ Free(buf);
+ return false;
+ }
+
+ if (token->NumTokens >= 1)
+ {
+ if (!StrCmpi(token->Token[0], TAG_DECLARE))
+ {
+ if (token->NumTokens >= 2)
+ {
+ // declare
+ name = CfgUnescape(token->Token[1]);
+
+ // Create a folder
+ f = CfgCreateFolder(current, name);
+
+ // Read the next folder
+ while (true)
+ {
+ if (CfgReadNextTextBUF(b, f) == false)
+ {
+ break;
+ }
+ }
+
+ Free(name);
+ }
+ }
+ if (!StrCmpi(token->Token[0], "}"))
+ {
+ // end
+ ret = false;
+ }
+ if (token->NumTokens >= 3)
+ {
+ name = CfgUnescape(token->Token[1]);
+ data = token->Token[2];
+
+ if (!StrCmpi(token->Token[0], TAG_STRING))
+ {
+ // string
+ wchar_t *uni;
+ UINT uni_size;
+ string = CfgUnescape(data);
+ uni_size = CalcUtf8ToUni(string, StrLen(string));
+ if (uni_size != 0)
+ {
+ uni = Malloc(uni_size);
+ Utf8ToUni(uni, uni_size, string, StrLen(string));
+ CfgAddUniStr(current, name, uni);
+ Free(uni);
+ }
+ Free(string);
+ }
+ if (!StrCmpi(token->Token[0], TAG_INT))
+ {
+ // uint
+ CfgAddInt(current, name, ToInt(data));
+ }
+ if (!StrCmpi(token->Token[0], TAG_INT64))
+ {
+ // uint64
+ CfgAddInt64(current, name, ToInt64(data));
+ }
+ if (!StrCmpi(token->Token[0], TAG_BOOL))
+ {
+ // bool
+ bool b = false;
+ if (!StrCmpi(data, TAG_TRUE))
+ {
+ b = true;
+ }
+ else if (ToInt(data) != 0)
+ {
+ b = true;
+ }
+ CfgAddBool(current, name, b);
+ }
+ if (!StrCmpi(token->Token[0], TAG_BYTE))
+ {
+ // byte
+ char *unescaped_b64 = CfgUnescape(data);
+ void *tmp = Malloc(StrLen(unescaped_b64) * 4 + 64);
+ int size = B64_Decode(tmp, unescaped_b64, StrLen(unescaped_b64));
+ CfgAddByte(current, name, tmp, size);
+ Free(tmp);
+ Free(unescaped_b64);
+ }
+
+ Free(name);
+ }
+ }
+
+ // Release of the token
+ FreeToken(token);
+
+ Free(buf);
+
+ return ret;
+}
+
+// Convert the stream text to a folder
+FOLDER *CfgBufTextToFolder(BUF *b)
+{
+ FOLDER *f, *c;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ // Read recursively from the root folder
+ c = CfgCreateFolder(NULL, "tmp");
+
+ while (true)
+ {
+ // Read the text stream
+ if (CfgReadNextTextBUF(b, c) == false)
+ {
+ break;
+ }
+ }
+
+ // Getting root folder
+ f = CfgGetFolder(c, TAG_ROOT);
+ if (f == NULL)
+ {
+ // Root folder is not found
+ CfgDeleteFolder(c);
+ return NULL;
+ }
+
+ // Remove the reference from tmp folder to the root
+ Delete(c->Folders, f);
+ f->Parent = NULL;
+
+ // Delete the tmp folder
+ CfgDeleteFolder(c);
+
+ // Return the root folder
+ return f;
+}
+
+// Read the next folder
+void CfgReadNextFolderBin(BUF *b, FOLDER *parent)
+{
+ char name[MAX_SIZE];
+ FOLDER *f;
+ UINT n, i;
+ UINT size;
+ UCHAR *buf;
+ wchar_t *string;
+ // Validate arguments
+ if (b == NULL || parent == NULL)
+ {
+ return;
+ }
+
+ // Folder name
+ ReadBufStr(b, name, sizeof(name));
+ f = CfgCreateFolder(parent, name);
+
+ // The number of the subfolder
+ n = ReadBufInt(b);
+ for (i = 0;i < n;i++)
+ {
+ // Subfolder
+ CfgReadNextFolderBin(b, f);
+ }
+
+ // The number of items
+ n = ReadBufInt(b);
+ for (i = 0;i < n;i++)
+ {
+ UINT type;
+
+ // Name
+ ReadBufStr(b, name, sizeof(name));
+ // Type
+ type = ReadBufInt(b);
+
+ switch (type)
+ {
+ case ITEM_TYPE_INT:
+ // int
+ CfgAddInt(f, name, ReadBufInt(b));
+ break;
+
+ case ITEM_TYPE_INT64:
+ // int64
+ CfgAddInt64(f, name, ReadBufInt64(b));
+ break;
+
+ case ITEM_TYPE_BYTE:
+ // data
+ size = ReadBufInt(b);
+ buf = ZeroMalloc(size);
+ ReadBuf(b, buf, size);
+ CfgAddByte(f, name, buf, size);
+ Free(buf);
+ break;
+
+ case ITEM_TYPE_STRING:
+ // string
+ size = ReadBufInt(b);
+ buf = ZeroMalloc(size + 1);
+ ReadBuf(b, buf, size);
+ string = ZeroMalloc(CalcUtf8ToUni(buf, StrLen(buf)) + 4);
+ Utf8ToUni(string, 0, buf, StrLen(buf));
+ CfgAddUniStr(f, name, string);
+ Free(string);
+ Free(buf);
+ break;
+
+ case ITEM_TYPE_BOOL:
+ // bool
+ CfgAddBool(f, name, ReadBufInt(b) == 0 ? false : true);
+ break;
+ }
+ }
+}
+
+// Convert the binary to folder
+FOLDER *CfgBufBinToFolder(BUF *b)
+{
+ FOLDER *f, *c;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ // Create a temporary folder
+ c = CfgCreateFolder(NULL, "tmp");
+
+ // Read a binary
+ CfgReadNextFolderBin(b, c);
+
+ // Get root folder
+ f = CfgGetFolder(c, TAG_ROOT);
+ if (f == NULL)
+ {
+ // Missing
+ CfgDeleteFolder(c);
+ return NULL;
+ }
+
+ Delete(c->Folders, f);
+ f->Parent = NULL;
+
+ CfgDeleteFolder(c);
+
+ return f;
+}
+
+// Convert the folder to binary
+BUF *CfgFolderToBufBin(FOLDER *f)
+{
+ BUF *b;
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+
+ // Header
+ WriteBuf(b, TAG_BINARY, 8);
+
+ // Hash area
+ Zero(hash, sizeof(hash));
+ WriteBuf(b, hash, sizeof(hash));
+
+ // Output the root folder (recursive)
+ CfgOutputFolderBin(b, f);
+
+ // Hash
+ Hash(((UCHAR *)b->Buf) + 8, ((UCHAR *)b->Buf) + 8 + SHA1_SIZE, b->Size - 8 - SHA1_SIZE, true);
+
+ return b;
+}
+
+// Convert the folder to a stream text
+BUF *CfgFolderToBufText(FOLDER *f)
+{
+ return CfgFolderToBufTextEx(f, false);
+}
+BUF *CfgFolderToBufTextEx(FOLDER *f, bool no_banner)
+{
+ BUF *b;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ // Create a stream
+ b = NewBuf();
+
+ // Copyright notice
+ if (no_banner == false)
+ {
+ WriteBuf(b, TAG_CPYRIGHT, StrLen(TAG_CPYRIGHT));
+ }
+
+ // Output the root folder (recursive)
+ CfgOutputFolderText(b, f, 0);
+
+ return b;
+}
+
+// Output the folder contents (Enumerate folders)
+bool CfgEnumFolderProc(FOLDER *f, void *param)
+{
+ CFG_ENUM_PARAM *p;
+ // Validate arguments
+ if (f == NULL || param == NULL)
+ {
+ return false;
+ }
+
+ p = (CFG_ENUM_PARAM *)param;
+ // Output the folder contents (recursive)
+ CfgOutputFolderText(p->b, f, p->depth);
+
+ return true;
+}
+
+// Output the contents of the item (enumeration)
+bool CfgEnumItemProc(ITEM *t, void *param)
+{
+ CFG_ENUM_PARAM *p;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return false;
+ }
+
+ p = (CFG_ENUM_PARAM *)param;
+ CfgAddItemText(p->b, t, p->depth);
+
+ return true;
+}
+
+// Output the folder contents (Recursive, binary)
+void CfgOutputFolderBin(BUF *b, FOLDER *f)
+{
+ UINT i;
+ // Validate arguments
+ if (b == NULL || f == NULL)
+ {
+ return;
+ }
+
+ // Folder name
+ WriteBufStr(b, f->Name);
+
+ // The number of the subfolder
+ WriteBufInt(b, LIST_NUM(f->Folders));
+
+ // Subfolder
+ for (i = 0;i < LIST_NUM(f->Folders);i++)
+ {
+ FOLDER *sub = LIST_DATA(f->Folders, i);
+ CfgOutputFolderBin(b, sub);
+
+ if ((i % 100) == 99)
+ {
+ YieldCpu();
+ }
+ }
+
+ // The number of Items
+ WriteBufInt(b, LIST_NUM(f->Items));
+
+ // Item
+ for (i = 0;i < LIST_NUM(f->Items);i++)
+ {
+ char *utf8;
+ UINT utf8_size;
+ ITEM *t = LIST_DATA(f->Items, i);
+
+ // Item Name
+ WriteBufStr(b, t->Name);
+
+ // Type
+ WriteBufInt(b, t->Type);
+
+ switch (t->Type)
+ {
+ case ITEM_TYPE_INT:
+ // Integer
+ WriteBufInt(b, *((UINT *)t->Buf));
+ break;
+
+ case ITEM_TYPE_INT64:
+ // 64-bit integer
+ WriteBufInt64(b, *((UINT64 *)t->Buf));
+ break;
+
+ case ITEM_TYPE_BYTE:
+ // Data size
+ WriteBufInt(b, t->size);
+ // Data
+ WriteBuf(b, t->Buf, t->size);
+ break;
+
+ case ITEM_TYPE_STRING:
+ // String
+ utf8_size = CalcUniToUtf8((wchar_t *)t->Buf) + 1;
+ utf8 = ZeroMalloc(utf8_size);
+ UniToUtf8(utf8, utf8_size, (wchar_t *)t->Buf);
+ WriteBufInt(b, StrLen(utf8));
+ WriteBuf(b, utf8, StrLen(utf8));
+ Free(utf8);
+ break;
+
+ case ITEM_TYPE_BOOL:
+ // Boolean type
+ if (*((bool *)t->Buf) == false)
+ {
+ WriteBufInt(b, 0);
+ }
+ else
+ {
+ WriteBufInt(b, 1);
+ }
+ break;
+ }
+ }
+}
+
+// Output the contents of the folder (Recursive, text)
+void CfgOutputFolderText(BUF *b, FOLDER *f, UINT depth)
+{
+ CFG_ENUM_PARAM p;
+ // Validate arguments
+ if (b == NULL || f == NULL)
+ {
+ return;
+ }
+
+ // Output starting of the folder
+ CfgAddDeclare(b, f->Name, depth);
+ depth++;
+
+ Zero(&p, sizeof(CFG_ENUM_PARAM));
+ p.depth = depth;
+ p.b = b;
+ p.f = f;
+
+ // Enumerate the list of items
+ CfgEnumItem(f, CfgEnumItemProc, &p);
+
+ if (LIST_NUM(f->Folders) != 0 && LIST_NUM(f->Items) != 0)
+ {
+ WriteBuf(b, "\r\n", 2);
+ }
+
+ // Enumerate the folder list
+ CfgEnumFolder(f, CfgEnumFolderProc, &p);
+ // Output the end of the folder
+ depth--;
+ CfgAddEnd(b, depth);
+
+ //WriteBuf(b, "\r\n", 2);
+}
+
+// Output contents of the item
+void CfgAddItemText(BUF *b, ITEM *t, UINT depth)
+{
+ char *data;
+ char *sub = NULL;
+ UINT len;
+ UINT size;
+ char *utf8;
+ UINT utf8_size;
+ wchar_t *string;
+ // Validate arguments
+ if (b == NULL || t == NULL)
+ {
+ return;
+ }
+
+ // Process the data by its type
+ data = NULL;
+ switch (t->Type)
+ {
+ case ITEM_TYPE_INT:
+ data = Malloc(32);
+ ToStr(data, *((UINT *)t->Buf));
+ break;
+
+ case ITEM_TYPE_INT64:
+ data = Malloc(64);
+ ToStr64(data, *((UINT64 *)t->Buf));
+ break;
+
+ case ITEM_TYPE_BYTE:
+ data = ZeroMalloc(t->size * 4 + 32);
+ len = B64_Encode(data, t->Buf, t->size);
+ data[len] = 0;
+ break;
+
+ case ITEM_TYPE_STRING:
+ string = t->Buf;
+ utf8_size = CalcUniToUtf8(string);
+ utf8_size++;
+ utf8 = ZeroMalloc(utf8_size);
+ utf8[0] = 0;
+ UniToUtf8(utf8, utf8_size, string);
+ size = utf8_size;
+ data = utf8;
+ break;
+
+ case ITEM_TYPE_BOOL:
+ size = 32;
+ data = Malloc(size);
+ if (*((bool *)t->Buf) == false)
+ {
+ StrCpy(data, size, TAG_FALSE);
+ }
+ else
+ {
+ StrCpy(data, size, TAG_TRUE);
+ }
+ break;
+ }
+ if (data == NULL)
+ {
+ return;
+ }
+
+ // Output the data line
+ CfgAddData(b, t->Type, t->Name, data, sub, depth);
+
+ // Memory release
+ Free(data);
+ if (sub != NULL)
+ {
+ Free(sub);
+ }
+}
+
+// Output the data line
+void CfgAddData(BUF *b, UINT type, char *name, char *data, char *sub, UINT depth)
+{
+ char *tmp;
+ char *name2;
+ char *data2;
+ char *sub2 = NULL;
+ UINT tmp_size;
+ // Validate arguments
+ if (b == NULL || type == 0 || name == NULL || data == NULL)
+ {
+ return;
+ }
+
+ name2 = CfgEscape(name);
+ data2 = CfgEscape(data);
+ if (sub != NULL)
+ {
+ sub2 = CfgEscape(sub);
+ }
+
+ tmp_size = StrLen(name2) + StrLen(data2) + 2 + 64 + 1;
+ tmp = Malloc(tmp_size);
+
+ if (sub2 != NULL)
+ {
+ StrCpy(tmp, tmp_size, CfgTypeToStr(type));
+ StrCat(tmp, tmp_size, " ");
+ StrCat(tmp, tmp_size, name2);
+ StrCat(tmp, tmp_size, " ");
+ StrCat(tmp, tmp_size, data2);
+ StrCat(tmp, tmp_size, " ");
+ StrCat(tmp, tmp_size, sub2);
+ }
+ else
+ {
+ StrCpy(tmp, tmp_size, CfgTypeToStr(type));
+ StrCat(tmp, tmp_size, " ");
+ StrCat(tmp, tmp_size, name2);
+ StrCat(tmp, tmp_size, " ");
+ StrCat(tmp, tmp_size, data2);
+ }
+
+ Free(name2);
+ Free(data2);
+ if (sub2 != NULL)
+ {
+ Free(sub2);
+ }
+ CfgAddLine(b, tmp, depth);
+ Free(tmp);
+}
+
+// Convert the data type string to an integer value
+UINT CfgStrToType(char *str)
+{
+ if (!StrCmpi(str, TAG_INT)) return ITEM_TYPE_INT;
+ if (!StrCmpi(str, TAG_INT64)) return ITEM_TYPE_INT64;
+ if (!StrCmpi(str, TAG_BYTE)) return ITEM_TYPE_BYTE;
+ if (!StrCmpi(str, TAG_STRING)) return ITEM_TYPE_STRING;
+ if (!StrCmpi(str, TAG_BOOL)) return ITEM_TYPE_BOOL;
+ return 0;
+}
+
+// Convert the type of data to a string
+char *CfgTypeToStr(UINT type)
+{
+ switch (type)
+ {
+ case ITEM_TYPE_INT:
+ return TAG_INT;
+ case ITEM_TYPE_INT64:
+ return TAG_INT64;
+ case ITEM_TYPE_BYTE:
+ return TAG_BYTE;
+ case ITEM_TYPE_STRING:
+ return TAG_STRING;
+ case ITEM_TYPE_BOOL:
+ return TAG_BOOL;
+ }
+ return NULL;
+}
+
+// Outputs the End line
+void CfgAddEnd(BUF *b, UINT depth)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ CfgAddLine(b, "}", depth);
+// CfgAddLine(b, TAG_END, depth);
+}
+
+// Outputs the Declare lines
+void CfgAddDeclare(BUF *b, char *name, UINT depth)
+{
+ char *tmp;
+ char *name2;
+ UINT tmp_size;
+ // Validate arguments
+ if (b == NULL || name == NULL)
+ {
+ return;
+ }
+
+ name2 = CfgEscape(name);
+
+ tmp_size = StrLen(name2) + 2 + StrLen(TAG_DECLARE);
+ tmp = Malloc(tmp_size);
+
+ Format(tmp, 0, "%s %s", TAG_DECLARE, name2);
+ CfgAddLine(b, tmp, depth);
+ CfgAddLine(b, "{", depth);
+ Free(tmp);
+ Free(name2);
+}
+
+// Outputs one line
+void CfgAddLine(BUF *b, char *str, UINT depth)
+{
+ UINT i;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < depth;i++)
+ {
+ WriteBuf(b, "\t", 1);
+ }
+ WriteBuf(b, str, StrLen(str));
+ WriteBuf(b, "\r\n", 2);
+}
+
+// Convert the folder to a stream
+BUF *CfgFolderToBuf(FOLDER *f, bool textmode)
+{
+ return CfgFolderToBufEx(f, textmode, false);
+}
+BUF *CfgFolderToBufEx(FOLDER *f, bool textmode, bool no_banner)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ if (textmode)
+ {
+ return CfgFolderToBufTextEx(f, no_banner);
+ }
+ else
+ {
+ return CfgFolderToBufBin(f);;
+ }
+}
+
+// Escape restoration of the string
+char *CfgUnescape(char *str)
+{
+ char *tmp;
+ char *ret;
+ char tmp2[16];
+ UINT len, wp, i;
+ UINT code;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = StrLen(str);
+ tmp = ZeroMalloc(len + 1);
+ wp = 0;
+ if (len == 1 && str[0] == '$')
+ {
+ // Empty character
+ tmp[0] = 0;
+ }
+ else
+ {
+ for (i = 0;i < len;i++)
+ {
+ if (str[i] != '$')
+ {
+ tmp[wp++] = str[i];
+ }
+ else
+ {
+ tmp2[0] = '0';
+ tmp2[1] = 'x';
+ tmp2[2] = str[i + 1];
+ tmp2[3] = str[i + 2];
+ i += 2;
+ tmp2[4] = 0;
+ code = ToInt(tmp2);
+ tmp[wp++] = (char)code;
+ }
+ }
+ }
+ ret = Malloc(StrLen(tmp) + 1);
+ StrCpy(ret, StrLen(tmp) + 1, tmp);
+ Free(tmp);
+ return ret;
+}
+
+// Escape the string
+char *CfgEscape(char *str)
+{
+ char *tmp;
+ char *ret;
+ char tmp2[16];
+ UINT len;
+ UINT wp, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = StrLen(str);
+ tmp = ZeroMalloc(len * 3 + 2);
+ if (len == 0)
+ {
+ // Empty character
+ StrCpy(tmp, (len * 3 + 2), "$");
+ }
+ else
+ {
+ // Non null character
+ wp = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (CfgCheckCharForName(str[i]))
+ {
+ tmp[wp++] = str[i];
+ }
+ else
+ {
+ tmp[wp++] = '$';
+ Format(tmp2, sizeof(tmp2), "%02X", (UINT)str[i]);
+ tmp[wp++] = tmp2[0];
+ tmp[wp++] = tmp2[1];
+ }
+ }
+ }
+ ret = Malloc(StrLen(tmp) + 1);
+ StrCpy(ret, 0, tmp);
+ Free(tmp);
+ return ret;
+}
+
+// Check if the character can be used in the name
+bool CfgCheckCharForName(char c)
+{
+ if (c >= 0 && c <= 31)
+ {
+ return false;
+ }
+ if (c == ' ' || c == '\t')
+ {
+ return false;
+ }
+ if (c == '$')
+ {
+ return false;
+ }
+ return true;
+}
+
+// Get the string type value
+bool CfgGetStr(FOLDER *f, char *name, char *str, UINT size)
+{
+ wchar_t *tmp;
+ UINT tmp_size;
+ // Validate arguments
+ if (f == NULL || name == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ str[0] = 0;
+
+ // Get unicode string temporarily
+ tmp_size = size * 4 + 10; // Just to make sure, a quantity of this amount is secured.
+ tmp = Malloc(tmp_size);
+ if (CfgGetUniStr(f, name, tmp, tmp_size) == false)
+ {
+ // Failure
+ Free(tmp);
+ return false;
+ }
+
+ // Copy to the ANSI string
+ UniToStr(str, size, tmp);
+ Free(tmp);
+
+ return true;
+}
+
+// Get the value of the unicode_string type
+bool CfgGetUniStr(FOLDER *f, char *name, wchar_t *str, UINT size)
+{
+ ITEM *t;
+ // Validate arguments
+ if (f == NULL || name == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ str[0] = 0;
+
+ t = CfgFindItem(f, name);
+ if (t == NULL)
+ {
+ return false;
+ }
+ if (t->Type != ITEM_TYPE_STRING)
+ {
+ return false;
+ }
+ UniStrCpy(str, size, t->Buf);
+ return true;
+}
+
+// Check for the existence of a folder
+bool CfgIsFolder(FOLDER *f, char *name)
+{
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ return (CfgGetFolder(f, name) == NULL) ? false : true;
+}
+
+// Check for the existence of item
+bool CfgIsItem(FOLDER *f, char *name)
+{
+ ITEM *t;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ t = CfgFindItem(f, name);
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the byte[] type as a BUF
+BUF *CfgGetBuf(FOLDER *f, char *name)
+{
+ ITEM *t;
+ BUF *b;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ t = CfgFindItem(f, name);
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, t->Buf, t->size);
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Get the value of type byte[]
+UINT CfgGetByte(FOLDER *f, char *name, void *buf, UINT size)
+{
+ ITEM *t;
+ // Validate arguments
+ if (f == NULL || name == NULL || buf == NULL)
+ {
+ return 0;
+ }
+
+ t = CfgFindItem(f, name);
+ if (t == NULL)
+ {
+ return 0;
+ }
+ if (t->Type != ITEM_TYPE_BYTE)
+ {
+ return 0;
+ }
+ if (t->size <= size)
+ {
+ Copy(buf, t->Buf, t->size);
+ return t->size;
+ }
+ else
+ {
+ Copy(buf, t->Buf, size);
+ return t->size;
+ }
+}
+
+// Get the value of type int64
+UINT64 CfgGetInt64(FOLDER *f, char *name)
+{
+ ITEM *t;
+ UINT64 *ret;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ t = CfgFindItem(f, name);
+ if (t == NULL)
+ {
+ return 0;
+ }
+ if (t->Type != ITEM_TYPE_INT64)
+ {
+ return 0;
+ }
+ if (t->size != sizeof(UINT64))
+ {
+ return 0;
+ }
+
+ ret = (UINT64 *)t->Buf;
+ return *ret;
+}
+
+// Get the value of the bool type
+bool CfgGetBool(FOLDER *f, char *name)
+{
+ ITEM *t;
+ bool *ret;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ t = CfgFindItem(f, name);
+ if (t == NULL)
+ {
+ return 0;
+ }
+ if (t->Type != ITEM_TYPE_BOOL)
+ {
+ return 0;
+ }
+ if (t->size != sizeof(bool))
+ {
+ return 0;
+ }
+
+ ret = (bool *)t->Buf;
+ if (*ret == false)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+// Get the value of the int type
+UINT CfgGetInt(FOLDER *f, char *name)
+{
+ ITEM *t;
+ UINT *ret;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ t = CfgFindItem(f, name);
+ if (t == NULL)
+ {
+ return 0;
+ }
+ if (t->Type != ITEM_TYPE_INT)
+ {
+ return 0;
+ }
+ if (t->size != sizeof(UINT))
+ {
+ return 0;
+ }
+
+ ret = (UINT *)t->Buf;
+ return *ret;
+}
+
+// Search for an item
+ITEM *CfgFindItem(FOLDER *parent, char *name)
+{
+ ITEM *t, tt;
+ // Validate arguments
+ if (parent == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ tt.Name = ZeroMalloc(StrLen(name) + 1);
+ StrCpy(tt.Name, 0, name);
+ t = Search(parent->Items, &tt);
+ Free(tt.Name);
+
+ return t;
+}
+
+// Get a folder
+FOLDER *CfgGetFolder(FOLDER *parent, char *name)
+{
+ return CfgFindFolder(parent, name);
+}
+
+// Search a folder
+FOLDER *CfgFindFolder(FOLDER *parent, char *name)
+{
+ FOLDER *f, ff;
+ // Validate arguments
+ if (parent == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ ff.Name = ZeroMalloc(StrLen(name) + 1);
+ StrCpy(ff.Name, 0, name);
+ f = Search(parent->Folders, &ff);
+ Free(ff.Name);
+
+ return f;
+}
+
+// Adding a string type
+ITEM *CfgAddStr(FOLDER *f, char *name, char *str)
+{
+ wchar_t *tmp;
+ UINT tmp_size;
+ ITEM *t;
+ // Validate arguments
+ if (f == NULL || name == NULL || str == NULL)
+ {
+ return NULL;
+ }
+
+ // Convert to a Unicode string
+ tmp_size = CalcStrToUni(str);
+ if (tmp_size == 0)
+ {
+ return NULL;
+ }
+ tmp = Malloc(tmp_size);
+ StrToUni(tmp, tmp_size, str);
+ t = CfgAddUniStr(f, name, tmp);
+ Free(tmp);
+
+ return t;
+}
+
+// Add unicode_string type
+ITEM *CfgAddUniStr(FOLDER *f, char *name, wchar_t *str)
+{
+ // Validate arguments
+ if (f == NULL || name == NULL || str == NULL)
+ {
+ return NULL;
+ }
+
+ return CfgCreateItem(f, name, ITEM_TYPE_STRING, str, UniStrSize(str));
+}
+
+// Add a binary
+ITEM *CfgAddBuf(FOLDER *f, char *name, BUF *b)
+{
+ // Validate arguments
+ if (f == NULL || name == NULL || b == NULL)
+ {
+ return NULL;
+ }
+ return CfgAddByte(f, name, b->Buf, b->Size);
+}
+
+// Add byte type
+ITEM *CfgAddByte(FOLDER *f, char *name, void *buf, UINT size)
+{
+ // Validate arguments
+ if (f == NULL || name == NULL || buf == NULL)
+ {
+ return NULL;
+ }
+ return CfgCreateItem(f, name, ITEM_TYPE_BYTE, buf, size);
+}
+
+// Add a 64-bit integer type
+ITEM *CfgAddInt64(FOLDER *f, char *name, UINT64 i)
+{
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return NULL;
+ }
+ return CfgCreateItem(f, name, ITEM_TYPE_INT64, &i, sizeof(UINT64));
+}
+
+// Get an IP address type
+bool CfgGetIp(FOLDER *f, char *name, struct IP *ip)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (f == NULL || name == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ Zero(ip, sizeof(IP));
+
+ if (CfgGetStr(f, name, tmp, sizeof(tmp)) == false)
+ {
+ return false;
+ }
+
+ if (StrToIP(ip, tmp) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+UINT CfgGetIp32(FOLDER *f, char *name)
+{
+ IP p;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ if (CfgGetIp(f, name, &p) == false)
+ {
+ return 0;
+ }
+
+ return IPToUINT(&p);
+}
+bool CfgGetIp6Addr(FOLDER *f, char *name, IPV6_ADDR *addr)
+{
+ IP ip;
+ // Validate arguments
+ Zero(addr, sizeof(IPV6_ADDR));
+ if (f == NULL || name == NULL || addr == NULL)
+ {
+ return false;
+ }
+
+ if (CfgGetIp(f, name, &ip) == false)
+ {
+ return false;
+ }
+
+ if (IsIP6(&ip) == false)
+ {
+ return false;
+ }
+
+ if (IPToIPv6Addr(addr, &ip) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Add an IP address type
+ITEM *CfgAddIp(FOLDER *f, char *name, struct IP *ip)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (f == NULL || name == NULL || ip == NULL)
+ {
+ return NULL;
+ }
+
+ IPToStr(tmp, sizeof(tmp), ip);
+
+ return CfgAddStr(f, name, tmp);
+}
+ITEM *CfgAddIp32(FOLDER *f, char *name, UINT ip)
+{
+ IP p;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ UINTToIP(&p, ip);
+
+ return CfgAddIp(f, name, &p);
+}
+ITEM *CfgAddIp6Addr(FOLDER *f, char *name, IPV6_ADDR *addr)
+{
+ IP ip;
+ // Validate arguments
+ if (f == NULL || name == NULL || addr == NULL)
+ {
+ return NULL;
+ }
+
+ IPv6AddrToIP(&ip, addr);
+
+ return CfgAddIp(f, name, &ip);
+}
+
+// Add an integer type
+ITEM *CfgAddInt(FOLDER *f, char *name, UINT i)
+{
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return NULL;
+ }
+ return CfgCreateItem(f, name, ITEM_TYPE_INT, &i, sizeof(UINT));
+}
+
+// Adding a bool type
+ITEM *CfgAddBool(FOLDER *f, char *name, bool b)
+{
+ bool v;
+ // Validate arguments
+ if (f == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ v = b ? 1 : 0;
+ return CfgCreateItem(f, name, ITEM_TYPE_BOOL, &b, sizeof(bool));
+}
+
+// Comparison function of the item names
+int CmpItemName(void *p1, void *p2)
+{
+ ITEM *f1, *f2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ f1 = *(ITEM **)p1;
+ f2 = *(ITEM **)p2;
+ if (f1 == NULL || f2 == NULL)
+ {
+ return 0;
+ }
+ return StrCmpi(f1->Name, f2->Name);
+}
+
+// Comparison function of the folder names
+int CmpFolderName(void *p1, void *p2)
+{
+ FOLDER *f1, *f2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ f1 = *(FOLDER **)p1;
+ f2 = *(FOLDER **)p2;
+ if (f1 == NULL || f2 == NULL)
+ {
+ return 0;
+ }
+ return StrCmpi(f1->Name, f2->Name);
+}
+
+// Enumeration of items
+void CfgEnumItem(FOLDER *f, ENUM_ITEM proc, void *param)
+{
+ UINT i;
+ // Validate arguments
+ if (f == NULL || proc == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(f->Items);i++)
+ {
+ ITEM *tt = LIST_DATA(f->Items, i);
+ if (proc(tt, param) == false)
+ {
+ break;
+ }
+ }
+}
+
+// Enumerate the folders and store it in the token list
+TOKEN_LIST *CfgEnumFolderToTokenList(FOLDER *f)
+{
+ TOKEN_LIST *t, *ret;
+ UINT i;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(f->Folders);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ FOLDER *ff = LIST_DATA(f->Folders, i);
+ t->Token[i] = CopyStr(ff->Name);
+ }
+
+ ret = UniqueToken(t);
+ FreeToken(t);
+
+ return ret;
+}
+
+// Enumerate items and store these to the token list
+TOKEN_LIST *CfgEnumItemToTokenList(FOLDER *f)
+{
+ TOKEN_LIST *t, *ret;
+ UINT i;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(f->Items);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ FOLDER *ff = LIST_DATA(f->Items, i);
+ t->Token[i] = CopyStr(ff->Name);
+ }
+
+ ret = UniqueToken(t);
+ FreeToken(t);
+
+ return ret;
+}
+
+// Folder enumeration
+void CfgEnumFolder(FOLDER *f, ENUM_FOLDER proc, void *param)
+{
+ UINT i;
+ // Validate arguments
+ if (f == NULL || proc == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(f->Folders);i++)
+ {
+ FOLDER *ff = LIST_DATA(f->Folders, i);
+ if (proc(ff, param) == false)
+ {
+ break;
+ }
+
+ if ((i % 100) == 99)
+ {
+ YieldCpu();
+ }
+ }
+}
+
+// Create an item
+ITEM *CfgCreateItem(FOLDER *parent, char *name, UINT type, void *buf, UINT size)
+{
+ UINT name_size;
+ ITEM *t;
+#ifdef CHECK_CFG_NAME_EXISTS
+ ITEM tt;
+#endif // CHECK_CFG_NAME_EXISTS
+ // Validate arguments
+ if (parent == NULL || name == NULL || type == 0 || buf == NULL)
+ {
+ return NULL;
+ }
+
+ name_size = StrLen(name) + 1;
+
+#ifdef CHECK_CFG_NAME_EXISTS
+
+ // Check whether there are any items with the same name already
+ tt.Name = ZeroMalloc(name_size);
+ StrCpy(tt.Name, 0, name);
+ t = Search(parent->Items, &tt);
+ Free(tt.Name);
+ if (t != NULL)
+ {
+ // Duplicated
+ return NULL;
+ }
+
+#endif // CHECK_CFG_NAME_EXISTS
+
+ t = ZeroMalloc(sizeof(ITEM));
+ t->Buf = Malloc(size);
+ Copy(t->Buf, buf, size);
+ t->Name = ZeroMalloc(name_size);
+ StrCpy(t->Name, 0, name);
+ t->Type = type;
+ t->size = size;
+ t->Parent = parent;
+
+ // Add to the parent list
+ Insert(parent->Items, t);
+
+ return t;
+}
+
+// Delete the item
+void CfgDeleteItem(ITEM *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // Remove from the parent list
+ Delete(t->Parent->Items, t);
+
+ // Memory release
+ Free(t->Buf);
+ Free(t->Name);
+ Free(t);
+}
+
+
+// Delete the folder
+void CfgDeleteFolder(FOLDER *f)
+{
+ FOLDER **ff;
+ ITEM **tt;
+ UINT num, i;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ // Remove all subfolders
+ num = LIST_NUM(f->Folders);
+ ff = Malloc(sizeof(FOLDER *) * num);
+ Copy(ff, f->Folders->p, sizeof(FOLDER *) * num);
+ for (i = 0;i < num;i++)
+ {
+ CfgDeleteFolder(ff[i]);
+ }
+ Free(ff);
+
+ // Remove all items
+ num = LIST_NUM(f->Items);
+ tt = Malloc(sizeof(ITEM *) * num);
+ Copy(tt, f->Items->p, sizeof(ITEM *) * num);
+ for (i = 0;i < num;i++)
+ {
+ CfgDeleteItem(tt[i]);
+ }
+ Free(tt);
+
+ // Memory release
+ Free(f->Name);
+ // Remove from the parent list
+ if (f->Parent != NULL)
+ {
+ Delete(f->Parent->Folders, f);
+ }
+ // Release the list
+ ReleaseList(f->Folders);
+ ReleaseList(f->Items);
+
+ // Release of the memory of the body
+ Free(f);
+}
+
+// Creating a root
+FOLDER *CfgCreateRoot()
+{
+ return CfgCreateFolder(NULL, TAG_ROOT);
+}
+
+// Create a folder
+FOLDER *CfgCreateFolder(FOLDER *parent, char *name)
+{
+ UINT size;
+ FOLDER *f;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ size = StrLen(name) + 1;
+
+#ifdef CHECK_CFG_NAME_EXISTS
+
+ // Check the name in the parent list
+ if (parent != NULL)
+ {
+ FOLDER ff;
+ ff.Name = ZeroMalloc(size);
+ StrCpy(ff.Name, 0, name);
+ f = Search(parent->Folders, &ff);
+ Free(ff.Name);
+ if (f != NULL)
+ {
+ // Folder with the same name already exists
+ return NULL;
+ }
+ }
+
+#endif // CHECK_CFG_NAME_EXISTS
+
+ f = ZeroMalloc(sizeof(FOLDER));
+ f->Items = NewListFast(CmpItemName);
+ f->Folders = NewListFast(CmpFolderName);
+ f->Name = ZeroMalloc(size);
+ StrCpy(f->Name, 0, name);
+ f->Parent = parent;
+
+ // Add to parentlist
+ if (f->Parent != NULL)
+ {
+ Insert(f->Parent->Folders, f);
+ }
+ return f;
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Cfg.h b/src/Mayaqua/Cfg.h
new file mode 100644
index 00000000..da403ebc
--- /dev/null
+++ b/src/Mayaqua/Cfg.h
@@ -0,0 +1,249 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Cfg.h
+// Header of Cfg.c
+
+#ifndef CFG_H
+#define CFG_H
+
+// Macro
+//#define CHECK_CFG_NAME_EXISTS // Check duplication of the existing name
+
+#define SAVE_BINARY_FILE_NAME_SWITCH L"@save_binary"
+
+// Constants
+#define TAG_DECLARE "declare"
+#define TAG_STRING "string"
+#define TAG_INT "uint"
+#define TAG_INT64 "uint64"
+#define TAG_BOOL "bool"
+#define TAG_BYTE "byte"
+#define TAG_TRUE "true"
+#define TAG_FALSE "false"
+#define TAG_END "end"
+#define TAG_ROOT "root"
+
+#define TAG_CPYRIGHT "\xef\xbb\xbf# Software Configuration File\r\n# \r\n# You can edit this file when the program is not working.\r\n# \r\n"
+#define TAG_BINARY "SEVPN_DB"
+
+// Data type
+#define ITEM_TYPE_INT 1 // int
+#define ITEM_TYPE_INT64 2 // int64
+#define ITEM_TYPE_BYTE 3 // byte
+#define ITEM_TYPE_STRING 4 // string
+#define ITEM_TYPE_BOOL 5 // bool
+
+// Folder
+struct FOLDER
+{
+ char *Name; // Folder name
+ LIST *Items; // List of items
+ LIST *Folders; // Subfolder
+ struct FOLDER *Parent; // Parent Folder
+};
+
+// Item
+struct ITEM
+{
+ char *Name; // Item Name
+ UINT Type; // Data type
+ void *Buf; // Data
+ UINT size; // Data size
+ FOLDER *Parent; // Parent Folder
+};
+
+// Configuration file reader and writer
+struct CFG_RW
+{
+ LOCK *lock; // Lock
+ char *FileName; // File name (ANSI)
+ wchar_t *FileNameW; // File name (Unicode)
+ IO *Io; // IO
+ UCHAR LashHash[SHA1_SIZE]; // Hash value which is written last
+ bool DontBackup; // Do not use the backup
+ wchar_t LastSavedDateStr[MAX_SIZE]; // Date and time string that last saved
+};
+
+typedef bool (*ENUM_FOLDER)(FOLDER *f, void *param);
+typedef bool (*ENUM_ITEM)(ITEM *t, void *param);
+
+// Parameters for the enumeration
+struct CFG_ENUM_PARAM
+{
+ BUF *b;
+ FOLDER *f;
+ UINT depth;
+};
+
+int CmpItemName(void *p1, void *p2);
+int CmpFolderName(void *p1, void *p2);
+ITEM *CfgCreateItem(FOLDER *parent, char *name, UINT type, void *buf, UINT size);
+void CfgDeleteFolder(FOLDER *f);
+FOLDER *CfgCreateFolder(FOLDER *parent, char *name);
+void CfgEnumFolder(FOLDER *f, ENUM_FOLDER proc, void *param);
+TOKEN_LIST *CfgEnumFolderToTokenList(FOLDER *f);
+TOKEN_LIST *CfgEnumItemToTokenList(FOLDER *f);
+void CfgEnumItem(FOLDER *f, ENUM_ITEM proc, void *param);
+FOLDER *CfgFindFolder(FOLDER *parent, char *name);
+ITEM *CfgFindItem(FOLDER *parent, char *name);
+ITEM *CfgAddInt(FOLDER *f, char *name, UINT i);
+ITEM *CfgAddBool(FOLDER *f, char *name, bool b);
+ITEM *CfgAddInt64(FOLDER *f, char *name, UINT64 i);
+ITEM *CfgAddByte(FOLDER *f, char *name, void *buf, UINT size);
+ITEM *CfgAddBuf(FOLDER *f, char *name, BUF *b);
+ITEM *CfgAddStr(FOLDER *f, char *name, char *str);
+ITEM *CfgAddUniStr(FOLDER *f, char *name, wchar_t *str);
+FOLDER *CfgGetFolder(FOLDER *parent, char *name);
+UINT CfgGetInt(FOLDER *f, char *name);
+bool CfgGetBool(FOLDER *f, char *name);
+UINT64 CfgGetInt64(FOLDER *f, char *name);
+UINT CfgGetByte(FOLDER *f, char *name, void *buf, UINT size);
+BUF *CfgGetBuf(FOLDER *f, char *name);
+bool CfgGetStr(FOLDER *f, char *name, char *str, UINT size);
+bool CfgGetUniStr(FOLDER *f, char *name, wchar_t *str, UINT size);
+bool CfgIsItem(FOLDER *f, char *name);
+bool CfgIsFolder(FOLDER *f, char *name);
+void CfgTest();
+void CfgTest2(FOLDER *f, UINT n);
+char *CfgEscape(char *name);
+bool CfgCheckCharForName(char c);
+char *CfgUnescape(char *str);
+BUF *CfgFolderToBuf(FOLDER *f, bool textmode);
+BUF *CfgFolderToBufEx(FOLDER *f, bool textmode, bool no_banner);
+BUF *CfgFolderToBufText(FOLDER *f);
+BUF *CfgFolderToBufTextEx(FOLDER *f, bool no_banner);
+BUF *CfgFolderToBufBin(FOLDER *f);
+void CfgOutputFolderText(BUF *b, FOLDER *f, UINT depth);
+void CfgOutputFolderBin(BUF *b, FOLDER *f);
+void CfgAddLine(BUF *b, char *str, UINT depth);
+void CfgAddDeclare(BUF *b, char *name, UINT depth);
+void CfgAddEnd(BUF *b, UINT depth);
+void CfgAddData(BUF *b, UINT type, char *name, char *data, char *sub, UINT depth);
+UINT CfgStrToType(char *str);
+char *CfgTypeToStr(UINT type);
+void CfgAddItemText(BUF *b, ITEM *t, UINT depth);
+bool CfgEnumFolderProc(FOLDER *f, void *param);
+bool CfgEnumItemProc(ITEM *t, void *param);
+FOLDER *CfgBufTextToFolder(BUF *b);
+FOLDER *CfgBufBinToFolder(BUF *b);
+void CfgReadNextFolderBin(BUF *b, FOLDER *parent);
+char *CfgReadNextLine(BUF *b);
+bool CfgReadNextTextBuf(BUF *b, FOLDER *current);
+void CfgSave(FOLDER *f, char *name);
+void CfgSaveW(FOLDER *f, wchar_t *name);
+bool CfgSaveEx(CFG_RW *rw, FOLDER *f, char *name);
+bool CfgSaveExW(CFG_RW *rw, FOLDER *f, wchar_t *name);
+bool CfgSaveExW2(CFG_RW *rw, FOLDER *f, wchar_t *name, UINT *written_size);
+bool CfgSaveExW3(CFG_RW *rw, FOLDER *f, wchar_t *name, UINT *written_size, bool write_binary);
+FOLDER *CfgRead(char *name);
+FOLDER *CfgReadW(wchar_t *name);
+FOLDER *CfgCreateRoot();
+void CfgTest();
+void CfgTest2(FOLDER *f, UINT n);
+CFG_RW *NewCfgRw(FOLDER **root, char *cfg_name);
+CFG_RW *NewCfgRwW(FOLDER **root, wchar_t *cfg_name);
+CFG_RW *NewCfgRwEx(FOLDER **root, char *cfg_name, bool dont_backup);
+CFG_RW *NewCfgRwExW(FOLDER **root, wchar_t *cfg_name, bool dont_backup);
+UINT SaveCfgRw(CFG_RW *rw, FOLDER *f);
+UINT SaveCfgRwEx(CFG_RW *rw, FOLDER *f, UINT revision_number);
+void FreeCfgRw(CFG_RW *rw);
+ITEM *CfgAddIp32(FOLDER *f, char *name, UINT ip);
+UINT CfgGetIp32(FOLDER *f, char *name);
+bool CfgGetIp6Addr(FOLDER *f, char *name, IPV6_ADDR *addr);
+ITEM *CfgAddIp6Addr(FOLDER *f, char *name, IPV6_ADDR *addr);
+bool FileCopy(char *src, char *dst);
+bool FileCopyW(wchar_t *src, wchar_t *dst);
+bool FileCopyExW(wchar_t *src, wchar_t *dst, bool read_lock);
+void BackupCfgWEx(CFG_RW *rw, FOLDER *f, wchar_t *original, UINT revision_number);
+
+#if (!defined(CFG_C)) || (!defined(OS_UNIX))
+bool CfgGetIp(FOLDER *f, char *name, struct IP *ip);
+ITEM *CfgAddIp(FOLDER *f, char *name, struct IP *ip);
+#endif
+
+#endif // CFG_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Encrypt.c b/src/Mayaqua/Encrypt.c
new file mode 100644
index 00000000..5c6e32e5
--- /dev/null
+++ b/src/Mayaqua/Encrypt.c
@@ -0,0 +1,4691 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Encrypt.c
+// Encryption and digital certification routine
+
+#include <GlobalConst.h>
+
+#define ENCRYPT_C
+
+#define __WINCRYPT_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/engine.h>
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs7.h>
+#include <openssl/pkcs12.h>
+#include <openssl/rc4.h>
+#include <openssl/md5.h>
+#include <openssl/md4.h>
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+#include <openssl/des.h>
+#include <openssl/aes.h>
+#include <openssl/dh.h>
+#include <openssl/pem.h>
+#include <Mayaqua/Mayaqua.h>
+
+#ifdef USE_INTEL_AESNI_LIBRARY
+#include <intelaes/iaesni.h>
+#endif // USE_INTEL_AESNI_LIBRARY
+
+LOCK *openssl_lock = NULL;
+
+LOCK **ssl_lock_obj = NULL;
+UINT ssl_lock_num;
+static bool openssl_inited = false;
+static bool is_intel_aes_supported = false;
+
+// For the callback function
+typedef struct CB_PARAM
+{
+ char *password;
+} CB_PARAM;
+
+// Copied from t1_enc.c of OpenSSL
+#define HMAC_Init_ex(ctx,sec,len,md,impl) HMAC_Init(ctx, sec, len, md)
+#define HMAC_CTX_cleanup(ctx) HMAC_cleanup(ctx)
+void Enc_tls1_P_hash(const EVP_MD *md, const unsigned char *sec, int sec_len,
+ const unsigned char *seed, int seed_len, unsigned char *out, int olen)
+{
+ int chunk,n;
+ unsigned int j;
+ HMAC_CTX ctx;
+ HMAC_CTX ctx_tmp;
+ unsigned char A1[EVP_MAX_MD_SIZE];
+ unsigned int A1_len;
+
+ chunk=EVP_MD_size(md);
+
+ Zero(&ctx, sizeof(ctx));
+ Zero(&ctx_tmp, sizeof(ctx_tmp));
+ HMAC_Init_ex(&ctx,sec,sec_len,md, NULL);
+ HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL);
+ HMAC_Update(&ctx,seed,seed_len);
+ HMAC_Final(&ctx,A1,&A1_len);
+
+ n=0;
+ for (;;)
+ {
+ HMAC_Init_ex(&ctx,NULL,0,NULL,NULL); /* re-init */
+ HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL); /* re-init */
+ HMAC_Update(&ctx,A1,A1_len);
+ HMAC_Update(&ctx_tmp,A1,A1_len);
+ HMAC_Update(&ctx,seed,seed_len);
+
+ if (olen > chunk)
+ {
+ HMAC_Final(&ctx,out,&j);
+ out+=j;
+ olen-=j;
+ HMAC_Final(&ctx_tmp,A1,&A1_len); /* calc the next A1 value */
+ }
+ else /* last one */
+ {
+ HMAC_Final(&ctx,A1,&A1_len);
+ memcpy(out,A1,olen);
+ break;
+ }
+ }
+ HMAC_CTX_cleanup(&ctx);
+ HMAC_CTX_cleanup(&ctx_tmp);
+ Zero (A1, sizeof(A1));
+}
+
+void Enc_tls1_PRF(unsigned char *label, int label_len, const unsigned char *sec,
+ int slen, unsigned char *out1, int olen)
+{
+ const EVP_MD *md5 = EVP_md5();
+ const EVP_MD *sha1 = EVP_sha1();
+ int len,i;
+ const unsigned char *S1,*S2;
+ unsigned char *out2;
+
+ out2 = (unsigned char *) Malloc (olen);
+
+ len=slen/2;
+ S1=sec;
+ S2= &(sec[len]);
+ len+=(slen&1); /* add for odd, make longer */
+
+
+ Enc_tls1_P_hash(md5 ,S1,len,label,label_len,out1,olen);
+ Enc_tls1_P_hash(sha1,S2,len,label,label_len,out2,olen);
+
+ for (i=0; i<olen; i++)
+ out1[i]^=out2[i];
+
+ memset (out2, 0, olen);
+ Free(out2);
+}
+
+// Calculation of HMAC (MD5)
+void HMacMd5(void *dst, void *key, UINT key_size, void *data, UINT data_size)
+{
+ UCHAR k[HMAC_BLOCK_SIZE];
+ UCHAR hash1[MD5_SIZE];
+ UCHAR data2[HMAC_BLOCK_SIZE];
+ MD5_CTX md5_ctx1;
+ UCHAR pad1[HMAC_BLOCK_SIZE];
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || (key == NULL && key_size != 0) || (data == NULL && data_size != 0))
+ {
+ return;
+ }
+
+ // Creating a K
+ if (key_size <= HMAC_BLOCK_SIZE)
+ {
+ for (i = 0;i < key_size;i++)
+ {
+ pad1[i] = ((UCHAR *)key)[i] ^ 0x36;
+ }
+ for (i = key_size;i < HMAC_BLOCK_SIZE;i++)
+ {
+ pad1[i] = 0 ^ 0x36;
+ }
+ }
+ else
+ {
+ Zero(k, sizeof(k));
+ Hash(k, key, key_size, false);
+
+ for (i = 0;i < HMAC_BLOCK_SIZE;i++)
+ {
+ pad1[i] = k[i] ^ 0x36;
+ }
+ }
+
+ MD5_Init(&md5_ctx1);
+ MD5_Update(&md5_ctx1, pad1, sizeof(pad1));
+ MD5_Update(&md5_ctx1, data, data_size);
+ MD5_Final(hash1, &md5_ctx1);
+
+ // Generation of data 2
+ if (key_size <= HMAC_BLOCK_SIZE)
+ {
+ for (i = 0;i < key_size;i++)
+ {
+ data2[i] = ((UCHAR *)key)[i] ^ 0x5c;
+ }
+ for (i = key_size;i < HMAC_BLOCK_SIZE;i++)
+ {
+ data2[i] = 0 ^ 0x5c;
+ }
+ }
+ else
+ {
+ for (i = 0;i < HMAC_BLOCK_SIZE;i++)
+ {
+ data2[i] = k[i] ^ 0x5c;
+ }
+ }
+
+ MD5_Init(&md5_ctx1);
+ MD5_Update(&md5_ctx1, data2, HMAC_BLOCK_SIZE);
+ MD5_Update(&md5_ctx1, hash1, MD5_SIZE);
+ MD5_Final(dst, &md5_ctx1);
+}
+
+// Calculation of HMAC (SHA-1)
+void HMacSha1(void *dst, void *key, UINT key_size, void *data, UINT data_size)
+{
+ UCHAR k[HMAC_BLOCK_SIZE];
+ UCHAR hash1[SHA1_SIZE];
+ UCHAR data2[HMAC_BLOCK_SIZE];
+ SHA_CTX sha_ctx1;
+ UCHAR pad1[HMAC_BLOCK_SIZE];
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || (key == NULL && key_size != 0) || (data == NULL && data_size != 0))
+ {
+ return;
+ }
+
+ // Creating a K
+ if (key_size <= HMAC_BLOCK_SIZE)
+ {
+ for (i = 0;i < key_size;i++)
+ {
+ pad1[i] = ((UCHAR *)key)[i] ^ 0x36;
+ }
+ for (i = key_size;i < HMAC_BLOCK_SIZE;i++)
+ {
+ pad1[i] = 0 ^ 0x36;
+ }
+ }
+ else
+ {
+ Zero(k, sizeof(k));
+ HashSha1(k, key, key_size);
+
+ for (i = 0;i < HMAC_BLOCK_SIZE;i++)
+ {
+ pad1[i] = k[i] ^ 0x36;
+ }
+ }
+
+ SHA1_Init(&sha_ctx1);
+ SHA1_Update(&sha_ctx1, pad1, sizeof(pad1));
+ SHA1_Update(&sha_ctx1, data, data_size);
+ SHA1_Final(hash1, &sha_ctx1);
+
+ // Generation of data 2
+ if (key_size <= HMAC_BLOCK_SIZE)
+ {
+ for (i = 0;i < key_size;i++)
+ {
+ data2[i] = ((UCHAR *)key)[i] ^ 0x5c;
+ }
+ for (i = key_size;i < HMAC_BLOCK_SIZE;i++)
+ {
+ data2[i] = 0 ^ 0x5c;
+ }
+ }
+ else
+ {
+ for (i = 0;i < HMAC_BLOCK_SIZE;i++)
+ {
+ data2[i] = k[i] ^ 0x5c;
+ }
+ }
+
+ SHA1_Init(&sha_ctx1);
+ SHA1_Update(&sha_ctx1, data2, HMAC_BLOCK_SIZE);
+ SHA1_Update(&sha_ctx1, hash1, SHA1_SIZE);
+ SHA1_Final(dst, &sha_ctx1);
+}
+
+// Calculate the HMAC
+void MdProcess(MD *md, void *dest, void *src, UINT size)
+{
+ int r;
+ // Validate arguments
+ if (md == NULL || dest == NULL || (src != NULL && size == 0))
+ {
+ return;
+ }
+
+ HMAC_Init(md->Ctx, NULL, 0, NULL);
+ HMAC_Update(md->Ctx, src, size);
+
+ r = 0;
+ HMAC_Final(md->Ctx, dest, &r);
+}
+
+// Set the key to the message digest object
+void SetMdKey(MD *md, void *key, UINT key_size)
+{
+ // Validate arguments
+ if (md == NULL || (key != NULL && key_size == 0))
+ {
+ return;
+ }
+
+ HMAC_Init(md->Ctx, key, key_size, md->Md);
+}
+
+// Creating a message digest object
+MD *NewMd(char *name)
+{
+ MD *m;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ m = ZeroMalloc(sizeof(MD));
+
+ StrCpy(m->Name, sizeof(m->Name), name);
+ m->Md = EVP_get_digestbyname(name);
+ if (m->Md == NULL)
+ {
+ FreeMd(m);
+ return NULL;
+ }
+
+ m->Ctx = ZeroMalloc(sizeof(struct hmac_ctx_st));
+ HMAC_CTX_init(m->Ctx);
+
+ m->Size = EVP_MD_size(m->Md);
+
+ return m;
+}
+
+// Release of the message digest object
+void FreeMd(MD *md)
+{
+ // Validate arguments
+ if (md == NULL)
+ {
+ return;
+ }
+
+ if (md->Ctx != NULL)
+ {
+ HMAC_CTX_cleanup(md->Ctx);
+ Free(md->Ctx);
+ }
+
+ Free(md);
+}
+
+// Creating a cipher object
+CIPHER *NewCipher(char *name)
+{
+ CIPHER *c;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ c = ZeroMalloc(sizeof(CIPHER));
+
+ StrCpy(c->Name, sizeof(c->Name), name);
+
+ if (StrCmpi(name, "[null-cipher]") == 0 ||
+ StrCmpi(name, "NULL") == 0 ||
+ IsEmptyStr(name))
+ {
+ c->IsNullCipher = true;
+ return c;
+ }
+
+ c->Cipher = EVP_get_cipherbyname(c->Name);
+ if (c->Cipher == NULL)
+ {
+ FreeCipher(c);
+ return NULL;
+ }
+
+ c->Ctx = ZeroMalloc(sizeof(struct evp_cipher_ctx_st));
+ EVP_CIPHER_CTX_init(c->Ctx);
+
+ c->BlockSize = EVP_CIPHER_block_size(c->Cipher);
+ c->KeySize = EVP_CIPHER_key_length(c->Cipher);
+ c->IvSize = EVP_CIPHER_iv_length(c->Cipher);
+
+ return c;
+}
+
+// Set the key to the cipher object
+void SetCipherKey(CIPHER *c, void *key, bool enc)
+{
+ // Validate arguments
+ if (c == NULL || key == NULL)
+ {
+ return;
+ }
+
+ if (c->IsNullCipher == false)
+ {
+ if (c->Ctx != NULL)
+ {
+ EVP_CipherInit(c->Ctx, c->Cipher, key, NULL, enc);
+ }
+ }
+
+ c->Encrypt = enc;
+}
+
+// Process encryption / decryption
+UINT CipherProcess(CIPHER *c, void *iv, void *dest, void *src, UINT size)
+{
+ int r = size;
+ int r2 = 0;
+ if (c != NULL && c->IsNullCipher)
+ {
+ if (dest != src)
+ {
+ Copy(dest, src, size);
+ }
+ return size;
+ }
+ // Validate arguments
+ if (c == NULL || iv == NULL || dest == NULL || src == NULL || size == 0)
+ {
+ return 0;
+ }
+
+ if (EVP_CipherInit(c->Ctx, NULL, NULL, iv, c->Encrypt) == 0)
+ {
+ return 0;
+ }
+
+ if (EVP_CipherUpdate(c->Ctx, dest, &r, src, size) == 0)
+ {
+ return 0;
+ }
+
+ if (EVP_CipherFinal(c->Ctx, ((UCHAR *)dest) + (UINT)r, &r2) == 0)
+ {
+ return 0;
+ }
+
+ return r + r2;
+}
+
+// Release of the cipher object
+void FreeCipher(CIPHER *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (c->Ctx != NULL)
+ {
+ EVP_CIPHER_CTX_cleanup(c->Ctx);
+ Free(c->Ctx);
+ }
+
+ Free(c);
+}
+
+// Verify whether the certificate is disabled by CRL in a particular directory
+bool IsXRevoked(X *x)
+{
+ char dirname[MAX_PATH];
+ UINT i;
+ bool ret = false;
+ DIRLIST *t;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return false;
+ }
+
+ GetExeDir(dirname, sizeof(dirname));
+
+ // Search the CRL file
+ t = EnumDir(dirname);
+
+ for (i = 0;i < t->NumFiles;i++)
+ {
+ char *name = t->File[i]->FileName;
+ if (t->File[i]->Folder == false)
+ {
+ if (EndWith(name, ".crl"))
+ {
+ char filename[MAX_PATH];
+ X_CRL *r;
+
+ ConbinePath(filename, sizeof(filename), dirname, name);
+
+ r = FileToXCrl(filename);
+
+ if (r != NULL)
+ {
+ if (IsXRevokedByXCrl(x, r))
+ {
+ ret = true;
+ }
+
+ FreeXCrl(r);
+ }
+ }
+ }
+ }
+
+ FreeDir(t);
+
+ return ret;
+}
+
+// Verify whether the certificate is disabled by the CRL
+bool IsXRevokedByXCrl(X *x, X_CRL *r)
+{
+#ifdef OS_WIN32
+ X509_REVOKED tmp;
+ X509_CRL_INFO *info;
+ int index;
+ // Validate arguments
+ if (x == NULL || r == NULL)
+ {
+ return false;
+ }
+
+ Zero(&tmp, sizeof(tmp));
+ tmp.serialNumber = X509_get_serialNumber(x->x509);
+
+ info = r->Crl->crl;
+
+ if (sk_X509_REVOKED_is_sorted(info->revoked) == false)
+ {
+ sk_X509_REVOKED_sort(info->revoked);
+ }
+
+ index = sk_X509_REVOKED_find(info->revoked, &tmp);
+
+ if (index < 0)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+#else // OS_WIN32
+ return false;
+#endif // OS_WIN32
+}
+
+// Release of the CRL
+void FreeXCrl(X_CRL *r)
+{
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ X509_CRL_free(r->Crl);
+
+ Free(r);
+}
+
+// Convert a file to a CRL
+X_CRL *FileToXCrl(char *filename)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ X_CRL *ret = FileToXCrlW(filename_w);
+
+ Free(filename_w);
+
+ return ret;
+}
+X_CRL *FileToXCrlW(wchar_t *filename)
+{
+ BUF *b;
+ X_CRL *r;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ b = ReadDumpW(filename);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ r = BufToXCrl(b);
+
+ FreeBuf(b);
+
+ return r;
+}
+
+// Convert the buffer to the CRL
+X_CRL *BufToXCrl(BUF *b)
+{
+ X_CRL *r;
+ X509_CRL *x509crl;
+ BIO *bio;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ bio = BufToBio(b);
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ x509crl = NULL;
+
+ if (d2i_X509_CRL_bio(bio, &x509crl) == NULL || x509crl == NULL)
+ {
+ FreeBio(bio);
+ return NULL;
+ }
+
+ r = ZeroMalloc(sizeof(X_CRL));
+ r->Crl = x509crl;
+
+ FreeBio(bio);
+
+ return r;
+}
+
+// Convert the buffer to the public key
+K *RsaBinToPublic(void *data, UINT size)
+{
+ RSA *rsa;
+ K *k;
+ BIO *bio;
+ // Validate arguments
+ if (data == NULL || size < 4)
+ {
+ return NULL;
+ }
+
+ rsa = RSA_new();
+
+ if (rsa->e != NULL)
+ {
+ BN_free(rsa->e);
+ }
+
+ rsa->e = BN_new();
+ BN_set_word(rsa->e, RSA_F4);
+
+ if (rsa->n != NULL)
+ {
+ BN_free(rsa->n);
+ }
+
+ rsa->n = BinToBigNum(data, size);
+
+ bio = NewBio();
+ Lock(openssl_lock);
+ {
+ i2d_RSA_PUBKEY_bio(bio, rsa);
+ }
+ Unlock(openssl_lock);
+ BIO_seek(bio, 0);
+ k = BioToK(bio, false, false, NULL);
+ FreeBio(bio);
+
+ RSA_free(rsa);
+
+ return k;
+}
+
+// Convert the public key to a buffer
+BUF *RsaPublicToBuf(K *k)
+{
+ BUF *b;
+ // Validate arguments
+ if (k == NULL || k->pkey == NULL || k->pkey->pkey.rsa == NULL
+ || k->pkey->pkey.rsa->n == NULL)
+ {
+ return NULL;
+ }
+
+ b = BigNumToBuf(k->pkey->pkey.rsa->n);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ return b;
+}
+
+// Convert the public key to a binary
+void RsaPublicToBin(K *k, void *data)
+{
+ BUF *b;
+ // Validate arguments
+ if (k == NULL || k->pkey == NULL || k->pkey->pkey.rsa == NULL
+ || k->pkey->pkey.rsa->n == NULL || data == NULL)
+ {
+ return;
+ }
+
+ b = BigNumToBuf(k->pkey->pkey.rsa->n);
+ if (b == NULL)
+ {
+ return;
+ }
+
+ Copy(data, b->Buf, b->Size);
+
+ FreeBuf(b);
+}
+
+// Get public key size
+UINT RsaPublicSize(K *k)
+{
+ BUF *b;
+ UINT ret;
+ // Validate arguments
+ if (k == NULL || k->pkey == NULL || k->pkey->pkey.rsa == NULL
+ || k->pkey->pkey.rsa->n == NULL)
+ {
+ return 0;
+ }
+
+ b = BigNumToBuf(k->pkey->pkey.rsa->n);
+ if (b == NULL)
+ {
+ return 0;
+ }
+
+ ret = b->Size;
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Stupid test
+void CertTest2()
+{
+}
+
+// Yagi test
+void CertTest()
+{
+}
+
+// Test function related to certificate
+void CertTest_()
+{
+}
+
+// Hash a pointer to a 32-bit
+UINT HashPtrToUINT(void *p)
+{
+ UCHAR hash_data[MD5_SIZE];
+ UINT ret;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return 0;
+ }
+
+ Hash(hash_data, &p, sizeof(p), false);
+
+ Copy(&ret, hash_data, sizeof(ret));
+
+ return ret;
+}
+
+// Copy of the NAME
+NAME *CopyName(NAME *n)
+{
+ // Validate arguments
+ if (n == NULL)
+ {
+ return NULL;
+ }
+
+ return NewName(n->CommonName, n->Organization, n->Unit,
+ n->Country, n->State, n->Local);
+}
+
+// Convert a BIGNUM to a string
+char *BigNumToStr(BIGNUM *bn)
+{
+ BIO *bio;
+ BUF *b;
+ char *ret;
+ // Validate arguments
+ if (bn == NULL)
+ {
+ return NULL;
+ }
+
+ bio = NewBio();
+
+ BN_print(bio, bn);
+
+ b = BioToBuf(bio);
+
+ FreeBio(bio);
+
+ ret = ZeroMalloc(b->Size + 1);
+ Copy(ret, b->Buf, b->Size);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Convert the binary to the BIGNUM
+BIGNUM *BinToBigNum(void *data, UINT size)
+{
+ BIGNUM *bn;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ bn = BN_new();
+ BN_bin2bn(data, size, bn);
+
+ return bn;
+}
+
+// Convert the buffer to a BIGNUM
+BIGNUM *BufToBigNum(BUF *b)
+{
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ return BinToBigNum(b->Buf, b->Size);
+}
+
+// Convert a BIGNUM to a buffer
+BUF *BigNumToBuf(BIGNUM *bn)
+{
+ UINT size;
+ UCHAR *tmp;
+ BUF *b;
+ // Validate arguments
+ if (bn == NULL)
+ {
+ return NULL;
+ }
+
+ size = BN_num_bytes(bn);
+ tmp = ZeroMalloc(size);
+ BN_bn2bin(bn, tmp);
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size);
+ Free(tmp);
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Initialization of the lock of OpenSSL
+void OpenSSL_InitLock()
+{
+ UINT i;
+
+ // Initialization of the lock object
+ ssl_lock_num = CRYPTO_num_locks();
+ ssl_lock_obj = Malloc(sizeof(LOCK *) * ssl_lock_num);
+ for (i = 0;i < ssl_lock_num;i++)
+ {
+ ssl_lock_obj[i] = NewLock();
+ }
+
+ // Setting the lock function
+ CRYPTO_set_locking_callback(OpenSSL_Lock);
+ CRYPTO_set_id_callback(OpenSSL_Id);
+}
+
+// Release of the lock of OpenSSL
+void OpenSSL_FreeLock()
+{
+ UINT i;
+
+ for (i = 0;i < ssl_lock_num;i++)
+ {
+ DeleteLock(ssl_lock_obj[i]);
+ }
+ Free(ssl_lock_obj);
+ ssl_lock_obj = NULL;
+
+ CRYPTO_set_locking_callback(NULL);
+ CRYPTO_set_id_callback(NULL);
+}
+
+// Lock function for OpenSSL
+void OpenSSL_Lock(int mode, int n, const char *file, int line)
+{
+ LOCK *lock = ssl_lock_obj[n];
+
+ if (mode & CRYPTO_LOCK)
+ {
+ // Lock
+ Lock(lock);
+ }
+ else
+ {
+ // Unlock
+ Unlock(lock);
+ }
+}
+
+// Return the thread ID
+unsigned long OpenSSL_Id(void)
+{
+ return (unsigned long)ThreadId();
+}
+
+// Get the display name of the certificate
+void GetPrintNameFromX(wchar_t *str, UINT size, X *x)
+{
+ // Validate arguments
+ if (x == NULL || str == NULL)
+ {
+ return;
+ }
+
+ GetPrintNameFromName(str, size, x->subject_name);
+}
+void GetPrintNameFromXA(char *str, UINT size, X *x)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL || x == NULL)
+ {
+ return;
+ }
+
+ GetPrintNameFromX(tmp, sizeof(tmp), x);
+
+ UniToStr(str, size, tmp);
+}
+void GetAllNameFromXEx(wchar_t *str, UINT size, X *x)
+{
+ // Validate arguments
+ if (x == NULL || str == NULL)
+ {
+ return;
+ }
+
+ GetAllNameFromNameEx(str, size, x->subject_name);
+}
+void GetAllNameFromXExA(char *str, UINT size, X *x)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL || x == NULL)
+ {
+ return;
+ }
+
+ GetAllNameFromXEx(tmp, sizeof(tmp), x);
+
+ UniToStr(str, size, tmp);
+}
+
+// Get the display name from NAME
+void GetPrintNameFromName(wchar_t *str, UINT size, NAME *name)
+{
+ // Validate arguments
+ if (str == NULL || name == NULL)
+ {
+ return;
+ }
+
+ if (name->CommonName != NULL)
+ {
+ UniStrCpy(str, size, name->CommonName);
+ }
+ else if (name->Organization != NULL)
+ {
+ UniStrCpy(str, size, name->Organization);
+ }
+ else if (name->Unit != NULL)
+ {
+ UniStrCpy(str, size, name->Unit);
+ }
+ else if (name->State != NULL)
+ {
+ UniStrCpy(str, size, name->State);
+ }
+ else if (name->Local != NULL)
+ {
+ UniStrCpy(str, size, name->Local);
+ }
+ else if (name->Country != NULL)
+ {
+ UniStrCpy(str, size, name->Country);
+ }
+ else
+ {
+ UniStrCpy(str, size, L"untitled");
+ }
+}
+
+// Get all the name strings from the certificate
+void GetAllNameFromX(wchar_t *str, UINT size, X *x)
+{
+ UCHAR md5[MD5_SIZE], sha1[SHA1_SIZE];
+ char tmp1[MD5_SIZE * 3 + 8], tmp2[SHA1_SIZE * 3 + 8];
+ wchar_t tmp3[sizeof(tmp1) + sizeof(tmp2) + 64];
+ // Validate arguments
+ if (str == NULL || x == NULL)
+ {
+ return;
+ }
+
+ GetAllNameFromName(str, size, x->subject_name);
+
+ if (x->serial != NULL && x->serial->size >= 1)
+ {
+ char tmp[128];
+ wchar_t tmp2[128];
+
+ BinToStr(tmp, sizeof(tmp), x->serial->data, x->serial->size);
+ UniFormat(tmp2, sizeof(tmp2), L", SERIAL=\"%S\"", tmp);
+
+ UniStrCat(str, size, tmp2);
+ }
+
+ // Digest value
+ GetXDigest(x, md5, false);
+ GetXDigest(x, sha1, true);
+
+ BinToStr(tmp1, sizeof(tmp1), md5, MD5_SIZE);
+ BinToStr(tmp2, sizeof(tmp2), sha1, SHA1_SIZE);
+
+ UniFormat(tmp3, sizeof(tmp3), L" (Digest: MD5=\"%S\", SHA1=\"%S\")", tmp1, tmp2);
+ UniStrCat(str, size, tmp3);
+}
+void GetAllNameFromA(char *str, UINT size, X *x)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL || x == NULL)
+ {
+ return;
+ }
+
+ GetAllNameFromX(tmp, sizeof(tmp), x);
+ UniToStr(str, size, tmp);
+}
+
+// Get the all name strings from NAME
+void GetAllNameFromName(wchar_t *str, UINT size, NAME *name)
+{
+ // Validate arguments
+ if (str == NULL || name == NULL)
+ {
+ return;
+ }
+
+ UniStrCpy(str, size, L"");
+ if (name->CommonName != NULL)
+ {
+ UniFormat(str, size, L"%sCN=%s, ", str, name->CommonName);
+ }
+ if (name->Organization != NULL)
+ {
+ UniFormat(str, size, L"%sO=%s, ", str, name->Organization);
+ }
+ if (name->Unit != NULL)
+ {
+ UniFormat(str, size, L"%sOU=%s, ", str, name->Unit);
+ }
+ if (name->State != NULL)
+ {
+ UniFormat(str, size, L"%sS=%s, ", str, name->State);
+ }
+ if (name->Local != NULL)
+ {
+ UniFormat(str, size, L"%sL=%s, ", str, name->Local);
+ }
+ if (name->Country != NULL)
+ {
+ UniFormat(str, size, L"%sC=%s, ", str, name->Country);
+ }
+
+ if (UniStrLen(str) >= 3)
+ {
+ UINT len = UniStrLen(str);
+ if (str[len - 2] == L',' &&
+ str[len - 1] == L' ')
+ {
+ str[len - 2] = 0;
+ }
+ }
+}
+void GetAllNameFromNameEx(wchar_t *str, UINT size, NAME *name)
+{
+ // Validate arguments
+ if (str == NULL || name == NULL)
+ {
+ return;
+ }
+
+ UniStrCpy(str, size, L"");
+ if (name->CommonName != NULL)
+ {
+ UniFormat(str, size, L"%s%s, ", str, name->CommonName);
+ }
+ if (name->Organization != NULL)
+ {
+ UniFormat(str, size, L"%s%s, ", str, name->Organization);
+ }
+ if (name->Unit != NULL)
+ {
+ UniFormat(str, size, L"%s%s, ", str, name->Unit);
+ }
+ if (name->State != NULL)
+ {
+ UniFormat(str, size, L"%s%s, ", str, name->State);
+ }
+ if (name->Local != NULL)
+ {
+ UniFormat(str, size, L"%s%s, ", str, name->Local);
+ }
+ if (name->Country != NULL)
+ {
+ UniFormat(str, size, L"%s%s, ", str, name->Country);
+ }
+
+ if (UniStrLen(str) >= 3)
+ {
+ UINT len = UniStrLen(str);
+ if (str[len - 2] == L',' &&
+ str[len - 1] == L' ')
+ {
+ str[len - 2] = 0;
+ }
+ }
+}
+
+// Clone of the key
+K *CloneK(K *k)
+{
+ BUF *b;
+ K *ret;
+ // Validate arguments
+ if (k == NULL)
+ {
+ return NULL;
+ }
+
+ b = KToBuf(k, false, NULL);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ ret = BufToK(b, k->private_key, false, NULL);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Clone of certificate
+X *CloneX(X *x)
+{
+ BUF *b;
+ X *ret;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return NULL;
+ }
+
+ b = XToBuf(x, false);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ ret = BufToX(b, false);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Generate a P12
+P12 *NewP12(X *x, K *k, char *password)
+{
+ PKCS12 *pkcs12;
+ P12 *p12;
+ // Validate arguments
+ if (x == NULL || k == NULL)
+ {
+ return false;
+ }
+ if (password && StrLen(password) == 0)
+ {
+ password = NULL;
+ }
+
+ Lock(openssl_lock);
+ {
+ pkcs12 = PKCS12_create(password, NULL, k->pkey, x->x509, NULL, 0, 0, 0, 0, 0);
+ if (pkcs12 == NULL)
+ {
+ Unlock(openssl_lock);
+ return NULL;
+ }
+ }
+ Unlock(openssl_lock);
+
+ p12 = PKCS12ToP12(pkcs12);
+
+ return p12;
+}
+
+// Check whether the P12 is encrypted
+bool IsEncryptedP12(P12 *p12)
+{
+ X *x;
+ K *k;
+ // Validate arguments
+ if (p12 == NULL)
+ {
+ return false;
+ }
+
+ if (ParseP12(p12, &x, &k, NULL) == true)
+ {
+ FreeX(x);
+ FreeK(k);
+ return false;
+ }
+
+ return true;
+}
+
+// Extract the X and the K from the P12
+bool ParseP12(P12 *p12, X **x, K **k, char *password)
+{
+ EVP_PKEY *pkey;
+ X509 *x509;
+ // Validate arguments
+ if (p12 == NULL || x == NULL || k == NULL)
+ {
+ return false;
+ }
+ if (password && StrLen(password) == 0)
+ {
+ password = NULL;
+ }
+ if (password == NULL)
+ {
+ password = "";
+ }
+
+ // Password confirmation
+ Lock(openssl_lock);
+ {
+ if (PKCS12_verify_mac(p12->pkcs12, password, -1) == false &&
+ PKCS12_verify_mac(p12->pkcs12, NULL, -1) == false)
+ {
+ Unlock(openssl_lock);
+ return false;
+ }
+ }
+ Unlock(openssl_lock);
+
+ // Extraction
+ Lock(openssl_lock);
+ {
+ if (PKCS12_parse(p12->pkcs12, password, &pkey, &x509, NULL) == false)
+ {
+ if (PKCS12_parse(p12->pkcs12, NULL, &pkey, &x509, NULL) == false)
+ {
+ Unlock(openssl_lock);
+ return false;
+ }
+ }
+ }
+ Unlock(openssl_lock);
+
+ // Conversion
+ *x = X509ToX(x509);
+
+ if (*x == NULL)
+ {
+ FreePKey(pkey);
+ return false;
+ }
+
+ *k = ZeroMalloc(sizeof(K));
+ (*k)->private_key = true;
+ (*k)->pkey = pkey;
+
+ return true;
+}
+
+// Write the P12 to a file
+bool P12ToFile(P12 *p12, char *filename)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ bool ret = P12ToFileW(p12, filename_w);
+
+ return ret;
+}
+bool P12ToFileW(P12 *p12, wchar_t *filename)
+{
+ BUF *b;
+ // Validate arguments
+ if (p12 == NULL || filename == NULL)
+ {
+ return false;
+ }
+
+ b = P12ToBuf(p12);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (DumpBufW(b, filename) == false)
+ {
+ FreeBuf(b);
+ return false;
+ }
+
+ FreeBuf(b);
+
+ return true;
+}
+
+// Read a P12 from the file
+P12 *FileToP12(char *filename)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ P12 *ret = FileToP12W(filename_w);
+
+ Free(filename_w);
+
+ return ret;
+}
+P12 *FileToP12W(wchar_t *filename)
+{
+ BUF *b;
+ P12 *p12;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ b = ReadDumpW(filename);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ p12 = BufToP12(b);
+ FreeBuf(b);
+
+ return p12;
+}
+
+// Release of P12
+void FreeP12(P12 *p12)
+{
+ // Validate arguments
+ if (p12 == NULL)
+ {
+ return;
+ }
+
+ FreePKCS12(p12->pkcs12);
+ Free(p12);
+}
+
+// Release of PKCS12
+void FreePKCS12(PKCS12 *pkcs12)
+{
+ // Validate arguments
+ if (pkcs12 == NULL)
+ {
+ return;
+ }
+
+ PKCS12_free(pkcs12);
+}
+
+// Converted the P12 to a BUF
+BUF *P12ToBuf(P12 *p12)
+{
+ BIO *bio;
+ BUF *buf;
+ // Validate arguments
+ if (p12 == NULL)
+ {
+ return NULL;
+ }
+
+ bio = P12ToBio(p12);
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ buf = BioToBuf(bio);
+ FreeBio(bio);
+
+ SeekBuf(buf, 0, 0);
+
+ return buf;
+}
+
+// Converted the P12 to a BIO
+BIO *P12ToBio(P12 *p12)
+{
+ BIO *bio;
+ // Validate arguments
+ if (p12 == NULL)
+ {
+ return NULL;
+ }
+
+ bio = NewBio();
+ Lock(openssl_lock);
+ {
+ i2d_PKCS12_bio(bio, p12->pkcs12);
+ }
+ Unlock(openssl_lock);
+
+ return bio;
+}
+
+// Read the P12 from the BUF
+P12 *BufToP12(BUF *b)
+{
+ P12 *p12;
+ BIO *bio;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ bio = BufToBio(b);
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ p12 = BioToP12(bio);
+ FreeBio(bio);
+
+ return p12;
+}
+
+// Read the P12 from the BIO
+P12 *BioToP12(BIO *bio)
+{
+ PKCS12 *pkcs12;
+ // Validate arguments
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ // Conversion
+ Lock(openssl_lock);
+ {
+ pkcs12 = d2i_PKCS12_bio(bio, NULL);
+ }
+ Unlock(openssl_lock);
+ if (pkcs12 == NULL)
+ {
+ // Failure
+ return NULL;
+ }
+
+ return PKCS12ToP12(pkcs12);
+}
+
+// Generate a P12 from a PKCS12
+P12 *PKCS12ToP12(PKCS12 *pkcs12)
+{
+ P12 *p12;
+ // Validate arguments
+ if (pkcs12 == NULL)
+ {
+ return NULL;
+ }
+
+ p12 = ZeroMalloc(sizeof(P12));
+ p12->pkcs12 = pkcs12;
+
+ return p12;
+}
+
+// Convert a binary to a string
+char *ByteToStr(BYTE *src, UINT src_size)
+{
+ UINT size;
+ char *dst;
+ UINT i;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return NULL;
+ }
+
+ size = MAX(src_size * 3, 1);
+ dst = Malloc(size);
+ dst[size - 1] = 0;
+ for (i = 0;i < src_size;i++)
+ {
+ char tmp[3];
+ Format(tmp, sizeof(tmp), "%02x", src[i]);
+ dst[i * 3 + 0] = tmp[0];
+ dst[i * 3 + 1] = tmp[1];
+ dst[i * 3 + 2] = ((i == (src_size - 1) ? 0 : ' '));
+ }
+
+ return dst;
+}
+
+// Release of X_SERIAL
+void FreeXSerial(X_SERIAL *serial)
+{
+ // Validate arguments
+ if (serial == NULL)
+ {
+ return;
+ }
+
+ Free(serial->data);
+ Free(serial);
+}
+
+// Comparison of X_SERIAL
+bool CompareXSerial(X_SERIAL *s1, X_SERIAL *s2)
+{
+ // Validate arguments
+ if (s1 == NULL || s2 == NULL)
+ {
+ return false;
+ }
+
+ if (s1->size != s2->size)
+ {
+ return false;
+ }
+
+ if (Cmp(s1->data, s2->data, s1->size) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Copy of X_SERIAL
+X_SERIAL *CloneXSerial(X_SERIAL *src)
+{
+ X_SERIAL *s;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return NULL;
+ }
+
+ s = ZeroMalloc(sizeof(X_SERIAL));
+ s->data = ZeroMalloc(src->size);
+ Copy(s->data, src->data, src->size);
+ s->size = src->size;
+
+ return s;
+}
+
+// Initialization of X_SERIAL
+X_SERIAL *NewXSerial(void *data, UINT size)
+{
+ X_SERIAL *serial;
+ UCHAR *buf = (UCHAR *)data;
+ UINT i;
+ // Validate arguments
+ if (data == NULL || size == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < size;i++)
+ {
+ if (buf[i] != 0)
+ {
+ break;
+ }
+ }
+ if (i == size)
+ {
+ i = size - 1;
+ }
+ buf += i;
+
+ serial = Malloc(sizeof(X_SERIAL));
+ serial->size = size - i;
+ serial->data = ZeroMalloc(size + 16);
+ Copy(serial->data, buf, size - i);
+
+ return serial;
+}
+
+// Get the number of days till January 1, 2038
+UINT GetDaysUntil2038()
+{
+ UINT64 now = SystemTime64();
+ UINT64 target;
+ SYSTEMTIME st;
+
+ Zero(&st, sizeof(st));
+ st.wYear = 2038;
+ st.wMonth = 1;
+ st.wDay = 1;
+
+ target = SystemToUINT64(&st);
+
+ if (now >= target)
+ {
+ return 0;
+ }
+ else
+ {
+ return (UINT)((target - now) / (UINT64)(1000 * 60 * 60 * 24));
+ }
+}
+
+// Issue an X509 certificate
+X *NewX(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial)
+{
+ X509 *x509;
+ X *x;
+ // Validate arguments
+ if (pub == NULL || priv == NULL || name == NULL || ca == NULL)
+ {
+ return NULL;
+ }
+
+ x509 = NewX509(pub, priv, ca, name, days, serial);
+ if (x509 == NULL)
+ {
+ return NULL;
+ }
+
+ x = X509ToX(x509);
+
+ if (x == NULL)
+ {
+ return NULL;
+ }
+
+ return x;
+}
+
+// Create a root certificate
+X *NewRootX(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial)
+{
+ X509 *x509;
+ X *x, *x2;
+ // Validate arguments
+ if (pub == NULL || priv == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ x509 = NewRootX509(pub, priv, name, days, serial);
+ if (x509 == NULL)
+ {
+ return NULL;
+ }
+
+ x = X509ToX(x509);
+ if (x == NULL)
+ {
+ return NULL;
+ }
+
+ x2 = CloneX(x);
+ FreeX(x);
+
+ return x2;
+}
+
+// Issue an X509 certificate
+X509 *NewX509(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial)
+{
+ X509 *x509;
+ UINT64 notBefore, notAfter;
+ ASN1_TIME *t1, *t2;
+ X509_NAME *subject_name, *issuer_name;
+ // Validate arguments
+ if (pub == NULL || name == NULL || ca == NULL)
+ {
+ return NULL;
+ }
+ if (pub->private_key != false)
+ {
+ return NULL;
+ }
+ if (priv->private_key == false)
+ {
+ return NULL;
+ }
+
+ notBefore = SystemTime64();
+ notAfter = notBefore + (UINT64)days * (UINT64)3600 * (UINT64)24 * (UINT64)1000;
+
+
+ // Creating a X509
+ x509 = X509_new();
+ if (x509 == NULL)
+ {
+ return NULL;
+ }
+
+ // Set the Expiration
+ t1 = X509_get_notBefore(x509);
+ t2 = X509_get_notAfter(x509);
+ if (!UINT64ToAsn1Time(t1, notBefore))
+ {
+ FreeX509(x509);
+ return NULL;
+ }
+ if (!UINT64ToAsn1Time(t2, notAfter))
+ {
+ FreeX509(x509);
+ return NULL;
+ }
+
+ // Set the name
+ subject_name = NameToX509Name(name);
+ if (subject_name == NULL)
+ {
+ FreeX509(x509);
+ return NULL;
+ }
+ issuer_name = X509_get_subject_name(ca->x509);
+ if (issuer_name == NULL)
+ {
+ FreeX509Name(subject_name);
+ FreeX509(x509);
+ return NULL;
+ }
+
+ X509_set_issuer_name(x509, issuer_name);
+ X509_set_subject_name(x509, subject_name);
+
+ FreeX509Name(subject_name);
+
+ // Set the Serial Number
+ if (serial == NULL)
+ {
+ char zero = 0;
+ ASN1_INTEGER *s = x509->cert_info->serialNumber;
+ OPENSSL_free(s->data);
+ s->data = OPENSSL_malloc(sizeof(char));
+ Copy(s->data, &zero, sizeof(char));
+ s->length = sizeof(char);
+ }
+ else
+ {
+ ASN1_INTEGER *s = x509->cert_info->serialNumber;
+ OPENSSL_free(s->data);
+ s->data = OPENSSL_malloc(serial->size);
+ Copy(s->data, serial->data, serial->size);
+ s->length = serial->size;
+ }
+
+ Lock(openssl_lock);
+ {
+ // Set the public key
+ X509_set_pubkey(x509, pub->pkey);
+
+ // Signature
+ X509_sign(x509, priv->pkey, EVP_sha1());
+ }
+ Unlock(openssl_lock);
+
+ return x509;
+}
+
+// Create an X509 root certificate
+X509 *NewRootX509(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial)
+{
+ X509 *x509;
+ UINT64 notBefore, notAfter;
+ ASN1_TIME *t1, *t2;
+ X509_NAME *subject_name, *issuer_name;
+ // Validate arguments
+ if (pub == NULL || name == NULL || priv == NULL)
+ {
+ return NULL;
+ }
+ if (days == 0)
+ {
+ days = 365;
+ }
+ if (priv->private_key == false)
+ {
+ return NULL;
+ }
+ if (pub->private_key != false)
+ {
+ return NULL;
+ }
+
+ notBefore = SystemTime64();
+ notAfter = notBefore + (UINT64)days * (UINT64)3600 * (UINT64)24 * (UINT64)1000;
+
+ // Creating a X509
+ x509 = X509_new();
+ if (x509 == NULL)
+ {
+ return NULL;
+ }
+
+ // Set the Expiration
+ t1 = X509_get_notBefore(x509);
+ t2 = X509_get_notAfter(x509);
+ if (!UINT64ToAsn1Time(t1, notBefore))
+ {
+ FreeX509(x509);
+ return NULL;
+ }
+ if (!UINT64ToAsn1Time(t2, notAfter))
+ {
+ FreeX509(x509);
+ return NULL;
+ }
+
+ // Set the name
+ subject_name = NameToX509Name(name);
+ if (subject_name == NULL)
+ {
+ FreeX509(x509);
+ return NULL;
+ }
+ issuer_name = NameToX509Name(name);
+ if (issuer_name == NULL)
+ {
+ FreeX509Name(subject_name);
+ FreeX509(x509);
+ return NULL;
+ }
+
+ X509_set_issuer_name(x509, issuer_name);
+ X509_set_subject_name(x509, subject_name);
+
+ FreeX509Name(subject_name);
+ FreeX509Name(issuer_name);
+
+ // Set a Serial Number
+ if (serial == NULL)
+ {
+ char zero = 0;
+ ASN1_INTEGER *s = x509->cert_info->serialNumber;
+ OPENSSL_free(s->data);
+ s->data = OPENSSL_malloc(sizeof(char));
+ Copy(s->data, &zero, sizeof(char));
+ s->length = sizeof(char);
+ }
+ else
+ {
+ ASN1_INTEGER *s = x509->cert_info->serialNumber;
+ OPENSSL_free(s->data);
+ s->data = OPENSSL_malloc(serial->size);
+ Copy(s->data, serial->data, serial->size);
+ s->length = serial->size;
+ }
+
+ Lock(openssl_lock);
+ {
+ // Set the public key
+ X509_set_pubkey(x509, pub->pkey);
+
+ // Signature
+ X509_sign(x509, priv->pkey, EVP_sha1());
+ }
+ Unlock(openssl_lock);
+
+ return x509;
+}
+
+// Convert the NAMEto a X509_NAME
+void *NameToX509Name(NAME *nm)
+{
+ X509_NAME *xn;
+ // Validate arguments
+ if (nm == NULL)
+ {
+ return NULL;
+ }
+
+ xn = X509_NAME_new();
+ if (xn == NULL)
+ {
+ return NULL;
+ }
+
+ // Add the entries
+ AddX509Name(xn, NID_commonName, nm->CommonName);
+ AddX509Name(xn, NID_organizationName, nm->Organization);
+ AddX509Name(xn, NID_organizationalUnitName, nm->Unit);
+ AddX509Name(xn, NID_countryName, nm->Country);
+ AddX509Name(xn, NID_stateOrProvinceName, nm->State);
+ AddX509Name(xn, NID_localityName, nm->Local);
+
+ return xn;
+}
+
+// Add an entry to the X509_NAME
+bool AddX509Name(void *xn, int nid, wchar_t *str)
+{
+ X509_NAME *x509_name;
+ UINT utf8_size;
+ BYTE *utf8;
+ // Validate arguments
+ if (xn == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ // Convert to UTF-8
+ utf8_size = CalcUniToUtf8(str);
+ if (utf8_size == 0)
+ {
+ return false;
+ }
+ utf8 = ZeroMalloc(utf8_size + 1);
+ UniToUtf8(utf8, utf8_size, str);
+ utf8[utf8_size] = 0;
+
+ // Adding
+ x509_name = (X509_NAME *)xn;
+ Lock(openssl_lock);
+ {
+ X509_NAME_add_entry_by_NID(x509_name, nid, MBSTRING_ASC, utf8, utf8_size, -1, 0);
+ }
+ Unlock(openssl_lock);
+ Free(utf8);
+
+ return true;
+}
+
+// Release the X509_NAME
+void FreeX509Name(void *xn)
+{
+ X509_NAME *x509_name;
+ // Validate arguments
+ if (xn == NULL)
+ {
+ return;
+ }
+
+ x509_name = (X509_NAME *)xn;
+ X509_NAME_free(x509_name);
+}
+
+// Creating the NAME
+NAME *NewName(wchar_t *common_name, wchar_t *organization, wchar_t *unit,
+ wchar_t *country, wchar_t *state, wchar_t *local)
+{
+ NAME *nm = ZeroMalloc(sizeof(NAME));
+
+ if (UniIsEmptyStr(common_name) == false)
+ {
+ nm->CommonName = CopyUniStr(common_name);
+ }
+
+ if (UniIsEmptyStr(organization) == false)
+ {
+ nm->Organization = CopyUniStr(organization);
+ }
+
+ if (UniIsEmptyStr(unit) == false)
+ {
+ nm->Unit = CopyUniStr(unit);
+ }
+
+ if (UniIsEmptyStr(country) == false)
+ {
+ nm->Country = CopyUniStr(country);
+ }
+
+ if (UniIsEmptyStr(state) == false)
+ {
+ nm->State = CopyUniStr(state);
+ }
+
+ if (UniIsEmptyStr(local) == false)
+ {
+ nm->Local = CopyUniStr(local);
+ }
+
+ return nm;
+}
+
+// Check the expiration date of the certificate by the current time
+bool CheckXDateNow(X *x)
+{
+ // Validate arguments
+ if (x == NULL)
+ {
+ return false;
+ }
+
+ return CheckXDate(x, SystemTime64());
+}
+
+// Check the expiration date of the certificate
+bool CheckXDate(X *x, UINT64 current_system_time)
+{
+ // Validate arguments
+ if (x == NULL)
+ {
+ return false;
+ }
+
+ if (x->notBefore >= current_system_time || x->notAfter <= current_system_time)
+ {
+ return false;
+ }
+ return true;
+}
+
+// Read the expiration date of the certificate
+void LoadXDates(X *x)
+{
+ // Validate arguments
+ if (x == NULL)
+ {
+ return;
+ }
+
+ x->notBefore = Asn1TimeToUINT64(x->x509->cert_info->validity->notBefore);
+ x->notAfter = Asn1TimeToUINT64(x->x509->cert_info->validity->notAfter);
+}
+
+// Convert the 64bit system time to ASN1 time
+bool UINT64ToAsn1Time(void *asn1_time, UINT64 t)
+{
+ SYSTEMTIME st;
+ // Validate arguments
+ if (asn1_time == NULL)
+ {
+ return false;
+ }
+
+ UINT64ToSystem(&st, t);
+ return SystemToAsn1Time(asn1_time, &st);
+}
+
+// Convert the system time to the ASN1 time
+bool SystemToAsn1Time(void *asn1_time, SYSTEMTIME *s)
+{
+ char tmp[20];
+ ASN1_TIME *t;
+ // Validate arguments
+ if (asn1_time == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ if (SystemToStr(tmp, sizeof(tmp), s) == false)
+ {
+ return false;
+ }
+ t = (ASN1_TIME *)asn1_time;
+ if (t->data == NULL || t->length < sizeof(tmp))
+ {
+ t->data = OPENSSL_malloc(sizeof(tmp));
+ }
+ StrCpy((char *)t->data, t->length, tmp);
+ t->length = StrLen(tmp);
+ t->type = V_ASN1_UTCTIME;
+
+ return true;
+}
+
+// Convert the system time to a string
+bool SystemToStr(char *str, UINT size, SYSTEMTIME *s)
+{
+ // Validate arguments
+ if (str == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ Format(str, size, "%02u%02u%02u%02u%02u%02uZ",
+ s->wYear % 100, s->wMonth, s->wDay,
+ s->wHour, s->wMinute, s->wSecond);
+
+ return true;
+}
+
+// Convert an ASN1 time to an UINT64 time
+UINT64 Asn1TimeToUINT64(void *asn1_time)
+{
+ SYSTEMTIME st;
+ // Validate arguments
+ if (asn1_time == NULL)
+ {
+ return 0;
+ }
+
+ if (Asn1TimeToSystem(&st, asn1_time) == false)
+ {
+ return 0;
+ }
+ return SystemToUINT64(&st);
+}
+
+// Converted an ASN1 time to a system time
+bool Asn1TimeToSystem(SYSTEMTIME *s, void *asn1_time)
+{
+ ASN1_TIME *t;
+ // Validate arguments
+ if (s == NULL || asn1_time == NULL)
+ {
+ return false;
+ }
+
+ t = (ASN1_TIME *)asn1_time;
+ if (StrToSystem(s, (char *)t->data) == false)
+ {
+ return false;
+ }
+
+ if (t->type == V_ASN1_GENERALIZEDTIME)
+ {
+ LocalToSystem(s, s);
+ }
+
+ return true;
+}
+
+// Convert the string to the system time
+bool StrToSystem(SYSTEMTIME *s, char *str)
+{
+ // Validate arguments
+ if (s == NULL || str == NULL)
+ {
+ return false;
+ }
+ if (StrLen(str) != 13)
+ {
+ return false;
+ }
+ if (str[12] != 'Z')
+ {
+ return false;
+ }
+
+ // Conversion
+ {
+ char year[3] = {str[0], str[1], 0},
+ month[3] = {str[2], str[3], 0},
+ day[3] = {str[4], str[5], 0},
+ hour[3] = {str[6], str[7], 0},
+ minute[3] = {str[8], str[9], 0},
+ second[3] = {str[10], str[11], 0};
+ Zero(s, sizeof(SYSTEMTIME));
+ s->wYear = ToInt(year);
+ if (s->wYear >= 60)
+ {
+ s->wYear += 1900;
+ }
+ else
+ {
+ s->wYear += 2000;
+ }
+ s->wMonth = ToInt(month);
+ s->wDay = ToInt(day);
+ s->wHour = ToInt(hour);
+ s->wMinute = ToInt(minute);
+ s->wSecond = ToInt(second);
+ NormalizeSystem(s);
+ }
+
+ return true;
+}
+
+// Verify the RSA signature
+bool RsaVerify(void *data, UINT data_size, void *sign, K *k)
+{
+ return RsaVerifyEx(data, data_size, sign, k, 0);
+}
+bool RsaVerifyEx(void *data, UINT data_size, void *sign, K *k, UINT bits)
+{
+ UCHAR hash_data[SIGN_HASH_SIZE];
+ UCHAR decrypt_data[SIGN_HASH_SIZE];
+ // Validate arguments
+ if (data == NULL || sign == NULL || k == NULL || k->private_key != false)
+ {
+ return false;
+ }
+ if (bits == 0)
+ {
+ bits = 1024;
+ }
+
+ // Hash the data
+ if (HashForSign(hash_data, sizeof(hash_data), data, data_size) == false)
+ {
+ return false;
+ }
+
+ // Decode the signature
+ if (RSA_public_decrypt(bits / 8, sign, decrypt_data, k->pkey->pkey.rsa, RSA_PKCS1_PADDING) <= 0)
+ {
+ return false;
+ }
+
+ // Comparison
+ if (Cmp(decrypt_data, hash_data, SIGN_HASH_SIZE) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// RSA signature
+bool RsaSign(void *dst, void *src, UINT size, K *k)
+{
+ return RsaSignEx(dst, src, size, k, 0);
+}
+bool RsaSignEx(void *dst, void *src, UINT size, K *k, UINT bits)
+{
+ UCHAR hash[SIGN_HASH_SIZE];
+ // Validate arguments
+ if (dst == NULL || src == NULL || k == NULL || k->pkey->type != EVP_PKEY_RSA)
+ {
+ return false;
+ }
+ if (bits == 0)
+ {
+ bits = 1024;
+ }
+
+ Zero(dst, bits / 8);
+
+ // Hash
+ if (HashForSign(hash, sizeof(hash), src, size) == false)
+ {
+ return false;
+ }
+
+ // Signature
+ if (RSA_private_encrypt(sizeof(hash), hash, dst, k->pkey->pkey.rsa, RSA_PKCS1_PADDING) <= 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Generation of signature data by SHA-1
+bool HashForSign(void *dst, UINT dst_size, void *src, UINT src_size)
+{
+ UCHAR *buf = (UCHAR *)dst;
+ UCHAR sign_data[] =
+ {
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E,
+ 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14,
+ };
+ // Validate arguments
+ if (dst == NULL || src == NULL || src_size == 0 || MIN_SIGN_HASH_SIZE > dst_size)
+ {
+ return false;
+ }
+
+ // Header part
+ Copy(buf, sign_data, sizeof(sign_data));
+
+ // Hash
+ HashSha1(HASHED_DATA(buf), src, src_size);
+
+ return true;
+}
+
+// Decrypt with the RSA public key
+bool RsaPublicDecrypt(void *dst, void *src, UINT size, K *k)
+{
+ void *tmp;
+ int ret;
+ // Validate arguments
+ if (src == NULL || size == 0 || k == NULL)
+ {
+ return false;
+ }
+
+ tmp = ZeroMalloc(size);
+ Lock(openssl_lock);
+ {
+ ret = RSA_public_decrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);
+ }
+ Unlock(openssl_lock);
+ if (ret <= 0)
+ {
+/* Debug("RSA Error: 0x%x\n",
+ ERR_get_error());
+*/ Free(tmp);
+ return false;
+ }
+
+ Copy(dst, tmp, size);
+ Free(tmp);
+
+ return true;
+}
+
+// Encrypt with the RSA private key
+bool RsaPrivateEncrypt(void *dst, void *src, UINT size, K *k)
+{
+ void *tmp;
+ int ret;
+ // Validate arguments
+ if (src == NULL || size == 0 || k == NULL)
+ {
+ return false;
+ }
+
+ tmp = ZeroMalloc(size);
+ Lock(openssl_lock);
+ {
+ ret = RSA_private_encrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);
+ }
+ Unlock(openssl_lock);
+ if (ret <= 0)
+ {
+/* Debug("RSA Error: %u\n",
+ ERR_GET_REASON(ERR_get_error()));
+*/ Free(tmp);
+ return false;
+ }
+
+ Copy(dst, tmp, size);
+ Free(tmp);
+
+ return true;
+}
+
+// Decrypt with the RSA private key
+bool RsaPrivateDecrypt(void *dst, void *src, UINT size, K *k)
+{
+ void *tmp;
+ int ret;
+ // Validate arguments
+ if (src == NULL || size == 0 || k == NULL)
+ {
+ return false;
+ }
+
+ tmp = ZeroMalloc(size);
+ Lock(openssl_lock);
+ {
+ ret = RSA_private_decrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);
+ }
+ Unlock(openssl_lock);
+ if (ret <= 0)
+ {
+ return false;
+ }
+
+ Copy(dst, tmp, size);
+ Free(tmp);
+
+ return true;
+}
+
+// Encrypt with the RSA public key
+bool RsaPublicEncrypt(void *dst, void *src, UINT size, K *k)
+{
+ void *tmp;
+ int ret;
+ // Validate arguments
+ if (src == NULL || size == 0 || k == NULL)
+ {
+ return false;
+ }
+
+ tmp = ZeroMalloc(size);
+ Lock(openssl_lock);
+ {
+ ret = RSA_public_encrypt(size, src, tmp, k->pkey->pkey.rsa, RSA_NO_PADDING);
+ }
+ Unlock(openssl_lock);
+ if (ret <= 0)
+ {
+ return false;
+ }
+
+ Copy(dst, tmp, size);
+ Free(tmp);
+
+ return true;
+}
+
+// RSA operating environment check
+bool RsaCheckEx()
+{
+ UINT num = 20;
+ UINT i;
+
+ for (i = 0;i < num;i++)
+ {
+ if (RsaCheck())
+ {
+ return true;
+ }
+
+ SleepThread(100);
+ }
+
+ return false;
+}
+bool RsaCheck()
+{
+ RSA *rsa;
+ K *priv_key, *pub_key;
+ BIO *bio;
+ char errbuf[MAX_SIZE];
+ UINT size = 0;
+ UINT bit = 32;
+ // Validate arguments
+
+ // Key generation
+ Lock(openssl_lock);
+ {
+ rsa = RSA_generate_key(bit, RSA_F4, NULL, NULL);
+ }
+ Unlock(openssl_lock);
+ if (rsa == NULL)
+ {
+ Debug("RSA_generate_key: err=%s\n", ERR_error_string(ERR_get_error(), errbuf));
+ return false;
+ }
+
+ // Secret key
+ bio = NewBio();
+ Lock(openssl_lock);
+ {
+ i2d_RSAPrivateKey_bio(bio, rsa);
+ }
+ Unlock(openssl_lock);
+ BIO_seek(bio, 0);
+ priv_key = BioToK(bio, true, false, NULL);
+ FreeBio(bio);
+
+ // Public key
+ bio = NewBio();
+ Lock(openssl_lock);
+ {
+ i2d_RSA_PUBKEY_bio(bio, rsa);
+ }
+ Unlock(openssl_lock);
+ BIO_seek(bio, 0);
+ pub_key = BioToK(bio, false, false, NULL);
+ FreeBio(bio);
+
+ RSA_free(rsa);
+
+ size = RsaPublicSize(pub_key);
+
+ if (size != ((bit + 7) / 8))
+ {
+ FreeK(priv_key);
+ FreeK(pub_key);
+
+ return false;
+ }
+
+ FreeK(priv_key);
+ FreeK(pub_key);
+
+ return true;
+}
+
+// Generation of RSA key
+bool RsaGen(K **priv, K **pub, UINT bit)
+{
+ RSA *rsa;
+ K *priv_key, *pub_key;
+ BIO *bio;
+ char errbuf[MAX_SIZE];
+ UINT size = 0;
+ // Validate arguments
+ if (priv == NULL || pub == NULL)
+ {
+ return false;
+ }
+ if (bit == 0)
+ {
+ bit = 1024;
+ }
+
+ // Key generation
+ Lock(openssl_lock);
+ {
+ rsa = RSA_generate_key(bit, RSA_F4, NULL, NULL);
+ }
+ Unlock(openssl_lock);
+ if (rsa == NULL)
+ {
+ Debug("RSA_generate_key: err=%s\n", ERR_error_string(ERR_get_error(), errbuf));
+ return false;
+ }
+
+ // Secret key
+ bio = NewBio();
+ Lock(openssl_lock);
+ {
+ i2d_RSAPrivateKey_bio(bio, rsa);
+ }
+ Unlock(openssl_lock);
+ BIO_seek(bio, 0);
+ priv_key = BioToK(bio, true, false, NULL);
+ FreeBio(bio);
+
+ // Public key
+ bio = NewBio();
+ Lock(openssl_lock);
+ {
+ i2d_RSA_PUBKEY_bio(bio, rsa);
+ }
+ Unlock(openssl_lock);
+ BIO_seek(bio, 0);
+ pub_key = BioToK(bio, false, false, NULL);
+ FreeBio(bio);
+
+ *priv = priv_key;
+ *pub = pub_key;
+
+ RSA_free(rsa);
+
+ size = RsaPublicSize(*pub);
+
+ if (size != ((bit + 7) / 8))
+ {
+ FreeK(*priv);
+ FreeK(*pub);
+
+ return RsaGen(priv, pub, bit);
+ }
+
+ return true;
+}
+
+// Confirm whether the certificate X is signed by the issuer of the certificate x_issuer
+bool CheckX(X *x, X *x_issuer)
+{
+ K *k;
+ bool ret;
+ // Validate arguments
+ if (x == NULL || x_issuer == NULL)
+ {
+ return false;
+ }
+
+ k = GetKFromX(x_issuer);
+ if (k == NULL)
+ {
+ return false;
+ }
+
+ ret = CheckSignature(x, k);
+ FreeK(k);
+
+ return ret;
+}
+
+// Confirm the signature of the certificate X with the public key K
+bool CheckSignature(X *x, K *k)
+{
+ // Validate arguments
+ if (x == NULL || k == NULL)
+ {
+ return false;
+ }
+
+ Lock(openssl_lock);
+ {
+ if (X509_verify(x->x509, k->pkey) == 0)
+ {
+ Unlock(openssl_lock);
+ return false;
+ }
+ }
+ Unlock(openssl_lock);
+ return true;
+}
+
+// Get the public key from the certificate
+K *GetKFromX(X *x)
+{
+ EVP_PKEY *pkey;
+ K *k;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return NULL;
+ }
+
+ Lock(openssl_lock);
+ {
+ pkey = X509_get_pubkey(x->x509);
+ }
+ Unlock(openssl_lock);
+ if (pkey == NULL)
+ {
+ return NULL;
+ }
+
+ k = ZeroMalloc(sizeof(K));
+ k->pkey = pkey;
+
+ return k;
+}
+
+// The name comparison
+bool CompareName(NAME *n1, NAME *n2)
+{
+ // Validate arguments
+ if (n1 == NULL || n2 == NULL)
+ {
+ return false;
+ }
+
+ // Name comparison
+ if (UniStrCmpi(n1->CommonName, n2->CommonName) == 0 &&
+ UniStrCmpi(n1->Organization, n2->Organization) == 0 &&
+ UniStrCmpi(n1->Unit, n2->Unit) == 0 &&
+ UniStrCmpi(n1->Country, n2->Country) == 0 &&
+ UniStrCmpi(n1->State, n2->State) == 0 &&
+ UniStrCmpi(n1->Local, n2->Local) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Release the name of the X
+void FreeXNames(X *x)
+{
+ // Validate arguments
+ if (x == NULL)
+ {
+ return;
+ }
+
+ FreeName(x->issuer_name);
+ x->issuer_name = NULL;
+
+ FreeName(x->subject_name);
+ x->subject_name = NULL;
+}
+
+// Release the name
+void FreeName(NAME *n)
+{
+ // Validate arguments
+ if (n == NULL)
+ {
+ return;
+ }
+
+ // Release the string
+ Free(n->CommonName);
+ Free(n->Organization);
+ Free(n->Unit);
+ Free(n->Country);
+ Free(n->State);
+ Free(n->Local);
+
+ // Release the object
+ Free(n);
+
+ return;
+}
+
+// Get the name of the certificate
+void LoadXNames(X *x)
+{
+ X509 *x509;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return;
+ }
+
+ x509 = x->x509;
+ x->issuer_name = X509NameToName(X509_get_issuer_name(x509));
+ x->subject_name = X509NameToName(X509_get_subject_name(x509));
+}
+
+// Convert the X509_NAME structure to the NAME structure
+NAME *X509NameToName(void *xn)
+{
+ NAME *n;
+ // Validate arguments
+ if (xn == NULL)
+ {
+ return NULL;
+ }
+
+ n = ZeroMalloc(sizeof(NAME));
+
+ // Get the strings one by one
+ n->CommonName = GetUniStrFromX509Name(xn, NID_commonName);
+ n->Organization = GetUniStrFromX509Name(xn, NID_organizationName);
+ n->Unit = GetUniStrFromX509Name(xn, NID_organizationalUnitName);
+ n->Country = GetUniStrFromX509Name(xn, NID_countryName);
+ n->State = GetUniStrFromX509Name(xn, NID_stateOrProvinceName);
+ n->Local = GetUniStrFromX509Name(xn, NID_localityName);
+
+ return n;
+}
+
+// Read a Unicode string from the X509_NAME structure
+wchar_t *GetUniStrFromX509Name(void *xn, int nid)
+{
+ UCHAR txt[1024];
+ bool b = false;
+ UINT i, size;
+ int index;
+ bool unicode = false;
+ bool is_utf_8 = false;
+ ASN1_OBJECT *obj;
+ ASN1_STRING *data;
+ // Validate arguments
+ if (xn == NULL || nid == 0)
+ {
+ return NULL;
+ }
+
+ Zero(txt, sizeof(txt));
+ if (X509_NAME_get_text_by_NID(xn, nid, (char *)txt, sizeof(txt) - 2) <= 0)
+ {
+ return NULL;
+ }
+
+ obj = OBJ_nid2obj(nid);
+ if (obj == NULL)
+ {
+ return NULL;
+ }
+ index = X509_NAME_get_index_by_OBJ(xn, obj, -1);
+ if (index < 0)
+ {
+ return NULL;
+ }
+ data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(xn, index));
+ if (data == NULL)
+ {
+ return NULL;
+ }
+ if (data->type == V_ASN1_BMPSTRING)
+ {
+ unicode = true;
+ }
+ if (data->type == V_ASN1_UTF8STRING || data->type == V_ASN1_T61STRING)
+ {
+ is_utf_8 = true;
+ }
+
+ size = UniStrLen((wchar_t *)txt) * 4 + 8;
+ for (i = 0;i < size;i++)
+ {
+ if (txt[i] >= 0x80)
+ {
+ unicode = true;
+ break;
+ }
+ }
+
+ if (is_utf_8)
+ {
+ wchar_t *ret;
+ UINT ret_size;
+
+ ret_size = CalcUtf8ToUni(txt, StrLen(txt));
+ ret = ZeroMalloc(ret_size + 8);
+ Utf8ToUni(ret, ret_size, txt, StrLen(txt));
+
+ return ret;
+ }
+ else if (unicode == false)
+ {
+ wchar_t tmp[1024];
+ StrToUni(tmp, sizeof(tmp), (char *)txt);
+ return CopyUniStr(tmp);
+ }
+ else
+ {
+ EndianUnicode((wchar_t *)txt);
+ return CopyUniStr((wchar_t *)txt);
+ }
+}
+
+// Check whether the certificate x1 equal to x2
+bool CompareX(X *x1, X *x2)
+{
+ // Validate arguments
+ if (x1 == NULL || x2 == NULL)
+ {
+ return false;
+ }
+
+ Lock(openssl_lock);
+ if (X509_cmp(x1->x509, x2->x509) == 0)
+ {
+ Unlock(openssl_lock);
+ return true;
+ }
+ else
+ {
+ Unlock(openssl_lock);
+ return false;
+ }
+}
+
+// Check whether K is private key of X
+bool CheckXandK(X *x, K *k)
+{
+ // Validate arguments
+ if (x == NULL || k == NULL)
+ {
+ return false;
+ }
+
+ Lock(openssl_lock);
+ if (X509_check_private_key(x->x509, k->pkey) != 0)
+ {
+ Unlock(openssl_lock);
+ return true;
+ }
+ else
+ {
+ Unlock(openssl_lock);
+ return false;
+ }
+}
+
+// Read a X from the file
+X *FileToX(char *filename)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ X *ret = FileToXW(filename_w);
+
+ Free(filename_w);
+
+ return ret;
+}
+X *FileToXW(wchar_t *filename)
+{
+ bool text;
+ BUF *b;
+ X *x;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ b = ReadDumpW(filename);
+ text = IsBase64(b);
+
+ x = BufToX(b, text);
+ FreeBuf(b);
+
+ return x;
+}
+
+// Write the X to a file
+bool XToFile(X *x, char *filename, bool text)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ bool ret = XToFileW(x, filename_w, text);
+
+ Free(filename_w);
+
+ return ret;
+}
+bool XToFileW(X *x, wchar_t *filename, bool text)
+{
+ BUF *b;
+ bool ret;
+ // Validate arguments
+ if (x == NULL || filename == NULL)
+ {
+ return false;
+ }
+
+ b = XToBuf(x, text);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ ret = DumpBufW(b, filename);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Read a K from the file
+K *FileToK(char *filename, bool private_key, char *password)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ K *ret;
+
+ ret = FileToKW(filename_w, private_key, password);
+
+ Free(filename_w);
+
+ return ret;
+}
+K *FileToKW(wchar_t *filename, bool private_key, char *password)
+{
+ bool text;
+ BUF *b;
+ K *k;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ b = ReadDumpW(filename);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ text = IsBase64(b);
+ if (text == false)
+ {
+ k = BufToK(b, private_key, false, NULL);
+ }
+ else
+ {
+ k = BufToK(b, private_key, true, NULL);
+ if (k == NULL)
+ {
+ k = BufToK(b, private_key, true, password);
+ }
+ }
+
+ FreeBuf(b);
+
+ return k;
+}
+
+// Save the K to a file
+bool KToFile(K *k, char *filename, bool text, char *password)
+{
+ wchar_t *filename_w = CopyStrToUni(filename);
+ bool ret = KToFileW(k, filename_w, text, password);
+
+ Free(filename_w);
+
+ return ret;
+}
+bool KToFileW(K *k, wchar_t *filename, bool text, char *password)
+{
+ BUF *b;
+ bool ret;
+ // Validate arguments
+ if (k == NULL || filename == NULL)
+ {
+ return false;
+ }
+
+ b = KToBuf(k, text, password);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ ret = DumpBufW(b, filename);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Convert the K to the BUF
+BUF *KToBuf(K *k, bool text, char *password)
+{
+ BUF *buf;
+ BIO *bio;
+ // Validate arguments
+ if (k == NULL)
+ {
+ return NULL;
+ }
+
+ bio = KToBio(k, text, password);
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ buf = BioToBuf(bio);
+ FreeBio(bio);
+
+ SeekBuf(buf, 0, 0);
+
+ return buf;
+}
+
+// Convert the K to the BIO
+BIO *KToBio(K *k, bool text, char *password)
+{
+ BIO *bio;
+ // Validate arguments
+ if (k == NULL)
+ {
+ return NULL;
+ }
+
+ bio = NewBio();
+
+ if (k->private_key)
+ {
+ // Secret key
+ if (text == false)
+ {
+ // Binary format
+ Lock(openssl_lock);
+ {
+ i2d_PrivateKey_bio(bio, k->pkey);
+ }
+ Unlock(openssl_lock);
+ }
+ else
+ {
+ // Text format
+ if (password == 0 || StrLen(password) == 0)
+ {
+ // No encryption
+ Lock(openssl_lock);
+ {
+ PEM_write_bio_PrivateKey(bio, k->pkey, NULL, NULL, 0, NULL, NULL);
+ }
+ Unlock(openssl_lock);
+ }
+ else
+ {
+ // Encrypt
+ CB_PARAM cb;
+ cb.password = password;
+ Lock(openssl_lock);
+ {
+ PEM_write_bio_PrivateKey(bio, k->pkey, EVP_des_ede3_cbc(),
+ NULL, 0, (pem_password_cb *)PKeyPasswordCallbackFunction, &cb);
+ }
+ Unlock(openssl_lock);
+ }
+ }
+ }
+ else
+ {
+ // Public key
+ if (text == false)
+ {
+ // Binary format
+ Lock(openssl_lock);
+ {
+ i2d_PUBKEY_bio(bio, k->pkey);
+ }
+ Unlock(openssl_lock);
+ }
+ else
+ {
+ // Text format
+ Lock(openssl_lock);
+ {
+ PEM_write_bio_PUBKEY(bio, k->pkey);
+ }
+ Unlock(openssl_lock);
+ }
+ }
+
+ return bio;
+}
+
+// Check whether the BUF is encoded as the Base64
+bool IsBase64(BUF *b)
+{
+ UINT i;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (SearchAsciiInBinary(b->Buf, b->Size, "-----BEGIN", false) != INFINITE)
+ {
+ return true;
+ }
+
+ for (i = 0;i < b->Size;i++)
+ {
+ char c = ((char *)b->Buf)[i];
+ bool b = false;
+ if ('a' <= c && c <= 'z')
+ {
+ b = true;
+ }
+ else if ('A' <= c && c <= 'Z')
+ {
+ b = true;
+ }
+ else if ('0' <= c && c <= '9')
+ {
+ b = true;
+ }
+ else if (c == ':' || c == '.' || c == ';' || c == ',')
+ {
+ b = true;
+ }
+ else if (c == '!' || c == '&' || c == '#' || c == '(' || c == ')')
+ {
+ b = true;
+ }
+ else if (c == '-' || c == ' ')
+ {
+ b = true;
+ }
+ else if (c == 13 || c == 10 || c == EOF)
+ {
+ b = true;
+ }
+ else if (c == '\t' || c == '=' || c == '+' || c == '/')
+ {
+ b = true;
+ }
+ if (b == false)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Check whether the K in the BUF is encrypted
+bool IsEncryptedK(BUF *b, bool private_key)
+{
+ K *k;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+ if (IsBase64(b) == false)
+ {
+ return false;
+ }
+
+ k = BufToK(b, private_key, true, NULL);
+ if (k != NULL)
+ {
+ FreeK(k);
+ return false;
+ }
+
+ return true;
+}
+
+// Convert the BUF to a K
+K *BufToK(BUF *b, bool private_key, bool text, char *password)
+{
+ BIO *bio;
+ K *k;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ bio = BufToBio(b);
+ k = BioToK(bio, private_key, text, password);
+ FreeBio(bio);
+
+ return k;
+}
+
+// Release of K
+void FreeK(K *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ FreePKey(k->pkey);
+ Free(k);
+}
+
+// Release the secret key
+void FreePKey(EVP_PKEY *pkey)
+{
+ // Validate arguments
+ if (pkey == NULL)
+ {
+ return;
+ }
+
+ EVP_PKEY_free(pkey);
+}
+
+// Convert the BIO to the K
+K *BioToK(BIO *bio, bool private_key, bool text, char *password)
+{
+ EVP_PKEY *pkey;
+ K *k;
+ // Validate arguments
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ if (password != NULL && StrLen(password) == 0)
+ {
+ password = NULL;
+ }
+
+ if (private_key == false)
+ {
+ // Public key
+ if (text == false)
+ {
+ // Binary format
+ pkey = d2i_PUBKEY_bio(bio, NULL);
+ if (pkey == NULL)
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ // Text format
+ CB_PARAM cb;
+ cb.password = password;
+ Lock(openssl_lock);
+ {
+ pkey = PEM_read_bio_PUBKEY(bio, NULL, (pem_password_cb *)PKeyPasswordCallbackFunction, &cb);
+ }
+ Unlock(openssl_lock);
+ if (pkey == NULL)
+ {
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ if (text == false)
+ {
+ // Binary format
+ Lock(openssl_lock);
+ {
+ pkey = d2i_PrivateKey_bio(bio, NULL);
+ }
+ Unlock(openssl_lock);
+ if (pkey == NULL)
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ // Text format
+ CB_PARAM cb;
+ cb.password = password;
+ Lock(openssl_lock);
+ {
+ pkey = PEM_read_bio_PrivateKey(bio, NULL, (pem_password_cb *)PKeyPasswordCallbackFunction, &cb);
+ }
+ Unlock(openssl_lock);
+ if (pkey == NULL)
+ {
+ return NULL;
+ }
+ }
+ }
+
+ k = ZeroMalloc(sizeof(K));
+ k->pkey = pkey;
+ k->private_key = private_key;
+
+ return k;
+}
+
+// Password callback function
+int PKeyPasswordCallbackFunction(char *buf, int bufsize, int verify, void *param)
+{
+ CB_PARAM *cb;
+ // Validate arguments
+ if (buf == NULL || param == NULL || bufsize == 0)
+ {
+ return 0;
+ }
+
+ cb = (CB_PARAM *)param;
+ if (cb->password == NULL)
+ {
+ return 0;
+ }
+
+ return StrCpy(buf, bufsize, cb->password);
+}
+
+// Convert the X to a BUF
+BUF *XToBuf(X *x, bool text)
+{
+ BIO *bio;
+ BUF *b;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return NULL;
+ }
+
+ bio = XToBio(x, text);
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ b = BioToBuf(bio);
+ FreeBio(bio);
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Convert the X to a BIO
+BIO *XToBio(X *x, bool text)
+{
+ BIO *bio;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return NULL;
+ }
+
+ bio = NewBio();
+
+ Lock(openssl_lock);
+ {
+ if (text == false)
+ {
+ // Binary format
+ i2d_X509_bio(bio, x->x509);
+ }
+ else
+ {
+ // Text format
+ PEM_write_bio_X509(bio, x->x509);
+ }
+ }
+ Unlock(openssl_lock);
+
+ return bio;
+}
+
+// Release of the X
+void FreeX(X *x)
+{
+ // Validate arguments
+ if (x == NULL)
+ {
+ return;
+ }
+
+ // Release the name
+ FreeXNames(x);
+
+
+ // Release the Serial
+ FreeXSerial(x->serial);
+
+ if (x->do_not_free == false)
+ {
+ FreeX509(x->x509);
+ }
+ Free(x);
+}
+
+// Release of the X509
+void FreeX509(X509 *x509)
+{
+ // Validate arguments
+ if (x509 == NULL)
+ {
+ return;
+ }
+
+ Lock(openssl_lock);
+ {
+ X509_free(x509);
+ }
+ Unlock(openssl_lock);
+}
+
+// Convert the BUF to a X
+X *BufToX(BUF *b, bool text)
+{
+ X *x;
+ BIO *bio;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ bio = BufToBio(b);
+ if (bio == NULL)
+ {
+ FreeBuf(b);
+ return NULL;
+ }
+
+ x = BioToX(bio, text);
+
+ FreeBio(bio);
+
+ return x;
+}
+
+// Create a new buffer by skipping the contents of the buffer to the specified string
+BUF *SkipBufBeforeString(BUF *b, char *str)
+{
+ char *tmp;
+ UINT tmp_size;
+ BUF *ret;
+ UINT i;
+ UINT offset = 0;
+ // Validate arguments
+ if (b == NULL || str == NULL)
+ {
+ return NULL;
+ }
+
+ tmp_size = b->Size + 1;
+ tmp = ZeroMalloc(tmp_size);
+ Copy(tmp, b->Buf, b->Size);
+
+ i = SearchStrEx(tmp, str, 0, false);
+ if (i != INFINITE)
+ {
+ offset = i;
+ }
+
+ ret = NewBuf();
+ WriteBuf(ret, ((UCHAR *)b->Buf) + offset, b->Size - offset);
+ SeekBuf(ret, 0, 0);
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Get a digest of the X
+void GetXDigest(X *x, UCHAR *buf, bool sha1)
+{
+ // Validate arguments
+ if (x == NULL)
+ {
+ return;
+ }
+
+ if (sha1 == false)
+ {
+ UINT size = MD5_SIZE;
+ X509_digest(x->x509, EVP_md5(), buf, (unsigned int *)&size);
+ }
+ else
+ {
+ UINT size = SHA1_SIZE;
+ X509_digest(x->x509, EVP_sha1(), buf, (unsigned int *)&size);
+ }
+}
+
+// Convert BIO to X
+X *BioToX(BIO *bio, bool text)
+{
+ X *x;
+ X509 *x509;
+ // Validate arguments
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ Lock(openssl_lock);
+ {
+ // Reading x509
+ if (text == false)
+ {
+ // Binary mode
+ x509 = d2i_X509_bio(bio, NULL);
+ }
+ else
+ {
+ // Text mode
+ x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+ }
+ }
+ Unlock(openssl_lock);
+
+ if (x509 == NULL)
+ {
+ return NULL;
+ }
+
+ x = X509ToX(x509);
+
+ if (x == NULL)
+ {
+ return NULL;
+ }
+
+ return x;
+}
+
+// Convert the X509 to X
+X *X509ToX(X509 *x509)
+{
+ X *x;
+ K *k;
+ BUF *b;
+ UINT size;
+ UINT type;
+ // Validate arguments
+ if (x509 == NULL)
+ {
+ return NULL;
+ }
+
+ x = ZeroMalloc(sizeof(X));
+ x->x509 = x509;
+
+ // Name
+ LoadXNames(x);
+
+ // Expiration date
+ LoadXDates(x);
+
+ // Check whether it is a root certificate
+ if (CompareName(x->issuer_name, x->subject_name))
+ {
+ K *pubkey = GetKFromX(x);
+ if (pubkey != NULL)
+ {
+ if (CheckXandK(x, pubkey))
+ {
+ x->root_cert = true;
+ }
+ FreeK(pubkey);
+ }
+ }
+
+ // Get the Serial Number
+ x->serial = NewXSerial(x509->cert_info->serialNumber->data,
+ x509->cert_info->serialNumber->length);
+ if (x->serial == NULL)
+ {
+ char zero = 0;
+ x->serial = NewXSerial(&zero, sizeof(char));
+ }
+
+ k = GetKFromX(x);
+ if (k == NULL)
+ {
+ FreeX(x);
+ return NULL;
+ }
+
+ b = KToBuf(k, false, NULL);
+
+ size = b->Size;
+ type = k->pkey->type;
+
+ FreeBuf(b);
+
+ FreeK(k);
+
+ if (type == EVP_PKEY_RSA)
+ {
+ x->is_compatible_bit = true;
+
+ switch (size)
+ {
+ case 162:
+ x->bits = 1024;
+ break;
+
+ case 226:
+ x->bits = 1536;
+ break;
+
+ case 294:
+ x->bits = 2048;
+ break;
+
+ case 442:
+ x->bits = 3072;
+ break;
+
+ case 550:
+ x->bits = 4096;
+ break;
+
+ default:
+ x->is_compatible_bit = false;
+ break;
+ }
+ }
+
+ return x;
+}
+
+// Create a BIO
+BIO *NewBio()
+{
+ return BIO_new(BIO_s_mem());
+}
+
+// Release the BIO
+void FreeBio(BIO *bio)
+{
+ // Validate arguments
+ if (bio == NULL)
+ {
+ return;
+ }
+
+ BIO_free(bio);
+}
+
+// Convert the BIO to the BUF
+BUF *BioToBuf(BIO *bio)
+{
+ BUF *b;
+ UINT size;
+ void *tmp;
+ // Validate arguments
+ if (bio == NULL)
+ {
+ return NULL;
+ }
+
+ BIO_seek(bio, 0);
+ size = bio->num_write;
+ tmp = Malloc(size);
+ BIO_read(bio, tmp, size);
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size);
+ Free(tmp);
+
+ return b;
+}
+
+// Convert the BUF to a BIO
+BIO *BufToBio(BUF *b)
+{
+ BIO *bio;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ Lock(openssl_lock);
+ {
+ bio = BIO_new(BIO_s_mem());
+ if (bio == NULL)
+ {
+ Unlock(openssl_lock);
+ return NULL;
+ }
+ BIO_write(bio, b->Buf, b->Size);
+ BIO_seek(bio, 0);
+ }
+ Unlock(openssl_lock);
+
+ return bio;
+}
+
+// 128-bit random number generation
+void Rand128(void *buf)
+{
+ Rand(buf, 16);
+}
+
+// 64-bit random number generation
+UINT64 Rand64()
+{
+ UINT64 i;
+ Rand(&i, sizeof(i));
+ return i;
+}
+
+// 32-bit random number generation
+UINT Rand32()
+{
+ UINT i;
+ Rand(&i, sizeof(i));
+ return i;
+}
+
+// 16-bit random number generation
+USHORT Rand16()
+{
+ USHORT i;
+ Rand(&i, sizeof(i));
+ return i;
+}
+
+// 8-bit random number generation
+UCHAR Rand8()
+{
+ UCHAR i;
+ Rand(&i, sizeof(i));
+ return i;
+}
+
+// 1-bit random number generation
+bool Rand1()
+{
+ return (Rand32() % 2) == 0 ? false : true;
+}
+
+// Random number generation
+void Rand(void *buf, UINT size)
+{
+ // Validate arguments
+ if (buf == NULL || size == 0)
+ {
+ return;
+ }
+ RAND_bytes(buf, size);
+}
+
+// Delete a thread-specific information that OpenSSL has holded
+void FreeOpenSSLThreadState()
+{
+ ERR_remove_state(0);
+}
+
+// Release the Crypt library
+void FreeCryptLibrary()
+{
+ openssl_inited = false;
+
+ DeleteLock(openssl_lock);
+ openssl_lock = NULL;
+// RAND_Free_For_SoftEther();
+ OpenSSL_FreeLock();
+}
+
+// Initialize the Crypt library
+void InitCryptLibrary()
+{
+ char tmp[16];
+
+ CheckIfIntelAesNiSupportedInit();
+// RAND_Init_For_SoftEther()
+ openssl_lock = NewLock();
+ SSL_library_init();
+ //OpenSSL_add_all_algorithms();
+ OpenSSL_add_all_ciphers();
+ SSLeay_add_all_digests();
+ ERR_load_crypto_strings();
+ SSL_load_error_strings();
+
+#ifdef OS_UNIX
+ {
+ char *name1 = "/dev/random";
+ char *name2 = "/dev/urandom";
+ IO *o;
+ o = FileOpen(name1, false);
+ if (o == NULL)
+ {
+ o = FileOpen(name2, false);
+ if (o == NULL)
+ {
+ UINT64 now = SystemTime64();
+ BUF *b;
+ UINT i;
+ b = NewBuf();
+ for (i = 0;i < 4096;i++)
+ {
+ UCHAR c = rand() % 256;
+ WriteBuf(b, &c, 1);
+ }
+ WriteBuf(b, &now, sizeof(now));
+ RAND_seed(b->Buf, b->Size);
+ FreeBuf(b);
+ }
+ else
+ {
+ FileClose(o);
+ }
+ }
+ else
+ {
+ FileClose(o);
+ }
+ }
+#endif // OS_UNIX
+
+ RAND_poll();
+
+#ifdef OS_WIN32
+// RAND_screen();
+#endif
+ Rand(tmp, sizeof(tmp));
+ OpenSSL_InitLock();
+
+ openssl_inited = true;
+}
+
+// Hash function
+void Hash(void *dst, void *src, UINT size, bool sha)
+{
+ // Validate arguments
+ if (dst == NULL || (src == NULL && size != 0))
+ {
+ return;
+ }
+
+ if (sha == false)
+ {
+ // MD5 hash
+ MD5(src, size, dst);
+ }
+ else
+ {
+ // SHA hash
+ SHA(src, size, dst);
+ }
+}
+
+// MD4 specific hash function
+void HashMd4(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || (size != 0 && src == NULL))
+ {
+ return;
+ }
+ MD4(src, size, dst);
+}
+
+// Hash with the SHA-1 and convert it to UINT
+UINT HashToUINT(void *data, UINT size)
+{
+ UCHAR hash[SHA1_SIZE];
+ UINT u;
+ // Validate arguments
+ if (data == NULL && size != 0)
+ {
+ return 0;
+ }
+
+ HashSha1(hash, data, size);
+
+ Copy(&u, hash, sizeof(UINT));
+
+ u = Endian32(u);
+
+ return u;
+}
+
+// SHA-1 specific hash function
+void HashSha1(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || (size != 0 && src == NULL))
+ {
+ return;
+ }
+ SHA1(src, size, dst);
+}
+
+// SHA-256 specific hash function
+void HashSha256(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || (size != 0 && src == NULL))
+ {
+ return;
+ }
+ SHA256(src, size, dst);
+}
+
+// Creating a new CRYPT object
+CRYPT *NewCrypt(void *key, UINT size)
+{
+ CRYPT *c = ZeroMalloc(sizeof(CRYPT));
+
+ c->Rc4Key = ZeroMalloc(sizeof(struct rc4_key_st));
+
+ RC4_set_key(c->Rc4Key, size, (UCHAR *)key);
+
+ return c;
+}
+
+// Release the CRYPT object
+void FreeCrypt(CRYPT *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ // Memory release
+ Free(c->Rc4Key);
+ Free(c);
+}
+
+// Encryption and decryption
+void Encrypt(CRYPT *c, void *dst, void *src, UINT size)
+{
+ RC4(c->Rc4Key, size, src, dst);
+}
+
+// SHA-1 hash
+void Sha1(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ SHA1(src, size, dst);
+}
+
+// MD5 hash
+void Md5(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ MD5(src, size, dst);
+}
+
+// 3DES encryption
+void Des3Encrypt(void *dest, void *src, UINT size, DES_KEY *key, void *ivec)
+{
+ UCHAR ivec_copy[DES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || key == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, DES_IV_SIZE);
+
+ DES_ede3_cbc_encrypt(src, dest, size,
+ key->k1->KeySchedule,
+ key->k2->KeySchedule,
+ key->k3->KeySchedule,
+ (DES_cblock *)ivec_copy,
+ 1);
+}
+void Des3Encrypt2(void *dest, void *src, UINT size, DES_KEY_VALUE *k1, DES_KEY_VALUE *k2, DES_KEY_VALUE *k3, void *ivec)
+{
+ UCHAR ivec_copy[DES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k1 == NULL || k2 == NULL || k3 == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, DES_IV_SIZE);
+
+ DES_ede3_cbc_encrypt(src, dest, size,
+ k1->KeySchedule,
+ k2->KeySchedule,
+ k3->KeySchedule,
+ (DES_cblock *)ivec_copy,
+ 1);
+}
+
+// DES encryption
+void DesEncrypt(void *dest, void *src, UINT size, DES_KEY_VALUE *k, void *ivec)
+{
+ UCHAR ivec_copy[DES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, DES_IV_SIZE);
+
+ DES_cbc_encrypt(src, dest, size,
+ k->KeySchedule,
+ (DES_cblock *)ivec_copy,
+ 1);
+}
+
+// 3DES decryption
+void Des3Decrypt(void *dest, void *src, UINT size, DES_KEY *key, void *ivec)
+{
+ UCHAR ivec_copy[DES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || key == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, DES_IV_SIZE);
+
+ DES_ede3_cbc_encrypt(src, dest, size,
+ key->k1->KeySchedule,
+ key->k2->KeySchedule,
+ key->k3->KeySchedule,
+ (DES_cblock *)ivec_copy,
+ 0);
+}
+void Des3Decrypt2(void *dest, void *src, UINT size, DES_KEY_VALUE *k1, DES_KEY_VALUE *k2, DES_KEY_VALUE *k3, void *ivec)
+{
+ UCHAR ivec_copy[DES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k1 == NULL || k2 == NULL || k3 == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, DES_IV_SIZE);
+
+ DES_ede3_cbc_encrypt(src, dest, size,
+ k1->KeySchedule,
+ k2->KeySchedule,
+ k3->KeySchedule,
+ (DES_cblock *)ivec_copy,
+ 0);
+}
+
+// DES-ECB encryption
+void DesEcbEncrypt(void *dst, void *src, void *key_7bytes)
+{
+ UCHAR *key_56;
+ DES_cblock key;
+ DES_key_schedule ks;
+ // Validate arguments
+ if (dst == NULL || src == NULL || key == NULL)
+ {
+ return;
+ }
+
+ key_56 = (UCHAR *)key_7bytes;
+
+ Zero(&key, sizeof(key));
+ Zero(&ks, sizeof(ks));
+
+ key[0] = key_56[0];
+ key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
+ key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
+ key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
+ key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
+ key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
+ key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
+ key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
+
+ DES_set_odd_parity(&key);
+ DES_set_key_unchecked(&key, &ks);
+
+ DES_ecb_encrypt(src, dst, &ks, 1);
+}
+
+// DES decryption
+void DesDecrypt(void *dest, void *src, UINT size, DES_KEY_VALUE *k, void *ivec)
+{
+ UCHAR ivec_copy[DES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, DES_IV_SIZE);
+
+ DES_cbc_encrypt(src, dest, size,
+ k->KeySchedule,
+ (DES_cblock *)ivec_copy,
+ 0);
+}
+
+// Generate a random 3DES key
+DES_KEY *Des3RandKey()
+{
+ DES_KEY *k = ZeroMalloc(sizeof(DES_KEY));
+
+ k->k1 = DesRandKeyValue();
+ k->k2 = DesRandKeyValue();
+ k->k3 = DesRandKeyValue();
+
+ return k;
+}
+
+// Generate a random DES key
+DES_KEY *DesRandKey()
+{
+ DES_KEY *k = ZeroMalloc(sizeof(DES_KEY));
+
+ k->k1 = DesRandKeyValue();
+ k->k2 = DesNewKeyValue(k->k1->KeyValue);
+ k->k3 = DesNewKeyValue(k->k1->KeyValue);
+
+ return k;
+}
+
+// Release the 3DES key
+void Des3FreeKey(DES_KEY *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ DesFreeKeyValue(k->k1);
+ DesFreeKeyValue(k->k2);
+ DesFreeKeyValue(k->k3);
+
+ Free(k);
+}
+
+// Release the DES key
+void DesFreeKey(DES_KEY *k)
+{
+ Des3FreeKey(k);
+}
+
+// Create a 3DES key
+DES_KEY *Des3NewKey(void *k1, void *k2, void *k3)
+{
+ DES_KEY *k;
+ // Validate arguments
+ if (k1 == NULL || k2 == NULL || k3 == NULL)
+ {
+ return NULL;
+ }
+
+ k = ZeroMalloc(sizeof(DES_KEY));
+
+ k->k1 = DesNewKeyValue(k1);
+ k->k2 = DesNewKeyValue(k2);
+ k->k3 = DesNewKeyValue(k3);
+
+ return k;
+}
+
+// Create a DES key
+DES_KEY *DesNewKey(void *k1)
+{
+ return Des3NewKey(k1, k1, k1);
+}
+
+// Create a new DES key element
+DES_KEY_VALUE *DesNewKeyValue(void *value)
+{
+ DES_KEY_VALUE *v;
+ // Validate arguments
+ if (value == NULL)
+ {
+ return NULL;
+ }
+
+ v = ZeroMalloc(sizeof(DES_KEY_VALUE));
+
+ Copy(v->KeyValue, value, DES_KEY_SIZE);
+
+ v->KeySchedule = ZeroMalloc(sizeof(DES_key_schedule));
+
+ DES_set_key_unchecked(value, v->KeySchedule);
+
+ return v;
+}
+
+// Random generation of new DES key element
+DES_KEY_VALUE *DesRandKeyValue()
+{
+ UCHAR key_value[DES_KEY_SIZE];
+
+ DES_random_key((DES_cblock *)key_value);
+
+ return DesNewKeyValue(key_value);
+}
+
+// Release of DES key element
+void DesFreeKeyValue(DES_KEY_VALUE *v)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ Free(v->KeySchedule);
+ Free(v);
+}
+
+// Create a new AES key
+AES_KEY_VALUE *AesNewKey(void *data, UINT size)
+{
+ AES_KEY_VALUE *k;
+ // Validate arguments
+ if (data == NULL || (!(size == 16 || size == 24 || size == 32)))
+ {
+ return NULL;
+ }
+
+ k = ZeroMalloc(sizeof(AES_KEY_VALUE));
+
+ k->EncryptKey = ZeroMalloc(sizeof(struct aes_key_st));
+ k->DecryptKey = ZeroMalloc(sizeof(struct aes_key_st));
+
+ k->KeySize = size;
+ Copy(k->KeyValue, data, size);
+
+ AES_set_encrypt_key(data, size * 8, k->EncryptKey);
+ AES_set_decrypt_key(data, size * 8, k->DecryptKey);
+
+ return k;
+}
+
+// Release the AES key
+void AesFreeKey(AES_KEY_VALUE *k)
+{
+ // Validate arguments
+ if (k == NULL)
+ {
+ return;
+ }
+
+ Free(k->EncryptKey);
+ Free(k->DecryptKey);
+
+ Free(k);
+}
+
+// AES encryption
+void AesEncrypt(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec)
+{
+ UCHAR ivec_copy[AES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+#ifdef USE_INTEL_AESNI_LIBRARY
+ if (is_intel_aes_supported)
+ {
+ AesEncryptWithIntel(dest, src, size, k, ivec);
+ return;
+ }
+#endif // USE_INTEL_AESNI_LIBRARY
+
+ Copy(ivec_copy, ivec, AES_IV_SIZE);
+
+ AES_cbc_encrypt(src, dest, size, k->EncryptKey, ivec, 1);
+}
+
+// AES decryption
+void AesDecrypt(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec)
+{
+ UCHAR ivec_copy[AES_IV_SIZE];
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+#ifdef USE_INTEL_AESNI_LIBRARY
+ if (is_intel_aes_supported)
+ {
+ AesDecryptWithIntel(dest, src, size, k, ivec);
+ return;
+ }
+#endif // USE_INTEL_AESNI_LIBRARY
+
+ Copy(ivec_copy, ivec, AES_IV_SIZE);
+
+ AES_cbc_encrypt(src, dest, size, k->DecryptKey, ivec, 0);
+}
+
+// Determine whether the Intel AES-NI is supported
+bool IsIntelAesNiSupported()
+{
+ return is_intel_aes_supported;
+}
+void CheckIfIntelAesNiSupportedInit()
+{
+#ifdef USE_INTEL_AESNI_LIBRARY
+ if (check_for_aes_instructions())
+ {
+ is_intel_aes_supported = true;
+ }
+ else
+ {
+ is_intel_aes_supported = false;
+ }
+#else // USE_INTEL_AESNI_LIBRARY
+ is_intel_aes_supported = false;
+#endif // USE_INTEL_AESNI_LIBRARY
+}
+
+// Disable the Intel AES-NI
+void DisableIntelAesAccel()
+{
+ is_intel_aes_supported = false;
+}
+
+#ifdef USE_INTEL_AESNI_LIBRARY
+// Encrypt AES using the Intel AES-NI
+void AesEncryptWithIntel(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec)
+{
+ UCHAR ivec_copy[AES_IV_SIZE];
+
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, AES_IV_SIZE);
+
+ switch (k->KeySize)
+ {
+ case 16:
+ intel_AES_enc128_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
+ break;
+
+ case 24:
+ intel_AES_enc192_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
+ break;
+
+ case 32:
+ intel_AES_enc256_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
+ break;
+ }
+}
+
+// Decrypt AES using the Intel AES-NI
+void AesDecryptWithIntel(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec)
+{
+ UCHAR ivec_copy[AES_IV_SIZE];
+
+ // Validate arguments
+ if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
+ {
+ return;
+ }
+
+ Copy(ivec_copy, ivec, AES_IV_SIZE);
+
+ switch (k->KeySize)
+ {
+ case 16:
+ intel_AES_dec128_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
+ break;
+
+ case 24:
+ intel_AES_dec192_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
+ break;
+
+ case 32:
+ intel_AES_dec256_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
+ break;
+ }
+}
+#endif // USE_INTEL_AESNI_LIBRARY
+
+// Calculation of HMAC-SHA-1-96
+void MacSha196(void *dst, void *key, void *data, UINT data_size)
+{
+ UCHAR tmp[HMAC_SHA1_SIZE];
+ // Validate arguments
+ if (dst == NULL || key == NULL || data == NULL)
+ {
+ return;
+ }
+
+ MacSha1(tmp, key, HMAC_SHA1_96_KEY_SIZE, data, data_size);
+
+ Copy(dst, tmp, HMAC_SHA1_96_HASH_SIZE);
+}
+
+// Calculation of HMAC-SHA-1
+void MacSha1(void *dst, void *key, UINT key_size, void *data, UINT data_size)
+{
+ UCHAR key_plus[SHA1_BLOCK_SIZE];
+ UCHAR key_plus2[SHA1_BLOCK_SIZE];
+ UCHAR key_plus5[SHA1_BLOCK_SIZE];
+ UCHAR hash4[SHA1_HASH_SIZE];
+ UINT i;
+ BUF *buf3;
+ BUF *buf6;
+ // Validate arguments
+ if (dst == NULL || key == NULL || data == NULL)
+ {
+ return;
+ }
+
+ Zero(key_plus, sizeof(key_plus));
+ if (key_size <= SHA1_BLOCK_SIZE)
+ {
+ Copy(key_plus, key, key_size);
+ }
+ else
+ {
+ Sha1(key_plus, key, key_size);
+ }
+
+ for (i = 0;i < sizeof(key_plus);i++)
+ {
+ key_plus2[i] = key_plus[i] ^ 0x36;
+ }
+
+ buf3 = NewBuf();
+ WriteBuf(buf3, key_plus2, sizeof(key_plus2));
+ WriteBuf(buf3, data, data_size);
+
+ Sha1(hash4, buf3->Buf, buf3->Size);
+
+ for (i = 0;i < sizeof(key_plus);i++)
+ {
+ key_plus5[i] = key_plus[i] ^ 0x5c;
+ }
+
+ buf6 = NewBuf();
+ WriteBuf(buf6, key_plus5, sizeof(key_plus5));
+ WriteBuf(buf6, hash4, sizeof(hash4));
+
+ Sha1(dst, buf6->Buf, buf6->Size);
+
+ FreeBuf(buf3);
+ FreeBuf(buf6);
+}
+
+// DH calculation
+bool DhCompute(DH_CTX *dh, void *dst_priv_key, void *src_pub_key, UINT key_size)
+{
+ int i;
+ BIGNUM *bn;
+ bool ret = false;
+ // Validate arguments
+ if (dh == NULL || dst_priv_key == NULL || src_pub_key == NULL)
+ {
+ return false;
+ }
+ if (key_size > dh->Size)
+ {
+ return false;
+ }
+
+ bn = BinToBigNum(src_pub_key, key_size);
+
+ i = DH_compute_key(dst_priv_key, bn, dh->dh);
+
+ if (i == dh->Size)
+ {
+ ret = true;
+ }
+ else if ((UINT)i < dh->Size)
+ {
+ UCHAR *dst2 = Clone(dst_priv_key, i);
+
+ Zero(dst_priv_key, dh->Size);
+
+ Copy(((UCHAR *)dst_priv_key) + (dh->Size - i), dst2, i);
+
+ ret = true;
+ }
+
+ BN_free(bn);
+
+ return ret;
+}
+
+// Creating a DH GROUP1
+DH_CTX *DhNewGroup1()
+{
+ return DhNew(DH_GROUP1_PRIME_768, 2);
+}
+
+// Creating a DH GROUP2
+DH_CTX *DhNewGroup2()
+{
+ return DhNew(DH_GROUP2_PRIME_1024, 2);
+}
+
+// Creating a DH GROUP5
+DH_CTX *DhNewGroup5()
+{
+ return DhNew(DH_GROUP5_PRIME_1536, 2);
+}
+
+// Creating a DH SIMPLE 160bits
+DH_CTX *DhNewSimple160()
+{
+ return DhNew(DH_SIMPLE_160, 2);
+}
+
+// Convert the DH parameters to file
+BUF *DhToBuf(DH_CTX *dh)
+{
+ BIO *bio;
+ BUF *buf = NULL;
+ int r;
+ // Validate arguments
+ if (dh == NULL)
+ {
+ return NULL;
+ }
+
+ bio = NewBio();
+
+ r = i2d_DHparams_bio(bio, dh->dh);
+ if (r > 1)
+ {
+ buf = BioToBuf(bio);
+ }
+
+ FreeBio(bio);
+
+ return buf;
+}
+
+// Creating a new DH
+DH_CTX *DhNew(char *prime, UINT g)
+{
+ DH_CTX *dh;
+ BUF *buf;
+ // Validate arguments
+ if (prime == NULL || g == 0)
+ {
+ return NULL;
+ }
+
+ buf = StrToBin(prime);
+
+ dh = ZeroMalloc(sizeof(DH_CTX));
+
+ dh->dh = DH_new();
+ dh->dh->p = BinToBigNum(buf->Buf, buf->Size);
+ dh->dh->g = BN_new();
+ BN_set_word(dh->dh->g, g);
+
+ DH_generate_key(dh->dh);
+
+ dh->MyPublicKey = BigNumToBuf(dh->dh->pub_key);
+ dh->MyPrivateKey = BigNumToBuf(dh->dh->priv_key);
+
+ dh->Size = buf->Size;
+
+ FreeBuf(buf);
+
+ return dh;
+}
+
+// Release of DH
+void DhFree(DH_CTX *dh)
+{
+ // Validate arguments
+ if (dh == NULL)
+ {
+ return;
+ }
+
+ DH_free(dh->dh);
+
+ FreeBuf(dh->MyPrivateKey);
+ FreeBuf(dh->MyPublicKey);
+
+ Free(dh);
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Encrypt.h b/src/Mayaqua/Encrypt.h
new file mode 100644
index 00000000..24cb11e6
--- /dev/null
+++ b/src/Mayaqua/Encrypt.h
@@ -0,0 +1,486 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Encrypt.h
+// Header of Encrypt.c
+
+#ifndef ENCRYPT_H
+#define ENCRYPT_H
+
+// Function of OpenSSL
+void RAND_Init_For_SoftEther();
+void RAND_Free_For_SoftEther();
+
+
+
+// Constant
+#define MIN_SIGN_HASH_SIZE (15 + SHA1_SIZE)
+#define SIGN_HASH_SIZE (MIN_SIGN_HASH_SIZE)
+
+#define DES_KEY_SIZE 8 // DES key size
+#define DES_IV_SIZE 8 // DES IV size
+#define DES_BLOCK_SIZE 8 // DES block size
+#define DES3_KEY_SIZE (8 * 3) // 3DES key size
+#define RSA_KEY_SIZE 128 // RSA key size
+#define DH_KEY_SIZE 128 // DH key size
+#define RSA_MIN_SIGN_HASH_SIZE (15 + SHA1_HASH_SIZE) // Minimum RSA hash size
+#define RSA_SIGN_HASH_SIZE (RSA_MIN_SIGN_HASH_SIZE) // RSA hash size
+#define MD5_HASH_SIZE 16 // MD5 hash size
+#define SHA1_HASH_SIZE 20 // SHA-1 hash size
+#define SHA1_BLOCK_SIZE 64 // SHA-1 block size
+#define HMAC_SHA1_96_KEY_SIZE 20 // HMAC-SHA-1-96 key size
+#define HMAC_SHA1_96_HASH_SIZE 12 // HMAC-SHA-1-96 hash size
+#define HMAC_SHA1_SIZE (SHA1_HASH_SIZE) // HMAC-SHA-1 hash size
+#define AES_IV_SIZE 16 // AES IV size
+#define AES_MAX_KEY_SIZE 32 // Maximum AES key size
+
+// HMAC block size
+#define HMAC_BLOCK_SIZE 64
+
+#define DH_GROUP1_PRIME_768 \
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+ "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"
+
+#define DH_GROUP2_PRIME_1024 \
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
+ "FFFFFFFFFFFFFFFF"
+
+#define DH_GROUP5_PRIME_1536 \
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
+ "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
+
+#define DH_SIMPLE_160 "AEE7561459353C95DDA966AE1FD25D95CD46E935"
+
+// Macro
+#define HASHED_DATA(p) (((UCHAR *)p) + 15)
+
+
+
+// Crypt context
+struct CRYPT
+{
+ struct rc4_key_st *Rc4Key;
+};
+
+// Name in the certificate
+struct NAME
+{
+ wchar_t *CommonName; // CN
+ wchar_t *Organization; // O
+ wchar_t *Unit; // OU
+ wchar_t *Country; // C
+ wchar_t *State; // ST
+ wchar_t *Local; // L
+};
+
+// Serial number
+struct X_SERIAL
+{
+ UINT size;
+ UCHAR *data;
+};
+
+// Certificate
+struct X
+{
+ X509 *x509;
+ NAME *issuer_name;
+ NAME *subject_name;
+ bool root_cert;
+ UINT64 notBefore;
+ UINT64 notAfter;
+ X_SERIAL *serial;
+ bool do_not_free;
+ bool is_compatible_bit;
+ UINT bits;
+};
+
+// Key
+struct K
+{
+ EVP_PKEY *pkey;
+ bool private_key;
+};
+
+// PKCS#12
+struct P12
+{
+ PKCS12 *pkcs12;
+};
+
+// CEL
+struct X_CRL
+{
+ X509_CRL *Crl;
+};
+
+// Constant
+#define MD5_SIZE 16
+#define SHA1_SIZE 20
+#define SHA256_SIZE 32
+
+// Key element of DES
+struct DES_KEY_VALUE
+{
+ struct DES_ks *KeySchedule;
+ UCHAR KeyValue[DES_KEY_SIZE];
+};
+
+// DES key
+struct DES_KEY
+{
+ DES_KEY_VALUE *k1, *k2, *k3;
+};
+
+// AES key
+struct AES_KEY_VALUE
+{
+ struct aes_key_st *EncryptKey;
+ struct aes_key_st *DecryptKey;
+ UCHAR KeyValue[AES_MAX_KEY_SIZE];
+ UINT KeySize;
+};
+
+// DH
+struct DH_CTX
+{
+ struct dh_st *dh;
+ BUF *MyPublicKey;
+ BUF *MyPrivateKey;
+ UINT Size;
+};
+
+// Cipher object
+struct CIPHER
+{
+ char Name[MAX_PATH];
+ bool IsNullCipher;
+ const struct evp_cipher_st *Cipher;
+ struct evp_cipher_ctx_st *Ctx;
+ bool Encrypt;
+ UINT BlockSize, IvSize, KeySize;
+};
+
+// Message digest object
+struct MD
+{
+ char Name[MAX_PATH];
+ const struct env_md_st *Md;
+ struct hmac_ctx_st *Ctx;
+ UINT Size;
+};
+
+
+// Lock of the OpenSSL
+extern LOCK **ssl_lock_obj;
+
+// Function prototype
+CRYPT *NewCrypt(void *key, UINT size);
+void FreeCrypt(CRYPT *c);
+void Encrypt(CRYPT *c, void *dst, void *src, UINT size);
+void Hash(void *dst, void *src, UINT size, bool sha);
+void HashSha1(void *dst, void *src, UINT size);
+void HashSha256(void *dst, void *src, UINT size);
+void HashMd4(void *dst, void *src, UINT size);
+void HashMd4(void *dst, void *src, UINT size);
+void InitCryptLibrary();
+void Rand(void *buf, UINT size);
+void Rand128(void *buf);
+UINT HashToUINT(void *data, UINT size);
+UINT64 Rand64();
+UINT Rand32();
+USHORT Rand16();
+UCHAR Rand8();
+bool Rand1();
+UINT HashPtrToUINT(void *p);
+
+void CertTest();
+BIO *BufToBio(BUF *b);
+BUF *BioToBuf(BIO *bio);
+BIO *NewBio();
+void FreeBio(BIO *bio);
+X *BioToX(BIO *bio, bool text);
+X *BufToX(BUF *b, bool text);
+BUF *SkipBufBeforeString(BUF *b, char *str);
+void FreeX509(X509 *x509);
+void FreeX(X *x);
+BIO *XToBio(X *x, bool text);
+BUF *XToBuf(X *x, bool text);
+K *BioToK(BIO *bio, bool private_key, bool text, char *password);
+int PKeyPasswordCallbackFunction(char *buf, int bufsize, int verify, void *param);
+void FreePKey(EVP_PKEY *pkey);
+void FreeK(K *k);
+K *BufToK(BUF *b, bool private_key, bool text, char *password);
+bool IsEncryptedK(BUF *b, bool private_key);
+bool IsBase64(BUF *b);
+BIO *KToBio(K *k, bool text, char *password);
+BUF *KToBuf(K *k, bool text, char *password);
+X *FileToX(char *filename);
+X *FileToXW(wchar_t *filename);
+bool XToFile(X *x, char *filename, bool text);
+bool XToFileW(X *x, wchar_t *filename, bool text);
+K *FileToK(char *filename, bool private_key, char *password);
+K *FileToKW(wchar_t *filename, bool private_key, char *password);
+bool KToFile(K *k, char *filename, bool text, char *password);
+bool KToFileW(K *k, wchar_t *filename, bool text, char *password);
+bool CheckXandK(X *x, K *k);
+bool CompareX(X *x1, X *x2);
+NAME *X509NameToName(void *xn);
+wchar_t *GetUniStrFromX509Name(void *xn, int nid);
+void LoadXNames(X *x);
+void FreeXNames(X *x);
+void FreeName(NAME *n);
+bool CompareName(NAME *n1, NAME *n2);
+K *GetKFromX(X *x);
+bool CheckSignature(X *x, K *k);
+X *X509ToX(X509 *x509);
+bool CheckX(X *x, X *x_issuer);
+bool Asn1TimeToSystem(SYSTEMTIME *s, void *asn1_time);
+bool StrToSystem(SYSTEMTIME *s, char *str);
+UINT64 Asn1TimeToUINT64(void *asn1_time);
+bool SystemToAsn1Time(void *asn1_time, SYSTEMTIME *s);
+bool UINT64ToAsn1Time(void *asn1_time, UINT64 t);
+bool SystemToStr(char *str, UINT size, SYSTEMTIME *s);
+void LoadXDates(X *x);
+bool CheckXDate(X *x, UINT64 current_system_time);
+bool CheckXDateNow(X *x);
+NAME *NewName(wchar_t *common_name, wchar_t *organization, wchar_t *unit,
+ wchar_t *country, wchar_t *state, wchar_t *local);
+void *NameToX509Name(NAME *nm);
+void FreeX509Name(void *xn);
+bool AddX509Name(void *xn, int nid, wchar_t *str);
+X509 *NewRootX509(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial);
+X *NewRootX(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial);
+X509 *NewX509(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial);
+X *NewX(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial);
+UINT GetDaysUntil2038();
+X_SERIAL *NewXSerial(void *data, UINT size);
+void FreeXSerial(X_SERIAL *serial);
+char *ByteToStr(BYTE *src, UINT src_size);
+P12 *BioToP12(BIO *bio);
+P12 *PKCS12ToP12(PKCS12 *pkcs12);
+P12 *BufToP12(BUF *b);
+BIO *P12ToBio(P12 *p12);
+BUF *P12ToBuf(P12 *p12);
+void FreePKCS12(PKCS12 *pkcs12);
+void FreeP12(P12 *p12);
+P12 *FileToP12(char *filename);
+P12 *FileToP12W(wchar_t *filename);
+bool P12ToFile(P12 *p12, char *filename);
+bool P12ToFileW(P12 *p12, wchar_t *filename);
+bool ParseP12(P12 *p12, X **x, K **k, char *password);
+bool IsEncryptedP12(P12 *p12);
+P12 *NewP12(X *x, K *k, char *password);
+X *CloneX(X *x);
+K *CloneK(K *k);
+void FreeCryptLibrary();
+void GetPrintNameFromX(wchar_t *str, UINT size, X *x);
+void GetPrintNameFromXA(char *str, UINT size, X *x);
+void GetPrintNameFromName(wchar_t *str, UINT size, NAME *name);
+void GetAllNameFromX(wchar_t *str, UINT size, X *x);
+void GetAllNameFromA(char *str, UINT size, X *x);
+void GetAllNameFromName(wchar_t *str, UINT size, NAME *name);
+void GetAllNameFromNameEx(wchar_t *str, UINT size, NAME *name);
+void GetAllNameFromXEx(wchar_t *str, UINT size, X *x);
+void GetAllNameFromXExA(char *str, UINT size, X *x);
+BUF *BigNumToBuf(BIGNUM *bn);
+BIGNUM *BinToBigNum(void *data, UINT size);
+BIGNUM *BufToBigNum(BUF *b);
+char *BigNumToStr(BIGNUM *bn);
+X_SERIAL *CloneXSerial(X_SERIAL *src);
+bool CompareXSerial(X_SERIAL *s1, X_SERIAL *s2);
+void GetXDigest(X *x, UCHAR *buf, bool sha1);
+NAME *CopyName(NAME *n);
+
+
+bool RsaGen(K **priv, K **pub, UINT bit);
+bool RsaCheck();
+bool RsaCheckEx();
+bool RsaPublicEncrypt(void *dst, void *src, UINT size, K *k);
+bool RsaPrivateDecrypt(void *dst, void *src, UINT size, K *k);
+bool RsaPrivateEncrypt(void *dst, void *src, UINT size, K *k);
+bool RsaPublicDecrypt(void *dst, void *src, UINT size, K *k);
+bool RsaSign(void *dst, void *src, UINT size, K *k);
+bool RsaSignEx(void *dst, void *src, UINT size, K *k, UINT bits);
+bool HashForSign(void *dst, UINT dst_size, void *src, UINT src_size);
+bool RsaVerify(void *data, UINT data_size, void *sign, K *k);
+bool RsaVerifyEx(void *data, UINT data_size, void *sign, K *k, UINT bits);
+UINT RsaPublicSize(K *k);
+void RsaPublicToBin(K *k, void *data);
+BUF *RsaPublicToBuf(K *k);
+K *RsaBinToPublic(void *data, UINT size);
+
+X_CRL *FileToXCrl(char *filename);
+X_CRL *FileToXCrlW(wchar_t *filename);
+X_CRL *BufToXCrl(BUF *b);
+void FreeXCrl(X_CRL *r);
+bool IsXRevokedByXCrl(X *x, X_CRL *r);
+bool IsXRevoked(X *x);
+
+DES_KEY_VALUE *DesNewKeyValue(void *value);
+DES_KEY_VALUE *DesRandKeyValue();
+void DesFreeKeyValue(DES_KEY_VALUE *v);
+DES_KEY *Des3NewKey(void *k1, void *k2, void *k3);
+void Des3FreeKey(DES_KEY *k);
+DES_KEY *DesNewKey(void *k1);
+void DesFreeKey(DES_KEY *k);
+DES_KEY *Des3RandKey();
+DES_KEY *DesRandKey();
+void Des3Encrypt(void *dest, void *src, UINT size, DES_KEY *key, void *ivec);
+void Des3Encrypt2(void *dest, void *src, UINT size, DES_KEY_VALUE *k1, DES_KEY_VALUE *k2, DES_KEY_VALUE *k3, void *ivec);
+void Des3Decrypt(void *dest, void *src, UINT size, DES_KEY *key, void *ivec);
+void Des3Decrypt2(void *dest, void *src, UINT size, DES_KEY_VALUE *k1, DES_KEY_VALUE *k2, DES_KEY_VALUE *k3, void *ivec);
+void Sha1(void *dst, void *src, UINT size);
+void Md5(void *dst, void *src, UINT size);
+void MacSha1(void *dst, void *key, UINT key_size, void *data, UINT data_size);
+void MacSha196(void *dst, void *key, void *data, UINT data_size);
+void DesEncrypt(void *dest, void *src, UINT size, DES_KEY_VALUE *k, void *ivec);
+void DesDecrypt(void *dest, void *src, UINT size, DES_KEY_VALUE *k, void *ivec);
+void DesEcbEncrypt(void *dst, void *src, void *key_7bytes);
+
+bool DhCompute(DH_CTX *dh, void *dst_priv_key, void *src_pub_key, UINT key_size);
+DH_CTX *DhNewGroup1();
+DH_CTX *DhNewGroup2();
+DH_CTX *DhNewGroup5();
+DH_CTX *DhNewSimple160();
+DH_CTX *DhNew(char *prime, UINT g);
+void DhFree(DH_CTX *dh);
+BUF *DhToBuf(DH_CTX *dh);
+
+AES_KEY_VALUE *AesNewKey(void *data, UINT size);
+void AesFreeKey(AES_KEY_VALUE *k);
+void AesEncrypt(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec);
+void AesDecrypt(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec);
+
+bool IsIntelAesNiSupported();
+void CheckIfIntelAesNiSupportedInit();
+
+#ifdef USE_INTEL_AESNI_LIBRARY
+void AesEncryptWithIntel(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec);
+void AesDecryptWithIntel(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec);
+#endif // USE_INTEL_AESNI_LIBRARY
+
+void OpenSSL_InitLock();
+void OpenSSL_FreeLock();
+void OpenSSL_Lock(int mode, int n, const char *file, int line);
+unsigned long OpenSSL_Id(void);
+void FreeOpenSSLThreadState();
+
+CIPHER *NewCipher(char *name);
+void FreeCipher(CIPHER *c);
+void SetCipherKey(CIPHER *c, void *key, bool enc);
+UINT CipherProcess(CIPHER *c, void *iv, void *dest, void *src, UINT size);
+
+MD *NewMd(char *name);
+void FreeMd(MD *md);
+void SetMdKey(MD *md, void *key, UINT key_size);
+void MdProcess(MD *md, void *dest, void *src, UINT size);
+void Enc_tls1_PRF(unsigned char *label, int label_len, const unsigned char *sec,
+ int slen, unsigned char *out1, int olen);
+
+void HMacSha1(void *dst, void *key, UINT key_size, void *data, UINT data_size);
+void HMacMd5(void *dst, void *key, UINT key_size, void *data, UINT data_size);
+
+void DisableIntelAesAccel();
+
+#ifdef ENCRYPT_C
+// Inner function
+
+
+#endif // ENCRYPT_C
+
+#endif // ENCRYPT_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/FileIO.c b/src/Mayaqua/FileIO.c
new file mode 100644
index 00000000..8cf0178e
--- /dev/null
+++ b/src/Mayaqua/FileIO.c
@@ -0,0 +1,2738 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// FileIO.c
+// File Input / Output code
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+static char exe_file_name[MAX_SIZE] = "/tmp/a.out";
+static wchar_t exe_file_name_w[MAX_SIZE] = L"/tmp/a.out";
+static LIST *hamcore = NULL;
+static IO *hamcore_io = NULL;
+
+#define NUM_CRC32_TABLE 256
+static UINT crc32_table[NUM_CRC32_TABLE];
+
+// Confirm that the specified string exists as a line
+bool IsInLines(BUF *buf, char *str, bool instr)
+{
+ bool ret = false;
+ // Validate arguments
+ if (buf == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ if (IsEmptyStr(str))
+ {
+ return false;
+ }
+
+ SeekBufToBegin(buf);
+
+ while (ret == false)
+ {
+ char *line = CfgReadNextLine(buf);
+
+ if (line == NULL)
+ {
+ break;
+ }
+
+ Trim(line);
+
+ if (IsEmptyStr(line) == false)
+ {
+ if (StrCmpi(line, str) == 0)
+ {
+ ret = true;
+ }
+
+ if (instr)
+ {
+ if (InStr(str, line))
+ {
+ ret = true;
+ }
+
+ if (InStr(line, str))
+ {
+ ret = true;
+ }
+ }
+ }
+
+ Free(line);
+ }
+
+ return ret;
+}
+bool IsInLinesFile(wchar_t *filename, char *str, bool instr)
+{
+ bool ret = false;
+ BUF *b;
+ // Validate arguments
+ if (filename == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDumpW(filename);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ ret = IsInLines(b, str, instr);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Check whether the file is write-locked
+bool IsFileWriteLockedW(wchar_t *name)
+{
+ IO *io;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (IsFileExistsW(name) == false)
+ {
+ return false;
+ }
+
+ io = FileOpenW(name, true);
+ if (io == NULL)
+ {
+ return true;
+ }
+
+ FileClose(io);
+
+ return false;
+}
+bool IsFileWriteLocked(char *name)
+{
+ bool ret;
+ wchar_t *tmp;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ tmp = CopyStrToUni(name);
+
+ ret = IsFileWriteLockedW(tmp);
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Creating a ZIP packer
+ZIP_PACKER *NewZipPacker()
+{
+ ZIP_PACKER *p = ZeroMalloc(sizeof(ZIP_PACKER));
+
+ p->Fifo = NewFifo();
+ p->FileList = NewList(NULL);
+ p->CurrentFile = NULL;
+
+ return p;
+}
+
+// Release of ZIP packer
+void FreeZipPacker(ZIP_PACKER *p)
+{
+ UINT i;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ ReleaseFifo(p->Fifo);
+
+ for (i = 0;i < LIST_NUM(p->FileList);i++)
+ {
+ ZIP_FILE *f = LIST_DATA(p->FileList, i);
+
+ Free(f);
+ }
+
+ ReleaseList(p->FileList);
+
+ Free(p);
+}
+
+// Simply add the file
+void ZipAddFileSimple(ZIP_PACKER *p, char *name, UINT64 dt, UINT attribute, void *data, UINT size)
+{
+ // Validate arguments
+ if (p == NULL || IsEmptyStr(name) || (size != 0 && data == NULL))
+ {
+ return;
+ }
+
+ ZipAddFileStart(p, name, size, dt, attribute);
+ ZipAddFileData(p, data, 0, size);
+}
+bool ZipAddRealFileW(ZIP_PACKER *p, char *name, UINT64 dt, UINT attribute, wchar_t *srcname)
+{
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || IsEmptyStr(name) || srcname == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDumpW(srcname);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ ZipAddFileSimple(p, name, dt, attribute, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ return true;
+}
+bool ZipAddRealFile(ZIP_PACKER *p, char *name, UINT64 dt, UINT attribute, char *srcname)
+{
+ bool ret = false;
+ wchar_t *s;
+
+ s = CopyStrToUni(srcname);
+
+ ret = ZipAddRealFileW(p, name, dt, attribute, s);
+
+ Free(s);
+
+ return ret;
+}
+
+// Start adding a file
+void ZipAddFileStart(ZIP_PACKER *p, char *name, UINT size, UINT64 dt, UINT attribute)
+{
+ char tmp[MAX_PATH];
+ ZIP_FILE *f;
+ ZIP_DATA_HEADER h;
+ // Validate arguments
+ if (p == NULL || IsEmptyStr(name))
+ {
+ return;
+ }
+ if (dt == 0)
+ {
+ dt = LocalTime64();
+ }
+
+ if (p->CurrentFile != NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp, sizeof(tmp), name);
+ ReplaceStrEx(tmp, sizeof(tmp), tmp, "/", "\\", true);
+
+ f = ZeroMalloc(sizeof(ZIP_FILE));
+
+ StrCpy(f->Name, sizeof(f->Name), tmp);
+ f->Size = size;
+ f->DateTime = dt;
+ f->Attributes = attribute;
+
+ Add(p->FileList, f);
+
+ Zero(&h, sizeof(h));
+ f->HeaderPos = (UINT)p->Fifo->total_write_size;
+ WriteZipDataHeader(f, &h, false);
+ WriteFifo(p->Fifo, &h, sizeof(h));
+ WriteFifo(p->Fifo, f->Name, StrLen(f->Name));
+ f->Crc32 = 0xffffffff;
+
+ p->CurrentFile = f;
+}
+
+// Add data to the file
+UINT ZipAddFileData(ZIP_PACKER *p, void *data, UINT pos, UINT len)
+{
+ UINT total_size = p->CurrentFile->CurrentSize + len;
+ UINT ret;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return 0;
+ }
+ if (total_size > p->CurrentFile->Size)
+ {
+ return 0;
+ }
+
+ WriteFifo(p->Fifo, ((UCHAR *)data) + pos, len);
+
+ p->CurrentFile->CurrentSize += len;
+ p->CurrentFile->Crc32 = Crc32Next(data, pos, len, p->CurrentFile->Crc32);
+
+ ret = p->CurrentFile->Size - p->CurrentFile->CurrentSize;
+
+ if (ret == 0)
+ {
+ p->CurrentFile->Crc32 = ~p->CurrentFile->Crc32;
+
+ ZipAddFileFooter(p);
+
+ p->CurrentFile = NULL;
+ }
+
+ return ret;
+}
+
+// Append a file footer
+void ZipAddFileFooter(ZIP_PACKER *p)
+{
+ ZIP_DATA_FOOTER f;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ Zero(&f, sizeof(f));
+ WriteZipDataFooter(p->CurrentFile, &f);
+
+ WriteFifo(p->Fifo, &f, sizeof(f));
+}
+
+// Output the ZIP data to a file
+bool ZipWriteW(ZIP_PACKER *p, wchar_t *name)
+{
+ FIFO *f;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ f = ZipFinish(p);
+ if (f == NULL)
+ {
+ return false;
+ }
+
+ return FileWriteAllW(name, FifoPtr(f), FifoSize(f));
+}
+
+// Complete the creation of the ZIP data
+FIFO *ZipFinish(ZIP_PACKER *p)
+{
+ UINT i;
+ UINT pos_start;
+ UINT pos_end;
+ ZIP_END_HEADER e;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ pos_start = (UINT)p->Fifo->total_write_size;
+
+ for (i = 0;i < LIST_NUM(p->FileList);i++)
+ {
+ ZIP_FILE *f = LIST_DATA(p->FileList, i);
+ ZIP_DIR_HEADER d;
+ ZIP_DATA_HEADER dh;
+
+ Zero(&d, sizeof(d));
+ Zero(&dh, sizeof(dh));
+
+ d.Signature = Endian32(Swap32(0x02014B50));
+ d.MadeVer = Endian16(Swap16(ZIP_VERSION));
+
+ WriteZipDataHeader(f, &dh, true);
+
+ d.NeedVer = dh.NeedVer;
+ d.Option = dh.Option;
+ d.CompType = dh.CompType;
+ d.FileTime = dh.FileTime;
+ d.FileDate = dh.FileDate;
+ d.Crc32 = dh.Crc32;
+ d.CompSize = dh.CompSize;
+ d.UncompSize = dh.UncompSize;
+ d.FileNameLen = dh.FileNameLen;
+ d.ExtraLen = dh.ExtraLen;
+ d.CommentLen = 0;
+ d.DiskNum = 0;
+ d.InAttr = 0;
+ d.OutAttr = Endian32(Swap32((USHORT)f->Attributes));
+ d.HeaderPos = Endian32(Swap32(f->HeaderPos));
+
+ WriteFifo(p->Fifo, &d, sizeof(d));
+ WriteFifo(p->Fifo, f->Name, StrLen(f->Name));
+ }
+
+ pos_end = (UINT)p->Fifo->total_write_size;
+
+ Zero(&e, sizeof(e));
+ e.Signature = Endian32(Swap32(ZIP_SIGNATURE_END));
+ e.DiskNum = e.StartDiskNum = 0;
+ e.DiskDirEntry = e.DirEntry = Endian16(Swap16((USHORT)LIST_NUM(p->FileList)));
+ e.DirSize = Endian32(Swap32((UINT)(pos_end - pos_start)));
+ e.StartPos = Endian32(Swap32(pos_start));
+ e.CommentLen = 0;
+
+ WriteFifo(p->Fifo, &e, sizeof(e));
+
+ return p->Fifo;
+}
+
+// Creating a ZIP data header
+void WriteZipDataHeader(ZIP_FILE *f, ZIP_DATA_HEADER *h, bool write_sizes)
+{
+ // Validate arguments
+ if (f == NULL || h ==NULL)
+ {
+ return;
+ }
+
+ h->Signature = Endian32(Swap32(ZIP_SIGNATURE));
+ h->NeedVer = Endian16(Swap16(ZIP_VERSION));
+ h->CompType = 0;
+ h->FileDate = Endian16(Swap16(System64ToDosDate(f->DateTime)));
+ h->FileTime = Endian16(Swap16(System64ToDosTime(f->DateTime)));
+ h->Option = Endian16(Swap16(8)); // bit3: Set the file-size and the CRC in local header to 0
+
+ if (write_sizes == false)
+ {
+ h->CompSize = h->UncompSize = 0;
+ h->Crc32 = 0;
+ }
+ else
+ {
+ h->CompSize = h->UncompSize = Endian32(Swap32(f->Size));
+ h->Crc32 = Endian32(Swap32(f->Crc32));
+ }
+
+ h->FileNameLen = Endian16(Swap16(StrLen(f->Name)));
+ h->ExtraLen = 0;
+}
+
+// Creating a ZIP data footer
+void WriteZipDataFooter(ZIP_FILE *f, ZIP_DATA_FOOTER *h)
+{
+ // Validate arguments
+ if (f == NULL || h ==NULL)
+ {
+ return;
+ }
+
+ h->Signature = Endian32(Swap32(0x08074B50));
+ h->CompSize = h->UncompSize = Endian32(Swap32(f->Size));
+ h->Crc32 = Endian32(Swap32(f->Crc32));
+}
+
+// Initialize the common table of CRC32
+void InitCrc32()
+{
+ UINT poly = 0xEDB88320;
+ UINT u, i, j;
+
+ for (i = 0;i < 256;i++)
+ {
+ u = i;
+
+ for (j = 0;j < 8;j++)
+ {
+ if ((u & 0x1) != 0)
+ {
+ u = (u >> 1) ^ poly;
+ }
+ else
+ {
+ u >>= 1;
+ }
+ }
+
+ crc32_table[i] = u;
+ }
+}
+
+// CRC32 arithmetic processing
+UINT Crc32(void *buf, UINT pos, UINT len)
+{
+ return Crc32Finish(Crc32First(buf, pos, len));
+}
+UINT Crc32First(void *buf, UINT pos, UINT len)
+{
+ return Crc32Next(buf, pos, len, 0xffffffff);
+}
+UINT Crc32Next(void *buf, UINT pos, UINT len, UINT last_crc32)
+{
+ UINT ret = last_crc32;
+ UINT i;
+
+ for (i = 0;i < len;i++)
+ {
+ ret = (ret >> 8) ^ crc32_table[((UCHAR *)buf)[pos + i] ^ (ret & 0xff)];
+ }
+
+ return ret;
+}
+UINT Crc32Finish(UINT last_crc32)
+{
+ return ~last_crc32;
+}
+
+// Save the file
+bool SaveFileW(wchar_t *name, void *data, UINT size)
+{
+ IO *io;
+ // Validate arguments
+ if (name == NULL || (data == NULL && size != 0))
+ {
+ return false;
+ }
+
+ io = FileCreateW(name);
+ if (io == NULL)
+ {
+ return false;
+ }
+
+ if (FileWrite(io, data, size) == false)
+ {
+ FileClose(io);
+ return false;
+ }
+
+ FileClose(io);
+
+ return true;
+}
+bool SaveFile(char *name, void *data, UINT size)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = SaveFileW(name_w, data, size);
+
+ Free(name_w);
+
+ return ret;
+}
+
+// Check whether the file exists
+bool IsFile(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = IsFileW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool IsFileW(wchar_t *name)
+{
+ IO *io;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ io = FileOpenExW(name, false, false);
+ if (io == NULL)
+ {
+ return false;
+ }
+
+ FileClose(io);
+
+ return true;
+}
+
+// Rename to replace the file
+bool FileReplaceRename(char *old_name, char *new_name)
+{
+ wchar_t *old_name_w = CopyStrToUni(old_name);
+ wchar_t *new_name_w = CopyStrToUni(new_name);
+ bool ret = FileReplaceRenameW(old_name_w, new_name_w);
+
+ Free(old_name_w);
+ Free(new_name_w);
+
+ return ret;
+}
+bool FileReplaceRenameW(wchar_t *old_name, wchar_t *new_name)
+{
+ // Validate arguments
+ if (old_name == NULL || new_name == NULL)
+ {
+ return false;
+ }
+
+ if (FileCopyW(old_name, new_name) == false)
+ {
+ return false;
+ }
+
+ FileDeleteW(old_name);
+
+ return true;
+}
+
+// Make the file name safe
+void ConvertSafeFileName(char *dst, UINT size, char *src)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ StrCpy(dst, size, src);
+ for (i = 0;i < StrLen(dst);i++)
+ {
+ if (IsSafeChar(dst[i]) == false)
+ {
+ dst[i] = '_';
+ }
+ }
+}
+void ConvertSafeFileNameW(wchar_t *dst, UINT size, wchar_t *src)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ UniStrCpy(dst, size, src);
+ for (i = 0;i < UniStrLen(dst);i++)
+ {
+ if (UniIsSafeChar(dst[i]) == false)
+ {
+ dst[i] = L'_';
+ }
+ }
+}
+
+// Get the free disk space
+bool GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
+{
+ bool ret;
+ // Validate arguments
+ if (path == NULL)
+ {
+ path = "./";
+ }
+
+#ifdef OS_WIN32
+ ret = Win32GetDiskFree(path, free_size, used_size, total_size);
+#else // OS_WIN32
+ ret = UnixGetDiskFree(path, free_size, used_size, total_size);
+#endif // OS_WIN32
+
+ return ret;
+}
+bool GetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
+{
+ bool ret;
+ // Validate arguments
+ if (path == NULL)
+ {
+ path = L"./";
+ }
+
+#ifdef OS_WIN32
+ ret = Win32GetDiskFreeW(path, free_size, used_size, total_size);
+#else // OS_WIN32
+ ret = UnixGetDiskFreeW(path, free_size, used_size, total_size);
+#endif // OS_WIN32
+
+ return ret;
+}
+
+// Enumeration of directory
+DIRLIST *EnumDirEx(char *dirname, COMPARE *compare)
+{
+ wchar_t *dirname_w = CopyStrToUni(dirname);
+ DIRLIST *ret = EnumDirExW(dirname_w, compare);
+
+ Free(dirname_w);
+
+ return ret;
+}
+DIRLIST *EnumDirExW(wchar_t *dirname, COMPARE *compare)
+{
+ DIRLIST *d = NULL;
+ // Validate arguments
+ if (dirname == NULL)
+ {
+ dirname = L"./";
+ }
+
+ if (compare == NULL)
+ {
+ compare = CompareDirListByName;
+ }
+
+#ifdef OS_WIN32
+ d = Win32EnumDirExW(dirname, compare);
+#else // OS_WIN32
+ d = UnixEnumDirExW(dirname, compare);
+#endif // OS_WIN32
+
+ return d;
+}
+DIRLIST *EnumDir(char *dirname)
+{
+ return EnumDirEx(dirname, NULL);
+}
+DIRLIST *EnumDirW(wchar_t *dirname)
+{
+ return EnumDirExW(dirname, NULL);
+}
+
+// Comparison of DIRLIST list entry
+int CompareDirListByName(void *p1, void *p2)
+{
+ DIRENT *d1, *d2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ d1 = *(DIRENT **)p1;
+ d2 = *(DIRENT **)p2;
+ if (d1 == NULL || d2 == NULL)
+ {
+ return 0;
+ }
+ return UniStrCmpi(d1->FileNameW, d2->FileNameW);
+}
+
+// Release the enumeration of the directory
+void FreeDir(DIRLIST *d)
+{
+ UINT i;
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < d->NumFiles;i++)
+ {
+ DIRENT *f = d->File[i];
+ Free(f->FileName);
+ Free(f->FileNameW);
+ Free(f);
+ }
+ Free(d->File);
+ Free(d);
+}
+
+
+// Make the file name safe
+void UniSafeFileName(wchar_t *name)
+{
+ UINT i, len, dlen;
+ static wchar_t *danger_str = L"\\/:*?\"<>|";
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ dlen = UniStrLen(danger_str);
+ len = UniStrLen(name);
+
+ for (i = 0;i < len;i++)
+ {
+ wchar_t c = name[i];
+ UINT j;
+ for (j = 0;j < dlen;j++)
+ {
+ if (c == danger_str[j])
+ {
+ c = L'_';
+ }
+ }
+ name[i] = c;
+ }
+}
+void SafeFileNameW(wchar_t *name)
+{
+ UniSafeFileName(name);
+}
+
+// Read HamCore file
+BUF *ReadHamcoreW(wchar_t *filename)
+{
+ char *filename_a = CopyUniToStr(filename);
+ BUF *ret;
+
+ ret = ReadHamcore(filename_a);
+
+ Free(filename_a);
+
+ return ret;
+}
+BUF *ReadHamcore(char *name)
+{
+ wchar_t tmp[MAX_SIZE];
+ wchar_t exe_dir[MAX_SIZE];
+ BUF *b;
+ char filename[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (name[0] == '|')
+ {
+ name++;
+ }
+
+ if (name[0] == '/' || name[0] == '\\')
+ {
+ name++;
+ }
+
+ StrCpy(filename, sizeof(filename), name);
+
+ ReplaceStrEx(filename, sizeof(filename), filename, "/", "\\", true);
+
+ if (MayaquaIsMinimalMode())
+ {
+ return NULL;
+ }
+
+ // If the file exist in hamcore/ directory on the local disk, read it
+ GetExeDirW(exe_dir, sizeof(exe_dir));
+
+ UniFormat(tmp, sizeof(tmp), L"%s/%S/%S", exe_dir, HAMCORE_DIR_NAME, filename);
+
+ b = ReadDumpW(tmp);
+ if (b != NULL)
+ {
+ return b;
+ }
+
+ // Search from HamCore file system if it isn't found
+ LockList(hamcore);
+ {
+ HC t, *c;
+ UINT i;
+
+ Zero(&t, sizeof(t));
+ t.FileName = filename;
+ c = Search(hamcore, &t);
+
+ if (c == NULL)
+ {
+ // File does not exist
+ b = NULL;
+ }
+ else
+ {
+ // File exists
+ if (c->Buffer != NULL)
+ {
+ // It is already loaded
+ b = NewBuf();
+ WriteBuf(b, c->Buffer, c->Size);
+ SeekBuf(b, 0, 0);
+ c->LastAccess = Tick64();
+ }
+ else
+ {
+ // Read from a file is if it is not read
+ if (FileSeek(hamcore_io, 0, c->Offset) == false)
+ {
+ // Failed to seek
+ b = NULL;
+ }
+ else
+ {
+ // Read the compressed data
+ void *data = Malloc(c->SizeCompressed);
+ if (FileRead(hamcore_io, data, c->SizeCompressed) == false)
+ {
+ // Failed to read
+ Free(data);
+ b = NULL;
+ }
+ else
+ {
+ // Expand
+ c->Buffer = ZeroMalloc(c->Size);
+ if (Uncompress(c->Buffer, c->Size, data, c->SizeCompressed) != c->Size)
+ {
+ // Failed to expand
+ Free(data);
+ Free(c->Buffer);
+ b = NULL;
+ }
+ else
+ {
+ // Successful
+ Free(data);
+ b = NewBuf();
+ WriteBuf(b, c->Buffer, c->Size);
+ SeekBuf(b, 0, 0);
+ c->LastAccess = Tick64();
+ }
+ }
+ }
+ }
+ }
+
+ // Delete the expired cache
+ for (i = 0;i < LIST_NUM(hamcore);i++)
+ {
+ HC *c = LIST_DATA(hamcore, i);
+
+ if (c->Buffer != NULL)
+ {
+ if (((c->LastAccess + HAMCORE_CACHE_EXPIRES) <= Tick64()) ||
+ (StartWith(c->FileName, "Li")))
+ {
+ Free(c->Buffer);
+ c->Buffer = NULL;
+ }
+ }
+ }
+ }
+ UnlockList(hamcore);
+
+ return b;
+}
+
+// Initialization of HamCore file system
+void InitHamcore()
+{
+ wchar_t tmp[MAX_PATH];
+ wchar_t tmp2[MAX_PATH];
+ wchar_t exe_dir[MAX_PATH];
+ UINT i, num;
+ char header[HAMCORE_HEADER_SIZE];
+
+ hamcore = NewList(CompareHamcore);
+
+ if (MayaquaIsMinimalMode())
+ {
+ return;
+ }
+
+ GetExeDirW(exe_dir, sizeof(exe_dir));
+ UniFormat(tmp, sizeof(tmp), L"%s/%S", exe_dir, HAMCORE_FILE_NAME);
+
+ UniFormat(tmp2, sizeof(tmp2), L"%s/%S", exe_dir, HAMCORE_FILE_NAME_2);
+
+ // If there is _hamcore.se2, overwrite it yo the hamcore.se2
+ FileReplaceRenameW(tmp2, tmp);
+
+ // Read if there is a file hamcore.se2
+ hamcore_io = FileOpenW(tmp, false);
+ if (hamcore_io == NULL)
+ {
+ // Look in other locations if it isn't found
+#ifdef OS_WIN32
+ UniFormat(tmp, sizeof(tmp), L"%S/%S", MsGetSystem32Dir(), HAMCORE_FILE_NAME);
+#else // OS_WIN32
+ UniFormat(tmp, sizeof(tmp), L"/bin/%S", HAMCORE_FILE_NAME);
+#endif // OS_WIN32
+
+ hamcore_io = FileOpenW(tmp, false);
+ if (hamcore_io == NULL)
+ {
+ return;
+ }
+ }
+
+ // Read the file header
+ Zero(header, sizeof(header));
+ FileRead(hamcore_io, header, HAMCORE_HEADER_SIZE);
+
+ if (Cmp(header, HAMCORE_HEADER_DATA, HAMCORE_HEADER_SIZE) != 0)
+ {
+ // Invalid header
+ FileClose(hamcore_io);
+ hamcore_io = NULL;
+ return;
+ }
+
+ // The number of the File
+ num = 0;
+ FileRead(hamcore_io, &num, sizeof(num));
+ num = Endian32(num);
+ for (i = 0;i < num;i++)
+ {
+ // File name
+ char tmp[MAX_SIZE];
+ UINT str_size = 0;
+ HC *c;
+
+ FileRead(hamcore_io, &str_size, sizeof(str_size));
+ str_size = Endian32(str_size);
+ if (str_size >= 1)
+ {
+ str_size--;
+ }
+
+ Zero(tmp, sizeof(tmp));
+ FileRead(hamcore_io, tmp, str_size);
+
+ c = ZeroMalloc(sizeof(HC));
+ c->FileName = CopyStr(tmp);
+
+ FileRead(hamcore_io, &c->Size, sizeof(UINT));
+ c->Size = Endian32(c->Size);
+
+ FileRead(hamcore_io, &c->SizeCompressed, sizeof(UINT));
+ c->SizeCompressed = Endian32(c->SizeCompressed);
+
+ FileRead(hamcore_io, &c->Offset, sizeof(UINT));
+ c->Offset = Endian32(c->Offset);
+
+ Insert(hamcore, c);
+ }
+}
+
+// Release of HamCore file system
+void FreeHamcore()
+{
+ UINT i;
+ for (i = 0;i < LIST_NUM(hamcore);i++)
+ {
+ HC *c = LIST_DATA(hamcore, i);
+ Free(c->FileName);
+ if (c->Buffer != NULL)
+ {
+ Free(c->Buffer);
+ }
+ Free(c);
+ }
+ ReleaseList(hamcore);
+
+ FileClose(hamcore_io);
+ hamcore_io = NULL;
+ hamcore = NULL;
+}
+
+// Build a Hamcore file
+void BuildHamcore()
+{
+ BUF *b;
+ char tmp[MAX_SIZE];
+ char exe_dir[MAX_SIZE];
+ char *s;
+ bool ok = true;
+ LIST *o;
+ UINT i;
+
+ GetExeDir(exe_dir, sizeof(exe_dir));
+ Format(tmp, sizeof(tmp), "%s/%s", exe_dir, HAMCORE_TEXT_NAME);
+
+ b = ReadDump(tmp);
+ if (b == NULL)
+ {
+ Print("Failed to open %s.\n", tmp);
+ return;
+ }
+
+ o = NewListFast(CompareHamcore);
+
+ while ((s = CfgReadNextLine(b)) != NULL)
+ {
+ char tmp[MAX_SIZE];
+ BUF *b;
+ Trim(s);
+
+ Format(tmp, sizeof(tmp), "%s/%s/%s", exe_dir, HAMCORE_DIR_NAME, s);
+
+ b = ReadDump(tmp);
+ if (b == NULL)
+ {
+ Print("Failed to open %s.\n", s);
+ ok = false;
+ }
+ else
+ {
+ HC *c = ZeroMalloc(sizeof(HC));
+ UINT tmp_size;
+ void *tmp;
+ c->FileName = CopyStr(s);
+ c->Size = b->Size;
+ tmp_size = CalcCompress(c->Size);
+ tmp = Malloc(tmp_size);
+ c->SizeCompressed = Compress(tmp, tmp_size, b->Buf, b->Size);
+ c->Buffer = tmp;
+ Insert(o, c);
+ Print("%s: %u -> %u\n", s, c->Size, c->SizeCompressed);
+ FreeBuf(b);
+ }
+
+ Free(s);
+ }
+
+ if (ok)
+ {
+ // Calculate the offset of the buffer for each file
+ UINT i, z;
+ char tmp[MAX_SIZE];
+ BUF *b;
+ z = 0;
+ z += HAMCORE_HEADER_SIZE;
+ // The number of files
+ z += sizeof(UINT);
+ // For file table first
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HC *c = LIST_DATA(o, i);
+ // File name
+ z += StrLen(c->FileName) + sizeof(UINT);
+ // File size
+ z += sizeof(UINT);
+ z += sizeof(UINT);
+ // Offset data
+ z += sizeof(UINT);
+ }
+ // File body
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HC *c = LIST_DATA(o, i);
+ // Buffer body
+ c->Offset = z;
+ printf("%s: offset: %u\n", c->FileName, c->Offset);
+ z += c->SizeCompressed;
+ }
+ // Writing
+ b = NewBuf();
+ // Header
+ WriteBuf(b, HAMCORE_HEADER_DATA, HAMCORE_HEADER_SIZE);
+ WriteBufInt(b, LIST_NUM(o));
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HC *c = LIST_DATA(o, i);
+ // File name
+ WriteBufStr(b, c->FileName);
+ // File size
+ WriteBufInt(b, c->Size);
+ WriteBufInt(b, c->SizeCompressed);
+ // Offset
+ WriteBufInt(b, c->Offset);
+ }
+ // Body
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HC *c = LIST_DATA(o, i);
+ WriteBuf(b, c->Buffer, c->SizeCompressed);
+ }
+ // Writing
+ Format(tmp, sizeof(tmp), "%s/%s", exe_dir, HAMCORE_FILE_NAME "__");
+ Print("Writing %s...\n", tmp);
+ FileDelete(tmp);
+ DumpBuf(b, tmp);
+ FreeBuf(b);
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HC *c = LIST_DATA(o, i);
+ Free(c->Buffer);
+ Free(c->FileName);
+ Free(c);
+ }
+
+ ReleaseList(o);
+
+ FreeBuf(b);
+}
+
+// Comparison of the HCs
+int CompareHamcore(void *p1, void *p2)
+{
+ HC *c1, *c2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ c1 = *(HC **)p1;
+ c2 = *(HC **)p2;
+ if (c1 == NULL || c2 == NULL)
+ {
+ return 0;
+ }
+ return StrCmpi(c1->FileName, c2->FileName);
+}
+
+// Getting the name of the directory where the EXE file is in
+void GetExeDir(char *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ GetDirNameFromFilePath(name, size, exe_file_name);
+}
+void GetExeDirW(wchar_t *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ GetDirNameFromFilePathW(name, size, exe_file_name_w);
+}
+
+// Get the EXE file name
+void GetExeName(char *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ StrCpy(name, size, exe_file_name);
+}
+void GetExeNameW(wchar_t *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ UniStrCpy(name, size, exe_file_name_w);
+}
+
+// Initialization of the aquisition of the EXE file name
+void InitGetExeName(char *arg)
+{
+ wchar_t *arg_w = NULL;
+ // Validate arguments
+ if (arg == NULL)
+ {
+ arg = "./a.out";
+ }
+
+ arg_w = CopyUtfToUni(arg);
+
+#ifdef OS_WIN32
+ Win32GetExeNameW(exe_file_name_w, sizeof(exe_file_name_w));
+#else // OS_WIN32
+ UnixGetExeNameW(exe_file_name_w, sizeof(exe_file_name_w), arg_w);
+#endif // OS_WIN32
+
+ UniToStr(exe_file_name, sizeof(exe_file_name), exe_file_name_w);
+
+ Free(arg_w);
+}
+
+// Get the full path of the executable binary file in Unix
+void UnixGetExeNameW(wchar_t *name, UINT size, wchar_t *arg)
+{
+ UNI_TOKEN_LIST *t;
+ char *path_str;
+ wchar_t *path_str_w;
+ bool ok = false;
+ // Validate arguments
+ if (name == NULL || arg == NULL)
+ {
+ return;
+ }
+
+ path_str = GetCurrentPathEnvStr();
+ path_str_w = CopyUtfToUni(path_str);
+
+ t = ParseSplitedPathW(path_str_w);
+
+ if (t != NULL)
+ {
+ UINT i;
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ wchar_t *s = t->Token[i];
+ wchar_t tmp[MAX_SIZE];
+
+ ConbinePathW(tmp, sizeof(tmp), s, arg);
+
+ if (IsFileExistsInnerW(tmp))
+ {
+#ifdef OS_UNIX
+ if (UnixCheckExecAccessW(tmp) == false)
+ {
+ continue;
+ }
+#endif // OS_UNIX
+ ok = true;
+ UniStrCpy(name, size, tmp);
+ break;
+ }
+ }
+
+ UniFreeToken(t);
+ }
+
+ Free(path_str);
+ Free(path_str_w);
+
+ if (ok == false)
+ {
+ // In the case of failing to find the path
+#ifdef OS_UNIX
+ UnixGetCurrentDirW(name, size);
+#else // OS_UNIX
+ Win32GetCurrentDirW(name, size);
+#endif // OS_UNIX
+ ConbinePathW(name, size, name, arg);
+ }
+}
+
+// Generate a secure file name
+void MakeSafeFileName(char *dst, UINT size, char *src)
+{
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp, sizeof(tmp), src);
+ ReplaceStrEx(tmp, sizeof(tmp), tmp, "..", "__", false);
+ ReplaceStrEx(tmp, sizeof(tmp), tmp, "/", "_", false);
+ ReplaceStrEx(tmp, sizeof(tmp), tmp, "\\", "_", false);
+ ReplaceStrEx(tmp, sizeof(tmp), tmp, "@", "_", false);
+ ReplaceStrEx(tmp, sizeof(tmp), tmp, "|", "_", false);
+
+ StrCpy(dst, size, tmp);
+}
+void MakeSafeFileNameW(wchar_t *dst, UINT size, wchar_t *src)
+{
+ wchar_t tmp[MAX_PATH];
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), src);
+ UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"..", L"__", false);
+ UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"/", L"_", false);
+ UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"\\", L"_", false);
+ UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"@", L"_", false);
+ UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"|", L"_", false);
+
+ UniStrCpy(dst, size, tmp);
+}
+
+// Get the file name from the file path
+void GetFileNameFromFilePathW(wchar_t *dst, UINT size, wchar_t *filepath)
+{
+ wchar_t tmp[MAX_SIZE];
+ UINT i, len, wp;
+ // Validate arguments
+ if (dst == NULL || filepath == NULL)
+ {
+ return;
+ }
+
+ len = MIN(UniStrLen(filepath), (MAX_SIZE - 2));
+ wp = 0;
+
+ for (i = 0;i < (len + 1);i++)
+ {
+ wchar_t c = filepath[i];
+
+ switch (c)
+ {
+ case L'\\':
+ case L'/':
+ case 0:
+ tmp[wp] = 0;
+ wp = 0;
+ break;
+
+ default:
+ tmp[wp] = c;
+ wp++;
+ break;
+ }
+ }
+
+ UniStrCpy(dst, size, tmp);
+}
+void GetFileNameFromFilePath(char *dst, UINT size, char *filepath)
+{
+ char tmp[MAX_SIZE];
+ UINT i, len, wp;
+ // Validate arguments
+ if (dst == NULL || filepath == NULL)
+ {
+ return;
+ }
+
+ len = MIN(StrLen(filepath), (MAX_SIZE - 2));
+ wp = 0;
+
+ for (i = 0;i < (len + 1);i++)
+ {
+ char c = filepath[i];
+
+ switch (c)
+ {
+ case '\\':
+ case '/':
+ case 0:
+ tmp[wp] = 0;
+ wp = 0;
+ break;
+
+ default:
+ tmp[wp] = c;
+ wp++;
+ break;
+ }
+ }
+
+ StrCpy(dst, size, tmp);
+}
+void GetDirNameFromFilePathW(wchar_t *dst, UINT size, wchar_t *filepath)
+{
+ wchar_t tmp[MAX_SIZE];
+ UINT wp;
+ UINT i;
+ UINT len;
+ // Validate arguments
+ if (dst == NULL || filepath == NULL)
+ {
+ return;
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), filepath);
+ if (UniEndWith(tmp, L"\\") || UniEndWith(tmp, L"/"))
+ {
+ tmp[UniStrLen(tmp) - 1] = 0;
+ }
+
+ len = UniStrLen(tmp);
+
+ UniStrCpy(dst, size, L"");
+
+ wp = 0;
+
+ for (i = 0;i < len;i++)
+ {
+ wchar_t c = tmp[i];
+ if (c == L'/' || c == L'\\')
+ {
+ tmp[wp++] = 0;
+ wp = 0;
+ UniStrCat(dst, size, tmp);
+ tmp[wp++] = c;
+ }
+ else
+ {
+ tmp[wp++] = c;
+ }
+ }
+
+ if (UniStrLen(dst) == 0)
+ {
+ UniStrCpy(dst, size, L"/");
+ }
+
+ NormalizePathW(dst, size, dst);
+}
+
+// Get the directory name from the file path
+void GetDirNameFromFilePath(char *dst, UINT size, char *filepath)
+{
+ char tmp[MAX_SIZE];
+ UINT wp;
+ UINT i;
+ UINT len;
+ // Validate arguments
+ if (dst == NULL || filepath == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp, sizeof(tmp), filepath);
+ if (EndWith(tmp, "\\") || EndWith(tmp, "/"))
+ {
+ tmp[StrLen(tmp) - 1] = 0;
+ }
+
+ len = StrLen(tmp);
+
+ StrCpy(dst, size, "");
+
+ wp = 0;
+
+ for (i = 0;i < len;i++)
+ {
+ char c = tmp[i];
+ if (c == '/' || c == '\\')
+ {
+ tmp[wp++] = 0;
+ wp = 0;
+ StrCat(dst, size, tmp);
+ tmp[wp++] = c;
+ }
+ else
+ {
+ tmp[wp++] = c;
+ }
+ }
+
+ if (StrLen(dst) == 0)
+ {
+ StrCpy(dst, size, "/");
+ }
+
+ NormalizePath(dst, size, dst);
+}
+
+// Combine the two paths
+void ConbinePath(char *dst, UINT size, char *dirname, char *filename)
+{
+ wchar_t dst_w[MAX_PATH];
+ wchar_t *dirname_w = CopyStrToUni(dirname);
+ wchar_t *filename_w = CopyStrToUni(filename);
+
+ ConbinePathW(dst_w, sizeof(dst_w), dirname_w, filename_w);
+
+ Free(dirname_w);
+ Free(filename_w);
+
+ UniToStr(dst, size, dst_w);
+}
+void ConbinePathW(wchar_t *dst, UINT size, wchar_t *dirname, wchar_t *filename)
+{
+ bool is_full_path;
+ wchar_t tmp[MAX_SIZE];
+ wchar_t filename_ident[MAX_SIZE];
+ // Validate arguments
+ if (dst == NULL || dirname == NULL || filename == NULL)
+ {
+ return;
+ }
+
+ NormalizePathW(filename_ident, sizeof(filename_ident), filename);
+
+ is_full_path = false;
+
+ if (UniStartWith(filename_ident, L"\\") || UniStartWith(filename_ident, L"/"))
+ {
+ is_full_path = true;
+ }
+
+ filename = &filename_ident[0];
+
+#ifdef OS_WIN32
+ if (UniStrLen(filename) >= 2)
+ {
+ if ((L'a' <= filename[0] && filename[0] <= L'z') || (L'A' <= filename[0] && filename[0] <= L'Z'))
+ {
+ if (filename[1] == L':')
+ {
+ is_full_path = true;
+ }
+ }
+ }
+#endif // OS_WIN32
+
+ if (is_full_path == false)
+ {
+ UniStrCpy(tmp, sizeof(tmp), dirname);
+ if (UniEndWith(tmp, L"/") == false && UniEndWith(tmp, L"\\") == false)
+ {
+ UniStrCat(tmp, sizeof(tmp), L"/");
+ }
+ UniStrCat(tmp, sizeof(tmp), filename);
+ }
+ else
+ {
+ UniStrCpy(tmp, sizeof(tmp), filename);
+ }
+
+ NormalizePathW(dst, size, tmp);
+}
+void CombinePath(char *dst, UINT size, char *dirname, char *filename)
+{
+ ConbinePath(dst, size, dirname, filename);
+}
+void CombinePathW(wchar_t *dst, UINT size, wchar_t *dirname, wchar_t *filename)
+{
+ ConbinePathW(dst, size, dirname, filename);
+}
+
+// Check whether the file exists
+bool IsFileExists(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = IsFileExistsW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool IsFileExistsW(wchar_t *name)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), name);
+
+ return IsFileExistsInnerW(tmp);
+}
+bool IsFileExistsInner(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = IsFileExistsInnerW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool IsFileExistsInnerW(wchar_t *name)
+{
+ IO *o;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ o = FileOpenInnerW(name, false, false);
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ FileClose(o);
+
+ return true;
+}
+
+// Get the current contents of the PATH environment variable
+char *GetCurrentPathEnvStr()
+{
+ char tmp[1024];
+ char *tag_name;
+
+#ifdef OS_WIN32
+ tag_name = "Path";
+#else // OS_WIN32
+ tag_name = "PATH";
+#endif // OS_WIN32
+
+ if (GetEnv(tag_name, tmp, sizeof(tmp)) == false)
+ {
+#ifdef OS_WIN32
+ Win32GetCurrentDir(tmp, sizeof(tmp));
+#else // OS_WIN32
+ UnixGetCurrentDir(tmp, sizeof(tmp));
+#endif // OS_WIN32
+ }
+
+ return CopyStr(tmp);
+}
+
+// Get multiple paths separated by colons
+UNI_TOKEN_LIST *ParseSplitedPathW(wchar_t *path)
+{
+ UNI_TOKEN_LIST *ret;
+ wchar_t *tmp = UniCopyStr(path);
+ wchar_t *split_str;
+ UINT i;
+
+ UniTrim(tmp);
+ UniTrimCrlf(tmp);
+ UniTrim(tmp);
+ UniTrimCrlf(tmp);
+
+#ifdef OS_WIN32
+ split_str = L";";
+#else // OS_WIN32
+ split_str = L":";
+#endif // OS_WIN32
+
+ ret = UniParseToken(tmp, split_str);
+
+ if (ret != NULL)
+ {
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ UniTrim(ret->Token[i]);
+ UniTrimCrlf(ret->Token[i]);
+ UniTrim(ret->Token[i]);
+ UniTrimCrlf(ret->Token[i]);
+ }
+ }
+
+ Free(tmp);
+
+ return ret;
+}
+TOKEN_LIST *ParseSplitedPath(char *path)
+{
+ TOKEN_LIST *ret;
+ char *tmp = CopyStr(path);
+ char *split_str;
+ UINT i;
+
+ Trim(tmp);
+ TrimCrlf(tmp);
+ Trim(tmp);
+ TrimCrlf(tmp);
+
+#ifdef OS_WIN32
+ split_str = ";";
+#else // OS_WIN32
+ split_str = ":";
+#endif // OS_WIN32
+
+ ret = ParseToken(tmp, split_str);
+
+ if (ret != NULL)
+ {
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ Trim(ret->Token[i]);
+ TrimCrlf(ret->Token[i]);
+ Trim(ret->Token[i]);
+ TrimCrlf(ret->Token[i]);
+ }
+ }
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Get the current directory
+void GetCurrentDirW(wchar_t *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ Win32GetCurrentDirW(name, size);
+#else // OS_WIN32
+ UnixGetCurrentDirW(name, size);
+#endif // OS_WIN32
+}
+void GetCurrentDir(char *name, UINT size)
+{
+ wchar_t name_w[MAX_PATH];
+
+ GetCurrentDirW(name_w, sizeof(name_w));
+
+ UniToStr(name, size, name_w);
+}
+
+// Normalize the file path
+void NormalizePathW(wchar_t *dst, UINT size, wchar_t *src)
+{
+ wchar_t tmp[MAX_SIZE];
+ UNI_TOKEN_LIST *t;
+ bool first_double_slash = false;
+ bool first_single_slash = false;
+ wchar_t win32_drive_char = 0;
+ bool is_full_path = false;
+ UINT i;
+ SK *sk;
+ // Validate arguments
+ if (dst == NULL || src == 0)
+ {
+ return;
+ }
+
+ // Convert the path (Win32, UNIX conversion)
+ UniStrCpy(tmp, sizeof(tmp), src);
+ ConvertPathW(tmp);
+ UniTrim(tmp);
+
+ // If the path begins with "./ " or " ../", replace it to the current directory
+ if (UniStartWith(tmp, L"./") || UniStartWith(tmp, L".\\") ||
+ UniStartWith(tmp, L"../") || UniStartWith(tmp, L"..\\") ||
+ UniStrCmpi(tmp, L".") == 0 || UniStrCmpi(tmp, L"..") == 0)
+ {
+ wchar_t cd[MAX_SIZE];
+ Zero(cd, sizeof(cd));
+
+#ifdef OS_WIN32
+ Win32GetCurrentDirW(cd, sizeof(cd));
+#else // OS_WIN32
+ UnixGetCurrentDirW(cd, sizeof(cd));
+#endif // OS_WIN32
+
+ if (UniStartWith(tmp, L".."))
+ {
+ UniStrCat(cd, sizeof(cd), L"/../");
+ UniStrCat(cd, sizeof(cd), tmp + 2);
+ }
+ else
+ {
+ UniStrCat(cd, sizeof(cd), L"/");
+ UniStrCat(cd, sizeof(cd), tmp);
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), cd);
+ }
+
+ // If the path starts with "~/", replace it with the home directory
+ if (UniStartWith(tmp, L"~/") || UniStartWith(tmp, L"~\\"))
+ {
+ wchar_t tmp2[MAX_SIZE];
+ GetHomeDirW(tmp2, sizeof(tmp2));
+ UniStrCat(tmp2, sizeof(tmp2), L"/");
+ UniStrCat(tmp2, sizeof(tmp2), tmp + 2);
+ UniStrCpy(tmp, sizeof(tmp), tmp2);
+ }
+
+ if (UniStartWith(tmp, L"//") || UniStartWith(tmp, L"\\\\"))
+ {
+ // Begin with "//" or "\\"
+ first_double_slash = true;
+ is_full_path = true;
+ }
+ else if (UniStartWith(tmp, L"/") || UniStartWith(tmp, L"\\"))
+ {
+ // Begin with "\"
+ first_single_slash = true;
+ is_full_path = true;
+ }
+
+#ifdef OS_WIN32
+ if (UniStrLen(tmp) >= 2)
+ {
+ if (tmp[1] == L':')
+ {
+ // The drive string representation of the Win32
+ wchar_t tmp2[MAX_SIZE];
+ is_full_path = true;
+ win32_drive_char = tmp[0];
+ UniStrCpy(tmp2, sizeof(tmp2), tmp + 2);
+ UniStrCpy(tmp, sizeof(tmp), tmp2);
+ }
+ }
+#endif // OS_WIN32
+
+ if (UniStrLen(tmp) == 1 && (tmp[0] == L'/' || tmp[0] == L'\\'))
+ {
+ tmp[0] = 0;
+ }
+
+ // Tokenize
+ t = UniParseToken(tmp, L"/\\");
+
+ sk = NewSk();
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ wchar_t *s = t->Token[i];
+
+ if (UniStrCmpi(s, L".") == 0)
+ {
+ continue;
+ }
+ else if (UniStrCmpi(s, L"..") == 0)
+ {
+ if (sk->num_item >= 1 && (first_double_slash == false || sk->num_item >= 2))
+ {
+ Pop(sk);
+ }
+ }
+ else
+ {
+ Push(sk, s);
+ }
+ }
+
+ // Token concatenation
+ UniStrCpy(tmp, sizeof(tmp), L"");
+
+ if (first_double_slash)
+ {
+ UniStrCat(tmp, sizeof(tmp), L"//");
+ }
+ else if (first_single_slash)
+ {
+ UniStrCat(tmp, sizeof(tmp), L"/");
+ }
+
+ if (win32_drive_char != 0)
+ {
+ wchar_t d[2];
+ d[0] = win32_drive_char;
+ d[1] = 0;
+ UniStrCat(tmp, sizeof(tmp), d);
+ UniStrCat(tmp, sizeof(tmp), L":/");
+ }
+
+ for (i = 0;i < sk->num_item;i++)
+ {
+ UniStrCat(tmp, sizeof(tmp), (wchar_t *)sk->p[i]);
+ if (i != (sk->num_item - 1))
+ {
+ UniStrCat(tmp, sizeof(tmp), L"/");
+ }
+ }
+
+ ReleaseSk(sk);
+
+ UniFreeToken(t);
+
+ ConvertPathW(tmp);
+
+ UniStrCpy(dst, size, tmp);
+}
+void NormalizePath(char *dst, UINT size, char *src)
+{
+ wchar_t dst_w[MAX_SIZE];
+ wchar_t *src_w = CopyStrToUni(src);
+
+ NormalizePathW(dst_w, sizeof(dst_w), src_w);
+
+ Free(src_w);
+
+ UniToStr(dst, size, dst_w);
+}
+
+// Close and delete the file
+void FileCloseAndDelete(IO *o)
+{
+ wchar_t *name;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ name = CopyUniStr(o->NameW);
+ FileClose(o);
+
+ FileDeleteW(name);
+
+ Free(name);
+}
+
+// Rename the file
+bool FileRename(char *old_name, char *new_name)
+{
+ wchar_t *old_name_w = CopyStrToUni(old_name);
+ wchar_t *new_name_w = CopyStrToUni(new_name);
+ bool ret = FileRenameW(old_name_w, new_name_w);
+
+ Free(old_name_w);
+ Free(new_name_w);
+
+ return ret;
+}
+bool FileRenameW(wchar_t *old_name, wchar_t *new_name)
+{
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ // Validate arguments
+ if (old_name == NULL || new_name == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePathW(tmp1, sizeof(tmp1), old_name);
+ InnerFilePathW(tmp2, sizeof(tmp2), new_name);
+
+ return FileRenameInnerW(tmp1, tmp2);
+}
+bool FileRenameInner(char *old_name, char *new_name)
+{
+ wchar_t *old_name_w = CopyStrToUni(old_name);
+ wchar_t *new_name_w = CopyStrToUni(new_name);
+ bool ret = FileRenameInnerW(old_name_w, new_name_w);
+
+ Free(old_name_w);
+ Free(new_name_w);
+
+ return ret;
+}
+bool FileRenameInnerW(wchar_t *old_name, wchar_t *new_name)
+{
+ // Validate arguments
+ if (old_name == NULL || new_name == NULL)
+ {
+ return false;
+ }
+
+ return OSFileRenameW(old_name, new_name);
+}
+
+// Convert the path
+void ConvertPath(char *path)
+{
+ UINT i, len;
+#ifdef PATH_BACKSLASH
+ char new_char = '\\';
+#else
+ char new_char = '/';
+#endif
+
+ len = StrLen(path);
+ for (i = 0;i < len;i++)
+ {
+ if (path[i] == '\\' || path[i] == '/')
+ {
+ path[i] = new_char;
+ }
+ }
+}
+void ConvertPathW(wchar_t *path)
+{
+ UINT i, len;
+#ifdef PATH_BACKSLASH
+ wchar_t new_char = L'\\';
+#else
+ wchar_t new_char = L'/';
+#endif
+
+ len = UniStrLen(path);
+ for (i = 0;i < len;i++)
+ {
+ if (path[i] == L'\\' || path[i] == L'/')
+ {
+ path[i] = new_char;
+ }
+ }
+}
+
+// Delete the directory
+bool DeleteDir(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = DeleteDirW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool DeleteDirW(wchar_t *name)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), name);
+
+ return DeleteDirInnerW(tmp);
+}
+bool DeleteDirInner(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = DeleteDirInnerW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool DeleteDirInnerW(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ return OSDeleteDirW(name);
+}
+
+// Generation of internal file path
+void InnerFilePathW(wchar_t *dst, UINT size, wchar_t *src)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ if (src[0] != L'@')
+ {
+ NormalizePathW(dst, size, src);
+ }
+ else
+ {
+ wchar_t dir[MAX_SIZE];
+ GetExeDirW(dir, sizeof(dir));
+ ConbinePathW(dst, size, dir, &src[1]);
+ }
+}
+void InnerFilePath(char *dst, UINT size, char *src)
+{
+ wchar_t dst_w[MAX_PATH];
+ wchar_t *src_w = CopyStrToUni(src);
+
+ InnerFilePathW(dst_w, sizeof(dst_w), src_w);
+
+ Free(src_w);
+
+ UniToStr(dst, size, dst_w);
+}
+
+// Recursive directory creation
+bool MakeDirEx(char *name)
+{
+ bool ret;
+ wchar_t *name_w = CopyStrToUni(name);
+
+ ret = MakeDirExW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool MakeDirExW(wchar_t *name)
+{
+ LIST *o;
+ wchar_t tmp[MAX_PATH];
+ wchar_t tmp2[MAX_PATH];
+ UINT i;
+ bool ret;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ o = NewListFast(NULL);
+
+ UniStrCpy(tmp, sizeof(tmp), name);
+ while (true)
+ {
+ wchar_t *s = CopyUniStr(tmp);
+
+ Add(o, s);
+
+ GetDirNameFromFilePathW(tmp2, sizeof(tmp2), tmp);
+
+ if (UniStrCmpi(tmp2, tmp) == 0)
+ {
+ break;
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), tmp2);
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ UINT j = LIST_NUM(o) - i - 1;
+ wchar_t *s = LIST_DATA(o, j);
+
+ if (UniStrCmpi(s, L"\\") != 0 && UniStrCmpi(s, L"/") != 0)
+ {
+ ret = MakeDirW(s);
+ }
+ }
+
+ UniFreeStrList(o);
+
+ return ret;
+}
+
+// Create a directory
+bool MakeDir(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = MakeDirW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool MakeDirW(wchar_t *name)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), name);
+
+ return MakeDirInnerW(tmp);
+}
+bool MakeDirInner(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = MakeDirInnerW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool MakeDirInnerW(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ return OSMakeDirW(name);
+}
+
+// Delete the file
+bool FileDelete(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = FileDeleteW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool FileDeleteW(wchar_t *name)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), name);
+
+ return FileDeleteInnerW(tmp);
+}
+bool FileDeleteInner(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ bool ret = FileDeleteInnerW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+bool FileDeleteInnerW(wchar_t *name)
+{
+ wchar_t name2[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ UniStrCpy(name2, sizeof(name2), name);
+ ConvertPathW(name2);
+
+ return OSFileDeleteW(name2);
+}
+
+// Seek the file
+bool FileSeek(IO *o, UINT mode, int offset)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ if (o->HamMode == false)
+ {
+ return OSFileSeek(o->pData, mode, offset);
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Get the file size by specifying the file name
+UINT FileSizeEx(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ UINT ret = FileSizeExW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+UINT FileSizeExW(wchar_t *name)
+{
+ IO *io;
+ UINT size;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return 0;
+ }
+
+ io = FileOpenW(name, false);
+ if (io == NULL)
+ {
+ return 0;
+ }
+
+ size = FileSize(io);
+
+ FileClose(io);
+
+ return size;
+}
+
+// Get the file size
+UINT64 FileSize64(IO *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return 0;
+ }
+
+ if (o->HamMode == false)
+ {
+ return OSFileSize(o->pData);
+ }
+ else
+ {
+ return (UINT64)o->HamBuf->Size;
+ }
+}
+UINT FileSize(IO *o)
+{
+ UINT64 size = (UINT)(FileSize64(o));
+
+ if (size >= 4294967296ULL)
+ {
+ size = 4294967295ULL;
+ }
+
+ return (UINT)size;
+}
+
+// Read from a file
+bool FileRead(IO *o, void *buf, UINT size)
+{
+ // Validate arguments
+ if (o == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // KS
+ KS_INC(KS_IO_READ_COUNT);
+ KS_ADD(KS_IO_TOTAL_READ_SIZE, size);
+
+ if (size == 0)
+ {
+ return true;
+ }
+
+ if (o->HamMode == false)
+ {
+ return OSFileRead(o->pData, buf, size);
+ }
+ else
+ {
+ return ReadBuf(o->HamBuf, buf, size) == size ? true : false;
+ }
+}
+
+// Write to a file
+bool FileWrite(IO *o, void *buf, UINT size)
+{
+ // Validate arguments
+ if (o == NULL || buf == NULL)
+ {
+ return false;
+ }
+ if (o->WriteMode == false)
+ {
+ return false;
+ }
+
+ // KS
+ KS_INC(KS_IO_WRITE_COUNT);
+ KS_ADD(KS_IO_TOTAL_WRITE_SIZE, size);
+
+ if (size == 0)
+ {
+ return true;
+ }
+
+ return OSFileWrite(o->pData, buf, size);
+}
+
+// Flush the file
+void FileFlush(IO *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (o->HamMode)
+ {
+ return;
+ }
+
+ OSFileFlush(o->pData);
+}
+
+// Close the file
+void FileClose(IO *o)
+{
+ FileCloseEx(o, false);
+}
+void FileCloseEx(IO *o, bool no_flush)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (o->HamMode == false)
+ {
+ if (o->WriteMode)
+ {
+#ifdef OS_WIN32
+ Win32FileSetDate(o->pData, o->SetCreateTime, o->SetUpdateTime);
+#endif // OS_WIN32
+ }
+
+ OSFileClose(o->pData, no_flush);
+ }
+ else
+ {
+ FreeBuf(o->HamBuf);
+ }
+ Free(o);
+
+ // KS
+ KS_INC(KS_IO_CLOSE_COUNT);
+}
+
+// Create a file
+IO *FileCreateInner(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ IO *ret = FileCreateInnerW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+IO *FileCreateInnerW(wchar_t *name)
+{
+ IO *o;
+ void *p;
+ wchar_t name2[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ UniStrCpy(name2, sizeof(name2), name);
+ ConvertPathW(name2);
+
+ p = OSFileCreateW(name2);
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ o = ZeroMalloc(sizeof(IO));
+ o->pData = p;
+ UniStrCpy(o->NameW, sizeof(o->NameW), name2);
+ UniToStr(o->Name, sizeof(o->Name), o->NameW);
+ o->WriteMode = true;
+
+ // KS
+ KS_INC(KS_IO_CREATE_COUNT);
+
+ return o;
+}
+IO *FileCreate(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ IO *ret = FileCreateW(name_w);
+
+ Free(name_w);
+
+ return ret;
+}
+IO *FileCreateW(wchar_t *name)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), name);
+
+ return FileCreateInnerW(tmp);
+}
+
+// Write all the data to the file
+bool FileWriteAll(char *name, void *data, UINT size)
+{
+ IO *io;
+ // Validate arguments
+ if (name == NULL || (data == NULL && size != 0))
+ {
+ return false;
+ }
+
+ io = FileCreate(name);
+
+ if (io == NULL)
+ {
+ return false;
+ }
+
+ FileWrite(io, data, size);
+
+ FileClose(io);
+
+ return true;
+}
+bool FileWriteAllW(wchar_t *name, void *data, UINT size)
+{
+ IO *io;
+ // Validate arguments
+ if (name == NULL || (data == NULL && size != 0))
+ {
+ return false;
+ }
+
+ io = FileCreateW(name);
+
+ if (io == NULL)
+ {
+ return false;
+ }
+
+ FileWrite(io, data, size);
+
+ FileClose(io);
+
+ return true;
+}
+
+// Open the file
+IO *FileOpenInner(char *name, bool write_mode, bool read_lock)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ IO *ret = FileOpenInnerW(name_w, write_mode, read_lock);
+
+ Free(name_w);
+
+ return ret;
+}
+IO *FileOpenInnerW(wchar_t *name, bool write_mode, bool read_lock)
+{
+ IO *o;
+ void *p;
+ wchar_t name2[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ UniStrCpy(name2, sizeof(name2), name);
+ ConvertPathW(name2);
+
+ p = OSFileOpenW(name2, write_mode, read_lock);
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ o = ZeroMalloc(sizeof(IO));
+ o->pData = p;
+ UniStrCpy(o->NameW, sizeof(o->NameW), name2);
+ UniToStr(o->Name, sizeof(o->Name), o->NameW);
+ o->WriteMode = write_mode;
+
+#ifdef OS_WIN32
+ Win32FileGetDate(p, &o->GetCreateTime, &o->GetUpdateTime, &o->GetAccessTime);
+#endif // OS_WIN32
+
+ // KS
+ KS_INC(KS_IO_OPEN_COUNT);
+
+ return o;
+}
+IO *FileOpen(char *name, bool write_mode)
+{
+ return FileOpenEx(name, write_mode, true);
+}
+IO *FileOpenW(wchar_t *name, bool write_mode)
+{
+ return FileOpenExW(name, write_mode, true);
+}
+IO *FileOpenEx(char *name, bool write_mode, bool read_lock)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+ IO *ret = FileOpenExW(name_w, write_mode, read_lock);
+
+ Free(name_w);
+
+ return ret;
+}
+IO *FileOpenExW(wchar_t *name, bool write_mode, bool read_lock)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), name);
+
+ if (name[0] == L'|')
+ {
+ IO *o = ZeroMalloc(sizeof(IO));
+ name++;
+ UniStrCpy(o->NameW, sizeof(o->NameW), name);
+ UniToStr(o->Name, sizeof(o->Name), o->NameW);
+ o->HamMode = true;
+ o->HamBuf = ReadHamcoreW(name);
+ if (o->HamBuf == NULL)
+ {
+ Free(o);
+ return NULL;
+ }
+ return o;
+ }
+ else
+ {
+ return FileOpenInnerW(tmp, write_mode, read_lock);
+ }
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/FileIO.h b/src/Mayaqua/FileIO.h
new file mode 100644
index 00000000..91fae2ac
--- /dev/null
+++ b/src/Mayaqua/FileIO.h
@@ -0,0 +1,354 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// FileIO.h
+// Header of FileIO.c
+
+#ifndef FILEIO_H
+#define FILEIO_H
+
+// Constant
+#define HAMCORE_DIR_NAME "hamcore"
+#define HAMCORE_FILE_NAME "hamcore.se2"
+#define HAMCORE_FILE_NAME_2 "_hamcore.se2"
+#define HAMCORE_TEXT_NAME "hamcore.txt"
+#define HAMCORE_HEADER_DATA "HamCore"
+#define HAMCORE_HEADER_SIZE 7
+#define HAMCORE_CACHE_EXPIRES (5 * 60 * 1000)
+
+// IO structure
+struct IO
+{
+ char Name[MAX_SIZE];
+ wchar_t NameW[MAX_SIZE];
+ void *pData;
+ bool WriteMode;
+ bool HamMode;
+ BUF *HamBuf;
+ UINT64 SetUpdateTime, SetCreateTime;
+ UINT64 GetUpdateTime, GetCreateTime, GetAccessTime;
+};
+
+// HC structure
+typedef struct HC
+{
+ char *FileName; // File name
+ UINT Size; // File size
+ UINT SizeCompressed; // Compressed file size
+ UINT Offset; // Offset
+ void *Buffer; // Buffer
+ UINT64 LastAccess; // Access Date
+} HC;
+
+// DIRENT structure
+struct DIRENT
+{
+ bool Folder; // Folder
+ char *FileName; // File name (ANSI)
+ wchar_t *FileNameW; // File name (Unicode)
+ UINT64 FileSize; // File size
+ UINT64 CreateDate; // Creation Date
+ UINT64 UpdateDate; // Updating date
+};
+
+// DIRLIST structure
+struct DIRLIST
+{
+ UINT NumFiles; // Number of files
+ struct DIRENT **File; // File array
+};
+
+// ZIP related structure
+#ifdef OS_WIN32
+#pragma pack(push, 1)
+#endif // OS_WIN32
+
+struct ZIP_DATA_HEADER
+{
+ UINT Signature;
+ USHORT NeedVer;
+ USHORT Option;
+ USHORT CompType;
+ USHORT FileTime;
+ USHORT FileDate;
+ UINT Crc32;
+ UINT CompSize;
+ UINT UncompSize;
+ USHORT FileNameLen;
+ USHORT ExtraLen;
+} GCC_PACKED;
+
+struct ZIP_DATA_FOOTER
+{
+ UINT Signature;
+ UINT Crc32;
+ UINT CompSize;
+ UINT UncompSize;
+} GCC_PACKED;
+
+struct ZIP_DIR_HEADER
+{
+ UINT Signature;
+ USHORT MadeVer;
+ USHORT NeedVer;
+ USHORT Option;
+ USHORT CompType;
+ USHORT FileTime;
+ USHORT FileDate;
+ UINT Crc32;
+ UINT CompSize;
+ UINT UncompSize;
+ USHORT FileNameLen;
+ USHORT ExtraLen;
+ USHORT CommentLen;
+ USHORT DiskNum;
+ USHORT InAttr;
+ UINT OutAttr;
+ UINT HeaderPos;
+} GCC_PACKED;
+
+struct ZIP_END_HEADER
+{
+ UINT Signature;
+ USHORT DiskNum;
+ USHORT StartDiskNum;
+ USHORT DiskDirEntry;
+ USHORT DirEntry;
+ UINT DirSize;
+ UINT StartPos;
+ USHORT CommentLen;
+} GCC_PACKED;
+
+#define ZIP_SIGNATURE 0x04034B50
+#define ZIP_SIGNATURE_END 0x06054B50
+#define ZIP_VERSION 10
+#define ZIP_VERSION_WITH_COMPRESS 20
+
+#ifdef OS_WIN32
+#pragma pack(pop)
+#endif // OS_WIN32
+
+struct ZIP_FILE
+{
+ char Name[MAX_PATH];
+ UINT Size;
+ UINT64 DateTime;
+ UINT Attributes;
+ UINT CurrentSize;
+ UINT CompressSize;
+ UINT Crc32;
+ UINT HeaderPos;
+};
+
+struct ZIP_PACKER
+{
+ FIFO *Fifo;
+ LIST *FileList;
+ ZIP_FILE *CurrentFile;
+};
+
+void InitCrc32();
+UINT Crc32(void *buf, UINT pos, UINT len);
+UINT Crc32First(void *buf, UINT pos, UINT len);
+UINT Crc32Next(void *buf, UINT pos, UINT len, UINT last_crc32);
+UINT Crc32Finish(UINT last_crc32);
+void WriteZipDataHeader(ZIP_FILE *f, ZIP_DATA_HEADER *h, bool write_sizes);
+void WriteZipDataFooter(ZIP_FILE *f, ZIP_DATA_FOOTER *h);
+ZIP_PACKER *NewZipPacker();
+void FreeZipPacker(ZIP_PACKER *p);
+void ZipAddFileSimple(ZIP_PACKER *p, char *name, UINT64 dt, UINT attribute, void *data, UINT size);
+bool ZipAddRealFileW(ZIP_PACKER *p, char *name, UINT64 dt, UINT attribute, wchar_t *srcname);
+bool ZipAddRealFile(ZIP_PACKER *p, char *name, UINT64 dt, UINT attribute, char *srcname);
+void ZipAddFileStart(ZIP_PACKER *p, char *name, UINT size, UINT64 dt, UINT attribute);
+UINT ZipAddFileData(ZIP_PACKER *p, void *data, UINT pos, UINT len);
+void ZipAddFileFooter(ZIP_PACKER *p);
+FIFO *ZipFinish(ZIP_PACKER *p);
+bool ZipWriteW(ZIP_PACKER *p, wchar_t *name);
+
+bool DeleteDirInner(char *name);
+bool DeleteDirInnerW(wchar_t *name);
+bool DeleteDir(char *name);
+bool DeleteDirW(wchar_t *name);
+bool MakeDirInner(char *name);
+bool MakeDirInnerW(wchar_t *name);
+bool MakeDir(char *name);
+bool MakeDirW(wchar_t *name);
+bool MakeDirEx(char *name);
+bool MakeDirExW(wchar_t *name);
+bool FileDeleteInner(char *name);
+bool FileDeleteInnerW(wchar_t *name);
+bool FileDelete(char *name);
+bool FileDeleteW(wchar_t *name);
+bool FileSeek(IO *o, UINT mode, int offset);
+UINT FileSize(IO *o);
+UINT64 FileSize64(IO *o);
+UINT FileSizeEx(char *name);
+UINT FileSizeExW(wchar_t *name);
+bool FileRead(IO *o, void *buf, UINT size);
+bool FileWrite(IO *o, void *buf, UINT size);
+void FileFlush(IO *o);
+void FileClose(IO *o);
+void FileCloseEx(IO *o, bool no_flush);
+void FileCloseAndDelete(IO *o);
+IO *FileCreateInner(char *name);
+IO *FileCreateInnerW(wchar_t *name);
+IO *FileCreate(char *name);
+IO *FileCreateW(wchar_t *name);
+bool FileWriteAll(char *name, void *data, UINT size);
+bool FileWriteAllW(wchar_t *name, void *data, UINT size);
+IO *FileOpenInner(char *name, bool write_mode, bool read_lock);
+IO *FileOpenInnerW(wchar_t *name, bool write_mode, bool read_lock);
+IO *FileOpen(char *name, bool write_mode);
+IO *FileOpenW(wchar_t *name, bool write_mode);
+IO *FileOpenEx(char *name, bool write_mode, bool read_lock);
+IO *FileOpenExW(wchar_t *name, bool write_mode, bool read_lock);
+void ConvertPath(char *path);
+void ConvertPathW(wchar_t *path);
+bool FileRenameInner(char *old_name, char *new_name);
+bool FileRenameInnerW(wchar_t *old_name, wchar_t *new_name);
+bool FileRename(char *old_name, char *new_name);
+bool FileRenameW(wchar_t *old_name, wchar_t *new_name);
+void NormalizePath(char *dst, UINT size, char *src);
+void NormalizePathW(wchar_t *dst, UINT size, wchar_t *src);
+TOKEN_LIST *ParseSplitedPath(char *path);
+UNI_TOKEN_LIST *ParseSplitedPathW(wchar_t *path);
+char *GetCurrentPathEnvStr();
+bool IsFileExistsInner(char *name);
+bool IsFileExistsInnerW(wchar_t *name);
+bool IsFileExists(char *name);
+bool IsFileExistsW(wchar_t *name);
+void InnerFilePath(char *dst, UINT size, char *src);
+void InnerFilePathW(wchar_t *dst, UINT size, wchar_t *src);
+void ConbinePath(char *dst, UINT size, char *dirname, char *filename);
+void ConbinePathW(wchar_t *dst, UINT size, wchar_t *dirname, wchar_t *filename);
+void CombinePath(char *dst, UINT size, char *dirname, char *filename);
+void CombinePathW(wchar_t *dst, UINT size, wchar_t *dirname, wchar_t *filename);
+void GetDirNameFromFilePath(char *dst, UINT size, char *filepath);
+void GetDirNameFromFilePathW(wchar_t *dst, UINT size, wchar_t *filepath);
+void GetFileNameFromFilePath(char *dst, UINT size, char *filepath);
+void GetFileNameFromFilePathW(wchar_t *dst, UINT size, wchar_t *filepath);
+void MakeSafeFileName(char *dst, UINT size, char *src);
+void MakeSafeFileNameW(wchar_t *dst, UINT size, wchar_t *src);
+void InitGetExeName(char *arg);
+void UnixGetExeNameW(wchar_t *name, UINT size, wchar_t *arg);
+void GetExeName(char *name, UINT size);
+void GetExeNameW(wchar_t *name, UINT size);
+void GetExeDir(char *name, UINT size);
+void GetExeDirW(wchar_t *name, UINT size);
+void BuildHamcore();
+int CompareHamcore(void *p1, void *p2);
+void InitHamcore();
+void FreeHamcore();
+BUF *ReadHamcore(char *name);
+BUF *ReadHamcoreW(wchar_t *filename);
+void SafeFileName(char *name);
+void SafeFileNameW(wchar_t *name);
+void UniSafeFileName(wchar_t *name);
+DIRLIST *EnumDir(char *dirname);
+DIRLIST *EnumDirW(wchar_t *dirname);
+DIRLIST *EnumDirEx(char *dirname, COMPARE *compare);
+DIRLIST *EnumDirExW(wchar_t *dirname, COMPARE *compare);
+void FreeDir(DIRLIST *d);
+int CompareDirListByName(void *p1, void *p2);
+bool GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
+bool GetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
+void ConvertSafeFileName(char *dst, UINT size, char *src);
+void ConvertSafeFileNameW(wchar_t *dst, UINT size, wchar_t *src);
+bool FileReplaceRename(char *old_name, char *new_name);
+bool FileReplaceRenameW(wchar_t *old_name, wchar_t *new_name);
+bool IsFile(char *name);
+bool IsFileW(wchar_t *name);
+void GetCurrentDirW(wchar_t *name, UINT size);
+void GetCurrentDir(char *name, UINT size);
+bool SaveFileW(wchar_t *name, void *data, UINT size);
+bool SaveFile(char *name, void *data, UINT size);
+bool IsFileWriteLockedW(wchar_t *name);
+bool IsFileWriteLocked(char *name);
+bool IsInLines(BUF *buf, char *str, bool instr);
+bool IsInLinesFile(wchar_t *filename, char *str, bool instr);
+
+#endif // FILEIO_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Internat.c b/src/Mayaqua/Internat.c
new file mode 100644
index 00000000..93392f93
--- /dev/null
+++ b/src/Mayaqua/Internat.c
@@ -0,0 +1,3483 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Internat.c
+// String conversion library for internationalization
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+extern LOCK *token_lock;
+static char charset[MAX_SIZE] = "EUCJP";
+static LOCK *iconv_lock = NULL;
+void *iconv_cache_wide_to_str = 0;
+void *iconv_cache_str_to_wide = 0;
+
+// Initialize the string
+void ClearUniStr(wchar_t *str, UINT str_size)
+{
+ UniStrCpy(str, str_size, L"");
+}
+
+// Examine whether the string contains the specified character
+bool UniInChar(wchar_t *string, wchar_t c)
+{
+ UINT i, len;
+ // Validate arguments
+ if (string == NULL)
+ {
+ return false;
+ }
+
+ len = UniStrLen(string);
+
+ for (i = 0;i < len;i++)
+ {
+ if (string[i] == c)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Check whether the string is included
+bool UniInStr(wchar_t *str, wchar_t *keyword)
+{
+ return UniInStrEx(str, keyword, false);
+}
+bool UniInStrEx(wchar_t *str, wchar_t *keyword, bool case_sensitive)
+{
+ // Validate arguments
+ if (UniIsEmptyStr(str) || UniIsEmptyStr(keyword))
+ {
+ return false;
+ }
+
+ if (UniSearchStrEx(str, keyword, 0, case_sensitive) == INFINITE)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Convert to binary data
+BUF *UniStrToBin(wchar_t *str)
+{
+ char *str_a = CopyUniToStr(str);
+ BUF *ret;
+
+ ret = StrToBin(str_a);
+
+ Free(str_a);
+
+ return ret;
+}
+
+// Generate a sequence of specified characters
+wchar_t *UniMakeCharArray(wchar_t c, UINT count)
+{
+ UINT i;
+ wchar_t *ret = Malloc(sizeof(wchar_t) * (count + 1));
+
+ for (i = 0;i < count;i++)
+ {
+ ret[i] = c;
+ }
+
+ ret[count] = 0;
+
+ return ret;
+}
+
+// Check whether the character is safe
+bool UniIsSafeChar(wchar_t c)
+{
+ UINT i, len;
+ wchar_t *check_str =
+ L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ L"abcdefghijklmnopqrstuvwxyz"
+ L"0123456789"
+ L" ()-_#%&.";
+
+ len = UniStrLen(check_str);
+ for (i = 0;i < len;i++)
+ {
+ if (c == check_str[i])
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Convert the token list to a string list
+LIST *UniTokenListToList(UNI_TOKEN_LIST *t)
+{
+ UINT i;
+ LIST *o;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ Insert(o, UniCopyStr(t->Token[i]));
+ }
+
+ return o;
+}
+
+// Convert a string list to a token list
+UNI_TOKEN_LIST *UniListToTokenList(LIST *o)
+{
+ UINT i;
+ UNI_TOKEN_LIST *t;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ t = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(wchar_t *) * t->NumTokens);
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ t->Token[i] = UniCopyStr(LIST_DATA(o, i));
+ }
+
+ return t;
+}
+
+// Free the string list
+void UniFreeStrList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ wchar_t *s = LIST_DATA(o, i);
+ Free(s);
+ }
+
+ ReleaseList(o);
+}
+
+// Convert the string list to a string
+BUF *UniStrListToStr(LIST *o)
+{
+ BUF *b;
+ UINT i;
+ wchar_t c;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+ b = NewBuf();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ wchar_t *s = LIST_DATA(o, i);
+ WriteBuf(b, s, UniStrSize(s));
+ }
+
+ c = 0;
+ WriteBuf(b, &c, sizeof(c));
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Convert a (NULL delimited) string to list
+LIST *UniStrToStrList(wchar_t *str, UINT size)
+{
+ LIST *o;
+ wchar_t *tmp;
+ UINT tmp_size;
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+
+ i = 0;
+ while (true)
+ {
+ if (i >= size)
+ {
+ break;
+ }
+ if (*str == 0)
+ {
+ break;
+ }
+
+ tmp_size = UniStrSize(str);
+ tmp = ZeroMalloc(tmp_size);
+ UniStrCpy(tmp, tmp_size, str);
+ Add(o, tmp);
+ str += UniStrLen(str) + 1;
+ i++;
+ }
+
+ return o;
+}
+
+// Normalize the line breaks
+wchar_t *UniNormalizeCrlf(wchar_t *str)
+{
+ wchar_t *ret;
+ UINT ret_size, i, len, wp;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = UniStrLen(str);
+ ret_size = sizeof(wchar_t) * (len + 32) * 2;
+ ret = Malloc(ret_size);
+
+ wp = 0;
+
+ for (i = 0;i < len;i++)
+ {
+ wchar_t c = str[i];
+
+ switch (c)
+ {
+ case L'\r':
+ if (str[i + 1] == L'\n')
+ {
+ i++;
+ }
+ ret[wp++] = L'\r';
+ ret[wp++] = L'\n';
+ break;
+
+ case L'\n':
+ ret[wp++] = L'\r';
+ ret[wp++] = L'\n';
+ break;
+
+ default:
+ ret[wp++] = c;
+ break;
+ }
+ }
+
+ ret[wp++] = 0;
+
+ return ret;
+}
+
+// Check whether str ends with the key
+bool UniEndWith(wchar_t *str, wchar_t *key)
+{
+ UINT str_len;
+ UINT key_len;
+ // Validate arguments
+ if (str == NULL || key == NULL)
+ {
+ return false;
+ }
+
+ // Comparison
+ str_len = UniStrLen(str);
+ key_len = UniStrLen(key);
+ if (str_len < key_len)
+ {
+ return false;
+ }
+
+ if (UniStrCmpi(str + (str_len - key_len), key) == 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Check whether str starts with the key
+bool UniStartWith(wchar_t *str, wchar_t *key)
+{
+ UINT str_len;
+ UINT key_len;
+ wchar_t *tmp;
+ bool ret;
+ // Validate arguments
+ if (str == NULL || key == NULL)
+ {
+ return false;
+ }
+
+ // Comparison
+ str_len = UniStrLen(str);
+ key_len = UniStrLen(key);
+ if (str_len < key_len)
+ {
+ return false;
+ }
+ if (str_len == 0 || key_len == 0)
+ {
+ return false;
+ }
+ tmp = CopyUniStr(str);
+ tmp[key_len] = 0;
+
+ if (UniStrCmpi(tmp, key) == 0)
+ {
+ ret = true;
+ }
+ else
+ {
+ ret = false;
+ }
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Convert the integer to a comma-separated string
+void UniToStr3(wchar_t *str, UINT size, UINT64 value)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ ToStr3(tmp, sizeof(tmp), value);
+
+ StrToUni(str, size, tmp);
+}
+
+// Format of the string (internal function)
+wchar_t *InternalFormatArgs(wchar_t *fmt, va_list args, bool ansi_mode)
+{
+ UINT i, len;
+ wchar_t *tmp;
+ UINT tmp_size;
+ LIST *o;
+ UINT mode = 0;
+ UINT wp;
+ UINT total_size;
+ wchar_t *ret;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return NULL;
+ }
+
+ len = UniStrLen(fmt);
+ tmp_size = UniStrSize(fmt);
+ tmp = Malloc(tmp_size);
+
+ o = NewListFast(NULL);
+
+ mode = 0;
+
+ wp = 0;
+
+ for (i = 0;i < len;i++)
+ {
+ wchar_t c = fmt[i];
+
+ if (mode == 0)
+ {
+ // Normal character mode
+ switch (c)
+ {
+ case L'%':
+ // The start of the format specification
+ if (fmt[i + 1] == L'%')
+ {
+ // If the next character is also '%', output a '%' simply
+ i++;
+ tmp[wp++] = c;
+ }
+ else
+ {
+ // Shift the state if the next character is not a '%'
+ mode = 1;
+ tmp[wp++] = 0;
+ wp = 0;
+ Add(o, CopyUniStr(tmp));
+ tmp[wp++] = c;
+ }
+ break;
+ default:
+ // Ordinary character
+ tmp[wp++] = c;
+ break;
+ }
+ }
+ else
+ {
+ char *tag;
+ char dst[MAX_SIZE];
+ wchar_t *target_str;
+ wchar_t *padding_str;
+ bool left_padding;
+ UINT target_str_len;
+ UINT total_len;
+ wchar_t *output_str;
+ UINT padding;
+ // Formatting mode
+ switch (c)
+ {
+ case L'c':
+ case L'C':
+ case L'd':
+ case L'i':
+ case L'o':
+ case L'u':
+ case L'x':
+ case L'X':
+ // int type
+ tmp[wp++] = c;
+ tmp[wp++] = 0;
+ tag = CopyUniToStr(tmp);
+
+ #ifdef OS_WIN32
+ ReplaceStrEx(tag, 0, tag, "ll", "I64", false);
+ #else // OS_WIN32
+ ReplaceStrEx(tag, 0, tag, "I64", "ll", false);
+ #endif // OS_WIN32
+
+ if ((UniStrLen(tmp) >= 5 && tmp[UniStrLen(tmp) - 4] == L'I' &&
+ tmp[UniStrLen(tmp) - 3] == L'6' &&
+ tmp[UniStrLen(tmp) - 2] == L'4') ||
+ (
+ UniStrLen(tmp) >= 4 && tmp[UniStrLen(tmp) - 3] == L'l' &&
+ tmp[UniStrLen(tmp) - 2] == L'l'))
+ {
+ #ifdef OS_WIN32
+ _snprintf(dst, sizeof(dst), tag, va_arg(args, UINT64));
+ #else // OS_WIN32
+ snprintf(dst, sizeof(dst), tag, va_arg(args, UINT64));
+ #endif // OS_WIN32
+ }
+ else
+ {
+ #ifdef OS_WIN32
+ _snprintf(dst, sizeof(dst), tag, va_arg(args, int));
+ #else // OS_WIN32
+ snprintf(dst, sizeof(dst), tag, va_arg(args, int));
+ #endif // OS_WIN32
+ }
+
+ Free(tag);
+ Add(o, CopyStrToUni(dst));
+
+ wp = 0;
+ mode = 0;
+ break;
+ case L'e':
+ case L'E':
+ case L'f':
+ case L'g':
+ case L'G':
+ // Double type
+ tmp[wp++] = c;
+ tmp[wp++] = 0;
+ tag = CopyUniToStr(tmp);
+
+ #ifdef OS_WIN32
+ _snprintf(dst, sizeof(dst), tag, va_arg(args, double));
+ #else // OS_WIN32
+ snprintf(dst, sizeof(dst), tag, va_arg(args, double));
+ #endif // OS_WIN32
+
+ Free(tag);
+ Add(o, CopyStrToUni(dst));
+
+ wp = 0;
+ mode = 0;
+ break;
+ case L'n':
+ case L'p':
+ // Pointer type
+ tmp[wp++] = c;
+ tmp[wp++] = 0;
+ tag = ZeroMalloc(UniStrSize(tmp) + 32);
+ UniToStr(tag, 0, tmp);
+
+ #ifdef OS_WIN32
+ _snprintf(dst, sizeof(dst), tag, va_arg(args, void *));
+ #else // OS_WIN32
+ snprintf(dst, sizeof(dst), tag, va_arg(args, void *));
+ #endif // OS_WIN32
+
+ Free(tag);
+ Add(o, CopyStrToUni(dst));
+
+ wp = 0;
+ mode = 0;
+ break;
+ case L'r':
+ case L'R':
+ // IP address type
+ tmp[wp++] = c;
+ tmp[wp++] = 0;
+
+ Zero(dst, sizeof(dst));
+ IPToStr(dst, sizeof(dst), va_arg(args, void *));
+
+ Add(o, CopyStrToUni(dst));
+
+ wp = 0;
+ mode = 0;
+ break;
+
+ case L's':
+ case L'S':
+ // String type
+ tmp[wp++] = c;
+ tmp[wp++] = 0;
+
+ if (ansi_mode == false)
+ {
+ if (c == L'S')
+ {
+ c = L's';
+ }
+ else
+ {
+ c = L'S';
+ }
+ }
+
+ if (c == L's')
+ {
+ target_str = CopyStrToUni(va_arg(args, char *));
+ }
+ else
+ {
+ target_str = CopyUniStr(va_arg(args, wchar_t *));
+ }
+
+ if (target_str == NULL)
+ {
+ target_str = CopyUniStr(L"(null)");
+ }
+
+ padding = 0;
+ left_padding = false;
+ if (tmp[1] == L'-')
+ {
+ // Left aligned
+ if (UniStrLen(tmp) >= 3)
+ {
+ padding = UniToInt(&tmp[2]);
+ }
+ left_padding = true;
+ }
+ else
+ {
+ // Right aligned
+ if (UniStrLen(tmp) >= 2)
+ {
+ padding = UniToInt(&tmp[1]);
+ }
+ }
+
+ target_str_len = UniStrWidth(target_str);
+
+ if (padding > target_str_len)
+ {
+ UINT len = padding - target_str_len;
+ UINT i;
+ padding_str = ZeroMalloc(sizeof(wchar_t) * (len + 1));
+ for (i = 0;i < len;i++)
+ {
+ padding_str[i] = L' ';
+ }
+ }
+ else
+ {
+ padding_str = ZeroMalloc(sizeof(wchar_t));
+ }
+
+ total_len = sizeof(wchar_t) * (UniStrLen(padding_str) + UniStrLen(target_str) + 1);
+ output_str = ZeroMalloc(total_len);
+ output_str[0] = 0;
+
+ if (left_padding == false)
+ {
+ UniStrCat(output_str, total_len, padding_str);
+ }
+ UniStrCat(output_str, total_len, target_str);
+ if (left_padding)
+ {
+ UniStrCat(output_str, total_len, padding_str);
+ }
+
+ Add(o, output_str);
+
+ Free(target_str);
+ Free(padding_str);
+
+ wp = 0;
+ mode = 0;
+ break;
+ default:
+ // Normal string
+ tmp[wp++] = c;
+ break;
+ }
+ }
+ }
+ tmp[wp++] = 0;
+ wp = 0;
+
+ if (UniStrLen(tmp) >= 1)
+ {
+ Add(o, CopyUniStr(tmp));
+ }
+
+ total_size = sizeof(wchar_t);
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ wchar_t *s = LIST_DATA(o, i);
+ total_size += UniStrLen(s) * sizeof(wchar_t);
+ }
+
+ ret = ZeroMalloc(total_size);
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ wchar_t *s = LIST_DATA(o, i);
+ UniStrCat(ret, total_size, s);
+ Free(s);
+ }
+
+ ReleaseList(o);
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Get the width of the string
+UINT UniStrWidth(wchar_t *str)
+{
+ UINT i, len, ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ ret = 0;
+ len = UniStrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ if (str[i] <= 255)
+ {
+ ret++;
+ }
+ else
+ {
+ ret += 2;
+ }
+ }
+ return ret;
+}
+
+// Display a dump of Unicode string
+void DumpUniStr(wchar_t *str)
+{
+ UINT i, len;
+ char *s;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ s = CopyUniToStr(str);
+
+ Print("DumpUniStr: %s\n ", s);
+
+ len = UniStrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ Print("0x%04X ", str[i]);
+ }
+ Print("\n");
+
+ Free(s);
+}
+
+// Display the dump of the string
+void DumpStr(char *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ Print("DumpStr: %s\n ", str);
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ Print("0x%02X ", str[i]);
+ }
+ Print("\n");
+}
+
+// Convert string of 2 byte/character to wchar_t of 4 byte/character
+wchar_t *Utf16ToWide(USHORT *str)
+{
+ wchar_t *ret;
+ UINT len, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = 0;
+ while (true)
+ {
+ if (str[len] == 0)
+ {
+ break;
+ }
+ len++;
+ }
+
+ ret = Malloc((len + 1) * sizeof(wchar_t));
+ for (i = 0;i < len + 1;i++)
+ {
+ ret[i] = (wchar_t)str[i];
+ }
+
+ return ret;
+}
+
+// Convert wchar_t string of 4 byte/character to string of 2 byte/character
+USHORT *WideToUtf16(wchar_t *str)
+{
+ USHORT *ret;
+ UINT len;
+ UINT ret_size;
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = UniStrLen(str);
+
+ ret_size = (len + 1) * 2;
+ ret = Malloc(ret_size);
+
+ for (i = 0;i < len + 1;i++)
+ {
+ ret[i] = (USHORT)str[i];
+ }
+
+ return ret;
+}
+
+// Initialization of the International Library
+void InitInternational()
+{
+#ifdef OS_UNIX
+ void *d;
+
+ if (iconv_lock != NULL)
+ {
+ return;
+ }
+
+ GetCurrentCharSet(charset, sizeof(charset));
+ d = IconvWideToStrInternal();
+ if (d == (void *)-1)
+ {
+#ifdef UNIX_MACOS
+ StrCpy(charset, sizeof(charset), "utf-8");
+#else // UNIX_MACOS
+ StrCpy(charset, sizeof(charset), "EUCJP");
+#endif // UNIX_MACOS
+ d = IconvWideToStrInternal();
+ if (d == (void *)-1)
+ {
+ StrCpy(charset, sizeof(charset), "US");
+ }
+ else
+ {
+ IconvFreeInternal(d);
+ }
+ }
+ else
+ {
+ IconvFreeInternal(d);
+ }
+
+ iconv_lock = NewLockMain();
+
+ iconv_cache_wide_to_str = IconvWideToStrInternal();
+ iconv_cache_str_to_wide = IconvStrToWideInternal();
+#endif // OS_UNIX
+}
+
+// Release of the International Library
+void FreeInternational()
+{
+#ifdef OS_UNIX
+#endif // OS_UNIX
+}
+
+#ifdef OS_UNIX
+
+// Calculate the size when the string converted to Unicode
+UINT UnixCalcStrToUni(char *str)
+{
+ wchar_t *tmp;
+ UINT len, tmp_size;
+ UINT ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ len = StrLen(str);
+ tmp_size = len * 5 + 10;
+ tmp = ZeroMalloc(tmp_size);
+ UnixStrToUni(tmp, tmp_size, str);
+ ret = UniStrLen(tmp);
+ Free(tmp);
+
+ return (ret + 1) * sizeof(wchar_t);
+}
+
+// Convert the strings to Unicode
+UINT UnixStrToUni(wchar_t *s, UINT size, char *str)
+{
+ void *d;
+ char *inbuf;
+ size_t insize;
+ char *outbuf;
+ char *outbuf_orig;
+ size_t outsize;
+ wchar_t *tmp;
+ // Validate arguments
+ if (s == NULL || str == NULL)
+ {
+ return 0;
+ }
+
+ d = IconvStrToWide();
+ if (d == (void *)-1)
+ {
+ UniStrCpy(s, size, L"");
+ return 0;
+ }
+
+ inbuf = (char *)str;
+ insize = StrLen(str) + 1;
+ outsize = insize * 5 + 10;
+ outbuf_orig = outbuf = ZeroMalloc(outsize);
+
+ if (iconv((iconv_t)d, (char **)&inbuf, (size_t *)&insize, (char **)&outbuf, (size_t *)&outsize) == (size_t)(-1))
+ {
+ Free(outbuf_orig);
+ UniStrCpy(s, size, L"");
+ IconvFree(d);
+ return 0;
+ }
+
+ tmp = Utf16ToWide((USHORT *)outbuf_orig);
+ Free(outbuf_orig);
+
+ UniStrCpy(s, size, tmp);
+ IconvFree(d);
+
+ Free(tmp);
+
+ return UniStrLen(s);
+}
+
+// Calculate the size when the Unicode converted to string
+UINT UnixCalcUniToStr(wchar_t *s)
+{
+ char *tmp;
+ UINT tmp_size;
+ UINT ret;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ tmp_size = UniStrLen(s) * 5 + 10;
+ tmp = ZeroMalloc(tmp_size);
+ UnixUniToStr(tmp, tmp_size, s);
+
+ ret = StrSize(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Converted a Unicode string to a string
+UINT UnixUniToStr(char *str, UINT size, wchar_t *s)
+{
+ USHORT *tmp;
+ char *inbuf;
+ size_t insize;
+ char *outbuf;
+ char *outbuf_orig;
+ size_t outsize;
+ void *d;
+ // Validate arguments
+ if (str == NULL || s == NULL)
+ {
+ return 0;
+ }
+
+ // Convert a wchar_t string to sequence of 2-bytes first
+ tmp = WideToUtf16(s);
+ inbuf = (char *)tmp;
+ insize = (UniStrLen(s) + 1) * 2;
+ outsize = insize * 5 + 10;
+ outbuf_orig = outbuf = ZeroMalloc(outsize);
+
+ d = IconvWideToStr();
+ if (d == (void *)-1)
+ {
+ StrCpy(str, size, "");
+ Free(outbuf);
+ Free(tmp);
+ return 0;
+ }
+
+ if (iconv((iconv_t)d, (char **)&inbuf, (size_t *)&insize, (char **)&outbuf, (size_t *)&outsize) == (size_t)(-1))
+ {
+ Free(outbuf_orig);
+ IconvFree(d);
+ StrCpy(str, size, "");
+ Free(tmp);
+ return 0;
+ }
+
+ StrCpy(str, size, outbuf_orig);
+
+ Free(outbuf_orig);
+ IconvFree(d);
+ Free(tmp);
+
+ return StrLen(str);
+}
+
+// Converted the whcar_t to char
+void *IconvWideToStrInternal()
+{
+ return (void *)iconv_open(charset, IsBigEndian() ? "UTF-16BE" : "UTF-16LE");
+}
+
+// Convert the char to a wchar_t
+void *IconvStrToWideInternal()
+{
+ return (void *)iconv_open(IsBigEndian() ? "UTF-16BE" : "UTF-16LE", charset);
+}
+
+// Close the handle
+int IconvFreeInternal(void *d)
+{
+ iconv_close((iconv_t)d);
+ return 0;
+}
+
+void *IconvWideToStr()
+{
+ if (iconv_cache_wide_to_str == (void *)-1)
+ {
+ return (void *)-1;
+ }
+
+ Lock(iconv_lock);
+
+ return iconv_cache_wide_to_str;
+}
+
+void *IconvStrToWide()
+{
+ if (iconv_cache_str_to_wide == (void *)-1)
+ {
+ return (void *)-1;
+ }
+
+ Lock(iconv_lock);
+
+ return iconv_cache_str_to_wide;
+}
+
+int IconvFree(void *d)
+{
+ Unlock(iconv_lock);
+
+ return 0;
+}
+
+// Get the character set that is currently used from the environment variable
+void GetCurrentCharSet(char *name, UINT size)
+{
+ char tmp[MAX_SIZE];
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ Zero(tmp, sizeof(tmp));
+ if (GetEnv("LANG", tmp, sizeof(tmp)) == false || IsEmptyStr(tmp))
+ {
+ Zero(tmp, sizeof(tmp));
+ if (GetEnv("LOCATION", tmp, sizeof(tmp)) == false || IsEmptyStr(tmp))
+ {
+ StrCpy(tmp, sizeof(tmp), "C");
+ }
+ }
+
+ Trim(tmp);
+
+ t = ParseToken(tmp, ".");
+ if (t->NumTokens >= 2)
+ {
+ StrCpy(name, size, t->Token[1]);
+ }
+ else
+ {
+ if (t->NumTokens == 1)
+ {
+ StrCpy(name, size, t->Token[0]);
+ }
+ else
+ {
+ StrCpy(name, size, "eucJP");
+ }
+ }
+ FreeToken(t);
+
+ StrUpper(name);
+}
+
+#endif // OS_UNIX
+
+// Check whether the specified string is a space
+bool UniIsEmptyStr(wchar_t *str)
+{
+ return IsEmptyUniStr(str);
+}
+bool IsEmptyUniStr(wchar_t *str)
+{
+ bool ret;
+ wchar_t *s;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return true;
+ }
+
+ s = UniCopyStr(str);
+
+ UniTrim(s);
+ if (UniStrLen(s) == 0)
+ {
+ ret = true;
+ }
+ else
+ {
+ ret = false;
+ }
+
+ Free(s);
+
+ return ret;
+}
+
+// Check whether the specified string is a number
+bool UniIsNum(wchar_t *str)
+{
+ char tmp[MAX_SIZE];
+
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ UniToStrForSingleChars(tmp, sizeof(tmp), str);
+
+ return IsNum(tmp);
+}
+
+
+// Empty Unicode token list
+UNI_TOKEN_LIST *UniNullToken()
+{
+ UNI_TOKEN_LIST *ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
+ ret->Token = ZeroMalloc(0);
+
+ return ret;
+}
+
+// Empty Unicode token list (Alias)
+UNI_TOKEN_LIST *NullUniToken()
+{
+ return UniNullToken();
+}
+
+// Convert the token list to Unicode token list
+UNI_TOKEN_LIST *TokenListToUniTokenList(TOKEN_LIST *src)
+{
+ UNI_TOKEN_LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
+ ret->NumTokens = src->NumTokens;
+ ret->Token = ZeroMalloc(sizeof(wchar_t *) * ret->NumTokens);
+
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ ret->Token[i] = CopyStrToUni(src->Token[i]);
+ }
+
+ return ret;
+}
+
+// Convert a Unicode token list to a token list
+TOKEN_LIST *UniTokenListToTokenList(UNI_TOKEN_LIST *src)
+{
+ TOKEN_LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->NumTokens = src->NumTokens;
+ ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
+
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ ret->Token[i] = CopyUniToStr(src->Token[i]);
+ }
+
+ return ret;
+}
+
+// Unicode string copy
+wchar_t *UniCopyStr(wchar_t *str)
+{
+ return CopyUniStr(str);
+}
+
+// Copy the token list
+UNI_TOKEN_LIST *UniCopyToken(UNI_TOKEN_LIST *src)
+{
+ UNI_TOKEN_LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->NumTokens = src->NumTokens;
+ ret->Token = ZeroMalloc(sizeof(wchar_t *) * ret->NumTokens);
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ ret->Token[i] = CopyUniStr(src->Token[i]);
+ }
+
+ return ret;
+}
+
+// Parse the command line string
+UNI_TOKEN_LIST *UniParseCmdLine(wchar_t *str)
+{
+ UNI_TOKEN_LIST *t;
+ LIST *o;
+ UINT i, len, wp, mode;
+ wchar_t c;
+ wchar_t *tmp;
+ bool ignore_space = false;
+ // Validate arguments
+ if (str == NULL)
+ {
+ // There is no token
+ return UniNullToken();
+ }
+
+ o = NewListFast(NULL);
+ tmp = Malloc(UniStrSize(str) + 32);
+
+ wp = 0;
+ mode = 0;
+
+ len = UniStrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ c = str[i];
+
+ switch (mode)
+ {
+ case 0:
+ // Mode to discover the next token
+ if (c == L' ' || c == L'\t')
+ {
+ // Advance to the next character
+ }
+ else
+ {
+ // Start of the token
+ if (c == L'\"')
+ {
+ if (str[i + 1] == L'\"')
+ {
+ // Regarded "" as a single " character
+ tmp[wp++] = L'\"';
+ i++;
+ }
+ else
+ {
+ // Single "(double-quote) enables the flag to ignore space
+ ignore_space = true;
+ }
+ }
+ else
+ {
+ tmp[wp++] = c;
+ }
+
+ mode = 1;
+ }
+ break;
+
+ case 1:
+ if (ignore_space == false && (c == L' ' || c == L'\t'))
+ {
+ // End of the token
+ tmp[wp++] = 0;
+ wp = 0;
+
+ Insert(o, UniCopyStr(tmp));
+ mode = 0;
+ }
+ else
+ {
+ if (c == L'\"')
+ {
+ if (str[i + 1] == L'\"')
+ {
+ // Regarded "" as a single " character
+ tmp[wp++] = L'\"';
+ i++;
+ }
+ else
+ {
+ if (ignore_space == false)
+ {
+ // Single "(double-quote) enables the flag to ignore space
+ ignore_space = true;
+ }
+ else
+ {
+ // Disable the flag to ignore space
+ ignore_space = false;
+ }
+ }
+ }
+ else
+ {
+ tmp[wp++] = c;
+ }
+ }
+ break;
+ }
+ }
+
+ if (wp != 0)
+ {
+ tmp[wp++] = 0;
+ Insert(o, UniCopyStr(tmp));
+ }
+
+ Free(tmp);
+
+ t = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(wchar_t *) * t->NumTokens);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+
+ return t;
+}
+
+// Convert Unicode string to 64bit integer
+UINT64 UniToInt64(wchar_t *str)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ UniToStrForSingleChars(tmp, sizeof(tmp), str);
+
+ return ToInt64(tmp);
+}
+
+// Convert a 64-bit integer to a Unicode string
+void UniToStr64(wchar_t *str, UINT64 value)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ ToStr64(tmp, value);
+
+ StrToUni(str, 0, tmp);
+}
+
+// Convert an ANSI string to UTF
+UINT StrToUtf(char *utfstr, UINT size, char *str)
+{
+ char *tmp;
+ // Validate arguments
+ if (utfstr == NULL || str == NULL)
+ {
+ StrCpy(utfstr, size, "");
+ return 0;
+ }
+
+ tmp = CopyStrToUtf(str);
+
+ StrCpy(utfstr, size, tmp);
+
+ Free(tmp);
+
+ return StrLen(utfstr);
+}
+
+// Convert an UTF string to an ANSI string
+UINT UtfToStr(char *str, UINT size, char *utfstr)
+{
+ char *tmp;
+ // Validate arguments
+ if (str == NULL || utfstr == NULL)
+ {
+ StrCpy(str, size, "");
+ return 0;
+ }
+
+ tmp = CopyUtfToStr(utfstr);
+
+ StrCpy(str, size, tmp);
+
+ Free(tmp);
+
+ return StrLen(str);
+}
+
+// Convert the Unicode string to the UTF string
+UINT UniToUtf(char *utfstr, UINT size, wchar_t *unistr)
+{
+ char *tmp;
+ // Validate arguments
+ if (utfstr == NULL || unistr == NULL)
+ {
+ StrCpy(utfstr, size, "");
+ return 0;
+ }
+
+ tmp = CopyUniToStr(unistr);
+
+ StrCpy(utfstr, size, tmp);
+
+ Free(tmp);
+
+ return StrLen(utfstr);
+}
+
+// Convert the UTF string to a Unicode string
+UINT UtfToUni(wchar_t *unistr, UINT size, char *utfstr)
+{
+ wchar_t *tmp;
+ // Validate arguments
+ if (unistr == NULL || utfstr == NULL)
+ {
+ UniStrCpy(unistr, size, L"");
+ return 0;
+ }
+
+ tmp = CopyUtfToUni(utfstr);
+
+ UniStrCpy(unistr, size, tmp);
+
+ Free(tmp);
+
+ return UniStrLen(unistr);
+}
+
+// Copy the UTF-8 string to a Unicode string
+wchar_t *CopyUtfToUni(char *utfstr)
+{
+ UINT size;
+ wchar_t *ret;
+ UINT utfstr_len;
+ // Validate arguments
+ if (utfstr == NULL)
+ {
+ return NULL;
+ }
+
+ utfstr_len = StrLen(utfstr);
+
+ size = CalcUtf8ToUni((BYTE *)utfstr, utfstr_len);
+ ret = ZeroMalloc(size + sizeof(wchar_t));
+ Utf8ToUni(ret, size, (BYTE *)utfstr, utfstr_len);
+
+ return ret;
+}
+
+// Copy the UTF8 string to the ANSI string
+char *CopyUtfToStr(char *utfstr)
+{
+ wchar_t *uni;
+ char *ret;
+ // Validate arguments
+ if (utfstr == NULL)
+ {
+ return NULL;
+ }
+
+ uni = CopyUtfToUni(utfstr);
+ if (uni == NULL)
+ {
+ return CopyStr("");
+ }
+
+ ret = CopyUniToStr(uni);
+
+ Free(uni);
+
+ return ret;
+}
+
+// Copy a Unicode string to ANSI string
+char *CopyUniToStr(wchar_t *unistr)
+{
+ char *str;
+ UINT str_size;
+ // Validate arguments
+ if (unistr == NULL)
+ {
+ return NULL;
+ }
+
+ str_size = CalcUniToStr(unistr);
+ if (str_size == 0)
+ {
+ return CopyStr("");
+ }
+ str = Malloc(str_size);
+ UniToStr(str, str_size, unistr);
+
+ return str;
+}
+
+// Copy an ANSI string to a Unicode string
+wchar_t *CopyStrToUni(char *str)
+{
+ wchar_t *uni;
+ UINT uni_size;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ uni_size = CalcStrToUni(str);
+ if (uni_size == 0)
+ {
+ return CopyUniStr(L"");
+ }
+ uni = Malloc(uni_size);
+ StrToUni(uni, uni_size, str);
+
+ return uni;
+}
+
+// Copy a Unicode string to UTF-8 string
+char *CopyUniToUtf(wchar_t *unistr)
+{
+ UINT size;
+ char *ret;
+ // Validate arguments
+ if (unistr == NULL)
+ {
+ return NULL;
+ }
+
+ size = CalcUniToUtf8(unistr);
+ ret = ZeroMalloc(size + sizeof(char));
+
+ UniToUtf8((char *)ret, size, unistr);
+
+ return ret;
+}
+
+// Copy ANSI string to UTF8 string
+char *CopyStrToUtf(char *str)
+{
+ wchar_t *unistr;
+ char *ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ unistr = CopyStrToUni(str);
+ if (unistr == NULL)
+ {
+ return CopyStr("");
+ }
+
+ ret = CopyUniToUtf(unistr);
+
+ Free(unistr);
+
+ return ret;
+}
+
+// Copy the Unicode string
+wchar_t *CopyUniStr(wchar_t *str)
+{
+ UINT len;
+ wchar_t *dst;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = UniStrLen(str);
+ dst = Malloc((len + 1) * sizeof(wchar_t));
+ UniStrCpy(dst, 0, str);
+
+ return dst;
+}
+
+// Check whether the string is safe
+bool IsSafeUniStr(wchar_t *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ len = UniStrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ if (IsSafeUniChar(str[i]) == false)
+ {
+ return false;
+ }
+ }
+ if (str[0] == L' ')
+ {
+ return false;
+ }
+ if (len != 0)
+ {
+ if (str[len - 1] == L' ')
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Check whether the character is safe
+bool IsSafeUniChar(wchar_t c)
+{
+ UINT i, len;
+ wchar_t *check_str =
+ L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ L"abcdefghijklmnopqrstuvwxyz"
+ L"0123456789"
+ L" ()-_#%&.";
+
+ len = UniStrLen(check_str);
+ for (i = 0;i < len;i++)
+ {
+ if (c == check_str[i])
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Convert an UTF-8 string to an ANSI string
+UINT Utf8ToStr(char *str, UINT str_size, BYTE *u, UINT size)
+{
+ UINT ret, uni_size;
+ wchar_t *tmp;
+ // Validate arguments
+ if (u == NULL || str == NULL)
+ {
+ return 0;
+ }
+
+ // Convert to Unicode
+ uni_size = CalcUtf8ToUni(u, size);
+ if (uni_size == 0)
+ {
+ if (str_size >= 1)
+ {
+ StrCpy(str, 0, "");
+ return 0;
+ }
+ }
+ tmp = Malloc(uni_size);
+ Utf8ToUni(tmp, uni_size, u, size);
+
+ // Convert to ANSI
+ ret = UniToStr(str, str_size, tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Get the size required when UTF-8 string is converted to ANSI string
+UINT CalcUtf8ToStr(BYTE *u, UINT size)
+{
+ UINT ret, uni_size;
+ wchar_t *tmp;
+ // Validate arguments
+ if (u == NULL)
+ {
+ return 0;
+ }
+
+ // Convert to Unicode
+ uni_size = CalcUtf8ToUni(u, size);
+ if (uni_size == 0)
+ {
+ return 0;
+ }
+ tmp = Malloc(uni_size);
+ Utf8ToUni(tmp, uni_size, u, size);
+
+ // Convert to ANSI
+ ret = CalcUniToStr(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Convert an ANSI string to UTF-8 string
+UINT StrToUtf8(BYTE *u, UINT size, char *str)
+{
+ UINT ret, uni_size;
+ wchar_t *tmp;
+ // Validate arguments
+ if (u == NULL || str == NULL)
+ {
+ return 0;
+ }
+
+ // Convert to Unicode
+ uni_size = CalcStrToUni(str);
+ if (uni_size == 0)
+ {
+ return 0;
+ }
+ tmp = Malloc(uni_size);
+ StrToUni(tmp, uni_size, str);
+
+ // Convert to UTF-8
+ ret = UniToUtf8(u, size, tmp);
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Get the required buffer size to convert an ANSI string to an UTF-8 string
+UINT CalcStrToUtf8(char *str)
+{
+ UINT ret;
+ UINT uni_size;
+ wchar_t *tmp;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ // Convert to Unicode
+ uni_size = CalcStrToUni(str);
+ if (uni_size == 0)
+ {
+ return 0;
+ }
+ tmp = Malloc(uni_size);
+ StrToUni(tmp, uni_size, str);
+
+ // Get the size as it was converted to UTF-8
+ ret = CalcUniToUtf8(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Convert Unicode string to ANSI string
+UINT UniToStr(char *str, UINT size, wchar_t *s)
+{
+#ifdef OS_WIN32
+ UINT ret;
+ char *tmp;
+ UINT new_size;
+ // Validate arguments
+ if (s == NULL || str == NULL)
+ {
+ return 0;
+ }
+
+ new_size = CalcUniToStr(s);
+ if (new_size == 0)
+ {
+ if (size >= 1)
+ {
+ StrCpy(str, 0, "");
+ }
+ return 0;
+ }
+ tmp = Malloc(new_size);
+ tmp[0] = 0;
+ wcstombs(tmp, s, new_size);
+ tmp[new_size - 1] = 0;
+ ret = StrCpy(str, size, tmp);
+ Free(tmp);
+
+ return ret;
+#else // OS_WIN32
+ return UnixUniToStr(str, size, s);
+#endif // OS_WIN32
+}
+
+// Get the required number of bytes to convert Unicode string to the ANSI string
+UINT CalcUniToStr(wchar_t *s)
+{
+#ifdef OS_WIN32
+ UINT ret;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ ret = (UINT)wcstombs(NULL, s, UniStrLen(s));
+ if (ret == (UINT)-1)
+ {
+ return 0;
+ }
+
+ return ret + 1;
+#else // OS_WIN32
+ return UnixCalcUniToStr(s);
+#endif // OS_WIN32
+}
+
+// Converted an ANSI string to a Unicode string
+UINT StrToUni(wchar_t *s, UINT size, char *str)
+{
+#ifdef OS_WIN32
+ UINT ret;
+ wchar_t *tmp;
+ UINT new_size;
+ // Validate arguments
+ if (s == NULL || str == NULL)
+ {
+ return 0;
+ }
+
+ new_size = CalcStrToUni(str);
+ if (new_size == 0)
+ {
+ if (size >= 2)
+ {
+ UniStrCpy(s, 0, L"");
+ }
+ return 0;
+ }
+ tmp = Malloc(new_size);
+ tmp[0] = 0;
+ mbstowcs(tmp, str, StrLen(str));
+ tmp[(new_size - 1) / sizeof(wchar_t)] = 0;
+ ret = UniStrCpy(s, size, tmp);
+ Free(tmp);
+
+ return ret;
+#else // OS_WIN32
+ return UnixStrToUni(s, size, str);
+#endif // OS_WIN32
+}
+
+// Get the required buffer size for converting an ANSI string to an Unicode string
+UINT CalcStrToUni(char *str)
+{
+#ifdef OS_WIN32
+ UINT ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ ret = (UINT)mbstowcs(NULL, str, StrLen(str));
+ if (ret == (UINT)-1)
+ {
+ return 0;
+ }
+
+ return (ret + 1) * sizeof(wchar_t);
+#else // OS_WIN32
+ return UnixCalcStrToUni(str);
+#endif // OS_WIN32
+}
+
+// Convert the UTF-8 strings to a Unicode string
+UINT Utf8ToUni(wchar_t *s, UINT size, BYTE *u, UINT u_size)
+{
+ UINT i, wp, num;
+ // Validate arguments
+ if (s == NULL || u == NULL)
+ {
+ return 0;
+ }
+ if (size == 0)
+ {
+ size = 0x3fffffff;
+ }
+ if (u_size == 0)
+ {
+ u_size = StrLen((char *)u);
+ }
+
+ i = 0;
+ wp = 0;
+ num = 0;
+ while (true)
+ {
+ UINT type;
+ wchar_t c;
+ BYTE c1, c2;
+
+ type = GetUtf8Type(u, u_size, i);
+ if (type == 0)
+ {
+ break;
+ }
+ switch (type)
+ {
+ case 1:
+ c1 = 0;
+ c2 = u[i];
+ break;
+ case 2:
+ c1 = (((u[i] & 0x1c) >> 2) & 0x07);
+ c2 = (((u[i] & 0x03) << 6) & 0xc0) | (u[i + 1] & 0x3f);
+ break;
+ case 3:
+ c1 = ((((u[i] & 0x0f) << 4) & 0xf0)) | (((u[i + 1] & 0x3c) >> 2) & 0x0f);
+ c2 = (((u[i + 1] & 0x03) << 6) & 0xc0) | (u[i + 2] & 0x3f);
+ break;
+ }
+ i += type;
+
+ c = 0;
+
+ if (IsBigEndian())
+ {
+ if (sizeof(wchar_t) == 2)
+ {
+ ((BYTE *)&c)[0] = c1;
+ ((BYTE *)&c)[1] = c2;
+ }
+ else
+ {
+ ((BYTE *)&c)[2] = c1;
+ ((BYTE *)&c)[3] = c2;
+ }
+ }
+ else
+ {
+ ((BYTE *)&c)[0] = c2;
+ ((BYTE *)&c)[1] = c1;
+ }
+
+ if (wp < ((size / sizeof(wchar_t)) - 1))
+ {
+ s[wp++] = c;
+ num++;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (wp < (size / sizeof(wchar_t)))
+ {
+ s[wp++] = 0;
+ }
+
+ return num;
+}
+
+// Get the buffer size when converted UTF-8 to Unicode
+UINT CalcUtf8ToUni(BYTE *u, UINT u_size)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return 0;
+ }
+ if (u_size == 0)
+ {
+ u_size = StrLen((char *)u);
+ }
+
+ return (Utf8Len(u, u_size) + 1) * sizeof(wchar_t);
+}
+
+// Get the number of characters in UTF-8 string
+UINT Utf8Len(BYTE *u, UINT size)
+{
+ UINT i, num;
+ // Validate arguments
+ if (u == NULL)
+ {
+ return 0;
+ }
+ if (size == 0)
+ {
+ size = StrLen((char *)u);
+ }
+
+ i = num = 0;
+ while (true)
+ {
+ UINT type;
+
+ type = GetUtf8Type(u, size, i);
+ if (type == 0)
+ {
+ break;
+ }
+ i += type;
+ num++;
+ }
+
+ return num;
+}
+
+// Convert an Unicode string to UTF-8 string
+UINT UniToUtf8(BYTE *u, UINT size, wchar_t *s)
+{
+ UINT i, len, type, wp;
+ // Validate arguments
+ if (u == NULL || s == NULL)
+ {
+ return 0;
+ }
+ if (size == 0)
+ {
+ size = 0x3fffffff;
+ }
+
+ len = UniStrLen(s);
+ wp = 0;
+ for (i = 0;i < len;i++)
+ {
+ BYTE c1, c2;
+ wchar_t c = s[i];
+
+ if (IsBigEndian())
+ {
+ if (sizeof(wchar_t) == 2)
+ {
+ c1 = ((BYTE *)&c)[0];
+ c2 = ((BYTE *)&c)[1];
+ }
+ else
+ {
+ c1 = ((BYTE *)&c)[2];
+ c2 = ((BYTE *)&c)[3];
+ }
+ }
+ else
+ {
+ c1 = ((BYTE *)&c)[1];
+ c2 = ((BYTE *)&c)[0];
+ }
+
+ type = GetUniType(s[i]);
+ switch (type)
+ {
+ case 1:
+ if (wp < size)
+ {
+ u[wp++] = c2;
+ }
+ break;
+ case 2:
+ if (wp < size)
+ {
+ u[wp++] = 0xc0 | (((((c1 & 0x07) << 2) & 0x1c)) | (((c2 & 0xc0) >> 6) & 0x03));
+ }
+ if (wp < size)
+ {
+ u[wp++] = 0x80 | (c2 & 0x3f);
+ }
+ break;
+ case 3:
+ if (wp < size)
+ {
+ u[wp++] = 0xe0 | (((c1 & 0xf0) >> 4) & 0x0f);
+ }
+ if (wp < size)
+ {
+ u[wp++] = 0x80 | (((c1 & 0x0f) << 2) & 0x3c) | (((c2 & 0xc0) >> 6) & 0x03);
+ }
+ if (wp < size)
+ {
+ u[wp++] = 0x80 | (c2 & 0x3f);
+ }
+ break;
+ }
+ }
+ if (wp < size)
+ {
+ u[wp] = 0;
+ }
+ return wp;
+}
+
+// Calculating the length of the string when converting Unicode string to UTF-8 string
+UINT CalcUniToUtf8(wchar_t *s)
+{
+ UINT i, len, size;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ size = 0;
+ len = UniStrLen(s);
+ for (i = 0;i < len;i++)
+ {
+ size += GetUniType(s[i]);
+ }
+
+ return size;
+}
+
+// Get the number of bytes of a first character of the offset address of the UTF-8 string that starts with s
+UINT GetUtf8Type(BYTE *s, UINT size, UINT offset)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+ if ((offset + 1) > size)
+ {
+ return 0;
+ }
+ if ((s[offset] & 0x80) == 0)
+ {
+ // 1 byte
+ return 1;
+ }
+ if ((s[offset] & 0x20) == 0)
+ {
+ // 2 bytes
+ if ((offset + 2) > size)
+ {
+ return 0;
+ }
+ return 2;
+ }
+ // 3 bytes
+ if ((offset + 3) > size)
+ {
+ return 0;
+ }
+ return 3;
+}
+
+// Type of the converted character 'c' to UTF-8 (in bytes)
+UINT GetUniType(wchar_t c)
+{
+ BYTE c1, c2;
+
+ if (IsBigEndian())
+ {
+ if (sizeof(wchar_t) == 2)
+ {
+ c1 = ((BYTE *)&c)[0];
+ c2 = ((BYTE *)&c)[1];
+ }
+ else
+ {
+ c1 = ((BYTE *)&c)[2];
+ c2 = ((BYTE *)&c)[3];
+ }
+ }
+ else
+ {
+ c1 = ((BYTE *)&c)[1];
+ c2 = ((BYTE *)&c)[0];
+ }
+
+ if (c1 == 0)
+ {
+ if (c2 <= 0x7f)
+ {
+ // 1 byte
+ return 1;
+ }
+ else
+ {
+ // 2 bytes
+ return 2;
+ }
+ }
+ if ((c1 & 0xf8) == 0)
+ {
+ // 2 bytes
+ return 2;
+ }
+ // 3 bytes
+ return 3;
+}
+
+// String replacing (case-insensitive)
+UINT UniReplaceStri(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword)
+{
+ return UniReplaceStrEx(dst, size, string, old_keyword, new_keyword, false);
+}
+
+// String replacing (case-sensitive)
+UINT UniReplaceStr(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword)
+{
+ return UniReplaceStrEx(dst, size, string, old_keyword, new_keyword, true);
+}
+
+// Replacement of string
+UINT UniReplaceStrEx(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword, bool case_sensitive)
+{
+ UINT i, j, num, len_string, len_old, len_new, len_ret, wp;
+ wchar_t *ret;
+ // Validate arguments
+ if (string == NULL || old_keyword == NULL || new_keyword == NULL)
+ {
+ return 0;
+ }
+
+ // Get the length of the string
+ len_string = UniStrLen(string);
+ len_old = UniStrLen(old_keyword);
+ len_new = UniStrLen(new_keyword);
+
+ // Get the final string length
+ len_ret = UniCalcReplaceStrEx(string, old_keyword, new_keyword, case_sensitive);
+ // Memory allocation
+ ret = Malloc((len_ret + 1) * sizeof(wchar_t));
+ ret[len_ret] = 0;
+
+ // Search and Replace
+ i = j = num = wp = 0;
+ while (true)
+ {
+ i = UniSearchStrEx(string, old_keyword, i, case_sensitive);
+ if (i == INFINITE)
+ {
+ Copy(&ret[wp], &string[j], (len_string - j) * sizeof(wchar_t));
+ wp += len_string - j;
+ break;
+ }
+ num++;
+ Copy(&ret[wp], &string[j], (i - j) * sizeof(wchar_t));
+ wp += i - j;
+ Copy(&ret[wp], new_keyword, len_new * sizeof(wchar_t));
+ wp += len_new;
+ i += len_old;
+ j = i;
+ }
+
+ // Copy of the search results
+ UniStrCpy(dst, size, ret);
+
+ // Memory release
+ Free(ret);
+
+ return num;
+}
+
+// Calculate the length of the result of string replacement
+UINT UniCalcReplaceStrEx(wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword, bool case_sensitive)
+{
+ UINT i, num;
+ UINT len_string, len_old, len_new;
+ // Validate arguments
+ if (string == NULL || old_keyword == NULL || new_keyword == NULL)
+ {
+ return 0;
+ }
+
+ // Get the length of the string
+ len_string = UniStrLen(string);
+ len_old = UniStrLen(old_keyword);
+ len_new = UniStrLen(new_keyword);
+
+ if (len_old == len_new)
+ {
+ return len_string;
+ }
+
+ // Search process
+ num = 0;
+ i = 0;
+ while (true)
+ {
+ i = UniSearchStrEx(string, old_keyword, i, case_sensitive);
+ if (i == INFINITE)
+ {
+ break;
+ }
+ i += len_old;
+ num++;
+ }
+
+ // Calculation
+ return len_string + len_new * num - len_old * num;
+}
+
+// Search for a string (distinguish between upper / lower case)
+UINT UniSearchStr(wchar_t *string, wchar_t *keyword, UINT start)
+{
+ return UniSearchStrEx(string, keyword, start, true);
+}
+
+// Search for a string (Don't distinguish between upper / lower case)
+UINT UniSearchStri(wchar_t *string, wchar_t *keyword, UINT start)
+{
+ return UniSearchStrEx(string, keyword, start, false);
+}
+
+// Return the position of the first found of the keyword in the string
+// (Found in first character: returns 0, Not found: returns INFINITE)
+UINT UniSearchStrEx(wchar_t *string, wchar_t *keyword, UINT start, bool case_sensitive)
+{
+ UINT len_string, len_keyword;
+ UINT i;
+ wchar_t *cmp_string, *cmp_keyword;
+ bool found;
+ // Validate arguments
+ if (string == NULL || keyword == NULL)
+ {
+ return INFINITE;
+ }
+
+ // Get the length of string
+ len_string = UniStrLen(string);
+ if (len_string <= start)
+ {
+ // Value of start is invalid
+ return INFINITE;
+ }
+
+ // Get the length of the keyword
+ len_keyword = UniStrLen(keyword);
+ if (len_keyword == 0)
+ {
+ // There is no keyword
+ return INFINITE;
+ }
+
+ if (len_string < len_keyword)
+ {
+ return INFINITE;
+ }
+
+ if (len_string == len_keyword)
+ {
+ if (case_sensitive)
+ {
+ if (UniStrCmp(string, keyword) == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return INFINITE;
+ }
+ }
+ else
+ {
+ if (UniStrCmpi(string, keyword) == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return INFINITE;
+ }
+ }
+ }
+
+ if (case_sensitive)
+ {
+ cmp_string = string;
+ cmp_keyword = keyword;
+ }
+ else
+ {
+ cmp_string = Malloc((len_string + 1) * sizeof(wchar_t));
+ UniStrCpy(cmp_string, (len_string + 1) * sizeof(wchar_t), string);
+ cmp_keyword = Malloc((len_keyword + 1) * sizeof(wchar_t));
+ UniStrCpy(cmp_keyword, (len_keyword + 1) * sizeof(wchar_t), keyword);
+ UniStrUpper(cmp_string);
+ UniStrUpper(cmp_keyword);
+ }
+
+ // Search
+ found = false;
+ for (i = start;i < (len_string - len_keyword + 1);i++)
+ {
+ // Compare
+ if (!wcsncmp(&cmp_string[i], cmp_keyword, len_keyword))
+ {
+ // Found
+ found = true;
+ break;
+ }
+ }
+
+ if (case_sensitive == false)
+ {
+ // Memory release
+ Free(cmp_keyword);
+ Free(cmp_string);
+ }
+
+ if (found == false)
+ {
+ return INFINITE;
+ }
+ return i;
+}
+
+// Release of the token list
+void UniFreeToken(UNI_TOKEN_LIST *tokens)
+{
+ UINT i;
+ if (tokens == NULL)
+ {
+ return;
+ }
+ for (i = 0;i < tokens->NumTokens;i++)
+ {
+ Free(tokens->Token[i]);
+ }
+ Free(tokens->Token);
+ Free(tokens);
+}
+
+// Parse token for UNIX
+UNI_TOKEN_LIST *UnixUniParseToken(wchar_t *src, wchar_t *separator)
+{
+ UNI_TOKEN_LIST *ret;
+ TOKEN_LIST *t;
+ char *src_s;
+ char *sep_s;
+
+ // Validate arguments
+ if (src == NULL || separator == NULL)
+ {
+ ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
+ ret->Token = ZeroMalloc(0);
+ return ret;
+ }
+
+ src_s = CopyUniToStr(src);
+ sep_s = CopyUniToStr(separator);
+
+ t = ParseToken(src_s, sep_s);
+
+ ret = TokenListToUniTokenList(t);
+ FreeToken(t);
+
+ Free(src_s);
+ Free(sep_s);
+
+ return ret;
+}
+
+// Parse the token
+UNI_TOKEN_LIST *UniParseToken(wchar_t *src, wchar_t *separator)
+{
+#ifdef OS_WIN32
+ UNI_TOKEN_LIST *ret;
+ wchar_t *tmp;
+ wchar_t *str1, *str2;
+ UINT len, num;
+
+#ifdef OS_UNIX
+ wchar_t *state = NULL;
+#endif // OS_UNIX
+
+ // Validate arguments
+ if (src == NULL)
+ {
+ ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
+ ret->Token = ZeroMalloc(0);
+ return ret;
+ }
+ if (separator == NULL)
+ {
+ separator = L" .\t\r\n";
+ }
+ len = UniStrLen(src);
+ str1 = Malloc((len + 1) * sizeof(wchar_t));
+ str2 = Malloc((len + 1) * sizeof(wchar_t));
+ UniStrCpy(str1, 0, src);
+ UniStrCpy(str2, 0, src);
+
+ Lock(token_lock);
+ {
+ tmp = wcstok(str1, separator
+#ifdef OS_UNIX
+ , &state
+#endif // OS_UNIX
+ );
+ num = 0;
+ while (tmp != NULL)
+ {
+ num++;
+ tmp = wcstok(NULL, separator
+#ifdef OS_UNIX
+ , &state
+#endif // OS_UNIX
+ );
+ }
+ ret = Malloc(sizeof(UNI_TOKEN_LIST));
+ ret->NumTokens = num;
+ ret->Token = (wchar_t **)Malloc(sizeof(wchar_t *) * num);
+ num = 0;
+ tmp = wcstok(str2, separator
+#ifdef OS_UNIX
+ , &state
+#endif // OS_UNIX
+ );
+ while (tmp != NULL)
+ {
+ ret->Token[num] = (wchar_t *)Malloc((UniStrLen(tmp) + 1) * sizeof(wchar_t));
+ UniStrCpy(ret->Token[num], 0, tmp);
+ num++;
+ tmp = wcstok(NULL, separator
+#ifdef OS_UNIX
+ , &state
+#endif // OS_UNIX
+ );
+ }
+ }
+ Unlock(token_lock);
+
+ Free(str1);
+ Free(str2);
+ return ret;
+#else // OS_WIN32
+ return UnixUniParseToken(src, separator);
+#endif // OS_WIN32
+}
+
+// Get a line from standard input
+bool UniGetLine(wchar_t *str, UINT size)
+{
+#ifdef OS_WIN32
+ return UniGetLineWin32(str, size);
+#else // OS_WIN32
+ return UniGetLineUnix(str, size);
+#endif // OS_WIN32
+}
+void AnsiGetLineUnix(char *str, UINT size)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ char tmp[MAX_SIZE];
+ fgets(tmp, sizeof(tmp) - 1, stdin);
+ return;
+ }
+ if (size <= 1)
+ {
+ return;
+ }
+
+ // Read data from standard input
+ fgets(str, (int)(size - 1), stdin);
+
+ TrimCrlf(str);
+}
+bool UniGetLineUnix(wchar_t *str, UINT size)
+{
+ char *str_a;
+ UINT str_a_size = size;
+ if (str == NULL || size < sizeof(wchar_t))
+ {
+ return false;
+ }
+ if (str_a_size >= 0x7fffffff)
+ {
+ str_a_size = MAX_SIZE;
+ }
+ str_a_size *= 2;
+
+ str_a = ZeroMalloc(str_a_size);
+
+ AnsiGetLineUnix(str_a, str_a_size);
+
+ StrToUni(str, size, str_a);
+
+ Free(str_a);
+
+ return true;
+}
+bool UniGetLineWin32(wchar_t *str, UINT size)
+{
+ bool ret = false;
+
+#ifdef OS_WIN32
+ ret = Win32InputW(str, size);
+#endif // OS_WIN32
+
+ return ret;
+}
+
+// Remove '\r\n' at the end
+void UniTrimCrlf(wchar_t *str)
+{
+ UINT len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ len = UniStrLen(str);
+ if (len == 0)
+ {
+ return;
+ }
+
+ if (str[len - 1] == L'\n')
+ {
+ if (len >= 2 && str[len - 2] == L'\r')
+ {
+ str[len - 2] = 0;
+ }
+ str[len - 1] = 0;
+ }
+ else if(str[len - 1] == L'\r')
+ {
+ str[len - 1] = 0;
+ }
+}
+
+// Remove white space of the both side of the string
+void UniTrim(wchar_t *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ UniTrimLeft(str);
+ UniTrimRight(str);
+}
+
+// Remove white space on the right side of the string
+void UniTrimRight(wchar_t *str)
+{
+ wchar_t *buf, *tmp;
+ UINT len, i, wp, wp2;
+ bool flag;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ len = UniStrLen(str);
+ if (len == 0)
+ {
+ return;
+ }
+ if (str[len - 1] != L' ' && str[len - 1] != L'\t')
+ {
+ return;
+ }
+
+ buf = Malloc((len + 1) * sizeof(wchar_t));
+ tmp = Malloc((len + 1) * sizeof(wchar_t));
+ flag = false;
+ wp = wp2 = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (str[i] != L' ' && str[i] != L'\t')
+ {
+ Copy(&buf[wp], tmp, wp2 * sizeof(wchar_t));
+ wp += wp2;
+ wp2 = 0;
+ buf[wp++] = str[i];
+ }
+ else
+ {
+ tmp[wp2++] = str[i];
+ }
+ }
+ buf[wp] = 0;
+ UniStrCpy(str, 0, buf);
+ Free(buf);
+ Free(tmp);
+}
+
+// Remove white space from the left side of the string
+void UniTrimLeft(wchar_t *str)
+{
+ wchar_t *buf;
+ UINT len, i, wp;
+ bool flag;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ len = UniStrLen(str);
+ if (len == 0)
+ {
+ return;
+ }
+ if (str[0] != L' ' && str[0] != L'\t')
+ {
+ return;
+ }
+
+ buf = Malloc((len + 1) * sizeof(wchar_t));
+ flag = false;
+ wp = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (str[i] != L' ' && str[i] != L'\t')
+ {
+ flag = true;
+ }
+ if (flag)
+ {
+ buf[wp++] = str[i];
+ }
+ }
+ buf[wp] = 0;
+ UniStrCpy(str, 0, buf);
+ Free(buf);
+}
+
+// Convert an integer to a hexadecimal string (8-digit fixed)
+void UniToStrx8(wchar_t *str, UINT i)
+{
+ UniFormat(str, 0, L"0x%08x", i);
+}
+
+// Convert an integer to a hexadecimal string
+void UniToStrx(wchar_t *str, UINT i)
+{
+ UniFormat(str, 0, L"0x%02x", i);
+}
+
+// Convert a signed integer to a string
+void UniToStri(wchar_t *str, int i)
+{
+ UniFormat(str, 0, L"%i", i);
+}
+
+// Convert an integer to a string
+void UniToStru(wchar_t *str, UINT i)
+{
+ UniFormat(str, 0, L"%u", i);
+}
+
+// Convert the string to signed integer
+int UniToInti(wchar_t *str)
+{
+ char tmp[128];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ UniToStrForSingleChars(tmp, sizeof(tmp), str);
+
+ return ToInt(tmp);
+}
+
+// Convert a string to an integer
+UINT UniToInt(wchar_t *str)
+{
+ char tmp[128];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ UniToStrForSingleChars(tmp, sizeof(tmp), str);
+
+ return ToInti(tmp);
+}
+
+// Convert only single-byte characters in the Unicode string to a char string
+void UniToStrForSingleChars(char *dst, UINT dst_size, wchar_t *src)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < UniStrLen(src) + 1;i++)
+ {
+ wchar_t s = src[i];
+ char d;
+
+ if (s == 0)
+ {
+ d = 0;
+ }
+ else if (s <= 0xff)
+ {
+ d = (char)s;
+ }
+ else
+ {
+ d = ' ';
+ }
+
+ dst[i] = d;
+ }
+}
+
+// Format string replacement for 64-bit
+wchar_t *UniReplaceFormatStringFor64(wchar_t *fmt)
+{
+ wchar_t *tmp;
+ wchar_t *ret;
+ UINT tmp_size;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return NULL;
+ }
+
+ tmp_size = UniStrSize(fmt) * 2;
+ tmp = ZeroMalloc(tmp_size);
+
+#ifdef OS_WIN32
+ UniReplaceStrEx(tmp, tmp_size, fmt, L"%ll", L"%I64", false);
+#else // OS_WIN32
+ UniReplaceStrEx(tmp, tmp_size, fmt, L"%I64", L"%ll", false);
+
+ if (1)
+ {
+ UINT i, len;
+ bool f = false;
+ len = UniStrLen(tmp);
+ for (i = 0;i < len;i++)
+ {
+ if (tmp[i] == L'%')
+ {
+ f = true;
+ }
+
+ if (f)
+ {
+ switch (tmp[i])
+ {
+ case L'c':
+ case L'C':
+ case L'd':
+ case L'i':
+ case L'o':
+ case L'u':
+ case L'x':
+ case L'X':
+ case L'e':
+ case L'E':
+ case L'f':
+ case L'g':
+ case L'G':
+ case L'n':
+ case L'p':
+ case L's':
+ case L'S':
+ if (tmp[i] == L's')
+ {
+ tmp[i] = L'S';
+ }
+ else if (tmp[i] == L'S')
+ {
+ tmp[i] = L's';
+ }
+ f = false;
+ break;
+ }
+ }
+ }
+ }
+
+#endif // OS_WIN32
+
+ ret = CopyUniStr(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Display the string on the screen
+void UniPrintStr(wchar_t *string)
+{
+ // Validate arguments
+ if (string == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_UNIX
+ if (true)
+ {
+ char *str = CopyUniToStr(string);
+
+ if (str != NULL)
+ {
+ fputs(str, stdout);
+ }
+ else
+ {
+ fputs("", stdout);
+ }
+
+ Free(str);
+ }
+#else // OS_UNIX
+ Win32PrintW(string);
+#endif // OS_UNIX
+}
+
+// Display a string with arguments
+void UniPrintArgs(wchar_t *fmt, va_list args)
+{
+ wchar_t *str;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+
+ str = InternalFormatArgs(fmt, args, false);
+
+ UniPrintStr(str);
+
+ Free(str);
+}
+
+// Display the string
+void UniPrint(wchar_t *fmt, ...)
+{
+ va_list args;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+ UniPrintArgs(fmt, args);
+ va_end(args);
+}
+
+// Display debug string with arguments
+void UniDebugArgs(wchar_t *fmt, va_list args)
+{
+ if (g_debug == false)
+ {
+ return;
+ }
+
+ UniPrintArgs(fmt, args);
+}
+
+// Display a debug string
+void UniDebug(wchar_t *fmt, ...)
+{
+ va_list args;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+ UniDebugArgs(fmt, args);
+ va_end(args);
+}
+
+// Format a string (argument list)
+void UniFormatArgs(wchar_t *buf, UINT size, wchar_t *fmt, va_list args)
+{
+ wchar_t *ret;
+ // Validate arguments
+ if (buf == NULL || fmt == NULL)
+ {
+ return;
+ }
+ if (size == 1)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_FORMAT_COUNT);
+
+ ret = InternalFormatArgs(fmt, args, false);
+
+ UniStrCpy(buf, size, ret);
+
+ Free(ret);
+}
+
+// Format the string, and copy it
+wchar_t *CopyUniFormat(wchar_t *fmt, ...)
+{
+ wchar_t *ret, *str;
+ UINT size;
+ va_list args;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return NULL;
+ }
+
+ size = MAX(UniStrSize(fmt) * 10, MAX_SIZE * 10);
+ str = Malloc(size);
+
+ va_start(args, fmt);
+ UniFormatArgs(str, size, fmt, args);
+
+ ret = UniCopyStr(str);
+ Free(str);
+ va_end(args);
+
+ return ret;
+}
+
+// Format the string
+void UniFormat(wchar_t *buf, UINT size, wchar_t *fmt, ...)
+{
+ va_list args;
+ // Validate arguments
+ if (buf == NULL || fmt == NULL)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+ UniFormatArgs(buf, size, fmt, args);
+ va_end(args);
+}
+
+// Flexible string comparison
+int UniSoftStrCmp(wchar_t *str1, wchar_t *str2)
+{
+ UINT ret;
+ wchar_t *tmp1, *tmp2;
+ // Validate arguments
+ if (str1 == NULL && str2 == NULL)
+ {
+ return 0;
+ }
+ if (str1 == NULL)
+ {
+ return 1;
+ }
+ if (str2 == NULL)
+ {
+ return -1;
+ }
+
+ tmp1 = CopyUniStr(str1);
+ tmp2 = CopyUniStr(str2);
+
+ UniTrim(tmp1);
+ UniTrim(tmp2);
+
+ ret = UniStrCmpi(tmp1, tmp2);
+
+ Free(tmp1);
+ Free(tmp2);
+
+ return ret;
+}
+
+// Compare the strings in case-insensitive mode
+int UniStrCmpi(wchar_t *str1, wchar_t *str2)
+{
+ UINT i;
+ // Validate arguments
+ if (str1 == NULL && str2 == NULL)
+ {
+ return 0;
+ }
+ if (str1 == NULL)
+ {
+ return 1;
+ }
+ if (str2 == NULL)
+ {
+ return -1;
+ }
+
+ // String comparison
+ i = 0;
+ while (true)
+ {
+ wchar_t c1, c2;
+ c1 = UniToUpper(str1[i]);
+ c2 = UniToUpper(str2[i]);
+ if (c1 > c2)
+ {
+ return 1;
+ }
+ else if (c1 < c2)
+ {
+ return -1;
+ }
+ if (str1[i] == 0 || str2[i] == 0)
+ {
+ return 0;
+ }
+ i++;
+ }
+}
+
+// Compare the string
+int UniStrCmp(wchar_t *str1, wchar_t *str2)
+{
+ // Validate arguments
+ if (str1 == NULL && str2 == NULL)
+ {
+ return 0;
+ }
+ if (str1 == NULL)
+ {
+ return 1;
+ }
+ if (str2 == NULL)
+ {
+ return -1;
+ }
+
+ return wcscmp(str1, str2);
+}
+
+// Uncapitalize the string
+void UniStrLower(wchar_t *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ len = UniStrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ str[i] = UniToLower(str[i]);
+ }
+}
+
+// Capitalize the string
+void UniStrUpper(wchar_t *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ len = UniStrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ str[i] = UniToUpper(str[i]);
+ }
+}
+
+// Uncapitalize a character
+wchar_t UniToLower(wchar_t c)
+{
+ if (c >= L'A' && c <= L'Z')
+ {
+ c += L'a' - L'A';
+ }
+
+ return c;
+}
+
+// Capitalize a character
+wchar_t UniToUpper(wchar_t c)
+{
+ if (c >= L'a' && c <= L'z')
+ {
+ c -= L'a' - L'A';
+ }
+
+ return c;
+}
+
+// String concatenation
+UINT UniStrCat(wchar_t *dst, UINT size, wchar_t *src)
+{
+ UINT len1, len2, len_test;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return 0;
+ }
+ if (size != 0 && size < sizeof(wchar_t))
+ {
+ return 0;
+ }
+ if (size == sizeof(wchar_t))
+ {
+ wcscpy(dst, L"");
+ return 0;
+ }
+ if (size == 0)
+ {
+ // Ignore the length
+ size = 0x3fffffff;
+ }
+
+ len1 = UniStrLen(dst);
+ len2 = UniStrLen(src);
+ len_test = len1 + len2 + 1;
+ if (len_test > (size / sizeof(wchar_t)))
+ {
+ if (len2 <= (len_test - (size / sizeof(wchar_t))))
+ {
+ return 0;
+ }
+ len2 -= len_test - (size / sizeof(wchar_t));
+ }
+ Copy(&dst[len1], src, len2 * sizeof(wchar_t));
+ dst[len1 + len2] = 0;
+
+ return len1 + len2;
+}
+UINT UniStrCatLeft(wchar_t *dst, UINT size, wchar_t *src)
+{
+ wchar_t *s;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return 0;
+ }
+
+ s = UniCopyStr(dst);
+ UniStrCpy(dst, size, s);
+ UniStrCat(dst, size, src);
+ Free(s);
+
+ return UniStrLen(dst);
+}
+
+// String copy
+UINT UniStrCpy(wchar_t *dst, UINT size, wchar_t *src)
+{
+ UINT len;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ if (src == NULL && dst != NULL)
+ {
+ if (size >= sizeof(wchar_t))
+ {
+ dst[0] = L'\0';
+ }
+ }
+ return 0;
+ }
+ if (dst == src)
+ {
+ return UniStrLen(src);
+ }
+ if (size != 0 && size < sizeof(wchar_t))
+ {
+ return 0;
+ }
+ if (size == sizeof(wchar_t))
+ {
+ wcscpy(dst, L"");
+ return 0;
+ }
+ if (size == 0)
+ {
+ // Ignore the length
+ size = 0x3fffffff;
+ }
+
+ // Check the length
+ len = UniStrLen(src);
+ if (len <= (size / sizeof(wchar_t) - 1))
+ {
+ Copy(dst, src, (len + 1) * sizeof(wchar_t));
+ }
+ else
+ {
+ len = size / 2 - 1;
+ Copy(dst, src, len * sizeof(wchar_t));
+ dst[len] = 0;
+ }
+
+ return len;
+}
+
+// Check whether the character is within specified buffer size
+bool UniCheckStrSize(wchar_t *str, UINT size)
+{
+ // Validate arguments
+ if (str == NULL || size <= 1)
+ {
+ return false;
+ }
+
+ return UniCheckStrLen(str, size / sizeof(wchar_t) - 1);
+}
+
+// Check whether the number of characters is within specified length
+bool UniCheckStrLen(wchar_t *str, UINT len)
+{
+ UINT count = 0;
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;;i++)
+ {
+ if (str[i] == 0)
+ {
+ return true;
+ }
+ count++;
+ if (count > len)
+ {
+ return false;
+ }
+ }
+}
+
+// Get the buffer size needed to store the string
+UINT UniStrSize(wchar_t *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ return (UniStrLen(str) + 1) * sizeof(wchar_t);
+}
+
+// Get the length of the string
+UINT UniStrLen(wchar_t *str)
+{
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ i = 0;
+ while (true)
+ {
+ if (str[i] == 0)
+ {
+ break;
+ }
+ i++;
+ }
+
+ return i;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Internat.h b/src/Mayaqua/Internat.h
new file mode 100644
index 00000000..4a5181b9
--- /dev/null
+++ b/src/Mayaqua/Internat.h
@@ -0,0 +1,227 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Internat.h
+// Header of Internat.c
+
+#ifndef INTERNAT_H
+#define INTERNAT_H
+
+// String token
+struct UNI_TOKEN_LIST
+{
+ UINT NumTokens;
+ wchar_t **Token;
+};
+
+UINT UniStrLen(wchar_t *str);
+UINT UniStrSize(wchar_t *str);
+UINT UniStrCpy(wchar_t *dst, UINT size, wchar_t *src);
+bool UniCheckStrSize(wchar_t *str, UINT size);
+bool UniCheckStrLen(wchar_t *str, UINT len);
+UINT UniStrCat(wchar_t *dst, UINT size, wchar_t *src);
+UINT UniStrCatLeft(wchar_t *dst, UINT size, wchar_t *src);
+wchar_t UniToLower(wchar_t c);
+wchar_t UniToUpper(wchar_t c);
+void UniStrLower(wchar_t *str);
+void UniStrUpper(wchar_t *str);
+int UniStrCmp(wchar_t *str1, wchar_t *str2);
+int UniStrCmpi(wchar_t *str1, wchar_t *str2);
+int UniSoftStrCmp(wchar_t *str1, wchar_t *str2);
+void UniFormat(wchar_t *buf, UINT size, wchar_t *fmt, ...);
+wchar_t *CopyUniFormat(wchar_t *fmt, ...);
+void UniFormatArgs(wchar_t *buf, UINT size, wchar_t *fmt, va_list args);
+void UniDebugArgs(wchar_t *fmt, va_list args);
+void UniDebug(wchar_t *fmt, ...);
+void UniPrint(wchar_t *fmt, ...);
+void UniPrintArgs(wchar_t *fmt, va_list args);
+void UniPrintStr(wchar_t *string);
+void UniToStrx8(wchar_t *str, UINT i);
+void UniToStrx(wchar_t *str, UINT i);
+void UniToStri(wchar_t *str, int i);
+void UniToStru(wchar_t *str, UINT i);
+int UniToInti(wchar_t *str);
+UINT UniToInt(wchar_t *str);
+void UniToStrForSingleChars(char *dst, UINT dst_size, wchar_t *src);
+void UniTrim(wchar_t *str);
+void UniTrimLeft(wchar_t *str);
+void UniTrimRight(wchar_t *str);
+void UniTrimCrlf(wchar_t *str);
+bool UniGetLine(wchar_t *str, UINT size);
+bool UniGetLineWin32(wchar_t *str, UINT size);
+bool UniGetLineUnix(wchar_t *str, UINT size);
+void UniFreeToken(UNI_TOKEN_LIST *tokens);
+UNI_TOKEN_LIST *UniParseToken(wchar_t *src, wchar_t *separator);
+UINT UniSearchStrEx(wchar_t *string, wchar_t *keyword, UINT start, bool case_sensitive);
+UINT UniSearchStri(wchar_t *string, wchar_t *keyword, UINT start);
+UINT UniSearchStr(wchar_t *string, wchar_t *keyword, UINT start);
+UINT UniCalcReplaceStrEx(wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword, bool case_sensitive);
+UINT UniReplaceStrEx(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword, bool case_sensitive);
+UINT UniReplaceStri(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword);
+UINT UniReplaceStr(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword);
+UINT GetUniType(wchar_t c);
+UINT GetUtf8Type(BYTE *s, UINT size, UINT offset);
+UINT CalcUniToUtf8(wchar_t *s);
+UINT UniToUtf8(BYTE *u, UINT size, wchar_t *s);
+UINT Utf8Len(BYTE *u, UINT size);
+UINT CalcUtf8ToUni(BYTE *u, UINT u_size);
+UINT Utf8ToUni(wchar_t *s, UINT size, BYTE *u, UINT u_size);
+UINT CalcStrToUni(char *str);
+UINT StrToUni(wchar_t *s, UINT size, char *str);
+UINT CalcUniToStr(wchar_t *s);
+UINT UniToStr(char *str, UINT size, wchar_t *s);
+UINT CalcStrToUtf8(char *str);
+UINT StrToUtf8(BYTE *u, UINT size, char *str);
+UINT CalcUtf8ToStr(BYTE *u, UINT size);
+UINT Utf8ToStr(char *str, UINT str_size, BYTE *u, UINT size);
+bool IsSafeUniStr(wchar_t *str);
+bool IsSafeUniChar(wchar_t c);
+wchar_t *CopyUniStr(wchar_t *str);
+wchar_t *CopyStrToUni(char *str);
+UINT StrToUtf(char *utfstr, UINT size, char *str);
+UINT UtfToStr(char *str, UINT size, char *utfstr);
+UINT UniToUtf(char *utfstr, UINT size, wchar_t *unistr);
+UINT UtfToUni(wchar_t *unistr, UINT size, char *utfstr);
+char *CopyUniToUtf(wchar_t *unistr);
+char *CopyStrToUtf(char *str);
+char *CopyUniToStr(wchar_t *unistr);
+wchar_t *CopyUtfToUni(char *utfstr);
+char *CopyUtfToStr(char *utfstr);
+wchar_t *UniReplaceFormatStringFor64(wchar_t *fmt);
+void UniToStr64(wchar_t *str, UINT64 value);
+UINT64 UniToInt64(wchar_t *str);
+UNI_TOKEN_LIST *UniParseCmdLine(wchar_t *str);
+UNI_TOKEN_LIST *UniCopyToken(UNI_TOKEN_LIST *src);
+wchar_t *UniCopyStr(wchar_t *str);
+TOKEN_LIST *UniTokenListToTokenList(UNI_TOKEN_LIST *src);
+UNI_TOKEN_LIST *TokenListToUniTokenList(TOKEN_LIST *src);
+UNI_TOKEN_LIST *UniNullToken();
+UNI_TOKEN_LIST *NullUniToken();
+bool UniIsNum(wchar_t *str);
+bool IsEmptyUniStr(wchar_t *str);
+bool UniIsEmptyStr(wchar_t *str);
+void InitInternational();
+void FreeInternational();
+USHORT *WideToUtf16(wchar_t *str);
+wchar_t *Utf16ToWide(USHORT *str);
+void DumpUniStr(wchar_t *str);
+void DumpStr(char *str);
+wchar_t *InternalFormatArgs(wchar_t *fmt, va_list args, bool ansi_mode);
+UINT UniStrWidth(wchar_t *str);
+UNI_TOKEN_LIST *UnixUniParseToken(wchar_t *src, wchar_t *separator);
+void UniToStr3(wchar_t *str, UINT size, UINT64 value);
+bool UniEndWith(wchar_t *str, wchar_t *key);
+bool UniStartWith(wchar_t *str, wchar_t *key);
+wchar_t *UniNormalizeCrlf(wchar_t *str);
+LIST *UniStrToStrList(wchar_t *str, UINT size);
+BUF *UniStrListToStr(LIST *o);
+void UniFreeStrList(LIST *o);
+UNI_TOKEN_LIST *UniListToTokenList(LIST *o);
+LIST *UniTokenListToList(UNI_TOKEN_LIST *t);
+bool UniIsSafeChar(wchar_t c);
+wchar_t *UniMakeCharArray(wchar_t c, UINT count);
+BUF *UniStrToBin(wchar_t *str);
+bool UniInStr(wchar_t *str, wchar_t *keyword);
+bool UniInStrEx(wchar_t *str, wchar_t *keyword, bool case_sensitive);
+void ClearUniStr(wchar_t *str, UINT str_size);
+bool UniInChar(wchar_t *string, wchar_t c);
+
+#ifdef OS_UNIX
+void GetCurrentCharSet(char *name, UINT size);
+UINT UnixCalcStrToUni(char *str);
+UINT UnixStrToUni(wchar_t *s, UINT size, char *str);
+UINT UnixCalcUniToStr(wchar_t *s);
+UINT UnixUniToStr(char *str, UINT size, wchar_t *s);
+void *IconvWideToStr();
+void *IconvStrToWide();
+int IconvFree(void *d);
+void *IconvWideToStrInternal();
+void *IconvStrToWideInternal();
+int IconvFreeInternal(void *d);
+#endif // OS_UNIX
+
+#endif // INTERNAT_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Kernel.c b/src/Mayaqua/Kernel.c
new file mode 100644
index 00000000..c331290b
--- /dev/null
+++ b/src/Mayaqua/Kernel.c
@@ -0,0 +1,2172 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Kernel.c
+// System service processing routine
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+#ifndef TM_YEAR_MAX
+#define TM_YEAR_MAX 2106
+#endif
+#ifndef TM_MON_MAX
+#define TM_MON_MAX 1
+#endif
+#ifndef TM_MDAY_MAX
+#define TM_MDAY_MAX 7
+#endif
+#ifndef TM_HOUR_MAX
+#define TM_HOUR_MAX 6
+#endif
+#ifndef TM_MIN_MAX
+#define TM_MIN_MAX 28
+#endif
+#ifndef TM_SEC_MAX
+#define TM_SEC_MAX 14
+#endif
+
+#define ADJUST_TM(tm_member, tm_carry, modulus) \
+ if ((tm_member) < 0){ \
+ tm_carry -= (1 - ((tm_member)+1) / (modulus)); \
+ tm_member = (modulus-1) + (((tm_member)+1) % (modulus)); \
+ } else if ((tm_member) >= (modulus)) { \
+ tm_carry += (tm_member) / (modulus); \
+ tm_member = (tm_member) % (modulus); \
+ }
+#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
+#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
+#define leapday(m, y) ((m) == 1 && leap (y))
+#define monthlen(m, y) (ydays[(m)+1] - ydays[m] + leapday (m, y))
+static int ydays[] =
+{
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
+};
+
+static UINT current_num_thread = 0;
+
+
+
+static wchar_t *default_locale_str =
+L"- - $ : : $ Sun Mon Tue Wed Thu Fri Sat : : : $ (None)";
+
+
+static LOCALE current_locale;
+LOCK *tick_manual_lock = NULL;
+UINT g_zero = 0;
+
+// Get the real-time system timer
+UINT TickRealtime()
+{
+#if defined(OS_WIN32) || defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC) || defined(CLOCK_HIGHRES)
+ return Tick() + 1;
+#else
+ return TickRealtimeManual() + 1;
+#endif
+}
+
+#ifndef OS_WIN32
+
+static UINT64 last_manual_tick = 0;
+static UINT64 manual_tick_add_value = 0;
+
+// For systems which not have clock_gettime (such as MacOS X)
+UINT TickRealtimeManual()
+{
+ UINT64 ret;
+ Lock(tick_manual_lock);
+ {
+ ret = TickGetRealtimeTickValue64();
+
+ if (last_manual_tick != 0 && (last_manual_tick > ret))
+ {
+ manual_tick_add_value += (last_manual_tick - ret);
+ }
+
+ last_manual_tick = ret;
+ }
+ Unlock(tick_manual_lock);
+
+ return (UINT)(ret + manual_tick_add_value);
+}
+
+// Returns a appropriate value from the current time
+UINT64 TickGetRealtimeTickValue64()
+{
+ struct timeval tv;
+ struct timezone tz;
+ UINT64 ret;
+
+ memset(&tv, 0, sizeof(tv));
+ memset(&tz, 0, sizeof(tz));
+
+ gettimeofday(&tv, &tz);
+
+ ret = (UINT64)tv.tv_sec * 1000ULL + (UINT64)tv.tv_usec / 1000ULL;
+
+ return ret;
+}
+
+#endif // OS_WIN32
+
+// Creating a thread list
+LIST *NewThreadList()
+{
+ LIST *o = NewList(NULL);
+
+ return o;
+}
+
+// Remove the thread from the thread list
+void DelThreadFromThreadList(LIST *o, THREAD *t)
+{
+ // Validate arguments
+ if (o == NULL || t == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ if (Delete(o, t))
+ {
+ ReleaseThread(t);
+ }
+ }
+ UnlockList(o);
+}
+
+// Add the thread to the thread list
+void AddThreadToThreadList(LIST *o, THREAD *t)
+{
+ // Validate arguments
+ if (o == NULL || t == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ if (IsInList(o, t) == false)
+ {
+ AddRef(t->ref);
+
+ Add(o, t);
+ }
+ }
+ UnlockList(o);
+}
+
+// Maintain thread list
+void MainteThreadList(LIST *o)
+{
+ UINT i;
+ LIST *delete_list = NULL;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ THREAD *t = LIST_DATA(o, i);
+
+ if (t->Stopped)
+ {
+ if (delete_list == NULL)
+ {
+ delete_list = NewListFast(NULL);
+ }
+
+ Add(delete_list, t);
+ }
+ }
+
+ if (delete_list != NULL)
+ {
+ for (i = 0;i < LIST_NUM(delete_list);i++)
+ {
+ THREAD *t = LIST_DATA(delete_list, i);
+
+ ReleaseThread(t);
+
+ Delete(o, t);
+ }
+
+ ReleaseList(delete_list);
+ }
+ }
+ UnlockList(o);
+}
+
+// Stop all the threads in the thread list
+void StopThreadList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ THREAD *t = LIST_DATA(o, i);
+
+ WaitThread(t, INFINITE);
+ }
+ }
+ UnlockList(o);
+}
+
+// Release the thread list
+void FreeThreadList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ LockList(o);
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ THREAD *t = LIST_DATA(o, i);
+
+ WaitThread(t, INFINITE);
+
+ ReleaseThread(t);
+ }
+
+ DeleteAll(o);
+ }
+ UnlockList(o);
+
+ ReleaseList(o);
+}
+
+// Get the home directory
+void GetHomeDirW(wchar_t *path, UINT size)
+{
+ // Validate arguments
+ if (path == NULL)
+ {
+ return;
+ }
+
+ if (GetEnvW(L"HOME", path, size) == false)
+ {
+ wchar_t drive[MAX_SIZE];
+ wchar_t hpath[MAX_SIZE];
+ if (GetEnvW(L"HOMEDRIVE", drive, sizeof(drive)) &&
+ GetEnvW(L"HOMEPATH", hpath, sizeof(hpath)))
+ {
+ UniFormat(path, sizeof(path), L"%s%s", drive, hpath);
+ }
+ else
+ {
+#ifdef OS_WIN32
+ Win32GetCurrentDirW(path, size);
+#else // OS_WIN32
+ UnixGetCurrentDirW(path, size);
+#endif // OS_WIN32
+ }
+ }
+}
+void GetHomeDir(char *path, UINT size)
+{
+ // Validate arguments
+ if (path == NULL)
+ {
+ return;
+ }
+
+ if (GetEnv("HOME", path, size) == false)
+ {
+ char drive[MAX_SIZE];
+ char hpath[MAX_SIZE];
+ if (GetEnv("HOMEDRIVE", drive, sizeof(drive)) &&
+ GetEnv("HOMEPATH", hpath, sizeof(hpath)))
+ {
+ Format(path, sizeof(path), "%s%s", drive, hpath);
+ }
+ else
+ {
+#ifdef OS_WIN32
+ Win32GetCurrentDir(path, size);
+#else // OS_WIN32
+ UnixGetCurrentDir(path, size);
+#endif // OS_WIN32
+ }
+ }
+}
+
+// Get the environment variable string
+bool GetEnv(char *name, char *data, UINT size)
+{
+ char *ret;
+ // Validate arguments
+ if (name == NULL || data == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(data, size, "");
+
+ ret = getenv(name);
+ if (ret == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(data, size, ret);
+
+ return true;
+}
+bool GetEnvW(wchar_t *name, wchar_t *data, UINT size)
+{
+#ifdef OS_WIN32
+ return GetEnvW_ForWin32(name, data, size);
+#else // OS_WIN32
+ return GetEnvW_ForUnix(name, data, size);
+#endif // OS_WIN32
+}
+
+#ifdef OS_WIN32
+bool GetEnvW_ForWin32(wchar_t *name, wchar_t *data, UINT size)
+{
+ wchar_t *ret;
+ // Validate arguments
+ if (name == NULL || data == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ bool ret;
+ char *name_a = CopyUniToStr(name);
+ char data_a[MAX_SIZE];
+
+ ret = GetEnv(name_a, data_a, sizeof(data_a));
+
+ if (ret)
+ {
+ StrToUni(data, size, data_a);
+ }
+
+ Free(name_a);
+
+ return ret;
+ }
+
+ UniStrCpy(data, size, L"");
+
+ ret = _wgetenv(name);
+ if (ret == NULL)
+ {
+ return false;
+ }
+
+ UniStrCpy(data, size, ret);
+
+ return true;
+}
+
+#endif // OS_WIN32
+
+#ifdef OS_UNIX
+
+bool GetEnvW_ForUnix(wchar_t *name, wchar_t *data, UINT size)
+{
+ char *name_a;
+ bool ret;
+ char data_a[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL || data == NULL)
+ {
+ return false;
+ }
+
+ name_a = CopyUniToUtf(name);
+
+ ret = GetEnv(name_a, data_a, sizeof(data_a));
+
+ if (ret)
+ {
+ UtfToUni(data, size, data_a);
+ }
+
+ Free(name_a);
+
+ return ret;
+}
+
+#endif // OS_UNIX
+
+// Get the memory information
+void GetMemInfo(MEMINFO *info)
+{
+ OSGetMemInfo(info);
+}
+
+// Start the single-instance
+INSTANCE *NewSingleInstance(char *instance_name)
+{
+ return NewSingleInstanceEx(instance_name, false);
+}
+INSTANCE *NewSingleInstanceEx(char *instance_name, bool user_local)
+{
+ char name[MAX_SIZE];
+ INSTANCE *ret;
+ void *data;
+
+ if (instance_name != NULL)
+ {
+ if (user_local == false)
+ {
+ HashInstanceName(name, sizeof(name), instance_name);
+ }
+ else
+ {
+ HashInstanceNameLocal(name, sizeof(name), instance_name);
+ }
+
+ data = OSNewSingleInstance(name);
+ }
+ else
+ {
+ data = OSNewSingleInstance(NULL);
+ }
+
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(INSTANCE));
+ if (instance_name != NULL)
+ {
+ ret->Name = CopyStr(instance_name);
+ }
+
+ ret->pData = data;
+
+ return ret;
+}
+
+// Release of single instance
+void FreeSingleInstance(INSTANCE *inst)
+{
+ // Validate arguments
+ if (inst == NULL)
+ {
+ return;
+ }
+
+ OSFreeSingleInstance(inst->pData);
+
+ if (inst->Name != NULL)
+ {
+ Free(inst->Name);
+ }
+ Free(inst);
+}
+
+// Hashing the instance name
+void HashInstanceName(char *name, UINT size, char *instance_name)
+{
+ char tmp[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ char key[11];
+ // Validate arguments
+ if (name == NULL || instance_name == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp, sizeof(tmp), instance_name);
+ Trim(tmp);
+ StrUpper(tmp);
+
+ Hash(hash, tmp, StrLen(tmp), SHA1_SIZE);
+ BinToStr(key, sizeof(key), hash, 5);
+ key[10] = 0;
+
+ Format(name, size, "VPN-%s", key);
+
+ if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
+ {
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
+ GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
+ {
+ StrCpy(tmp, sizeof(tmp), name);
+ Format(name, size, "Global\\%s", tmp);
+ }
+ }
+}
+void HashInstanceNameLocal(char *name, UINT size, char *instance_name)
+{
+ char tmp[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ char key[11];
+ // Validate arguments
+ if (name == NULL || instance_name == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp, sizeof(tmp), instance_name);
+ Trim(tmp);
+ StrUpper(tmp);
+
+ Hash(hash, tmp, StrLen(tmp), SHA1_SIZE);
+ BinToStr(key, sizeof(key), hash, 5);
+ key[10] = 0;
+
+ Format(name, size, "VPN-%s", key);
+
+ if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
+ {
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
+ GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
+ {
+ StrCpy(tmp, sizeof(tmp), name);
+ Format(name, size, "Local\\%s", tmp);
+ }
+ }
+}
+
+// Run the process
+bool Run(char *filename, char *arg, bool hide, bool wait)
+{
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return false;
+ }
+
+ return OSRun(filename, arg, hide, wait);
+}
+bool RunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
+{
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return false;
+ }
+
+ return OSRunW(filename, arg, hide, wait);
+}
+
+// Date and time related functions
+void GetDateTimeStr64Uni(wchar_t *str, UINT size, UINT64 sec64)
+{
+ char tmp[MAX_SIZE];
+ if (str == NULL)
+ {
+ return;
+ }
+
+ GetDateTimeStr64(tmp, sizeof(tmp), sec64);
+ StrToUni(str, size, tmp);
+}
+void GetDateTimeStr64(char *str, UINT size, UINT64 sec64)
+{
+ SYSTEMTIME st;
+ UINT64ToSystem(&st, sec64);
+ GetDateTimeStr(str, size, &st);
+}
+void GetDateTimeStrMilli64(char *str, UINT size, UINT64 sec64)
+{
+ SYSTEMTIME st;
+ UINT64ToSystem(&st, sec64);
+ GetDateTimeStrMilli(str, size, &st);
+}
+void GetDateStr64(char *str, UINT size, UINT64 sec64)
+{
+ SYSTEMTIME st;
+ if (sec64 == 0)
+ {
+ StrCpy(str, size, "(Unknown)");
+ return;
+ }
+ UINT64ToSystem(&st, sec64);
+ GetDateStr(str, size, &st);
+}
+void GetDateTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
+{
+ SYSTEMTIME st;
+ if (locale == NULL)
+ {
+ locale = &current_locale;
+ }
+ if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
+ {
+ UniStrCpy(str, size, locale->Unknown);
+ return;
+ }
+ UINT64ToSystem(&st, sec64);
+ GetDateTimeStrEx(str, size, &st, locale);
+}
+void GetTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
+{
+ SYSTEMTIME st;
+ if (locale == NULL)
+ {
+ locale = &current_locale;
+ }
+ if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
+ {
+ UniStrCpy(str, size, locale->Unknown);
+ return;
+ }
+ UINT64ToSystem(&st, sec64);
+ GetTimeStrEx(str, size, &st, locale);
+}
+void GetDateStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
+{
+ SYSTEMTIME st;
+ if (locale == NULL)
+ {
+ locale = &current_locale;
+ }
+ if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
+ {
+ UniStrCpy(str, size, locale->Unknown);
+ return;
+ }
+ UINT64ToSystem(&st, sec64);
+ GetDateStrEx(str, size, &st, locale);
+}
+void GetTimeStrMilli64(char *str, UINT size, UINT64 sec64)
+{
+ SYSTEMTIME st;
+ if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
+ {
+ StrCpy(str, size, "(Unknown)");
+ return;
+ }
+ UINT64ToSystem(&st, sec64);
+ GetTimeStrMilli(str, size, &st);
+}
+void GetTimeStr64(char *str, UINT size, UINT64 sec64)
+{
+ SYSTEMTIME st;
+ if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
+ {
+ StrCpy(str, size, "(Unknown)");
+ return;
+ }
+ UINT64ToSystem(&st, sec64);
+ GetTimeStr(str, size, &st);
+}
+
+// Convert to a time to be used safely in the current POSIX implementation
+UINT64 SafeTime64(UINT64 sec64)
+{
+ return MAKESURE(sec64, 0, 2115947647000ULL);
+}
+
+// Thread pool
+static SK *thread_pool = NULL;
+static COUNTER *thread_count = NULL;
+
+// Initialization of thread pool
+void InitThreading()
+{
+ thread_pool = NewSk();
+ thread_count = NewCounter();
+}
+
+// Release of thread pool
+void FreeThreading()
+{
+ while (true)
+ {
+ if (Count(thread_count) == 0)
+ {
+ break;
+ }
+
+ SleepThread(25);
+ }
+
+ while (true)
+ {
+ THREAD_POOL_DATA *pd;
+ THREAD *t = Pop(thread_pool);
+
+ if (t == NULL)
+ {
+ break;
+ }
+
+ pd = (THREAD_POOL_DATA *)t->param;
+
+ pd->ThreadProc = NULL;
+ Set(pd->Event);
+
+ WaitThreadInternal(t);
+
+ pd = (THREAD_POOL_DATA *)t->param;
+ ReleaseEvent(pd->Event);
+ ReleaseEvent(pd->InitFinishEvent);
+
+ ReleaseThreadInternal(t);
+
+ Free(pd);
+ }
+
+ ReleaseSk(thread_pool);
+
+ DeleteCounter(thread_count);
+ thread_count = NULL;
+}
+
+// Thread pool procedure
+void ThreadPoolProc(THREAD *t, void *param)
+{
+ THREAD_POOL_DATA *pd;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ pd = (THREAD_POOL_DATA *)param;
+
+ NoticeThreadInitInternal(t);
+
+ while (true)
+ {
+ THREAD *thread;
+ UINT i, num;
+ EVENT **ee;
+
+ // Wait for the next job
+ Wait(pd->Event, INFINITE);
+
+ if (pd->ThreadProc == NULL)
+ {
+ // Stop the pool thread
+ break;
+ }
+
+ thread = pd->Thread;
+ thread->ThreadId = ThreadId();
+
+ // Initialization is completed
+ Set(pd->InitFinishEvent);
+
+ // Set the thread name
+ if (thread->Name != NULL)
+ {
+ SetThreadName(thread->ThreadId, thread->Name, thread->param);
+ }
+ else
+ {
+ SetThreadName(thread->ThreadId, "Unknown", 0);
+ }
+
+ // Run the thread procedure
+ pd->ThreadProc(pd->Thread, thread->param);
+
+ // Set the thread name
+ SetThreadName(thread->ThreadId, NULL, 0);
+
+ pd->Thread->Stopped = true;
+
+ thread->PoolHalting = true;
+
+ // Set the waiting event list
+ LockList(thread->PoolWaitList);
+ {
+ num = LIST_NUM(thread->PoolWaitList);
+ ee = ToArray(thread->PoolWaitList);
+
+ DeleteAll(thread->PoolWaitList);
+ }
+ UnlockList(thread->PoolWaitList);
+
+ for (i = 0;i < num;i++)
+ {
+ EVENT *e = ee[i];
+
+ Set(e);
+ ReleaseEvent(e);
+ }
+
+ Free(ee);
+
+ while (true)
+ {
+ if (Count(thread->ref->c) <= 1)
+ {
+ break;
+ }
+
+ Wait(thread->release_event, 256);
+ }
+
+ ReleaseThread(thread);
+
+#ifdef OS_WIN32
+ // For Win32: Recover the priority of the thread
+ MsRestoreThreadPriority();
+#endif // OS_WIN32
+
+ // Register the thread itself to the thread pool
+ LockSk(thread_pool);
+ {
+ Push(thread_pool, t);
+ }
+ UnlockSk(thread_pool);
+
+ Dec(thread_count);
+ }
+}
+
+// Set the thread name
+void SetThreadName(UINT thread_id, char *name, void *param)
+{
+#ifdef OS_WIN32
+ if (IsDebug())
+ {
+ char tmp[MAX_SIZE];
+
+ if (name == NULL)
+ {
+ strcpy(tmp, "idle");
+ }
+ else
+ {
+ sprintf(tmp, "%s (0x%x)", name, param);
+ }
+
+ Win32SetThreadName(thread_id, tmp);
+ }
+#else // OS_WIN32
+#ifdef _DEBUG
+#ifdef PR_SET_NAME
+ char tmp[MAX_SIZE];
+
+ if (name == NULL)
+ {
+ strcpy(tmp, "idle");
+ }
+ else
+ {
+ sprintf(tmp, "%s (%p)", name, param);
+ }
+
+ tmp[15] = 0;
+
+ prctl(PR_SET_NAME, (unsigned long)tmp, 0, 0, 0);
+#endif // PR_SET_NAME
+#endif // _DEBUG
+#endif // OS_WIN32
+}
+
+// Do Nothing
+UINT DoNothing()
+{
+ return g_zero;
+}
+
+// Thread creation (pool)
+THREAD *NewThreadNamed(THREAD_PROC *thread_proc, void *param, char *name)
+{
+ THREAD *host = NULL;
+ THREAD_POOL_DATA *pd = NULL;
+ THREAD *ret;
+ bool new_thread = false;
+ // Validate arguments
+ if (thread_proc == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsTrackingEnabled() == false)
+ {
+ DoNothing();
+ }
+
+ Inc(thread_count);
+
+ LockSk(thread_pool);
+ {
+ // Examine whether there is a thread that is currently vacant in the pool
+ host = Pop(thread_pool);
+ }
+ UnlockSk(thread_pool);
+
+ if (host == NULL)
+ {
+ // Create a new thread because a vacant thread is not found
+ pd = ZeroMalloc(sizeof(THREAD_POOL_DATA));
+ pd->Event = NewEvent();
+ pd->InitFinishEvent = NewEvent();
+ host = NewThreadInternal(ThreadPoolProc, pd);
+ WaitThreadInitInternal(host);
+
+ new_thread = true;
+ }
+ else
+ {
+ pd = (THREAD_POOL_DATA *)host->param;
+ }
+
+ // Creating a thread pool
+ ret = ZeroMalloc(sizeof(THREAD));
+ ret->ref = NewRef();
+ ret->thread_proc = thread_proc;
+ ret->param = param;
+ ret->pData = NULL;
+ ret->init_finished_event = NewEvent();
+ ret->PoolThread = true;
+ ret->PoolWaitList = NewList(NULL);
+ ret->PoolHostThread = host;
+ ret->release_event = NewEvent();
+
+ if (IsEmptyStr(name) == false)
+ {
+ ret->Name = CopyStr(name);
+ }
+
+ // Run
+ pd->ThreadProc = thread_proc;
+ pd->Thread = ret;
+ AddRef(ret->ref);
+
+ Set(pd->Event);
+
+ Wait(pd->InitFinishEvent, INFINITE);
+
+ current_num_thread++;
+
+// Debug("current_num_thread = %u\n", current_num_thread);
+
+ return ret;
+}
+
+// Clean up of thread (pool)
+void CleanupThread(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ ReleaseEvent(t->init_finished_event);
+ ReleaseEvent(t->release_event);
+ ReleaseList(t->PoolWaitList);
+
+ if (t->Name != NULL)
+ {
+ Free(t->Name);
+ }
+
+ Free(t);
+
+ current_num_thread--;
+ //Debug("current_num_thread = %u\n", current_num_thread);
+}
+
+// Release thread (pool)
+void ReleaseThread(THREAD *t)
+{
+ UINT ret;
+ EVENT *e;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ e = t->release_event;
+ if (e != NULL)
+ {
+ AddRef(e->ref);
+ }
+
+ ret = Release(t->ref);
+ Set(e);
+
+ ReleaseEvent(e);
+
+ if (ret == 0)
+ {
+ CleanupThread(t);
+ }
+}
+
+// Notify the completion of the thread initialization (pool)
+void NoticeThreadInit(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // Notification
+ Set(t->init_finished_event);
+}
+
+// Wait the completion of the thread initialization (pool)
+void WaitThreadInit(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_WAITFORTHREAD_COUNT);
+
+ // Wait
+ Wait(t->init_finished_event, INFINITE);
+}
+
+// Wait for the termination of the thread (pool)
+bool WaitThread(THREAD *t, UINT timeout)
+{
+ bool ret = false;
+ EVENT *e = NULL;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ LockList(t->PoolWaitList);
+ {
+ if (t->PoolHalting)
+ {
+ // Has already been stopped
+ ret = true;
+ }
+ else
+ {
+ // Register the completion notifying event to the list
+ e = NewEvent();
+ AddRef(e->ref);
+ Insert(t->PoolWaitList, e);
+ }
+ }
+ UnlockList(t->PoolWaitList);
+
+ if (e != NULL)
+ {
+ // Wait Event
+ ret = Wait(e, timeout);
+
+ LockList(t->PoolWaitList);
+ {
+ if (Delete(t->PoolWaitList, e))
+ {
+ ReleaseEvent(e);
+ }
+ }
+ UnlockList(t->PoolWaitList);
+
+ ReleaseEvent(e);
+ }
+
+ return ret;
+}
+
+// Get Thread ID
+UINT ThreadId()
+{
+ return OSThreadId();
+}
+
+// Creating a thread
+THREAD *NewThreadInternal(THREAD_PROC *thread_proc, void *param)
+{
+ THREAD *t;
+ UINT retry = 0;
+ // Validate arguments
+ if (thread_proc == NULL)
+ {
+ return NULL;
+ }
+
+ // Initialize Thread object
+ t = ZeroMalloc(sizeof(THREAD));
+ t->init_finished_event = NewEvent();
+
+ t->param = param;
+ t->ref = NewRef();
+ t->thread_proc = thread_proc;
+
+ // Wait until the OS to initialize the thread
+ while (true)
+ {
+ if ((retry++) > 60)
+ {
+ printf("\n\n*** error: new thread create failed.\n\n");
+ AbortExit();
+ }
+ if (OSInitThread(t))
+ {
+ break;
+ }
+ SleepThread(500);
+ }
+
+ // KS
+ KS_INC(KS_NEWTHREAD_COUNT);
+
+ return t;
+}
+
+// Release of thread
+void ReleaseThreadInternal(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (Release(t->ref) == 0)
+ {
+ CleanupThreadInternal(t);
+ }
+}
+
+// Clean up of the thread
+void CleanupThreadInternal(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // Release of the thread
+ OSFreeThread(t);
+
+ // Release the event
+ ReleaseEvent(t->init_finished_event);
+ // Memory release
+ Free(t);
+
+ // KS
+ KS_INC(KS_FREETHREAD_COUNT);
+}
+
+// Wait for the termination of the thread
+bool WaitThreadInternal(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ return OSWaitThread(t);
+}
+
+// Notify that the thread initialization is complete
+void NoticeThreadInitInternal(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // Notify
+ Set(t->init_finished_event);
+}
+
+// Wait for completion of thread initialization
+void WaitThreadInitInternal(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_WAITFORTHREAD_COUNT);
+
+ // Wait
+ Wait(t->init_finished_event, INFINITE);
+}
+
+// Get the date and time string by using the locale information
+void GetDateTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
+{
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL || st == NULL)
+ {
+ return;
+ }
+
+ GetDateStrEx(tmp1, sizeof(tmp1), st, locale);
+ GetTimeStrEx(tmp2, sizeof(tmp2), st, locale);
+ UniFormat(str, size, L"%s %s", tmp1, tmp2);
+}
+
+// Get the time string by using the locale information
+void GetTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
+{
+ wchar_t *tag = L"%02u%s%02u%s%02u%s";
+ // Validate arguments
+ if (str == NULL || st == NULL)
+ {
+ return;
+ }
+
+ if (_GETLANG() == SE_LANG_JAPANESE || _GETLANG() == SE_LANG_CHINESE_ZH)
+ {
+ tag = L"%2u%s%2u%s%2u%s";
+ }
+
+ locale = (locale != NULL ? locale : &current_locale);
+ UniFormat(str, size,
+ tag,
+ st->wHour, locale->HourStr,
+ st->wMinute, locale->MinuteStr,
+ st->wSecond, locale->SecondStr);
+}
+
+// Get a date string by using the locale information
+void GetDateStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
+{
+ wchar_t *tag = L"%04u%s%02u%s%02u%s (%s)";
+ // Validate arguments
+ if (str == NULL || st == NULL)
+ {
+ return;
+ }
+
+ if (_GETLANG() == SE_LANG_JAPANESE || _GETLANG() == SE_LANG_CHINESE_ZH)
+ {
+ tag = L"%4u%s%2u%s%2u%s(%s)";
+ }
+
+ locale = (locale != NULL ? locale : &current_locale);
+ UniFormat(str, size,
+ tag,
+ st->wYear, locale->YearStr,
+ st->wMonth, locale->MonthStr,
+ st->wDay, locale->DayStr,
+ locale->DayOfWeek[st->wDayOfWeek]);
+}
+
+// Get the time string to milliseconds (for example, 12:34:56.789)
+void GetTimeStrMilli(char *str, UINT size, SYSTEMTIME *st)
+{
+ // Validate arguments
+ if (st == NULL || str == NULL)
+ {
+ return;
+ }
+
+ Format(str, size, "%02u:%02u:%02u.%03u",
+ st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
+}
+
+// Get the time string (for example, 12:34:56)
+void GetTimeStr(char *str, UINT size, SYSTEMTIME *st)
+{
+ // Validate arguments
+ if (str == NULL || st == NULL)
+ {
+ return;
+ }
+
+ Format(str, size, "%02u:%02u:%02u",
+ st->wHour, st->wMinute, st->wSecond);
+}
+
+// Get the date string (example: 2004/07/23)
+void GetDateStr(char *str, UINT size, SYSTEMTIME *st)
+{
+ // Validate arguments
+ if (str == NULL || st == NULL)
+ {
+ return;
+ }
+
+ Format(str, size, "%04u-%02u-%02u",
+ st->wYear, st->wMonth, st->wDay);
+}
+
+// Get the date and time string (example: 2004/07/23 12:34:56)
+void GetDateTimeStr(char *str, UINT size, SYSTEMTIME *st)
+{
+ // Validate arguments
+ if (str == NULL || st == NULL)
+ {
+ return;
+ }
+
+ Format(str, size, "%04u-%02u-%02u %02u:%02u:%02u",
+ st->wYear, st->wMonth, st->wDay,
+ st->wHour, st->wMinute, st->wSecond);
+}
+
+// Get the date and time string in milliseconds (example: 2004/07/23 12:34:56.789)
+void GetDateTimeStrMilli(char *str, UINT size, SYSTEMTIME *st)
+{
+ // Validate arguments
+ if (str == NULL || st == NULL)
+ {
+ return;
+ }
+
+ Format(str, size, "%04u-%02u-%02u %02u:%02u:%02u.%03u",
+ st->wYear, st->wMonth, st->wDay,
+ st->wHour, st->wMinute, st->wSecond,
+ st->wMilliseconds);
+}
+
+// Get the time string
+void GetSpanStr(char *str, UINT size, UINT64 sec64)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp, sizeof(tmp), "");
+ if (sec64 >= (UINT64)(1000 * 3600 * 24))
+ {
+ Format(tmp, sizeof(tmp), "%u:", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)));
+ }
+
+ Format(tmp, sizeof(tmp), "%s%02u:%02u:%02u", tmp,
+ (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
+ (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
+ (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000);
+
+ Trim(tmp);
+ StrCpy(str, size, tmp);
+}
+
+// Get the time string (in milliseconds)
+void GetSpanStrMilli(char *str, UINT size, UINT64 sec64)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp, sizeof(tmp), "");
+ if (sec64 >= (UINT64)(1000 * 3600 * 24))
+ {
+ Format(tmp, sizeof(tmp), "%u:", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)));
+ }
+
+ Format(tmp, sizeof(tmp), "%s%02u:%02u:%02u.%03u", tmp,
+ (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
+ (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
+ (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000,
+ (UINT)(sec64 % (UINT64)(1000)));
+
+ Trim(tmp);
+ StrCpy(str, size, tmp);
+}
+
+// Get the time string (extended)
+void GetSpanStrEx(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
+{
+ wchar_t tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ locale = (locale != NULL ? locale : &current_locale);
+
+ UniStrCpy(tmp, sizeof(tmp), L"");
+ if (sec64 >= (UINT64)(1000 * 3600 * 24))
+ {
+ UniFormat(tmp, sizeof(tmp), L"%u%s ", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)),
+ locale->SpanDay);
+ }
+
+ UniFormat(tmp, sizeof(tmp), L"%s%u%s %02u%s %02u%s", tmp,
+ (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
+ locale->SpanHour,
+ (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
+ locale->SpanMinute,
+ (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000,
+ locale->SpanSecond);
+
+ UniTrim(tmp);
+ UniStrCpy(str, size, tmp);
+}
+
+// Get the current locale information
+void GetCurrentLocale(LOCALE *locale)
+{
+ // Validate arguments
+ if (locale == NULL)
+ {
+ return;
+ }
+
+ Copy(locale, &current_locale, sizeof(LOCALE));
+}
+
+// Set the locale information
+void SetLocale(wchar_t *str)
+{
+ wchar_t *set_locale_str;
+ LOCALE tmp;
+
+ if (str != NULL)
+ {
+ set_locale_str = str;
+ }
+ else
+ {
+ set_locale_str = default_locale_str;
+ }
+
+ if (LoadLocale(&tmp, set_locale_str) == false)
+ {
+ if (LoadLocale(&tmp, default_locale_str) == false)
+ {
+ return;
+ }
+ }
+
+ Copy(&current_locale, &tmp, sizeof(LOCALE));
+}
+
+#define COPY_LOCALE_STR(dest, size, src) UniStrCpy(dest, size, UniStrCmp(src, L"$") == 0 ? L"" : src)
+
+// Read the locale information
+bool LoadLocale(LOCALE *locale, wchar_t *str)
+{
+ UNI_TOKEN_LIST *tokens;
+ UINT i;
+ // Validate arguments
+ if (locale == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ // Analysis of the token
+ tokens = UniParseToken(str, L" ");
+ if (tokens->NumTokens != 18)
+ {
+ UniFreeToken(tokens);
+ return false;
+ }
+
+ // Set to the structure
+ Zero(locale, sizeof(LOCALE));
+ COPY_LOCALE_STR(locale->YearStr, sizeof(locale->YearStr), tokens->Token[0]);
+ COPY_LOCALE_STR(locale->MonthStr, sizeof(locale->MonthStr), tokens->Token[1]);
+ COPY_LOCALE_STR(locale->DayStr, sizeof(locale->DayStr), tokens->Token[2]);
+ COPY_LOCALE_STR(locale->HourStr, sizeof(locale->HourStr), tokens->Token[3]);
+ COPY_LOCALE_STR(locale->MinuteStr, sizeof(locale->MinuteStr), tokens->Token[4]);
+ COPY_LOCALE_STR(locale->SecondStr, sizeof(locale->SecondStr), tokens->Token[5]);
+
+ for (i = 0;i < 7;i++)
+ {
+ COPY_LOCALE_STR(locale->DayOfWeek[i], sizeof(locale->DayOfWeek[i]),
+ tokens->Token[6 + i]);
+ }
+
+ COPY_LOCALE_STR(locale->SpanDay, sizeof(locale->SpanDay), tokens->Token[13]);
+ COPY_LOCALE_STR(locale->SpanHour, sizeof(locale->SpanHour), tokens->Token[14]);
+ COPY_LOCALE_STR(locale->SpanMinute, sizeof(locale->SpanMinute), tokens->Token[15]);
+ COPY_LOCALE_STR(locale->SpanSecond, sizeof(locale->SpanSecond), tokens->Token[16]);
+
+ COPY_LOCALE_STR(locale->Unknown, sizeof(locale->Unknown), tokens->Token[17]);
+
+ UniFreeToken(tokens);
+ return true;
+}
+
+// Convert SYSTEMTIME into DOS date
+USHORT SystemToDosDate(SYSTEMTIME *st)
+{
+ return (USHORT)(
+ ((UINT)(st->wYear - 1980) << 9) |
+ ((UINT)st->wMonth<< 5) |
+ (UINT)st->wDay);
+}
+USHORT System64ToDosDate(UINT64 i)
+{
+ SYSTEMTIME st;
+ UINT64ToSystem(&st, i);
+ return SystemToDosDate(&st);
+}
+
+// Convert SYSTEMTIME into DOS time
+USHORT SystemToDosTime(SYSTEMTIME *st)
+{
+ return (USHORT)(
+ ((UINT)st->wHour << 11) |
+ ((UINT)st->wMinute << 5) |
+ ((UINT)st->wSecond >> 1));
+}
+USHORT System64ToDosTime(UINT64 i)
+{
+ SYSTEMTIME st;
+ UINT64ToSystem(&st, i);
+ return SystemToDosTime(&st);
+}
+
+// Convert the tm to the SYSTEMTIME
+void TmToSystem(SYSTEMTIME *st, struct tm *t)
+{
+ struct tm tmp;
+ // Validate arguments
+ if (st == NULL || t == NULL)
+ {
+ return;
+ }
+
+ Copy(&tmp, t, sizeof(struct tm));
+ NormalizeTm(&tmp);
+
+ Zero(st, sizeof(SYSTEMTIME));
+ st->wYear = MAKESURE(tmp.tm_year + 1900, 1970, 2037);
+ st->wMonth = MAKESURE(tmp.tm_mon + 1, 1, 12);
+ st->wDay = MAKESURE(tmp.tm_mday, 1, 31);
+ st->wDayOfWeek = MAKESURE(tmp.tm_wday, 0, 6);
+ st->wHour = MAKESURE(tmp.tm_hour, 0, 23);
+ st->wMinute = MAKESURE(tmp.tm_min, 0, 59);
+ st->wSecond = MAKESURE(tmp.tm_sec, 0, 59);
+ st->wMilliseconds = 0;
+}
+
+// Convert the SYSTEMTIME to tm
+void SystemToTm(struct tm *t, SYSTEMTIME *st)
+{
+ // Validate arguments
+ if (t == NULL || st == NULL)
+ {
+ return;
+ }
+
+ Zero(t, sizeof(struct tm));
+ t->tm_year = MAKESURE(st->wYear, 1970, 2037) - 1900;
+ t->tm_mon = MAKESURE(st->wMonth, 1, 12) - 1;
+ t->tm_mday = MAKESURE(st->wDay, 1, 31);
+ t->tm_hour = MAKESURE(st->wHour, 0, 23);
+ t->tm_min = MAKESURE(st->wMinute, 0, 59);
+ t->tm_sec = MAKESURE(st->wSecond, 0, 59);
+
+ t->tm_isdst = -1;
+ NormalizeTm(t);
+}
+
+// Convert the time_t to SYSTEMTIME
+void TimeToSystem(SYSTEMTIME *st, time_t t)
+{
+ struct tm tmp;
+ // Validate arguments
+ if (st == NULL)
+ {
+ return;
+ }
+
+ TimeToTm(&tmp, t);
+ TmToSystem(st, &tmp);
+}
+
+// Convert the time_t to 64-bit SYSTEMTIME
+UINT64 TimeToSystem64(time_t t)
+{
+ SYSTEMTIME st;
+
+ TimeToSystem(&st, t);
+
+ return SystemToUINT64(&st);
+}
+
+// Convert the SYSTEMTIME to time_t
+time_t SystemToTime(SYSTEMTIME *st)
+{
+ struct tm t;
+ // Validate arguments
+ if (st == NULL)
+ {
+ return 0;
+ }
+
+ SystemToTm(&t, st);
+ return TmToTime(&t);
+}
+
+// Convert a 64-bit SYSTEMTIME to a time_t
+time_t System64ToTime(UINT64 i)
+{
+ SYSTEMTIME st;
+
+ UINT64ToSystem(&st, i);
+
+ return SystemToTime(&st);
+}
+
+// Convert the tm to time_t
+time_t TmToTime(struct tm *t)
+{
+ time_t tmp;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return 0;
+ }
+
+ tmp = c_mkgmtime(t);
+ if (tmp == (time_t)-1)
+ {
+ return 0;
+ }
+ return tmp;
+}
+
+// Convert time_t to tm
+void TimeToTm(struct tm *t, time_t time)
+{
+ struct tm *ret;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+#ifndef OS_UNIX
+ ret = gmtime(&time);
+#else // OS_UNIX
+ ret = malloc(sizeof(struct tm));
+ memset(ret, 0, sizeof(ret));
+ gmtime_r(&time, ret);
+#endif // OS_UNIX
+
+ if (ret == NULL)
+ {
+ Zero(t, sizeof(struct tm));
+ }
+ else
+ {
+ Copy(t, ret, sizeof(struct tm));
+ }
+
+#ifdef OS_UNIX
+ free(ret);
+#endif // OS_UNIX
+}
+
+// Normalize the tm
+void NormalizeTm(struct tm *t)
+{
+ struct tm *ret;
+ time_t tmp;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ tmp = c_mkgmtime(t);
+ if (tmp == (time_t)-1)
+ {
+ return;
+ }
+
+#ifndef OS_UNIX
+ ret = gmtime(&tmp);
+#else // OS_UNIX
+ ret = malloc(sizeof(struct tm));
+ memset(ret, 0, sizeof(ret));
+ gmtime_r(&tmp, ret);
+#endif // OS_UNIX
+
+ if (ret == NULL)
+ {
+ Zero(t, sizeof(struct tm));
+ }
+ else
+ {
+ Copy(t, ret, sizeof(struct tm));
+ }
+
+#ifdef OS_UNIX
+ free(ret);
+#endif // OS_UNIX
+}
+
+// Normalize the SYSTEMTIME
+void NormalizeSystem(SYSTEMTIME *st)
+{
+ UINT64 sec64;
+ // Validate arguments
+ if (st == NULL)
+ {
+ return;
+ }
+
+ sec64 = SystemToUINT64(st);
+ UINT64ToSystem(st, sec64);
+}
+
+// Convert a 64-bit local time to a system time
+UINT64 LocalToSystem64(UINT64 t)
+{
+ SYSTEMTIME st;
+ UINT64ToSystem(&st, t);
+ LocalToSystem(&st, &st);
+ return SystemToUINT64(&st);
+}
+
+// Convert the 64bit system time to local time
+UINT64 SystemToLocal64(UINT64 t)
+{
+ SYSTEMTIME st;
+ UINT64ToSystem(&st, t);
+ SystemToLocal(&st, &st);
+ return SystemToUINT64(&st);
+}
+
+// Convert local time to system time
+void LocalToSystem(SYSTEMTIME *system, SYSTEMTIME *local)
+{
+ UINT64 sec64;
+ // Validate arguments
+ if (local == NULL || system == NULL)
+ {
+ return;
+ }
+
+ sec64 = (UINT64)((INT64)SystemToUINT64(local) - GetTimeDiffEx(local, true));
+ UINT64ToSystem(system, sec64);
+}
+
+// Convert the system time to local time
+void SystemToLocal(SYSTEMTIME *local, SYSTEMTIME *system)
+{
+ UINT64 sec64;
+ // Validate arguments
+ if (local == NULL || system == NULL)
+ {
+ return;
+ }
+
+ sec64 = (UINT64)((INT64)SystemToUINT64(system) + GetTimeDiffEx(system, false));
+ UINT64ToSystem(local, sec64);
+}
+
+// Get the time difference between the local time and the system time based on the specified time
+INT64 GetTimeDiffEx(SYSTEMTIME *basetime, bool local_time)
+{
+ time_t tmp;
+ struct tm t1, t2;
+ SYSTEMTIME snow;
+ struct tm now;
+ SYSTEMTIME s1, s2;
+ INT64 ret;
+
+ Copy(&snow, basetime, sizeof(SYSTEMTIME));
+
+ SystemToTm(&now, &snow);
+ if (local_time == false)
+ {
+ tmp = c_mkgmtime(&now);
+ }
+ else
+ {
+ tmp = mktime(&now);
+ }
+
+ if (tmp == (time_t)-1)
+ {
+ return 0;
+ }
+
+ Copy(&t1, localtime(&tmp), sizeof(struct tm));
+ Copy(&t2, gmtime(&tmp), sizeof(struct tm));
+ TmToSystem(&s1, &t1);
+ TmToSystem(&s2, &t2);
+
+ ret = (INT)SystemToUINT64(&s1) - (INT)SystemToUINT64(&s2);
+
+ return ret;
+}
+
+// Get the time difference between the local time and system time
+INT64 GetTimeDiff()
+{
+ time_t tmp;
+ struct tm t1, t2;
+ SYSTEMTIME snow;
+ struct tm now;
+ SYSTEMTIME s1, s2;
+ INT64 ret;
+
+ static INT64 cache = INFINITE;
+
+ if (cache != INFINITE)
+ {
+ // Returns the cache data after measured once
+ return cache;
+ }
+
+ SystemTime(&snow);
+ SystemToTm(&now, &snow);
+ tmp = c_mkgmtime(&now);
+ if (tmp == (time_t)-1)
+ {
+ return 0;
+ }
+
+ Copy(&t1, localtime(&tmp), sizeof(struct tm));
+ Copy(&t2, gmtime(&tmp), sizeof(struct tm));
+ TmToSystem(&s1, &t1);
+ TmToSystem(&s2, &t2);
+
+ cache = ret = (INT)SystemToUINT64(&s1) - (INT)SystemToUINT64(&s2);
+
+ return ret;
+}
+
+// Convert UINT64 to the SYSTEMTIME
+void UINT64ToSystem(SYSTEMTIME *st, UINT64 sec64)
+{
+ UINT64 tmp64;
+ UINT sec, millisec;
+ time_t time;
+ // Validate arguments
+ if (st == NULL)
+ {
+ return;
+ }
+
+ sec64 = SafeTime64(sec64 + 32400000ULL);
+ tmp64 = sec64 / (UINT64)1000;
+ millisec = (UINT)(sec64 - tmp64 * (UINT64)1000);
+ sec = (UINT)tmp64;
+ time = (time_t)sec;
+ TimeToSystem(st, time);
+ st->wMilliseconds = (WORD)millisec;
+}
+
+// Convert the SYSTEMTIME to UINT64
+UINT64 SystemToUINT64(SYSTEMTIME *st)
+{
+ UINT64 sec64;
+ time_t time;
+ // Validate arguments
+ if (st == NULL)
+ {
+ return 0;
+ }
+
+ time = SystemToTime(st);
+ sec64 = (UINT64)time * (UINT64)1000;
+ sec64 += st->wMilliseconds;
+
+ return sec64 - 32400000ULL;
+}
+
+// Get local time in UINT64
+UINT64 LocalTime64()
+{
+ SYSTEMTIME s;
+ LocalTime(&s);
+ return SystemToUINT64(&s);
+}
+
+// Get the system time in UINT64
+UINT64 SystemTime64()
+{
+ SYSTEMTIME s;
+ SystemTime(&s);
+ return SystemToUINT64(&s);
+}
+
+// Get local time
+void LocalTime(SYSTEMTIME *st)
+{
+ SYSTEMTIME tmp;
+ // Validate arguments
+ if (st == NULL)
+ {
+ return;
+ }
+
+ SystemTime(&tmp);
+ SystemToLocal(st, &tmp);
+}
+
+// Get the System Time
+void SystemTime(SYSTEMTIME *st)
+{
+ // Validate arguments
+ if (st == NULL)
+ {
+ return;
+ }
+
+ OSGetSystemTime(st);
+
+ // KS
+ KS_INC(KS_GETTIME_COUNT);
+}
+
+time_t c_mkgmtime(struct tm *tm)
+{
+ int years, months, days, hours, minutes, seconds;
+
+ years = tm->tm_year + 1900; /* year - 1900 -> year */
+ months = tm->tm_mon; /* 0..11 */
+ days = tm->tm_mday - 1; /* 1..31 -> 0..30 */
+ hours = tm->tm_hour; /* 0..23 */
+ minutes = tm->tm_min; /* 0..59 */
+ seconds = tm->tm_sec; /* 0..61 in ANSI C. */
+
+ ADJUST_TM(seconds, minutes, 60);
+ ADJUST_TM(minutes, hours, 60);
+ ADJUST_TM(hours, days, 24);
+ ADJUST_TM(months, years, 12);
+ if (days < 0)
+ do {
+ if (--months < 0) {
+ --years;
+ months = 11;
+ }
+ days += monthlen(months, years);
+ } while (days < 0);
+ else
+ while (days >= monthlen(months, years)) {
+ days -= monthlen(months, years);
+ if (++months >= 12) {
+ ++years;
+ months = 0;
+ }
+ }
+
+ /* Restore adjusted values in tm structure */
+ tm->tm_year = years - 1900;
+ tm->tm_mon = months;
+ tm->tm_mday = days + 1;
+ tm->tm_hour = hours;
+ tm->tm_min = minutes;
+ tm->tm_sec = seconds;
+
+ /* Set `days' to the number of days into the year. */
+ days += ydays[months] + (months > 1 && leap (years));
+ tm->tm_yday = days;
+
+ /* Now calculate `days' to the number of days since Jan 1, 1970. */
+ days = (unsigned)days + 365 * (unsigned)(years - 1970) +
+ (unsigned)(nleap (years));
+ tm->tm_wday = ((unsigned)days + 4) % 7; /* Jan 1, 1970 was Thursday. */
+ tm->tm_isdst = 0;
+
+ if (years < 1970)
+ return (time_t)-1;
+
+#if (defined(TM_YEAR_MAX) && defined(TM_MON_MAX) && defined(TM_MDAY_MAX))
+#if (defined(TM_HOUR_MAX) && defined(TM_MIN_MAX) && defined(TM_SEC_MAX))
+ if (years > TM_YEAR_MAX ||
+ (years == TM_YEAR_MAX &&
+ (tm->tm_yday > ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
+ (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) ||
+ (tm->tm_yday == ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
+ (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) &&
+ (hours > TM_HOUR_MAX ||
+ (hours == TM_HOUR_MAX &&
+ (minutes > TM_MIN_MAX ||
+ (minutes == TM_MIN_MAX && seconds > TM_SEC_MAX) )))))))
+ return (time_t)-1;
+#endif
+#endif
+
+ return (time_t)(86400L * (unsigned long)(unsigned)days +
+ 3600L * (unsigned long)hours +
+ (unsigned long)(60 * minutes + seconds));
+}
+
+// Get the system timer
+UINT Tick()
+{
+ // KS
+ KS_INC(KS_GETTICK_COUNT);
+ return OSGetTick();
+}
+
+// Sleep thread
+void SleepThread(UINT time)
+{
+ // KS
+ KS_INC(KS_SLEEPTHREAD_COUNT);
+
+ OSSleep(time);
+}
+
+// Yield
+void YieldCpu()
+{
+ OSYield();
+}
+
+// Stop system (abnormal termination)
+void AbortExit()
+{
+#ifdef OS_WIN32
+ _exit(1);
+#else // OS_WIN32
+
+#ifdef RLIMIT_CORE
+ UnixSetResourceLimit(RLIMIT_CORE, 0);
+#endif // RLIMIT_CORE
+
+ abort();
+#endif // OS_WIN32
+}
+
+
+void AbortExitEx(char *msg)
+{
+ FILE *f;
+ // Validate arguments
+ if (msg == NULL)
+ {
+ msg = "Unknown Error";
+ }
+
+ f = fopen("abort_error_log.txt", "w");
+ if (f != NULL)
+ {
+ fwrite(msg, 1, strlen(msg), f);
+ fclose(f);
+ }
+
+ fputs("Fatal Error: ", stdout);
+ fputs(msg, stdout);
+ fputs("\r\n", stdout);
+
+#ifdef OS_WIN32
+ _exit(1);
+#else // OS_WIN32
+
+#ifdef RLIMIT_CORE
+ UnixSetResourceLimit(RLIMIT_CORE, 0);
+#endif // RLIMIT_CORE
+
+ abort();
+#endif // OS_WIN32
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Kernel.h b/src/Mayaqua/Kernel.h
new file mode 100644
index 00000000..9e55979d
--- /dev/null
+++ b/src/Mayaqua/Kernel.h
@@ -0,0 +1,252 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+#ifndef KERNEL_H
+#define KERNEL_H
+
+// Memory usage information
+struct MEMINFO
+{
+ UINT64 TotalMemory;
+ UINT64 UsedMemory;
+ UINT64 FreeMemory;
+ UINT64 TotalPhys;
+ UINT64 UsedPhys;
+ UINT64 FreePhys;
+};
+
+// Locale information
+struct LOCALE
+{
+ wchar_t YearStr[16], MonthStr[16], DayStr[16];
+ wchar_t HourStr[16], MinuteStr[16], SecondStr[16];
+ wchar_t DayOfWeek[7][16];
+ wchar_t SpanDay[16], SpanHour[16], SpanMinute[16], SpanSecond[16];
+ wchar_t Unknown[32];
+};
+
+
+// Thread procedure
+typedef void (THREAD_PROC)(THREAD *thread, void *param);
+
+// Thread
+struct THREAD
+{
+ REF *ref;
+ THREAD_PROC *thread_proc;
+ void *param;
+ void *pData;
+ EVENT *init_finished_event;
+ void *AppData1, *AppData2, *AppData3;
+ UINT AppInt1, AppInt2, AppInt3;
+ UINT ThreadId;
+ bool PoolThread;
+ THREAD *PoolHostThread;
+ LIST *PoolWaitList; // Thread termination waiting list
+ volatile bool PoolHalting; // Thread stopped
+ EVENT *release_event;
+ bool Stopped; // Indicates that the operation is Stopped
+ char *Name; // Thread name
+};
+
+// Thread pool data
+struct THREAD_POOL_DATA
+{
+ EVENT *Event; // Waiting Event
+ EVENT *InitFinishEvent; // Initialization is completed event
+ THREAD *Thread; // Threads that are currently assigned
+ THREAD_PROC *ThreadProc; // Thread procedure that is currently assigned
+};
+
+// Instance
+struct INSTANCE
+{
+ char *Name; // Name
+ void *pData; // Data
+};
+
+// Create a new thread
+#define NewThread(thread_proc, param) NewThreadNamed((thread_proc), (param), (#thread_proc))
+
+// Function prototype
+void SleepThread(UINT time);
+THREAD *NewThreadInternal(THREAD_PROC *thread_proc, void *param);
+void ReleaseThreadInternal(THREAD *t);
+void CleanupThreadInternal(THREAD *t);
+void NoticeThreadInitInternal(THREAD *t);
+void WaitThreadInitInternal(THREAD *t);
+bool WaitThreadInternal(THREAD *t);
+THREAD *NewThreadNamed(THREAD_PROC *thread_proc, void *param, char *name);
+void ReleaseThread(THREAD *t);
+void CleanupThread(THREAD *t);
+void NoticeThreadInit(THREAD *t);
+void WaitThreadInit(THREAD *t);
+bool WaitThread(THREAD *t, UINT timeout);
+void InitThreading();
+void FreeThreading();
+void ThreadPoolProc(THREAD *t, void *param);
+void SetThreadName(UINT thread_id, char *name, void *param);
+
+time_t c_mkgmtime(struct tm *tm);
+time_t System64ToTime(UINT64 i);
+void TmToSystem(SYSTEMTIME *st, struct tm *t);
+void SystemToTm(struct tm *t, SYSTEMTIME *st);
+void TimeToSystem(SYSTEMTIME *st, time_t t);
+UINT64 TimeToSystem64(time_t t);
+time_t SystemToTime(SYSTEMTIME *st);
+time_t TmToTime(struct tm *t);
+void TimeToTm(struct tm *t, time_t time);
+void NormalizeTm(struct tm *t);
+void NormalizeSystem(SYSTEMTIME *st);
+void LocalToSystem(SYSTEMTIME *system, SYSTEMTIME *local);
+void SystemToLocal(SYSTEMTIME *local, SYSTEMTIME *system);
+INT64 GetTimeDiffEx(SYSTEMTIME *basetime, bool local_time);
+void UINT64ToSystem(SYSTEMTIME *st, UINT64 sec64);
+UINT64 SystemToUINT64(SYSTEMTIME *st);
+UINT64 LocalTime64();
+UINT64 SystemTime64();
+USHORT SystemToDosDate(SYSTEMTIME *st);
+USHORT System64ToDosDate(UINT64 i);
+USHORT SystemToDosTime(SYSTEMTIME *st);
+USHORT System64ToDosTime(UINT64 i);
+void LocalTime(SYSTEMTIME *st);
+void SystemTime(SYSTEMTIME *st);
+void SetLocale(wchar_t *str);
+bool LoadLocale(LOCALE *locale, wchar_t *str);
+void GetCurrentLocale(LOCALE *locale);
+void GetDateTimeStr(char *str, UINT size, SYSTEMTIME *st);
+void GetDateTimeStrMilli(char *str, UINT size, SYSTEMTIME *st);
+void GetDateStr(char *str, UINT size, SYSTEMTIME *st);
+void GetDateTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale);
+void GetTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale);
+void GetDateStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale);
+void GetTimeStrMilli(char *str, UINT size, SYSTEMTIME *st);
+void GetTimeStr(char *str, UINT size, SYSTEMTIME *st);
+UINT Tick();
+UINT TickRealtime();
+UINT TickRealtimeManual();
+UINT64 TickGetRealtimeTickValue64();
+UINT64 SystemToLocal64(UINT64 t);
+UINT64 LocalToSystem64(UINT64 t);
+UINT ThreadId();
+void GetDateTimeStr64(char *str, UINT size, UINT64 sec64);
+void GetDateTimeStr64Uni(wchar_t *str, UINT size, UINT64 sec64);
+void GetDateTimeStrMilli64(char *str, UINT size, UINT64 sec64);
+void GetDateStr64(char *str, UINT size, UINT64 sec64);
+void GetDateTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale);
+void GetTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale);
+void GetDateStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale);
+void GetTimeStrMilli64(char *str, UINT size, UINT64 sec64);
+void GetTimeStr64(char *str, UINT size, UINT64 sec64);
+UINT64 SafeTime64(UINT64 sec64);
+bool Run(char *filename, char *arg, bool hide, bool wait);
+bool RunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait);
+void HashInstanceName(char *name, UINT size, char *instance_name);
+void HashInstanceNameLocal(char *name, UINT size, char *instance_name);
+INSTANCE *NewSingleInstance(char *instance_name);
+INSTANCE *NewSingleInstanceEx(char *instance_name, bool user_local);
+void FreeSingleInstance(INSTANCE *inst);
+void GetSpanStr(char *str, UINT size, UINT64 sec64);
+void GetSpanStrEx(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale);
+void GetSpanStrMilli(char *str, UINT size, UINT64 sec64);
+void GetMemInfo(MEMINFO *info);
+bool GetEnv(char *name, char *data, UINT size);
+bool GetEnvW(wchar_t *name, wchar_t *data, UINT size);
+bool GetEnvW_ForWin32(wchar_t *name, wchar_t *data, UINT size);
+bool GetEnvW_ForUnix(wchar_t *name, wchar_t *data, UINT size);
+void GetHomeDir(char *path, UINT size);
+void GetHomeDirW(wchar_t *path, UINT size);
+void AbortExit();
+void AbortExitEx(char *msg);
+void YieldCpu();
+UINT DoNothing();
+LIST *NewThreadList();
+void AddThreadToThreadList(LIST *o, THREAD *t);
+void DelThreadFromThreadList(LIST *o, THREAD *t);
+void MainteThreadList(LIST *o);
+void FreeThreadList(LIST *o);
+void StopThreadList(LIST *o);
+
+#endif // KERNEL_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/MayaType.h b/src/Mayaqua/MayaType.h
new file mode 100644
index 00000000..c3949872
--- /dev/null
+++ b/src/Mayaqua/MayaType.h
@@ -0,0 +1,553 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// MayaType.h
+// Mayaqua Kernel type declaration header file
+
+#ifndef MAYATYPE_H
+#define MAYATYPE_H
+
+// Check whether the windows.h header is included
+#ifndef WINDOWS_H
+#ifdef _WINDOWS_
+#define WINDOWS_H
+#endif // _WINDOWS_
+#endif // WINDOWS_H
+
+
+#if !defined(ENCRYPT_C) && !defined(HAM_C)
+// Structure which is used by OpenSSL
+typedef struct x509_st X509;
+typedef struct evp_pkey_st EVP_PKEY;
+typedef struct bio_st BIO;
+typedef struct ssl_st SSL;
+typedef struct ssl_ctx_st SSL_CTX;
+typedef struct X509_req_st X509_REQ;
+typedef struct PKCS12 PKCS12;
+typedef struct bignum_st BIGNUM;
+typedef struct x509_crl_st X509_CRL;
+#endif // ENCRYPT_C
+
+//
+// Constant
+//
+
+// Standard buffer size
+#define STD_SIZE 512
+#define MAX_SIZE 512
+#define BUF_SIZE 512
+
+// Support Windows OS list
+#define SUPPORTED_WINDOWS_LIST "Windows 98 / 98 SE / ME / NT 4.0 SP6a / 2000 SP4 / XP SP2, SP3 / Server 2003 SP2 / Vista SP1, SP2 / Server 2008 SP1, SP2 / Hyper-V Server 2008 / 7 SP1 / Server 2008 R2 SP1 / Hyper-V Server 2008 R2 / 8 / Server 2012 / Hyper-V Server 2012 / 8.1 / Server 2012 R2 / Hyper-V Server 2012 R2"
+
+// Infinite
+#ifndef WINDOWS_H
+#define INFINITE (0xFFFFFFFF)
+#endif
+
+
+#define SRC_NAME __FILE__ // File name of the source code
+#define SRC_LINE __LINE__ // Line number in the source code
+
+// Maximum path size
+#ifndef WINDOWS_H
+#define MAX_PATH 260
+#endif // WINDOWS_H
+
+// Types of seek
+#ifndef FILE_BEGIN
+#define FILE_BEGIN SEEK_SET
+#endif // FILE_BEGIN
+#ifndef FILE_END
+#define FILE_END SEEK_END
+#endif // FILE_END
+#ifndef FILE_CURRENT
+#define FILE_CURRENT SEEK_CUR
+#endif // FILE_CURRENT
+
+#ifndef INVALID_SOCKET
+#define INVALID_SOCKET (-1)
+#endif // INVALID_SOCKET
+
+#ifndef SOCKET_ERROR
+#define SOCKET_ERROR (-1)
+#endif //SOCKET_ERROR
+
+// Comparison function
+typedef int (COMPARE)(void *p1, void *p2);
+
+
+//
+// Macro
+
+
+#ifdef MAX
+#undef MAX
+#endif // MAX
+
+#ifdef MIN
+#undef MIN
+#endif // MIN
+
+// Minimum value of a and b
+#define MIN(a, b) ((a) >= (b) ? (b) : (a))
+// Maximum value of a and b
+#define MAX(a, b) ((a) >= (b) ? (a) : (b))
+
+// Convert an int value to bool
+#define INT_TO_BOOL(i) (((i) == 0) ? false : true)
+#define MAKEBOOL(i) INT_TO_BOOL(i)
+#define BOOL_TO_INT(i) (((i) == false) ? 0 : 1)
+
+// Invert the bool type value
+#define NEGATIVE_BOOL(i) (((i) == false) ? true : false)
+
+// Return 'a' less than max_value
+#define LESS(a, max_value) ((a) <= (max_value) ? (a) : (max_value))
+// Return 'a' greater than min_value
+#define MORE(a, min_value) ((a) >= (min_value) ? (a) : (min_value))
+// Examine whether the value a is between the b and c
+#define INNER(a, b, c) (((b) <= (c) && (a) >= (b) && (a) <= (c)) || ((b) >= (c) && (a) >= (c) && (a) <= (b)))
+// Examine whether the value a is outbound of b and c
+#define OUTER(a, b, c) (!INNER((a), (b), (c)))
+// Adjust value 'a' to be between b and c
+#define MAKESURE(a, b, c) (((b) <= (c)) ? (MORE(LESS((a), (c)), (b))) : (MORE(LESS((a), (b)), (c))))
+// Compare a and b
+#define COMPARE_RET(a, b) (((a) == (b)) ? 0 : (((a) > (b)) ? 1 : -1))
+// Compare bool type values
+#define EQUAL_BOOL(a, b) (((a) && (b)) || ((!(a)) && (!(b))))
+// Get the absolute value
+#define GET_ABS(a) ((a) >= 0 ? (a) : -(a))
+
+// Convert the pointer to UINT
+#define POINTER_TO_KEY(p) ((sizeof(void *) == sizeof(UINT)) ? (UINT)(p) : HashPtrToUINT(p))
+// Compare the pointer and UINT
+#define COMPARE_POINTER_AND_KEY(p, i) (POINTER_TO_KEY(p) == (i))
+// Convert the pointer to UINT64
+#define POINTER_TO_UINT64(p) (((sizeof(void *) == sizeof(UINT64)) ? (UINT64)(p) : (UINT64)((UINT)(p))))
+// Convert a UINT64 to pointer
+#define UINT64_TO_POINTER(i) ((sizeof(void *) == sizeof(UINT64)) ? (void *)(i) : (void *)((UINT)(i)))
+
+// Add the value
+#define UINT_ADD(i, j) ((i == INFINITE || i == 0x7fffffff) ? (i) : (i += j))
+
+// Reading data that is not dependent on the boundary or the endian
+#define READ_USHORT(buf) (USHORT)((((USHORT)((UCHAR *)(buf))[0]) << 8) | (((USHORT)((UCHAR *)(buf))[1])))
+#define READ_UINT(buf) (UINT)((((UINT)((UCHAR *)(buf))[0]) << 24) | (((UINT)((UCHAR *)(buf))[1]) << 16) | (((UINT)((UCHAR *)(buf))[2]) << 8) | (((UINT)((UCHAR *)(buf))[3])))
+#define READ_UINT64(buf) (UINT64)((((UINT64)((UCHAR *)(buf))[0]) << 56) | (((UINT64)((UCHAR *)(buf))[1]) << 48) | (((UINT64)((UCHAR *)(buf))[2]) << 40) | (((UINT64)((UCHAR *)(buf))[3]) << 32) | (((UINT64)((UCHAR *)(buf))[4]) << 24) | (((UINT64)((UCHAR *)(buf))[5]) << 16) | (((UINT64)((UCHAR *)(buf))[6]) << 8) | (((UINT64)((UCHAR *)(buf))[7])))
+
+// Writing data that is not dependent on the boundary or endian
+#define WRITE_USHORT(buf, i) (((UCHAR *)(buf))[0]) = ((((USHORT)(i)) >> 8) & 0xFF); (((UCHAR *)(buf))[1]) = ((((USHORT)(i))) & 0xFF)
+#define WRITE_UINT(buf, i) (((UCHAR *)(buf))[0]) = ((((UINT)(i)) >> 24) & 0xFF); (((UCHAR *)(buf))[1]) = ((((UINT)(i)) >> 16) & 0xFF); (((UCHAR *)(buf))[2]) = ((((UINT)(i)) >> 8) & 0xFF); (((UCHAR *)(buf))[3]) = ((((UINT)(i))) & 0xFF)
+#define WRITE_UINT64(buf, i) (((UCHAR *)(buf))[0]) = ((((UINT64)(i)) >> 56) & 0xFF); (((UCHAR *)(buf))[1]) = ((((UINT64)(i)) >> 48) & 0xFF); (((UCHAR *)(buf))[2]) = ((((UINT64)(i)) >> 40) & 0xFF); (((UCHAR *)(buf))[3]) = ((((UINT64)(i)) >> 32) & 0xFF); (((UCHAR *)(buf))[4]) = ((((UINT64)(i)) >> 24) & 0xFF); (((UCHAR *)(buf))[5]) = ((((UINT64)(i)) >> 16) & 0xFF); (((UCHAR *)(buf))[6]) = ((((UINT64)(i)) >> 8) & 0xFF); (((UCHAR *)(buf))[7]) = ((((UINT64)(i))) & 0xFF)
+
+
+
+//
+// Type declaration
+//
+
+// bool type
+#ifndef WINDOWS_H
+typedef unsigned int BOOL;
+#define TRUE 1
+#define FALSE 0
+#endif // WINDOWS_H
+
+// bool type
+#ifndef WIN32COM_CPP
+typedef unsigned int bool;
+#define true 1
+#define false 0
+#endif // WIN32COM_CPP
+
+// 32bit integer type
+#ifndef WINDOWS_H
+typedef unsigned int UINT;
+typedef unsigned int UINT32;
+typedef unsigned int DWORD;
+typedef signed int INT;
+typedef signed int INT32;
+
+typedef int UINT_PTR;
+typedef long LONG_PTR;
+
+#endif
+
+// 16bit integer type
+typedef unsigned short WORD;
+typedef unsigned short USHORT;
+typedef signed short SHORT;
+
+// 8bit integer type
+typedef unsigned char BYTE;
+typedef unsigned char UCHAR;
+
+#ifndef WIN32COM_CPP
+typedef signed char CHAR;
+#endif // WIN32COM_CPP
+
+
+// 64-bit integer type
+typedef unsigned long long UINT64;
+typedef signed long long INT64;
+
+#ifdef OS_UNIX
+// Avoiding compile error
+#define __cdecl
+#define __declspec(x)
+// socket type
+typedef int SOCKET;
+#else // OS_UNIX
+#ifndef _WINSOCK2API_
+typedef UINT_PTR SOCKET;
+#endif // _WINSOCK2API_
+#endif // OS_UNIX
+
+// OS type
+#define OSTYPE_WINDOWS_95 1100 // Windows 95
+#define OSTYPE_WINDOWS_98 1200 // Windows 98
+#define OSTYPE_WINDOWS_ME 1300 // Windows Me
+#define OSTYPE_WINDOWS_UNKNOWN 1400 // Windows (unknown)
+#define OSTYPE_WINDOWS_NT_4_WORKSTATION 2100 // Windows NT 4.0 Workstation
+#define OSTYPE_WINDOWS_NT_4_SERVER 2110 // Windows NT 4.0 Server
+#define OSTYPE_WINDOWS_NT_4_SERVER_ENTERPRISE 2111 // Windows NT 4.0 Server, Enterprise Edition
+#define OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER 2112 // Windows NT 4.0 Terminal Server
+#define OSTYPE_WINDOWS_NT_4_BACKOFFICE 2113 // BackOffice Server 4.5
+#define OSTYPE_WINDOWS_NT_4_SMS 2114 // Small Business Server 4.5
+#define OSTYPE_WINDOWS_2000_PROFESSIONAL 2200 // Windows 2000 Professional
+#define OSTYPE_WINDOWS_2000_SERVER 2211 // Windows 2000 Server
+#define OSTYPE_WINDOWS_2000_ADVANCED_SERVER 2212 // Windows 2000 Advanced Server
+#define OSTYPE_WINDOWS_2000_DATACENTER_SERVER 2213 // Windows 2000 Datacenter Server
+#define OSTYPE_WINDOWS_2000_BACKOFFICE 2214 // BackOffice Server 2000
+#define OSTYPE_WINDOWS_2000_SBS 2215 // Small Business Server 2000
+#define OSTYPE_WINDOWS_XP_HOME 2300 // Windows XP Home Edition
+#define OSTYPE_WINDOWS_XP_PROFESSIONAL 2301 // Windows XP Professional
+#define OSTYPE_WINDOWS_2003_WEB 2410 // Windows Server 2003 Web Edition
+#define OSTYPE_WINDOWS_2003_STANDARD 2411 // Windows Server 2003 Standard Edition
+#define OSTYPE_WINDOWS_2003_ENTERPRISE 2412 // Windows Server 2003 Enterprise Edition
+#define OSTYPE_WINDOWS_2003_DATACENTER 2413 // Windows Server 2003 DataCenter Edition
+#define OSTYPE_WINDOWS_2003_BACKOFFICE 2414 // BackOffice Server 2003
+#define OSTYPE_WINDOWS_2003_SBS 2415 // Small Business Server 2003
+#define OSTYPE_WINDOWS_LONGHORN_PROFESSIONAL 2500 // Windows Vista
+#define OSTYPE_WINDOWS_LONGHORN_SERVER 2510 // Windows Server 2008
+#define OSTYPE_WINDOWS_7 2600 // Windows 7
+#define OSTYPE_WINDOWS_SERVER_2008_R2 2610 // Windows Server 2008 R2
+#define OSTYPE_WINDOWS_8 2700 // Windows 8
+#define OSTYPE_WINDOWS_SERVER_8 2710 // Windows Server 2012
+#define OSTYPE_WINDOWS_81 2701 // Windows 8.1
+#define OSTYPE_WINDOWS_SERVER_81 2711 // Windows Server 2012 R2
+#define OSTYPE_WINDOWS_9 2800 // Windows 9
+#define OSTYPE_WINDOWS_SERVER_9 2810 // Windows Server 9
+#define OSTYPE_UNIX_UNKNOWN 3000 // Unknown UNIX
+#define OSTYPE_LINUX 3100 // Linux
+#define OSTYPE_SOLARIS 3200 // Solaris
+#define OSTYPE_CYGWIN 3300 // Cygwin
+#define OSTYPE_BSD 3400 // BSD
+#define OSTYPE_MACOS_X 3500 // MacOS X
+
+
+// OS discrimination macro
+#define GET_KETA(t, i) (((t) % (i * 10)) / i)
+#define OS_IS_WINDOWS_9X(t) (GET_KETA(t, 1000) == 1)
+#define OS_IS_WINDOWS_NT(t) (GET_KETA(t, 1000) == 2)
+#define OS_IS_WINDOWS(t) (OS_IS_WINDOWS_9X(t) || OS_IS_WINDOWS_NT(t))
+#define OS_IS_SERVER(t) (OS_IS_WINDOWS_NT(t) && GET_KETA(t, 10))
+#define OS_IS_WORKSTATION(t) ((OS_IS_WINDOWS_NT(t) && (!(GET_KETA(t, 10)))) || OS_IS_WINDOWS_9X(t))
+#define OS_IS_UNIX(t) (GET_KETA(t, 1000) == 3)
+
+
+// OS information
+typedef struct OS_INFO
+{
+ UINT OsType; // OS type
+ UINT OsServicePack; // Service pack number
+ char *OsSystemName; // OS system name
+ char *OsProductName; // OS product name
+ char *OsVendorName; // OS vendor name
+ char *OsVersion; // OS version
+ char *KernelName; // Kernel name
+ char *KernelVersion; // Kernel version
+} OS_INFO;
+
+// Time type
+#ifndef WINDOWS_H
+typedef struct SYSTEMTIME
+{
+ WORD wYear;
+ WORD wMonth;
+ WORD wDayOfWeek;
+ WORD wDay;
+ WORD wHour;
+ WORD wMinute;
+ WORD wSecond;
+ WORD wMilliseconds;
+} SYSTEMTIME;
+#endif // WINDOWS_H
+
+
+// Object.h
+typedef struct LOCK LOCK;
+typedef struct COUNTER COUNTER;
+typedef struct REF REF;
+typedef struct EVENT EVENT;
+typedef struct DEADCHECK DEADCHECK;
+
+// Tracking.h
+typedef struct CALLSTACK_DATA CALLSTACK_DATA;
+typedef struct TRACKING_OBJECT TRACKING_OBJECT;
+typedef struct MEMORY_STATUS MEMORY_STATUS;
+typedef struct TRACKING_LIST TRACKING_LIST;
+
+// FileIO.h
+typedef struct IO IO;
+
+// Memory.h
+typedef struct MEMTAG MEMTAG;
+typedef struct BUF BUF;
+typedef struct FIFO FIFO;
+typedef struct LIST LIST;
+typedef struct QUEUE QUEUE;
+typedef struct SK SK;
+typedef struct CANDIDATE CANDIDATE;
+typedef struct STRMAP_ENTRY STRMAP_ENTRY;
+typedef struct SHARED_BUFFER SHARED_BUFFER;
+typedef struct HASH_LIST HASH_LIST;
+typedef struct HASH_ENTRY HASH_ENTRY;
+
+// Str.h
+typedef struct TOKEN_LIST TOKEN_LIST;
+typedef struct INI_ENTRY INI_ENTRY;
+
+// Internat.h
+typedef struct UNI_TOKEN_LIST UNI_TOKEN_LIST;
+
+// Encrypt.h
+typedef struct CRYPT CRYPT;
+typedef struct NAME NAME;
+typedef struct X_SERIAL X_SERIAL;
+typedef struct X X;
+typedef struct K K;
+typedef struct P12 P12;
+typedef struct X_CRL X_CRL;
+typedef struct DES_KEY_VALUE DES_KEY_VALUE;
+typedef struct DES_KEY DES_KEY;
+typedef struct DH_CTX DH_CTX;
+typedef struct AES_KEY_VALUE AES_KEY_VALUE;
+typedef struct CIPHER CIPHER;
+typedef struct MD MD;
+
+// Secure.h
+typedef struct SECURE_DEVICE SECURE_DEVICE;
+typedef struct SEC_INFO SEC_INFO;
+typedef struct SECURE SECURE;
+typedef struct SEC_OBJ SEC_OBJ;
+
+// Kernel.h
+typedef struct MEMINFO MEMINFO;
+typedef struct LOCALE LOCALE;
+typedef struct THREAD THREAD;
+typedef struct THREAD_POOL_DATA THREAD_POOL_DATA;
+typedef struct INSTANCE INSTANCE;
+
+// Pack.h
+typedef struct VALUE VALUE;
+typedef struct ELEMENT ELEMENT;
+typedef struct PACK PACK;
+
+// Cfg.h
+typedef struct FOLDER FOLDER;
+typedef struct ITEM ITEM;
+typedef struct CFG_RW CFG_RW;
+typedef struct CFG_ENUM_PARAM CFG_ENUM_PARAM;
+
+// Table.h
+typedef struct TABLE TABLE;
+typedef struct LANGLIST LANGLIST;
+
+// Network.h
+typedef struct IP IP;
+typedef struct DNSCACHE DNSCACHE;
+typedef struct SOCK_EVENT SOCK_EVENT;
+typedef struct SOCK SOCK;
+typedef struct SOCKSET SOCKSET;
+typedef struct CANCEL CANCEL;
+typedef struct ROUTE_ENTRY ROUTE_ENTRY;
+typedef struct ROUTE_TABLE ROUTE_TABLE;
+typedef struct IP_CLIENT IP_CLIENT;
+typedef struct ROUTE_CHANGE ROUTE_CHANGE;
+typedef struct ROUTE_CHANGE_DATA ROUTE_CHANGE_DATA;
+typedef struct GETIP_THREAD_PARAM GETIP_THREAD_PARAM;
+typedef struct WIN32_RELEASEADDRESS_THREAD_PARAM WIN32_RELEASEADDRESS_THREAD_PARAM;
+typedef struct IPV6_ADDR IPV6_ADDR;
+typedef struct TUBE TUBE;
+typedef struct TUBEDATA TUBEDATA;
+typedef struct PSEUDO PSEUDO;
+typedef struct TUBEPAIR_DATA TUBEPAIR_DATA;
+typedef struct UDPLISTENER UDPLISTENER;
+typedef struct UDPLISTENER_SOCK UDPLISTENER_SOCK;
+typedef struct UDPPACKET UDPPACKET;
+typedef struct INTERRUPT_MANAGER INTERRUPT_MANAGER;
+typedef struct TUBE_FLUSH_LIST TUBE_FLUSH_LIST;
+typedef struct ICMP_RESULT ICMP_RESULT;
+typedef struct SSL_PIPE SSL_PIPE;
+typedef struct SSL_BIO SSL_BIO;
+typedef struct RUDP_STACK RUDP_STACK;
+typedef struct RUDP_SESSION RUDP_SESSION;
+typedef struct RUDP_SEGMENT RUDP_SEGMENT;
+typedef struct CONNECT_TCP_RUDP_PARAM CONNECT_TCP_RUDP_PARAM;
+typedef struct TCP_PAIR_HEADER TCP_PAIR_HEADER;
+typedef struct NIC_ENTRY NIC_ENTRY;
+typedef struct HTTP_VALUE HTTP_VALUE;
+typedef struct HTTP_HEADER HTTP_HEADER;
+typedef struct DNSPROXY_CLIENT DNSPROXY_CLIENT;
+typedef struct DNSPROXY_CACHE DNSPROXY_CACHE;
+typedef struct QUERYIPTHREAD QUERYIPTHREAD;
+typedef struct IPBLOCK IPBLOCK;
+typedef struct SAFE_REQUEST SAFE_REQUEST;
+typedef struct SAFE_LIST SAFE_LIST;
+typedef struct SAFE_QUOTA SAFE_QUOTA;
+typedef struct SAFE_QUOTA2 SAFE_QUOTA2;
+typedef struct SAFE_BLOCK SAFE_BLOCK;
+typedef struct SAFE_REQUEST_LOG SAFE_REQUEST_LOG;
+typedef struct DYN_VALUE DYN_VALUE;
+
+// Tick64.h
+typedef struct ADJUST_TIME ADJUST_TIME;
+typedef struct TICK64 TICK64;
+
+// FileIO.h
+typedef struct DIRENT DIRENT;
+typedef struct DIRLIST DIRLIST;
+typedef struct ZIP_DATA_HEADER ZIP_DATA_HEADER;
+typedef struct ZIP_DATA_FOOTER ZIP_DATA_FOOTER;
+typedef struct ZIP_DIR_HEADER ZIP_DIR_HEADER;
+typedef struct ZIP_END_HEADER ZIP_END_HEADER;
+typedef struct ZIP_FILE ZIP_FILE;
+typedef struct ZIP_PACKER ZIP_PACKER;
+
+// TcpIp.h
+typedef struct MAC_HEADER MAC_HEADER;
+typedef struct ARPV4_HEADER ARPV4_HEADER;
+typedef struct IPV4_HEADER IPV4_HEADER;
+typedef struct TAGVLAN_HEADER TAGVLAN_HEADER;
+typedef struct UDP_HEADER UDP_HEADER;
+typedef struct UDPV4_PSEUDO_HEADER UDPV4_PSEUDO_HEADER;
+typedef struct IPV4_PSEUDO_HEADER IPV4_PSEUDO_HEADER;
+typedef struct TCP_HEADER TCP_HEADER;
+typedef struct ICMP_HEADER ICMP_HEADER;
+typedef struct ICMP_ECHO ICMP_ECHO;
+typedef struct DHCPV4_HEADER DHCPV4_HEADER;
+typedef struct DNSV4_HEADER DNSV4_HEADER;
+typedef struct BPDU_HEADER BPDU_HEADER;
+typedef struct LLC_HEADER LLC_HEADER;
+typedef struct PKT PKT;
+typedef struct IPV6_HEADER_PACKET_INFO IPV6_HEADER_PACKET_INFO;
+typedef struct IPV6_HEADER IPV6_HEADER;
+typedef struct IPV6_OPTION_HEADER IPV6_OPTION_HEADER;
+typedef struct IPV6_FRAGMENT_HEADER IPV6_FRAGMENT_HEADER;
+typedef struct IPV6_PSEUDO_HEADER IPV6_PSEUDO_HEADER;
+typedef struct ICMPV6_ROUTER_SOLICIATION_HEADER ICMPV6_ROUTER_SOLICIATION_HEADER;
+typedef struct ICMPV6_ROUTER_ADVERTISEMENT_HEADER ICMPV6_ROUTER_ADVERTISEMENT_HEADER;
+typedef struct ICMPV6_NEIGHBOR_SOLICIATION_HEADER ICMPV6_NEIGHBOR_SOLICIATION_HEADER;
+typedef struct ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER;
+typedef struct ICMPV6_OPTION_LIST ICMPV6_OPTION_LIST;
+typedef struct ICMPV6_OPTION ICMPV6_OPTION;
+typedef struct ICMPV6_OPTION_LINK_LAYER ICMPV6_OPTION_LINK_LAYER;
+typedef struct ICMPV6_OPTION_PREFIX ICMPV6_OPTION_PREFIX;
+typedef struct ICMPV6_OPTION_MTU ICMPV6_OPTION_MTU;
+typedef struct IPV6_HEADER_INFO IPV6_HEADER_INFO;
+typedef struct ICMPV6_HEADER_INFO ICMPV6_HEADER_INFO;
+typedef struct DHCPV4_DATA DHCPV4_DATA;
+typedef struct DHCP_OPTION DHCP_OPTION;
+typedef struct DHCP_OPTION_LIST DHCP_OPTION_LIST;
+typedef struct HTTPLOG HTTPLOG;
+typedef struct DHCP_MODIFY_OPTION DHCP_MODIFY_OPTION;
+typedef struct NBTDG_HEADER NBTDG_HEADER;
+typedef struct IKE_HEADER IKE_HEADER;
+
+
+
+#endif // MAYATYPE_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Mayaqua.c b/src/Mayaqua/Mayaqua.c
new file mode 100644
index 00000000..5cc78a23
--- /dev/null
+++ b/src/Mayaqua/Mayaqua.c
@@ -0,0 +1,1200 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Mayaqua.c
+// Mayaqua Kernel program
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <locale.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// Global variable
+bool g_memcheck; // Enable memory check
+bool g_debug; // Debug mode
+UINT64 kernel_status[NUM_KERNEL_STATUS]; // Kernel state
+UINT64 kernel_status_max[NUM_KERNEL_STATUS]; // Kernel state (maximum value)
+LOCK *kernel_status_lock[NUM_KERNEL_STATUS]; // Kernel state lock
+BOOL kernel_status_inited = false; // Kernel state initialization flag
+bool g_little_endian = true;
+char *cmdline = NULL; // Command line
+wchar_t *uni_cmdline = NULL; // Unicode command line
+
+// Static variable
+static char *exename = NULL; // EXE file name (ANSI)
+static wchar_t *exename_w = NULL; // EXE file name (Unicode)
+static TOKEN_LIST *cmdline_token = NULL; // Command line token
+static UNI_TOKEN_LIST *cmdline_uni_token = NULL; // Command line token (Unicode)
+static OS_INFO *os_info = NULL; // OS information
+static bool dot_net_mode = false;
+static bool minimal_mode = false;
+static UINT last_time_check = 0;
+static UINT first_time_check = 0;
+static bool is_nt = false;
+static bool is_ham_mode = false;
+static UINT init_mayaqua_counter = 0;
+static bool use_probe = false;
+static BUF *probe_buf = NULL;
+static LOCK *probe_lock = NULL;
+static UINT64 probe_start = 0;
+static UINT64 probe_last = 0;
+static bool probe_enabled = false;
+
+
+
+// Calculate the checksum
+USHORT CalcChecksum16(void *buf, UINT size)
+{
+ int sum = 0;
+ USHORT *addr = (USHORT *)buf;
+ int len = (int)size;
+ USHORT *w = addr;
+ int nleft = len;
+ USHORT answer = 0;
+
+ while (nleft > 1)
+ {
+ USHORT ww = 0;
+ Copy(&ww, w++, sizeof(USHORT));
+ sum += ww;
+ nleft -= 2;
+ }
+
+ if (nleft == 1)
+ {
+ *(UCHAR *)(&answer) = *(UCHAR *)w;
+ sum += answer;
+ }
+
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+
+ answer = ~sum;
+
+ return answer;
+}
+
+// Writing a probe with the data
+void WriteProbeData(char *filename, UINT line, char *str, void *data, UINT size)
+{
+ char tmp[MAX_SIZE];
+ USHORT cs;
+
+ if (IsProbeEnabled() == false)
+ {
+ return;
+ }
+
+ // Take a checksum of the data
+ if (size != 0)
+ {
+ cs = CalcChecksum16(data, size);
+ }
+ else
+ {
+ cs = 0;
+ }
+
+ // Generating a String
+ snprintf(tmp, sizeof(tmp), "\"%s\" (Size=%5u, Crc=0x%04X)", str, size, cs);
+
+ WriteProbe(filename, line, tmp);
+}
+
+// Writing Probe
+void WriteProbe(char *filename, UINT line, char *str)
+{
+#ifdef OS_WIN32
+ char *s;
+ char tmp[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ UINT64 now = 0;
+ UINT64 time;
+
+ if (IsProbeEnabled() == false)
+ {
+ return;
+ }
+
+ now = MsGetHiResCounter();
+
+ Lock(probe_lock);
+ {
+ UINT64 diff;
+
+ time = MsGetHiResTimeSpanUSec(now - probe_start);
+
+ diff = time - probe_last;
+
+ if (time < probe_last)
+ {
+ diff = 0;
+ }
+
+ probe_last = time;
+
+ ToStr64(tmp, time);
+ MakeCharArray2(tmp2, ' ', (UINT)(MIN(12, (int)12 - (int)StrLen(tmp))));
+ WriteBuf(probe_buf, tmp2, StrLen(tmp2));
+ WriteBuf(probe_buf, tmp, StrLen(tmp));
+
+ s = " [+";
+ WriteBuf(probe_buf, s, StrLen(s));
+
+ ToStr64(tmp, diff);
+ MakeCharArray2(tmp2, ' ', (UINT)(MIN(12, (int)12 - (int)StrLen(tmp))));
+ WriteBuf(probe_buf, tmp2, StrLen(tmp2));
+ WriteBuf(probe_buf, tmp, StrLen(tmp));
+
+ s = "] - ";
+ WriteBuf(probe_buf, s, StrLen(s));
+
+ WriteBuf(probe_buf, filename, StrLen(filename));
+
+ s = "(";
+ WriteBuf(probe_buf, s, StrLen(s));
+
+ ToStr64(tmp, (UINT64)line);
+ WriteBuf(probe_buf, tmp, StrLen(tmp));
+
+ s = "): ";
+ WriteBuf(probe_buf, s, StrLen(s));
+
+ WriteBuf(probe_buf, str, StrLen(str));
+
+ s = "\r\n";
+ WriteBuf(probe_buf, s, StrLen(s));
+ }
+ Unlock(probe_lock);
+#endif // OS_WIN32
+}
+
+// Initialization of Probe
+void InitProbe()
+{
+ probe_buf = NewBuf();
+ probe_lock = NewLock();
+ probe_enabled = false;
+
+ probe_start = 0;
+
+#ifdef OS_WIN32
+ probe_start = MsGetHiResCounter();
+#endif // OS_WIN32
+}
+
+// Release of Probe
+void FreeProbe()
+{
+ if (probe_buf->Size >= 1)
+ {
+ SYSTEMTIME st;
+ char filename[MAX_SIZE];
+
+ // Write all to the file
+ MakeDirEx("@probe_log");
+
+ LocalTime(&st);
+
+ snprintf(filename, sizeof(filename), "@probe_log/%04u%02u%02u_%02u%02u%02u.log",
+ st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
+
+ DumpBuf(probe_buf, filename);
+ }
+
+ FreeBuf(probe_buf);
+ DeleteLock(probe_lock);
+}
+
+// Set enable / disable the Probe
+void EnableProbe(bool enable)
+{
+ probe_enabled = enable;
+}
+
+// Get whether the Probe is enabled?
+bool IsProbeEnabled()
+{
+#ifndef USE_PROBE
+ return false;
+#else // USE_PROBE
+ return probe_enabled;
+#endif // USE_PROBE
+}
+
+// Set the Ham mode
+void SetHamMode()
+{
+ is_ham_mode = true;
+}
+
+// Get whether in Ham mode
+bool IsHamMode()
+{
+ return is_ham_mode;
+}
+
+// Display the time from the previous call to now
+void TimeCheck()
+{
+#ifdef OS_WIN32
+ UINT now, ret, total;
+ now = Win32GetTick();
+ if (last_time_check == 0)
+ {
+ ret = 0;
+ }
+ else
+ {
+ ret = now - last_time_check;
+ }
+ last_time_check = now;
+
+ if (first_time_check == 0)
+ {
+ first_time_check = now;
+ }
+
+ total = now - first_time_check;
+
+ printf(" -- %3.3f / %3.3f\n", (double)ret / 1000.0f, (double)total / 1000.0f);
+#endif // OS_WIN32
+}
+
+// Whether this system is IA64
+bool IsIA64()
+{
+ if (Is64() == false)
+ {
+ return false;
+ }
+
+#ifndef MAYAQUA_IA_64
+ return false;
+#else // MAYAQUA_IA_64
+ return true;
+#endif // MAYAQUA_IA_64
+}
+
+// Whether in x64
+bool IsX64()
+{
+ if (Is64() == false)
+ {
+ return false;
+ }
+
+#ifndef MAYAQUA_IA_64
+ return true;
+#else // MAYAQUA_IA_64
+ return false;
+#endif // MAYAQUA_IA_64
+}
+
+// Whether 64bit
+bool Is64()
+{
+#ifdef CPU_64
+ return true;
+#else // CPU_64
+ return false;
+#endif // CPU_64
+}
+
+// Whether 32bit
+bool Is32()
+{
+ return Is64() ? false : true;
+}
+
+// .NET mode
+void MayaquaDotNetMode()
+{
+ dot_net_mode = true;
+}
+
+// Acquisition whether in .NET mode
+bool MayaquaIsDotNetMode()
+{
+ return dot_net_mode;
+}
+
+// Check the endian
+void CheckEndian()
+{
+ unsigned short test;
+ UCHAR *buf;
+
+ test = 0x1234;
+ buf = (UCHAR *)&test;
+ if (buf[0] == 0x12)
+ {
+ g_little_endian = false;
+ }
+ else
+ {
+ g_little_endian = true;
+ }
+}
+
+// Minimize mode
+void MayaquaMinimalMode()
+{
+ minimal_mode = true;
+}
+bool MayaquaIsMinimalMode()
+{
+ return minimal_mode;
+}
+
+// Whether in NT
+bool IsNt()
+{
+ return is_nt;
+}
+
+// Whether the Unicode is supported
+bool IsUnicode()
+{
+#ifdef OS_WIN32
+ // Windows
+ return IsNt();
+#else // OS_WIN32
+ // UNIX
+ return true;
+#endif // OS_WIN32
+}
+
+// Initialization of Mayaqua library
+void InitMayaqua(bool memcheck, bool debug, int argc, char **argv)
+{
+ wchar_t tmp[MAX_PATH];
+ UCHAR hash[SHA1_SIZE];
+
+ if ((init_mayaqua_counter++) > 0)
+ {
+ return;
+ }
+
+ g_memcheck = memcheck;
+ g_debug = debug;
+ cmdline = NULL;
+ if (dot_net_mode == false)
+ {
+ // Fail this for some reason when this is called this in .NET mode
+ setbuf(stdout, NULL);
+ }
+
+ // Acquisition whether NT
+#ifdef OS_WIN32
+ is_nt = Win32IsNt();
+#endif // OS_WIN32
+
+ // Check endian
+ CheckEndian();
+
+#ifdef OS_WIN32
+ _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
+#endif // OS_WIN32
+
+ // Set the locale information of the CRT to the Japanese
+ setlocale(LC_ALL, "");
+
+ // Initialization of OS
+ OSInit();
+
+ // Initialize the random number
+ srand((UINT)SystemTime64());
+
+ tick_manual_lock = NewLock();
+
+ // Initialization of CRC32
+ InitCrc32();
+
+ // Initialization of the FIFO system
+ InitFifo();
+
+ // Initialize the Kernel status
+ InitKernelStatus();
+
+ // Initialize the tracking
+ InitTracking();
+
+ // Initialization of thread pool
+ InitThreading();
+
+ // Initialize the string library
+ InitStringLibrary();
+
+ // Initialization of the locale information
+ SetLocale(NULL);
+
+ // Initialization of the crypt library
+ InitCryptLibrary();
+
+ // Initialization of the real-time clock
+ InitTick64();
+
+ // Initialize the network communication module
+ InitNetwork();
+
+ // Initialization of the aquisition of the EXE file name
+ InitGetExeName(argc >= 1 ? argv[0] : NULL);
+
+ // Initialization of the command line string
+ InitCommandLineStr(argc, argv);
+
+ // Initialization of OS information
+ InitOsInfo();
+
+ // Initialization of the operating system-specific module
+#ifdef OS_WIN32
+ MsInit(); // Microsoft Win32
+#endif // OS_WIN32
+
+ // Initialization of the security token module
+ InitSecure();
+
+ if (OSIsSupportedOs() == false)
+ {
+ // Abort
+ exit(0);
+ }
+
+ // RSA Check
+ if (RsaCheckEx() == false)
+ {
+ // Abort
+ Alert("OpenSSL Library Init Failed. (too old?)\nPlease install the latest version of OpenSSL.\n\n", "RsaCheck()");
+ exit(0);
+ }
+
+ // Initialization of HamCore file system
+ InitHamcore();
+
+ // Initialization of string table routine
+ InitTable();
+
+ if (exename == NULL)
+ {
+ // Executable file name
+ exename = CopyStr("unknown");
+ }
+
+ // Check whether the executable file name of themselves is found
+ // (If not found, quit because this is started in strange path)
+ GetExeNameW(tmp, sizeof(tmp));
+ if (IsFileExistsW(tmp) == false)
+ {
+ wchar_t tmp2[MAX_SIZE];
+
+ UniFormat(tmp2, sizeof(tmp2),
+ L"Error: Executable binary file \"%s\" not found.\r\n\r\n"
+ L"Please execute program with full path.\r\n",
+ tmp);
+
+ AlertW(tmp2, NULL);
+ _exit(0);
+ }
+
+ CheckUnixTempDir();
+
+ // Initialization of Probe
+ InitProbe();
+
+ // Initialization of Machine Hash
+ GetCurrentMachineIpProcessHash(hash);
+
+ // Reading Private IP file
+ LoadPrivateIPFile();
+}
+
+// Release of Mayaqua library
+void FreeMayaqua()
+{
+ if ((--init_mayaqua_counter) > 0)
+ {
+ return;
+ }
+
+ // Release of Private IP File
+ FreePrivateIPFile();
+
+ // Release of Probe
+ FreeProbe();
+
+ // Delete the table
+ FreeTable();
+
+ // Release of security token module
+ FreeSecure();
+
+ // Release of the operating system specific module
+#ifdef OS_WIN32
+ MsFree();
+#endif // OS_WIN32
+
+ // Release of OS information
+ FreeOsInfo();
+
+ // Release of HamCore file system
+ FreeHamcore();
+
+ // Release of the command line string
+ FreeCommandLineStr();
+
+ // Release of the command line token
+ FreeCommandLineTokens();
+
+ // Release of network communication module
+ FreeNetwork();
+
+ // Release of real-time clock
+ FreeTick64();
+
+ // Release of crypt library
+ FreeCryptLibrary();
+
+ // Release of the string library
+ FreeStringLibrary();
+
+ // Release of thread pool
+ FreeThreading();
+
+#ifndef VPN_SPEED
+ // Show the kernel status
+ if (g_debug)
+ {
+ PrintKernelStatus();
+ }
+
+ // Display the debug information
+ if (g_memcheck)
+ {
+ PrintDebugInformation();
+ }
+#endif // VPN_SPEED
+
+ // Release the tracking
+ FreeTracking();
+
+ // Release of the kernel status
+ FreeKernelStatus();
+
+ DeleteLock(tick_manual_lock);
+ tick_manual_lock = NULL;
+
+ // Release of OS
+ OSFree();
+}
+
+// Check whether /tmp is available in the UNIX
+void CheckUnixTempDir()
+{
+ if (OS_IS_UNIX(GetOsInfo()->OsType))
+ {
+ char tmp[128], tmp2[64];
+ UINT64 now = SystemTime64();
+ IO *o;
+
+ MakeDir("/tmp");
+
+ Format(tmp2, sizeof(tmp2), "%I64u", now);
+
+ Format(tmp, sizeof(tmp), "/tmp/.%s", tmp2);
+
+ o = FileCreate(tmp);
+ if (o == NULL)
+ {
+ o = FileOpen(tmp, false);
+ if (o == NULL)
+ {
+ Print("Unable to use /tmp.\n\n");
+ exit(0);
+ return;
+ }
+ }
+
+ FileClose(o);
+
+ FileDelete(tmp);
+ }
+}
+
+// Show an alert
+void Alert(char *msg, char *caption)
+{
+ OSAlert(msg, caption);
+}
+void AlertW(wchar_t *msg, wchar_t *caption)
+{
+ OSAlertW(msg, caption);
+}
+
+// Display of OS information
+void PrintOsInfo(OS_INFO *info)
+{
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ Print(
+ "OS Type : %u\n"
+ "OS Service Pack : %u\n"
+ "os_is_windows : %s\n"
+ "os_is_windows_nt : %s\n"
+ "OS System Name : %s\n"
+ "OS Product Name : %s\n"
+ "OS Vendor Name : %s\n"
+ "OS Version : %s\n"
+ "Kernel Name : %s\n"
+ "Kernel Version : %s\n",
+ info->OsType,
+ info->OsServicePack,
+ OS_IS_WINDOWS(info->OsType) ? "true" : "false",
+ OS_IS_WINDOWS_NT(info->OsType) ? "true" : "false",
+ info->OsSystemName,
+ info->OsProductName,
+ info->OsVendorName,
+ info->OsVersion,
+ info->KernelName,
+ info->KernelVersion);
+
+#ifdef OS_WIN32
+ {
+ char *exe, *dir;
+ exe = MsGetExeFileName();
+ dir = MsGetExeDirName();
+
+ Print(
+ "EXE File Path : %s\n"
+ "EXE Dir Path : %s\n"
+ "Process Id : %u\n"
+ "Process Handle : 0x%X\n",
+ exe, dir, MsGetCurrentProcessId(), MsGetCurrentProcess());
+ }
+#endif // OS_WIN32
+}
+
+// Get the OS type
+UINT GetOsType()
+{
+ OS_INFO *i = GetOsInfo();
+
+ if (i == NULL)
+ {
+ return 0;
+ }
+
+ return i->OsType;
+}
+
+// Getting OS information
+OS_INFO *GetOsInfo()
+{
+ return os_info;
+}
+
+// Initialization of OS information
+void InitOsInfo()
+{
+ if (os_info != NULL)
+ {
+ return;
+ }
+
+ os_info = ZeroMalloc(sizeof(OS_INFO));
+
+ OSGetOsInfo(os_info);
+}
+
+// Release of OS information
+void FreeOsInfo()
+{
+ if (os_info == NULL)
+ {
+ return;
+ }
+
+ Free(os_info->OsSystemName);
+ Free(os_info->OsProductName);
+ Free(os_info->OsVendorName);
+ Free(os_info->OsVersion);
+ Free(os_info->KernelName);
+ Free(os_info->KernelVersion);
+ Free(os_info);
+
+ os_info = NULL;
+}
+
+// Get the Unicode command line tokens
+UNI_TOKEN_LIST *GetCommandLineUniToken()
+{
+ if (cmdline_uni_token == NULL)
+ {
+ return UniNullToken();
+ }
+ else
+ {
+ return UniCopyToken(cmdline_uni_token);
+ }
+}
+
+// Getting the command line tokens
+TOKEN_LIST *GetCommandLineToken()
+{
+ if (cmdline_token == NULL)
+ {
+ return NullToken();
+ }
+ else
+ {
+ return CopyToken(cmdline_token);
+ }
+}
+
+// Convert the command line string into tokens
+void ParseCommandLineTokens()
+{
+ if (cmdline_token != NULL)
+ {
+ FreeToken(cmdline_token);
+ }
+ cmdline_token = ParseCmdLine(cmdline);
+
+ if (cmdline_uni_token != NULL)
+ {
+ UniFreeToken(cmdline_uni_token);
+ }
+ cmdline_uni_token = UniParseCmdLine(uni_cmdline);
+}
+
+// Release command line tokens
+void FreeCommandLineTokens()
+{
+ if (cmdline_token != NULL)
+ {
+ FreeToken(cmdline_token);
+ }
+ cmdline_token = NULL;
+
+ if (cmdline_uni_token != NULL)
+ {
+ UniFreeToken(cmdline_uni_token);
+ }
+ cmdline_uni_token = NULL;
+}
+
+// Initialization of the command line string
+void InitCommandLineStr(int argc, char **argv)
+{
+ if (argc >= 1)
+ {
+#ifdef OS_UNIX
+ exename_w = CopyUtfToUni(argv[0]);
+ exename = CopyUniToStr(exename_w);
+#else // OS_UNIX
+ exename = CopyStr(argv[0]);
+ exename_w = CopyStrToUni(exename);
+#endif // OS_UNIX
+ }
+ if (argc < 2 || argv == NULL)
+ {
+ // No command-line string
+ SetCommandLineStr(NULL);
+ }
+ else
+ {
+ // There are command-line string
+ int i, total_len = 1;
+ char *tmp;
+
+ for (i = 1;i < argc;i++)
+ {
+ total_len += StrLen(argv[i]) * 2 + 32;
+ }
+ tmp = ZeroMalloc(total_len);
+
+ for (i = 1;i < argc;i++)
+ {
+ UINT s_size = StrLen(argv[i]) * 2;
+ char *s = ZeroMalloc(s_size);
+ bool dq = (SearchStrEx(argv[i], " ", 0, true) != INFINITE);
+ ReplaceStrEx(s, s_size, argv[i], "\"", "\"\"", true);
+ if (dq)
+ {
+ StrCat(tmp, total_len, "\"");
+ }
+ StrCat(tmp, total_len, s);
+ if (dq)
+ {
+ StrCat(tmp, total_len, "\"");
+ }
+ StrCat(tmp, total_len, " ");
+ Free(s);
+ }
+
+ Trim(tmp);
+ SetCommandLineStr(tmp);
+ Free(tmp);
+ }
+}
+
+// Release of the command line string
+void FreeCommandLineStr()
+{
+ SetCommandLineStr(NULL);
+
+ if (exename != NULL)
+ {
+ Free(exename);
+ exename = NULL;
+ }
+
+ if (exename_w != NULL)
+ {
+ Free(exename_w);
+ exename_w = NULL;
+ }
+}
+
+// Get the Unicode command line string
+wchar_t *GetCommandLineUniStr()
+{
+ if (uni_cmdline == NULL)
+ {
+ return UniCopyStr(L"");
+ }
+ else
+ {
+ return UniCopyStr(uni_cmdline);
+ }
+}
+
+// Get the command line string
+char *GetCommandLineStr()
+{
+ if (cmdline == NULL)
+ {
+ return CopyStr("");
+ }
+ else
+ {
+ return CopyStr(cmdline);
+ }
+}
+
+// Set the Unicode command line string
+void SetCommandLineUniStr(wchar_t *str)
+{
+ if (uni_cmdline != NULL)
+ {
+ Free(uni_cmdline);
+ }
+ if (str == NULL)
+ {
+ uni_cmdline = NULL;
+ }
+ else
+ {
+ uni_cmdline = CopyUniStr(str);
+ }
+
+ ParseCommandLineTokens();
+}
+
+// Set the command-line string
+void SetCommandLineStr(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ if (cmdline != NULL)
+ {
+ Free(cmdline);
+ }
+ cmdline = NULL;
+ }
+ else
+ {
+ if (cmdline != NULL)
+ {
+ Free(cmdline);
+ }
+ cmdline = CopyStr(str);
+ }
+
+ if (cmdline == NULL)
+ {
+ if (uni_cmdline != NULL)
+ {
+ Free(uni_cmdline);
+ uni_cmdline = NULL;
+ }
+ }
+ else
+ {
+ if (uni_cmdline != NULL)
+ {
+ Free(uni_cmdline);
+ }
+ uni_cmdline = CopyStrToUni(cmdline);
+ }
+
+ ParseCommandLineTokens();
+}
+
+// Display the kernel status
+void PrintKernelStatus()
+{
+ bool leaked = false;
+
+ Print("\n");
+ Print(
+ " --------- Mayaqua Kernel Status ---------\n"
+ " Malloc Count ............... %u\n"
+ " ReAlloc Count .............. %u\n"
+ " Free Count ................. %u\n"
+ " Total Memory Size .......... %I64u bytes\n"
+ " * Current Memory Blocks ...... %u Blocks (Peek: %u)\n"
+ " Total Memory Blocks ........ %u Blocks\n"
+ " * Current MemPool Blocks ..... %u Blocks (Peek: %u)\n"
+ " Total MemPool Mallocs ...... %u Mallocs\n"
+ " Total MemPool ReAllocs ..... %u ReAllocs\n"
+ " NewLock Count .............. %u\n"
+ " DeleteLock Count ........... %u\n"
+ " * Current Lock Objects ....... %u Objects\n"
+ " * Current Locked Objects ..... %u Objects\n"
+ " NewRef Count ............... %u\n"
+ " FreeRef Count .............. %u\n"
+ " * Current Ref Objects ........ %u Objects\n"
+ " * Current Ref Count .......... %u Refs\n"
+ " GetTime Count .............. %u\n"
+ " GetTick Count .............. %u\n"
+ " NewThread Count ............ %u\n"
+ " FreeThread Count ........... %u\n"
+ " * Current Threads ............ %u Threads\n"
+ " Wait For Event Count ....... %u\n\n",
+ KS_GET(KS_MALLOC_COUNT),
+ KS_GET(KS_REALLOC_COUNT),
+ KS_GET(KS_FREE_COUNT),
+ KS_GET64(KS_TOTAL_MEM_SIZE),
+ KS_GET(KS_CURRENT_MEM_COUNT),
+ KS_GETMAX(KS_CURRENT_MEM_COUNT),
+ KS_GET(KS_TOTAL_MEM_COUNT),
+ KS_GET(KS_MEMPOOL_CURRENT_NUM),
+ KS_GETMAX(KS_MEMPOOL_CURRENT_NUM),
+ KS_GET(KS_MEMPOOL_MALLOC_COUNT),
+ KS_GET(KS_MEMPOOL_REALLOC_COUNT),
+ KS_GET(KS_NEWLOCK_COUNT),
+ KS_GET(KS_DELETELOCK_COUNT),
+ KS_GET(KS_CURRENT_LOCK_COUNT),
+ KS_GET(KS_CURRENT_LOCKED_COUNT),
+ KS_GET(KS_NEWREF_COUNT),
+ KS_GET(KS_FREEREF_COUNT),
+ KS_GET(KS_CURRENT_REF_COUNT),
+ KS_GET(KS_CURRENT_REFED_COUNT),
+ KS_GET(KS_GETTIME_COUNT),
+ KS_GET(KS_GETTICK_COUNT),
+ KS_GET(KS_NEWTHREAD_COUNT),
+ KS_GET(KS_FREETHREAD_COUNT),
+ KS_GET(KS_NEWTHREAD_COUNT) - KS_GET(KS_FREETHREAD_COUNT),
+ KS_GET(KS_WAIT_COUNT)
+ );
+
+ if (KS_GET(KS_CURRENT_MEM_COUNT) != 0 || KS_GET(KS_CURRENT_LOCK_COUNT) != 0 ||
+ KS_GET(KS_MEMPOOL_CURRENT_NUM) != 0 ||
+ KS_GET(KS_CURRENT_LOCKED_COUNT) != 0 || KS_GET(KS_CURRENT_REF_COUNT) != 0)
+ {
+ leaked = true;
+ }
+
+ if (leaked)
+ {
+ Print(" !!! MEMORY LEAKS DETECTED !!!\n\n");
+ if (g_memcheck == false)
+ {
+ GetLine(NULL, 0);
+ }
+ }
+ else
+ {
+ Print(" @@@ NO MEMORY LEAKS @@@\n\n");
+ }
+}
+
+// Initialize Kernel status
+void InitKernelStatus()
+{
+ UINT i;
+
+ // Memory initialization
+ Zero(kernel_status, sizeof(kernel_status));
+ Zero(kernel_status_max, sizeof(kernel_status_max));
+
+ // Lock initialization
+ for (i = 0;i < NUM_KERNEL_STATUS;i++)
+ {
+ kernel_status_lock[i] = OSNewLock();
+ }
+
+ kernel_status_inited = true;
+}
+
+// Release of the kernel status
+void FreeKernelStatus()
+{
+ UINT i;
+
+ kernel_status_inited = false;
+
+ // Lock release
+ for (i = 0;i < NUM_KERNEL_STATUS;i++)
+ {
+ OSDeleteLock(kernel_status_lock[i]);
+ }
+}
+
+// Lock the kernel status
+void LockKernelStatus(UINT id)
+{
+ // Validate arguments
+ if (id >= NUM_KERNEL_STATUS)
+ {
+ return;
+ }
+
+ OSLock(kernel_status_lock[id]);
+}
+
+// Unlock the kernel status
+void UnlockKernelStatus(UINT id)
+{
+ // Validate arguments
+ if (id >= NUM_KERNEL_STATUS)
+ {
+ return;
+ }
+
+ OSUnlock(kernel_status_lock[id]);
+}
+
+// Display the debug information
+void PrintDebugInformation()
+{
+ MEMORY_STATUS memory_status;
+ GetMemoryStatus(&memory_status);
+
+ // Header
+ Print("====== " CEDAR_PRODUCT_STR " VPN System Debug Information ======\n");
+
+ // Memory information
+ Print(" <Memory Status>\n"
+ " Number of Allocated Memory Blocks: %u\n"
+ " Total Size of Allocated Memory Blocks: %u bytes\n",
+ memory_status.MemoryBlocksNum, memory_status.MemorySize);
+
+ // Footer
+ Print("====================================================\n");
+
+ if (KS_GET(KS_CURRENT_MEM_COUNT) != 0 || KS_GET(KS_CURRENT_LOCK_COUNT) != 0 ||
+ KS_GET(KS_CURRENT_LOCKED_COUNT) != 0 || KS_GET(KS_CURRENT_REF_COUNT) != 0)
+ {
+ // Show a debug menu because memory leaks suspected
+ MemoryDebugMenu();
+ }
+}
+
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Mayaqua.h b/src/Mayaqua/Mayaqua.h
new file mode 100644
index 00000000..75e6b9d9
--- /dev/null
+++ b/src/Mayaqua/Mayaqua.h
@@ -0,0 +1,595 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Mayaqua.h
+// Mayaqua Kernel header file
+
+#ifndef MAYAQUA_H
+#define MAYAQUA_H
+
+// PenCore.dll related
+#define PENCORE_DLL_NAME "|PenCore.dll"
+// #define PENCORE_DLL_NAME_X64 "|PenCore_x64.dll" // commonized to x86
+// #define PENCORE_DLL_NAME_IA64 "|PenCore_ia64.dll" // commonized to x86
+
+
+//#define USE_PROBE // Use Probe
+
+// Macro for the release flag
+#ifdef VPN_SPEED
+
+#define DONT_USE_KERNEL_STATUS // Do not update the kernel status
+#define WIN32_USE_HEAP_API_FOR_MEMORY // Use the heap API to allocate memory
+#define WIN32_NO_DEBUG_HELP_DLL // Do not call the DLL for debugging
+#define DONT_CHECK_HEAP // Do not check the status of the heap
+#define DONT_ALLOW_RUN_ON_DEBUGGER // Do not allow running on the debugger
+
+#endif // VPN_SPEED
+
+#ifdef VPN_EXE
+// To build the executable file
+#ifdef WIN32
+#include <windows.h>
+#include "../PenCore/resource.h"
+int main(int argc, char *argv[]);
+int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow)
+{
+ char *argv[] = { CmdLine, };
+ return main(1, argv);
+}
+#endif // WIN32
+#endif // VPN_EXE
+
+// Constant
+#define DEFAULT_TABLE_FILE_NAME "|strtable.stb" // Default string table
+//#define DEFAULT_TABLE_FILE_NAME "@hamcore_zh/strtable.stb" // Test for Chinese
+
+#define STRTABLE_ID "SE_VPN_20121007" // String table identifier
+
+// Determining the OS
+#ifdef WIN32
+#define OS_WIN32 // Microsoft Windows
+#else
+#define OS_UNIX // UNIX
+#endif // WIN32
+
+// Directory separator
+#ifdef OS_WIN32
+#define PATH_BACKSLASH // Backslash (\)
+#else // WIN32
+#define PATH_SLASH // Slash (/)
+#endif // WIN32
+
+// Character code
+#ifdef OS_WIN32
+#define CODE_SHIFTJIS // Shift_JIS code
+#else // WIN32
+#define CODE_EUC // euc-jp code
+#endif // WIN32
+
+// Endian
+#define IsBigEndian() (g_little_endian ? false : true)
+#define IsLittleEndian() (g_little_endian)
+
+#ifdef OS_WIN32
+// Replace the snprintf function
+#define snprintf _snprintf
+#endif // OS_WIN32
+
+// Compiler dependent
+#ifndef OS_WIN32
+// Gcc compiler
+#define GCC_PACKED __attribute__ ((__packed__))
+#else // OS_WIN32
+// VC++ compiler
+#define GCC_PACKED
+#endif // OS_WIN32
+
+// Macro that displays the current file name and line number
+#define WHERE if (IsDebug()){printf("%s: %u\n", __FILE__, __LINE__); SleepThread(10);}
+#define WHERE32 if (IsDebug()){ \
+ char tmp[128]; sprintf(tmp, "%s: %u", __FILE__, __LINE__); Win32DebugAlert(tmp); \
+ }
+#define TIMECHECK if (IsDebug()){printf("%-12s:%5u", __FILE__, __LINE__);TimeCheck();}
+
+// Probe related
+#ifdef USE_PROBE
+#define PROBE_WHERE WriteProbe(__FILE__, __LINE__, "");
+#define PROBE_STR(str) WriteProbe(__FILE__, __LINE__, (str));
+#define PROBE_DATA2(str, data, size) WriteProbeData(__FILE__, __LINE__, (str), (data), (size));
+#define PROBE_DATA(data, size) WriteProbeData(__FILE__, __LINE__, "", (data), (size));
+#else // USE_PROBE
+#define PROBE_WHERE
+#define PROBE_STR(str)
+#define PROBE_DATA2(str, data, size)
+#define PROBE_DATA(data, size)
+#endif // USE_PROBE
+
+// About Intel AES-NI Library
+#if (defined(OS_WIN32) || (defined(UNIX_LINUX) && (defined(CPU_X86) || defined(CPU_X64))))
+// Supports only for Linux (x86 / x64) or Windows
+#define USE_INTEL_AESNI_LIBRARY
+#endif
+
+// Macro that displays the current time
+#ifdef WIN32
+#define WHEN if (IsDebug()){WHERE; MsPrintTick();}
+#else // WIN32
+#define WHEN
+#endif // WIN32
+
+#ifdef OS_UNIX
+#ifndef UNIX_SOLARIS
+#ifndef CPU_SH4
+// Getifaddrs system call is supported on UNIX other than Solaris.
+// However, it is not supported also by the Linux on SH4 CPU
+#define MAYAQUA_SUPPORTS_GETIFADDRS
+#endif // CPU_SH4
+#endif // UNIX_SOLARIS
+#endif // OS_UNIX
+
+#ifdef OS_UNIX
+// Header only needed in UNIX OS
+#include <sys/types.h>
+#include <unistd.h>
+#include <termios.h>
+#include <dirent.h>
+#ifdef UNIX_LINUX
+#include <sys/vfs.h>
+#elif UNIX_BSD
+#include <sys/param.h>
+#include <sys/mount.h>
+#endif
+#ifdef UNIX_SOLARIS
+#include <sys/statvfs.h>
+#define USE_STATVFS
+#endif // UNIX_SOLARIS
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#ifdef UNIX_SOLARIS
+#include <sys/filio.h>
+#endif // UNIX_SOLARIS
+#include <sys/poll.h>
+#include <sys/resource.h>
+#include <pthread.h>
+#ifdef UNIX_LINUX
+#include <sys/prctl.h>
+#endif // UNIX_LINUX
+#include <signal.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+//#include <netinet/ip.h>
+#include <netdb.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+//#include <curses.h>
+#ifdef MAYAQUA_SUPPORTS_GETIFADDRS
+#include <ifaddrs.h>
+#endif // MAYAQUA_SUPPORTS_GETIFADDRS
+
+#ifdef UNIX_LINUX
+typedef void *iconv_t;
+iconv_t iconv_open (__const char *__tocode, __const char *__fromcode);
+size_t iconv (iconv_t __cd, char **__restrict __inbuf,
+ size_t *__restrict __inbytesleft,
+ char **__restrict __outbuf,
+ size_t *__restrict __outbytesleft);
+int iconv_close (iconv_t __cd);
+#else // UNIX_LINUX
+#include <iconv.h>
+#endif // UNIX_LINUX
+
+
+
+#ifdef UNIX_LINUX
+#include <netinet/if_ether.h>
+#include <net/ethernet.h>
+#include <netpacket/packet.h>
+#endif // UNIX_LINUX
+
+#ifdef UNIX_SOLARIS
+#include <sys/dlpi.h>
+#include <sys/stropts.h>
+#include <sys/stream.h>
+#endif // UNIX_SOLARIS
+
+#ifndef NO_VLAN
+
+#include <Mayaqua/TunTap.h>
+
+#endif // NO_VLAN
+
+#define closesocket(s) close(s)
+
+#else // Win32 only
+
+#include <conio.h>
+
+#endif // OS_UNIX
+
+// IPv6 support flag
+#ifndef WIN32
+#ifndef AF_INET6
+#define NO_IPV6
+#endif // AF_INET6
+#endif // WIN32
+
+// Basic type declaration
+#include <Mayaqua/MayaType.h>
+
+// Object management
+#include <Mayaqua/Object.h>
+
+// Object tracking
+#include <Mayaqua/Tracking.h>
+
+// File I/O
+#include <Mayaqua/FileIO.h>
+
+// Memory management
+#include <Mayaqua/Memory.h>
+
+// String processing
+#include <Mayaqua/Str.h>
+
+// Internationalized string processing
+#include <Mayaqua/Internat.h>
+
+// Encryption processing
+#include <Mayaqua/Encrypt.h>
+
+// Secure token
+#include <Mayaqua/Secure.h>
+
+// Kernel
+#include <Mayaqua/Kernel.h>
+
+// Package
+#include <Mayaqua/Pack.h>
+
+// Configuration file
+#include <Mayaqua/Cfg.h>
+
+// String table
+#include <Mayaqua/Table.h>
+
+// Network communication
+#include <Mayaqua/Network.h>
+
+// TCP/IP
+#include <Mayaqua/TcpIp.h>
+
+// 64 bit real-time clock
+#include <Mayaqua/Tick64.h>
+
+// OS-dependent code
+#include <Mayaqua/OS.h>
+
+// Code for Microsoft Windows
+#include <Mayaqua/Microsoft.h>
+
+
+// Global variables
+extern bool g_memcheck;
+extern bool g_debug;
+extern char *cmdline;
+extern wchar_t *uni_cmdline;
+extern bool g_little_endian;
+extern LOCK *tick_manual_lock;
+
+// Kernel state
+#define NUM_KERNEL_STATUS 128
+extern UINT64 kernel_status[NUM_KERNEL_STATUS];
+extern UINT64 kernel_status_max[NUM_KERNEL_STATUS];
+extern LOCK *kernel_status_lock[NUM_KERNEL_STATUS];
+extern BOOL kernel_status_inited;
+
+// Kernel state operation macro
+#define KS_LOCK(id) LockKernelStatus(id)
+#define KS_UNLOCK(id) UnlockKernelStatus(id)
+#define KS_GET64(id) (kernel_status[id])
+#define KS_GET(id) ((UINT)KS_GET64(id))
+#define KS_GETMAX64(id) (kernel_status_max[id])
+#define KS_GETMAX(id) ((UINT)KS_GETMAX64(id))
+
+#ifdef DONT_USE_KERNEL_STATUS
+// Disable operations of the kernel status
+#define KS_INC(id)
+#define KS_DEC(id)
+#define KS_ADD(id, n)
+#define KS_SUB(id, n)
+#else // DONT_USE_KERNEL_STATUS
+// Enable operations of the kernel status
+#define KS_INC(id) \
+if (kernel_status_inited) { \
+ KS_LOCK(id); \
+ kernel_status[id]++; \
+ kernel_status_max[id] = MAX(kernel_status_max[id], kernel_status[id]); \
+ KS_UNLOCK(id); \
+}
+#define KS_DEC(id) \
+if (kernel_status_inited) { \
+ KS_LOCK(id); \
+ kernel_status[id]--; \
+ kernel_status_max[id] = MAX(kernel_status_max[id], kernel_status[id]); \
+ KS_UNLOCK(id); \
+}
+#define KS_ADD(id, n) \
+if (kernel_status_inited) { \
+ KS_LOCK(id); \
+ kernel_status[id] += n; \
+ kernel_status_max[id] = MAX(kernel_status_max[id], kernel_status[id]); \
+ KS_UNLOCK(id); \
+}
+#define KS_SUB(id, n) \
+if (kernel_status_inited) { \
+ KS_LOCK(id); \
+ kernel_status[id] -= n; \
+ kernel_status_max[id] = MAX(kernel_status_max[id], kernel_status[id]); \
+ KS_UNLOCK(id); \
+}
+#endif // DONT_USE_KERNEL_STATUS
+
+// Kernel status
+// String related
+#define KS_STRCPY_COUNT 0 // number of calls StrCpy
+#define KS_STRLEN_COUNT 1 // number of calls StrLen
+#define KS_STRCHECK_COUNT 2 // number of calls StrCheck
+#define KS_STRCAT_COUNT 3 // number of calls StrCat
+#define KS_FORMAT_COUNT 4 // number of calls Format
+// Memory related
+#define KS_MALLOC_COUNT 5 // Number of calls Malloc
+#define KS_REALLOC_COUNT 6 // Number of calls ReAlloc
+#define KS_FREE_COUNT 7 // number of calls Free
+#define KS_TOTAL_MEM_SIZE 8 // The total size of the memory that was allocated so far
+#define KS_CURRENT_MEM_COUNT 9 // Number of memory blocks that are currently reserved
+#define KS_TOTAL_MEM_COUNT 10 // The total number of memory blocks that ware allocated so far
+#define KS_ZERO_COUNT 11 // Number of calls Zero
+#define KS_COPY_COUNT 12 // Number of calls Copy
+// Lock related
+#define KS_NEWLOCK_COUNT 13 // Number of calls NewLock
+#define KS_DELETELOCK_COUNT 14 // Number of calls DeleteLock
+#define KS_LOCK_COUNT 15 // Number of calls Lock
+#define KS_UNLOCK_COUNT 16 // Number of calls Unlock
+#define KS_CURRENT_LOCK_COUNT 17 // Current number of LOCK objects
+#define KS_CURRENT_LOCKED_COUNT 18 // Current number of locked LOCK objects
+// Counter information
+#define KS_NEW_COUNTER_COUNT 19 // Number of calls NewCounter
+#define KS_DELETE_COUNTER_COUNT 20 // Number of calls DeleteCounter
+#define KS_INC_COUNT 21 // Number of calls Inc
+#define KS_DEC_COUNT 22 // Number of calls Dec
+#define KS_CURRENT_COUNT 23 // Current total number of counts
+// Reference counter information
+#define KS_NEWREF_COUNT 24 // Number of calls NewRef
+#define KS_FREEREF_COUNT 72 // Number of times REF objects are deleted
+#define KS_ADDREF_COUNT 25 // Number of calls AddRef
+#define KS_RELEASE_COUNT 26 // Number of calls Release
+#define KS_CURRENT_REF_COUNT 27 // Current number of REF objects
+#define KS_CURRENT_REFED_COUNT 28 // The sum of the current number of references
+// Buffer information
+#define KS_NEWBUF_COUNT 29 // Number of calls NewBuf
+#define KS_FREEBUF_COUNT 30 // NNumber of calls FreeBuf
+#define KS_CURRENT_BUF_COUNT 31 // Current number of objects in the BUF
+#define KS_READ_BUF_COUNT 32 // Number of calls ReadBuf
+#define KS_WRITE_BUF_COUNT 33 // Number of calls WriteBuf
+#define KS_ADJUST_BUFSIZE_COUNT 34 // Number of times to adjust the buffer size
+#define KS_SEEK_BUF_COUNT 35 // Number of calls SeekBuf
+// FIFO information
+#define KS_NEWFIFO_COUNT 36 // Number of calls NewFifo
+#define KS_FREEFIFO_COUNT 37 // Number of times the FIFO object is deleted
+#define KS_READ_FIFO_COUNT 38 // Number of calls ReadFifo
+#define KS_WRITE_FIFO_COUNT 39 // Number of calls WriteFifo
+#define KS_PEEK_FIFO_COUNT 40 // Number of calls PeekFifo
+// List related
+#define KS_NEWLIST_COUNT 41 // Number of calls NewList
+#define KS_FREELIST_COUNT 42 // Number of times the object LIST was deleted
+#define KS_INSERT_COUNT 43 // Number of calls Add
+#define KS_DELETE_COUNT 44 // Number of calls Delete
+#define KS_SORT_COUNT 45 // Number of calls Sort
+#define KS_SEARCH_COUNT 46 // Number of calls Search
+#define KS_TOARRAY_COUNT 47 // Number of calls ToArray
+// Queue related
+#define KS_NEWQUEUE_COUNT 48 // Number of calls NewQueue
+#define KS_FREEQUEUE_COUNT 49 // Number of times you delete the object QUEUE
+#define KS_PUSH_COUNT 50 // Number of calls Push
+#define KS_POP_COUNT 51 // Number of calls POP
+// Stack related
+#define KS_NEWSK_COUNT 52 // Number of calls NewSk
+#define KS_FREESK_COUNT 53 // Number of times you delete the object SK
+#define KS_INSERT_QUEUE_COUNT 54 // Number of calls InsertQueue
+#define KS_GETNEXT_COUNT 55 // Number of calls GetNext
+// Kernel related
+#define KS_GETTIME_COUNT 56 // Number of times to get the time
+#define KS_GETTICK_COUNT 57 // Number of times to get the system timer
+#define KS_NEWTHREAD_COUNT 58 // Number of calls NewThread
+#define KS_FREETHREAD_COUNT 59 // Number of times you delete the object THREAD
+#define KS_WAITFORTHREAD_COUNT 60 // Number of calls WaitForThread
+#define KS_NEWEVENT_COUNT 61 // Number of calls NewEvent
+#define KS_FREEEVENT_COUNT 62 // Number of times which EVENT object is deleted
+#define KS_WAIT_COUNT 63 // Number of calls Wait
+#define KS_SLEEPTHREAD_COUNT 64 // Number of calls SleepThread
+// About IO
+#define KS_IO_OPEN_COUNT 65 // Number of times to open the file
+#define KS_IO_CREATE_COUNT 66 // Number of times that the file was created
+#define KS_IO_CLOSE_COUNT 67 // Number of times to close the file
+#define KS_IO_READ_COUNT 68 // Number of times to read from the file
+#define KS_IO_WRITE_COUNT 69 // Number of times to write to a file
+#define KS_IO_TOTAL_READ_SIZE 70 // Total number of bytes read from the file
+#define KS_IO_TOTAL_WRITE_SIZE 71 // The total number of bytes written to the file
+// Memory pool related
+#define KS_MEMPOOL_MALLOC_COUNT 75 // Number of times to allocate the memory pool
+#define KS_MEMPOOL_FREE_COUNT 73 // Number of times you release the memory pool
+#define KS_MEMPOOL_CURRENT_NUM 74 // Current number of the memory pool
+#define KS_MEMPOOL_REALLOC_COUNT 76 // Number of times you have realloc the memory pool
+
+
+// Macro
+#define IsDebug() (g_debug) // A debug mode
+#define IsMemCheck() (g_memcheck) // Memory check mode
+
+// Function prototype
+void InitMayaqua(bool memcheck, bool debug, int argc, char **argv);
+void FreeMayaqua();
+bool IsNt();
+bool IsUnicode();
+void MayaquaDotNetMode();
+bool MayaquaIsDotNetMode();
+void MayaquaMinimalMode();
+bool MayaquaIsMinimalMode();
+bool Is64();
+bool Is32();
+bool IsIA64();
+bool IsX64();
+void InitKernelStatus();
+void FreeKernelStatus();
+void PrintDebugInformation();
+void LockKernelStatus(UINT id);
+void UnlockKernelStatus(UINT id);
+void PrintKernelStatus();
+void InitCommandLineStr(int argc, char **argv);
+void FreeCommandLineStr();
+void SetCommandLineStr(char *str);
+void SetCommandLineUniStr(wchar_t *str);
+char *GetCommandLineStr();
+wchar_t *GetCommandLineUniStr();
+void ParseCommandLineTokens();
+void FreeCommandLineTokens();
+TOKEN_LIST *GetCommandLineToken();
+UNI_TOKEN_LIST *GetCommandLineUniToken();
+void InitOsInfo();
+void FreeOsInfo();
+void Alert(char *msg, char *caption);
+void AlertW(wchar_t *msg, wchar_t *caption);
+OS_INFO *GetOsInfo();
+UINT GetOsType();
+void PrintOsInfo(OS_INFO *info);
+void CheckEndian();
+void CheckUnixTempDir();
+void TimeCheck();
+void SetHamMode();
+bool IsHamMode();
+void InitProbe();
+void FreeProbe();
+void EnableProbe(bool enable);
+bool IsProbeEnabled();
+void WriteProbe(char *filename, UINT line, char *str);
+void WriteProbeData(char *filename, UINT line, char *str, void *data, UINT size);
+USHORT CalcChecksum16(void *buf, UINT size);
+
+
+#ifdef OS_WIN32
+// Import library (for Win32)
+#pragma comment(lib, "Ws2_32.lib")
+#pragma comment(lib, "winmm.lib")
+#pragma comment(lib, "kernel32.lib")
+#pragma comment(lib, "user32.lib")
+#pragma comment(lib, "gdi32.lib")
+#pragma comment(lib, "shell32.lib")
+#pragma comment(lib, "comctl32.lib")
+#pragma comment(lib, "dbghelp.lib")
+#pragma comment(lib, "Iphlpapi.lib")
+#pragma comment(lib, "setupapi.lib")
+#pragma comment(lib, "version.lib")
+#pragma comment(lib, "Netapi32.lib")
+#pragma comment(lib, "shlwapi.lib")
+#pragma warning( disable : 4099 )
+#endif // OS_WIN32
+
+// For Debugging
+#ifndef ENCRYPT_C
+//#define Disconnect(s) {Debug("Disconnect() Called: %s %u\n", __FILE__, __LINE__);Disconnect(s);}
+#endif
+
+
+#endif // MAYAQUA_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Mayaqua.vcproj b/src/Mayaqua/Mayaqua.vcproj
new file mode 100644
index 00000000..af36ad18
--- /dev/null
+++ b/src/Mayaqua/Mayaqua.vcproj
@@ -0,0 +1,833 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="Mayaqua"
+ ProjectGUID="{70486335-7814-40E2-A561-BBCB6025F5C9}"
+ RootNamespace="Mayaqua"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="libeay32.lib ssleay32.lib zlib.lib libintelaes.lib"
+ AdditionalLibraryDirectories="$(SolutionDir)BuildFiles\Library\$(PlatformName)_$(ConfigurationName)"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;CPU_64"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="4"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="libeay32.lib ssleay32.lib zlib.lib libintelaes.lib"
+ AdditionalLibraryDirectories="$(SolutionDir)BuildFiles\Library\$(PlatformName)_$(ConfigurationName)"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="libeay32.lib ssleay32.lib zlib.lib libintelaes.lib"
+ AdditionalLibraryDirectories="$(SolutionDir)BuildFiles\Library\$(PlatformName)_$(ConfigurationName)"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;.;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ AdditionalDependencies="libeay32.lib ssleay32.lib zlib.lib libintelaes.lib"
+ AdditionalLibraryDirectories="$(SolutionDir)BuildFiles\Library\$(PlatformName)_$(ConfigurationName)"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\Cfg.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Encrypt.c"
+ >
+ </File>
+ <File
+ RelativePath=".\FileIO.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Internat.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Kernel.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Mayaqua.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Memory.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Microsoft.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Network.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Object.c"
+ >
+ </File>
+ <File
+ RelativePath=".\OS.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Pack.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Secure.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Str.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Table.c"
+ >
+ </File>
+ <File
+ RelativePath=".\TcpIp.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Tick64.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Tracking.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Unix.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Win32.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\Cfg.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cryptoki.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Encrypt.h"
+ >
+ </File>
+ <File
+ RelativePath=".\FileIO.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Internat.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Kernel.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Mayaqua.h"
+ >
+ </File>
+ <File
+ RelativePath=".\MayaType.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Memory.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Microsoft.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Network.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Object.h"
+ >
+ </File>
+ <File
+ RelativePath=".\OS.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Pack.h"
+ >
+ </File>
+ <File
+ RelativePath=".\pkcs11.h"
+ >
+ </File>
+ <File
+ RelativePath=".\pkcs11f.h"
+ >
+ </File>
+ <File
+ RelativePath=".\pkcs11t.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Secure.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Str.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Table.h"
+ >
+ </File>
+ <File
+ RelativePath=".\TcpIp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Tick64.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Tracking.h"
+ >
+ </File>
+ <File
+ RelativePath=".\TunTap.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Unix.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Win32.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="openssl"
+ >
+ <File
+ RelativePath=".\openssl\aes.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\asn1.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\asn1_mac.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\asn1t.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\bio.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\blowfish.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\bn.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\buffer.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\cast.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\comp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\conf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\conf_api.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\crypto.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\des.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\des_old.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\dh.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\dsa.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\dso.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\dtls1.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\e_os2.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ebcdic.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ec.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ecdh.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ecdsa.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\engine.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\err.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\evp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\fips.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\fips_rand.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\hmac.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\idea.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\krb5_asn.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\kssl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\lhash.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\md2.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\md4.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\md5.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\mdc2.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\obj_mac.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\objects.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ocsp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\opensslconf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\opensslv.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ossl_typ.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\pem.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\pem2.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\pkcs12.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\pkcs7.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\pq_compat.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\pqueue.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\rand.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\rc2.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\rc4.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\rc5.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ripemd.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\rsa.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\safestack.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\sha.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ssl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ssl2.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ssl23.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ssl3.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\stack.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\store.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\symhacks.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\tls1.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\tmdiff.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\txt_db.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ui.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\ui_compat.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\x509.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\x509_vfy.h"
+ >
+ </File>
+ <File
+ RelativePath=".\openssl\x509v3.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="zlib"
+ >
+ <File
+ RelativePath=".\zlib\zconf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\zlib\zlib.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="intelaes"
+ >
+ <File
+ RelativePath=".\intelaes\iaesni.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/Mayaqua/Memory.c b/src/Mayaqua/Memory.c
new file mode 100644
index 00000000..2fc00844
--- /dev/null
+++ b/src/Mayaqua/Memory.c
@@ -0,0 +1,4124 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Memory.c
+// Memory management program
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <zlib/zlib.h>
+#include <Mayaqua/Mayaqua.h>
+
+#define MEMORY_SLEEP_TIME 150
+#define MEMORY_MAX_RETRY 30
+#define INIT_BUF_SIZE 10240
+
+#define FIFO_INIT_MEM_SIZE 4096
+#define FIFO_REALLOC_MEM_SIZE (65536 * 10) // Exquisite value
+#define FIFO_REALLOC_MEM_SIZE_SMALL 65536
+
+#define INIT_NUM_RESERVED 32
+
+static UINT fifo_default_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;
+
+// Lock the hash list
+void LockHashList(HASH_LIST *h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ Lock(h->Lock);
+}
+
+// Unlock the hash list
+void UnlockHashList(HASH_LIST *h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ Unlock(h->Lock);
+}
+
+// Write the contents of the hash list to array
+void **HashListToArray(HASH_LIST *h, UINT *num)
+{
+ void **ret = NULL;
+ UINT i;
+ UINT n = 0;
+ // Validate arguments
+ if (h == NULL || num == NULL)
+ {
+ if (num != NULL)
+ {
+ *num = 0;
+ }
+ return NULL;
+ }
+
+ if (h->AllList != NULL)
+ {
+ *num = LIST_NUM(h->AllList);
+
+ return ToArray(h->AllList);
+ }
+
+ ret = ZeroMalloc(sizeof(void *) * h->NumItems);
+
+ for (i = 0;i < h->Size;i++)
+ {
+ LIST *o = h->Entries[i];
+
+ if (o != NULL)
+ {
+ UINT j;
+
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ void *p = LIST_DATA(o, j);
+
+ ret[n] = p;
+ n++;
+ }
+ }
+ }
+
+ *num = n;
+
+ return ret;
+}
+
+// Search an item in the hash list
+void *SearchHash(HASH_LIST *h, void *t)
+{
+ UINT r;
+ void *ret = NULL;
+ // Validate arguments
+ if (h == NULL || t == NULL)
+ {
+ return NULL;
+ }
+
+ r = CalcHashForHashList(h, t);
+
+ if (h->Entries[r] != NULL)
+ {
+ LIST *o = h->Entries[r];
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ void *p = LIST_DATA(o, i);
+
+ if (h->CompareProc(&p, &t) == 0)
+ {
+ ret = p;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Remove an item from the hash list
+bool DeleteHash(HASH_LIST *h, void *p)
+{
+ UINT r;
+ bool ret = false;
+ // Validate arguments
+ if (h == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ r = CalcHashForHashList(h, p);
+
+ if (h->Entries[r] != NULL)
+ {
+ if (Delete(h->Entries[r], p))
+ {
+ ret = true;
+ h->NumItems--;
+ }
+
+ if (LIST_NUM(h->Entries[r]) == 0)
+ {
+ ReleaseList(h->Entries[r]);
+ h->Entries[r] = NULL;
+ }
+ }
+
+ if (ret)
+ {
+ if (h->AllList != NULL)
+ {
+ Delete(h->AllList, p);
+ }
+ }
+
+ return ret;
+}
+
+// Add an item to the hash list
+void AddHash(HASH_LIST *h, void *p)
+{
+ UINT r;
+ // Validate arguments
+ if (h == NULL || p == NULL)
+ {
+ return;
+ }
+
+ r = CalcHashForHashList(h, p);
+
+ if (h->Entries[r] == NULL)
+ {
+ h->Entries[r] = NewListFast(NULL);
+ }
+
+ Add(h->Entries[r], p);
+
+ if (h->AllList != NULL)
+ {
+ Add(h->AllList, p);
+ }
+
+ h->NumItems++;
+}
+
+// Calculation of the hash value of the object
+UINT CalcHashForHashList(HASH_LIST *h, void *p)
+{
+ UINT r;
+ // Validate arguments
+ if (h == NULL || p == NULL)
+ {
+ return 0;
+ }
+
+ r = h->GetHashProc(p);
+
+ return (r % h->Size);
+}
+
+// Creating a hash list
+HASH_LIST *NewHashList(GET_HASH *get_hash_proc, COMPARE *compare_proc, UINT bits, bool make_list)
+{
+ HASH_LIST *h;
+ // Validate arguments
+ if (get_hash_proc == NULL || compare_proc == NULL)
+ {
+ return NULL;
+ }
+ if (bits == 0)
+ {
+ bits = 16;
+ }
+
+ bits = MIN(bits, 31);
+
+ h = ZeroMalloc(sizeof(HASH_LIST));
+
+ h->Bits = bits;
+ h->Size = Power(2, bits);
+
+ h->Lock = NewLock();
+ h->Ref = NewRef();
+
+ h->Entries = ZeroMalloc(sizeof(LIST *) * h->Size);
+
+ h->GetHashProc = get_hash_proc;
+ h->CompareProc = compare_proc;
+
+ if (make_list)
+ {
+ h->AllList = NewListFast(NULL);
+ }
+
+ return h;
+}
+
+// Release the hash list
+void ReleaseHashList(HASH_LIST *h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ if (Release(h->Ref) == 0)
+ {
+ CleanupHashList(h);
+ }
+}
+void CleanupHashList(HASH_LIST *h)
+{
+ UINT i;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < h->Size;i++)
+ {
+ LIST *o = h->Entries[i];
+
+ if (o != NULL)
+ {
+ ReleaseList(o);
+ }
+ }
+
+ Free(h->Entries);
+
+ DeleteLock(h->Lock);
+
+ if (h->AllList != NULL)
+ {
+ ReleaseList(h->AllList);
+ }
+
+ Free(h);
+}
+
+// Append a string to the buffer
+void AppendBufStr(BUF *b, char *str)
+{
+ // Validate arguments
+ if (b == NULL || str == NULL)
+ {
+ return;
+ }
+
+ WriteBuf(b, str, StrLen(str));
+}
+
+// Add a UTF-8 string to the buffer
+void AppendBufUtf8(BUF *b, wchar_t *str)
+{
+ UINT size;
+ UCHAR *data;
+ // Validate arguments
+ if (b == NULL || str == NULL)
+ {
+ return;
+ }
+
+ size = CalcUniToUtf8(str) + 1;
+ data = ZeroMalloc(size);
+
+ UniToUtf8(data, size, str);
+
+ WriteBuf(b, data, size - 1);
+
+ Free(data);
+}
+
+// Creating a shared buffer
+SHARED_BUFFER *NewSharedBuffer(void *data, UINT size)
+{
+ SHARED_BUFFER *b = ZeroMalloc(sizeof(SHARED_BUFFER));
+
+ b->Ref = NewRef();
+ b->Data = ZeroMalloc(size);
+ b->Size = size;
+
+ if (data != NULL)
+ {
+ Copy(b->Data, data, size);
+ }
+
+ return b;
+}
+
+// Release of the shared buffer
+void ReleaseSharedBuffer(SHARED_BUFFER *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ if (Release(b->Ref) == 0)
+ {
+ CleanupSharedBuffer(b);
+ }
+}
+void CleanupSharedBuffer(SHARED_BUFFER *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ Free(b->Data);
+
+ Free(b);
+}
+
+// Calculation of a ^ b (a to the b-th power)
+UINT Power(UINT a, UINT b)
+{
+ UINT ret, i;
+ if (a == 0)
+ {
+ return 0;
+ }
+ if (b == 0)
+ {
+ return 1;
+ }
+
+ ret = 1;
+ for (i = 0;i < b;i++)
+ {
+ ret *= a;
+ }
+
+ return ret;
+}
+
+// Search in the binary
+UINT SearchBin(void *data, UINT data_start, UINT data_size, void *key, UINT key_size)
+{
+ UINT i;
+ // Validate arguments
+ if (data == NULL || key == NULL || key_size == 0 || data_size == 0 ||
+ (data_start >= data_size) || (data_start + key_size > data_size))
+ {
+ return INFINITE;
+ }
+
+ for (i = data_start;i < (data_size - key_size + 1);i++)
+ {
+ UCHAR *p = ((UCHAR *)data) + i;
+
+ if (Cmp(p, key, key_size) == 0)
+ {
+ return i;
+ }
+ }
+
+ return INFINITE;
+}
+
+// Crash immediately
+void CrashNow()
+{
+ while (true)
+ {
+ UINT r = Rand32();
+ UCHAR *c = (UCHAR *)r;
+
+ *c = Rand8();
+ }
+}
+
+// Convert the buffer to candidate
+LIST *BufToCandidate(BUF *b)
+{
+ LIST *o;
+ UINT i;
+ UINT num;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ num = ReadBufInt(b);
+ o = NewCandidateList();
+
+ for (i = 0;i < num;i++)
+ {
+ CANDIDATE *c;
+ wchar_t *s;
+ UINT64 sec64;
+ UINT len, size;
+ sec64 = ReadBufInt64(b);
+ len = ReadBufInt(b);
+ if (len >= 65536)
+ {
+ break;
+ }
+ size = (len + 1) * 2;
+ s = ZeroMalloc(size);
+ if (ReadBuf(b, s, size) != size)
+ {
+ Free(s);
+ break;
+ }
+ else
+ {
+ c = ZeroMalloc(sizeof(CANDIDATE));
+ c->LastSelectedTime = sec64;
+ c->Str = s;
+ Add(o, c);
+ }
+ }
+
+ Sort(o);
+ return o;
+}
+
+// Convert the candidate to buffer
+BUF *CandidateToBuf(LIST *o)
+{
+ BUF *b;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBufInt(b, LIST_NUM(o));
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ CANDIDATE *c = LIST_DATA(o, i);
+ WriteBufInt64(b, c->LastSelectedTime);
+ WriteBufInt(b, UniStrLen(c->Str));
+ WriteBuf(b, c->Str, UniStrSize(c->Str));
+ }
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Adding a candidate
+void AddCandidate(LIST *o, wchar_t *str, UINT num_max)
+{
+ UINT i;
+ bool exists;
+ // Validate arguments
+ if (o == NULL || str == NULL)
+ {
+ return;
+ }
+ if (num_max == 0)
+ {
+ num_max = 0x7fffffff;
+ }
+
+ // String copy
+ str = UniCopyStr(str);
+ UniTrim(str);
+
+ exists = false;
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ CANDIDATE *c = LIST_DATA(o, i);
+ if (UniStrCmpi(c->Str, str) == 0)
+ {
+ // Update the time that an existing entry have been found
+ c->LastSelectedTime = SystemTime64();
+ exists = true;
+ break;
+ }
+ }
+
+ if (exists == false)
+ {
+ // Insert new
+ CANDIDATE *c = ZeroMalloc(sizeof(CANDIDATE));
+ c->LastSelectedTime = SystemTime64();
+ c->Str = UniCopyStr(str);
+ Insert(o, c);
+ }
+
+ // Release the string
+ Free(str);
+
+ // Check the current number of candidates.
+ // If it is more than num_max, remove from an oldest candidate sequentially.
+ if (LIST_NUM(o) > num_max)
+ {
+ while (LIST_NUM(o) > num_max)
+ {
+ UINT index = LIST_NUM(o) - 1;
+ CANDIDATE *c = LIST_DATA(o, index);
+ Delete(o, c);
+ Free(c->Str);
+ Free(c);
+ }
+ }
+}
+
+// Comparison of candidates
+int ComapreCandidate(void *p1, void *p2)
+{
+ CANDIDATE *c1, *c2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ c1 = *(CANDIDATE **)p1;
+ c2 = *(CANDIDATE **)p2;
+ if (c1 == NULL || c2 == NULL)
+ {
+ return 0;
+ }
+ if (c1->LastSelectedTime > c2->LastSelectedTime)
+ {
+ return -1;
+ }
+ else if (c1->LastSelectedTime < c2->LastSelectedTime)
+ {
+ return 1;
+ }
+ else
+ {
+ return UniStrCmpi(c1->Str, c2->Str);
+ }
+}
+
+// Release of the candidate list
+void FreeCandidateList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ CANDIDATE *c = LIST_DATA(o, i);
+ Free(c->Str);
+ Free(c);
+ }
+
+ ReleaseList(o);
+}
+
+// Creating a new candidate list
+LIST *NewCandidateList()
+{
+ return NewList(ComapreCandidate);
+}
+
+// Fill a range of memory
+void FillBytes(void *data, UINT size, UCHAR c)
+{
+ UCHAR *buf = (UCHAR *)data;
+ UINT i;
+
+ for (i = 0;i < size;i++)
+ {
+ buf[i] = c;
+ }
+}
+
+// Examine whether the specified address points all-zero area
+bool IsZero(void *data, UINT size)
+{
+ UINT i;
+ UCHAR *c = (UCHAR *)data;
+ // Validate arguments
+ if (data == NULL || size == 0)
+ {
+ return true;
+ }
+
+ for (i = 0;i < size;i++)
+ {
+ if (c[i] != 0)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Expand the data
+UINT Uncompress(void *dst, UINT dst_size, void *src, UINT src_size)
+{
+ unsigned long dst_size_long = dst_size;
+ // Validate arguments
+ if (dst == NULL || dst_size_long == 0 || src == NULL)
+ {
+ return 0;
+ }
+
+ if (uncompress(dst, &dst_size_long, src, src_size) != Z_OK)
+ {
+ return 0;
+ }
+
+ return (UINT)dst_size_long;
+}
+BUF *UncompressBuf(BUF *src_buf)
+{
+ UINT dst_size, dst_size2;
+ UCHAR *dst;
+ BUF *b;
+ // Validate arguments
+ if (src_buf == NULL)
+ {
+ return NULL;
+ }
+
+ SeekBuf(src_buf, 0, 0);
+ dst_size = ReadBufInt(src_buf);
+
+ dst = Malloc(dst_size);
+
+ dst_size2 = Uncompress(dst, dst_size, ((UCHAR *)src_buf->Buf) + sizeof(UINT), src_buf->Size - sizeof(UINT));
+
+ b = NewBuf();
+ WriteBuf(b, dst, dst_size2);
+ Free(dst);
+
+ return b;
+}
+
+// Compress the data
+UINT Compress(void *dst, UINT dst_size, void *src, UINT src_size)
+{
+ return CompressEx(dst, dst_size, src, src_size, Z_DEFAULT_COMPRESSION);
+}
+BUF *CompressBuf(BUF *src_buf)
+{
+ UINT dst_size;
+ UCHAR *dst_buf;
+ BUF *b;
+ // Validate arguments
+ if (src_buf == NULL)
+ {
+ return NULL;
+ }
+
+ dst_size = CalcCompress(src_buf->Size);
+ dst_buf = Malloc(dst_size);
+
+ dst_size = Compress(dst_buf, dst_size, src_buf->Buf, src_buf->Size);
+
+ if (dst_size == 0)
+ {
+ Free(dst_buf);
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBufInt(b, src_buf->Size);
+ WriteBuf(b, dst_buf, dst_size);
+
+ Free(dst_buf);
+
+ return b;
+}
+
+// Compress the data with options
+UINT CompressEx(void *dst, UINT dst_size, void *src, UINT src_size, UINT level)
+{
+ unsigned long dst_size_long = dst_size;
+ // Validate arguments
+ if (dst == NULL || dst_size_long == 0 || src == NULL)
+ {
+ return 0;
+ }
+
+ if (compress2(dst, &dst_size_long, src, src_size, (int)level) != Z_OK)
+ {
+ return 0;
+ }
+
+ return dst_size_long;
+}
+
+// Get the maximum size of compressed data from data of src_size
+UINT CalcCompress(UINT src_size)
+{
+ return src_size * 2 + 256;
+}
+
+// Creating a Stack
+SK *NewSk()
+{
+ return NewSkEx(false);
+}
+SK *NewSkEx(bool no_compact)
+{
+ SK *s;
+
+ s = Malloc(sizeof(SK));
+ s->lock = NewLock();
+ s->ref = NewRef();
+ s->num_item = 0;
+ s->num_reserved = INIT_NUM_RESERVED;
+ s->p = Malloc(sizeof(void *) * s->num_reserved);
+ s->no_compact = no_compact;
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackNewObj(POINTER_TO_UINT64(s), "SK", 0);
+#endif // DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_NEWSK_COUNT);
+
+ return s;
+}
+
+// Release of the stack
+void ReleaseSk(SK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (Release(s->ref) == 0)
+ {
+ CleanupSk(s);
+ }
+}
+
+// Clean up the stack
+void CleanupSk(SK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ // Memory release
+ Free(s->p);
+ DeleteLock(s->lock);
+ Free(s);
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackDeleteObj(POINTER_TO_UINT64(s));
+#endif // DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_FREESK_COUNT);
+}
+
+// Lock of the stack
+void LockSk(SK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Lock(s->lock);
+}
+
+// Unlock the stack
+void UnlockSk(SK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Unlock(s->lock);
+}
+
+// Push to the stack
+void Push(SK *s, void *p)
+{
+ UINT i;
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return;
+ }
+
+ i = s->num_item;
+ s->num_item++;
+
+ // Size expansion
+ if (s->num_item > s->num_reserved)
+ {
+ s->num_reserved = s->num_reserved * 2;
+ s->p = ReAlloc(s->p, sizeof(void *) * s->num_reserved);
+ }
+ s->p[i] = p;
+
+ // KS
+ KS_INC(KS_PUSH_COUNT);
+}
+
+// Pop from the stack
+void *Pop(SK *s)
+{
+ void *ret;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+ if (s->num_item == 0)
+ {
+ return NULL;
+ }
+ ret = s->p[s->num_item - 1];
+ s->num_item--;
+
+ // Size reduction
+ if (s->no_compact == false)
+ {
+ // Not to shrink when no_compact is true
+ if ((s->num_item * 2) <= s->num_reserved)
+ {
+ if (s->num_reserved >= (INIT_NUM_RESERVED * 2))
+ {
+ s->num_reserved = s->num_reserved / 2;
+ s->p = ReAlloc(s->p, sizeof(void *) * s->num_reserved);
+ }
+ }
+ }
+
+ // KS
+ KS_INC(KS_POP_COUNT);
+
+ return ret;
+}
+
+// Peep
+void *PeekQueue(QUEUE *q)
+{
+ void *p = NULL;
+ // Validate arguments
+ if (q == NULL)
+ {
+ return NULL;
+ }
+
+ if (q->num_item == 0)
+ {
+ // No items
+ return NULL;
+ }
+
+ // Read from the FIFO
+ PeekFifo(q->fifo, &p, sizeof(void *));
+
+ return p;
+}
+
+// Get one
+void *GetNext(QUEUE *q)
+{
+ void *p = NULL;
+ // Validate arguments
+ if (q == NULL)
+ {
+ return NULL;
+ }
+
+ if (q->num_item == 0)
+ {
+ // No items
+ return NULL;
+ }
+
+ // Read from the FIFO
+ ReadFifo(q->fifo, &p, sizeof(void *));
+ q->num_item--;
+
+ // KS
+ KS_INC(KS_GETNEXT_COUNT);
+
+ return p;
+}
+
+// Get one item from the queue (locking)
+void *GetNextWithLock(QUEUE *q)
+{
+ void *p;
+ // Validate arguments
+ if (q == NULL)
+ {
+ return NULL;
+ }
+
+ LockQueue(q);
+ {
+ p = GetNext(q);
+ }
+ UnlockQueue(q);
+
+ return p;
+}
+
+// Insert the int type in the queue
+void InsertQueueInt(QUEUE *q, UINT value)
+{
+ UINT *p;
+ // Validate arguments
+ if (q == NULL)
+ {
+ return;
+ }
+
+ p = Clone(&value, sizeof(UINT));
+
+ InsertQueue(q, p);
+}
+
+// Insert to the queue
+void InsertQueue(QUEUE *q, void *p)
+{
+ // Validate arguments
+ if (q == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Write to the FIFO
+ WriteFifo(q->fifo, &p, sizeof(void *));
+
+ q->num_item++;
+
+ // KS
+ KS_INC(KS_INSERT_QUEUE_COUNT);
+}
+
+// Insert to the queue (locking)
+void InsertQueueWithLock(QUEUE *q, void *p)
+{
+ // Validate arguments
+ if (q == NULL || p == NULL)
+ {
+ return;
+ }
+
+ LockQueue(q);
+ {
+ InsertQueue(q, p);
+ }
+ UnlockQueue(q);
+}
+
+// Lock the queue
+void LockQueue(QUEUE *q)
+{
+ // Validate arguments
+ if (q == NULL)
+ {
+ return;
+ }
+
+ Lock(q->lock);
+}
+
+// Unlock the queue
+void UnlockQueue(QUEUE *q)
+{
+ // Validate arguments
+ if (q == NULL)
+ {
+ return;
+ }
+
+ Unlock(q->lock);
+}
+
+// Release of the queue
+void ReleaseQueue(QUEUE *q)
+{
+ // Validate arguments
+ if (q == NULL)
+ {
+ return;
+ }
+
+ if (q->ref == NULL || Release(q->ref) == 0)
+ {
+ CleanupQueue(q);
+ }
+}
+
+// Clean-up the queue
+void CleanupQueue(QUEUE *q)
+{
+ // Validate arguments
+ if (q == NULL)
+ {
+ return;
+ }
+
+ // Memory release
+ ReleaseFifo(q->fifo);
+ DeleteLock(q->lock);
+ Free(q);
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackDeleteObj(POINTER_TO_UINT64(q));
+#endif // DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_FREEQUEUE_COUNT);
+}
+
+// Creating a Queue
+QUEUE *NewQueue()
+{
+ QUEUE *q;
+
+ q = ZeroMalloc(sizeof(QUEUE));
+ q->lock = NewLock();
+ q->ref = NewRef();
+ q->num_item = 0;
+ q->fifo = NewFifo();
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackNewObj(POINTER_TO_UINT64(q), "QUEUE", 0);
+#endif // DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_NEWQUEUE_COUNT);
+
+ return q;
+}
+QUEUE *NewQueueFast()
+{
+ QUEUE *q;
+
+ q = ZeroMalloc(sizeof(QUEUE));
+ q->lock = NULL;
+ q->ref = NULL;
+ q->num_item = 0;
+ q->fifo = NewFifoFast();
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackNewObj(POINTER_TO_UINT64(q), "QUEUE", 0);
+#endif // DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_NEWQUEUE_COUNT);
+
+ return q;
+}
+
+// Set the comparison function to list
+void SetCmp(LIST *o, COMPARE *cmp)
+{
+ // Validate arguments
+ if (o == NULL || cmp == NULL)
+ {
+ return;
+ }
+
+ if (o->cmp != cmp)
+ {
+ o->cmp = cmp;
+ o->sorted = false;
+ }
+}
+
+// Clone the list
+LIST *CloneList(LIST *o)
+{
+ LIST *n = NewList(o->cmp);
+
+ // Memory reallocation
+ Free(n->p);
+ n->p = ToArray(o);
+ n->num_item = n->num_reserved = LIST_NUM(o);
+ n->sorted = o->sorted;
+
+ return n;
+}
+
+// Copy the list to an array
+void CopyToArray(LIST *o, void *p)
+{
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_TOARRAY_COUNT);
+
+ Copy(p, o->p, sizeof(void *) * o->num_item);
+}
+
+// Arrange the list to an array
+void *ToArray(LIST *o)
+{
+ return ToArrayEx(o, false);
+}
+void *ToArrayEx(LIST *o, bool fast)
+{
+ void *p;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ if (fast == false)
+ {
+ p = Malloc(sizeof(void *) * LIST_NUM(o));
+ }
+ else
+ {
+ p = MallocFast(sizeof(void *) * LIST_NUM(o));
+ }
+ // Copy
+ CopyToArray(o, p);
+
+ return p;
+}
+
+// Search in the list
+void *Search(LIST *o, void *target)
+{
+ void **ret;
+ // Validate arguments
+ if (o == NULL || target == NULL)
+ {
+ return NULL;
+ }
+ if (o->cmp == NULL)
+ {
+ return NULL;
+ }
+
+ // Check the sort
+ if (o->sorted == false)
+ {
+ // Sort because it is not sorted
+ Sort(o);
+ }
+
+ ret = (void **)bsearch(&target, o->p, o->num_item, sizeof(void *),
+ (int(*)(const void *, const void *))o->cmp);
+
+ // KS
+ KS_INC(KS_SEARCH_COUNT);
+
+ if (ret != NULL)
+ {
+ return *ret;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+// Insert an item to the list (Do not insert if it already exists)
+void InsertDistinct(LIST *o, void *p)
+{
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (IsInList(o, p))
+ {
+ return;
+ }
+
+ Insert(o, p);
+}
+
+// Insert an item to the list
+void Insert(LIST *o, void *p)
+{
+ int low, high, middle;
+ UINT pos;
+ int i;
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (o->cmp == NULL)
+ {
+ // adding simply if there is no sort function
+ Add(o, p);
+ return;
+ }
+
+ // Sort immediately if it is not sorted
+ if (o->sorted == false)
+ {
+ Sort(o);
+ }
+
+ low = 0;
+ high = LIST_NUM(o) - 1;
+
+ pos = INFINITE;
+
+ while (low <= high)
+ {
+ int ret;
+
+ middle = (low + high) / 2;
+ ret = o->cmp(&(o->p[middle]), &p);
+
+ if (ret == 0)
+ {
+ pos = middle;
+ break;
+ }
+ else if (ret > 0)
+ {
+ high = middle - 1;
+ }
+ else
+ {
+ low = middle + 1;
+ }
+ }
+
+ if (pos == INFINITE)
+ {
+ pos = low;
+ }
+
+ o->num_item++;
+ if (o->num_item > o->num_reserved)
+ {
+ o->num_reserved *= 2;
+ o->p = ReAlloc(o->p, sizeof(void *) * o->num_reserved);
+ }
+
+ if (LIST_NUM(o) >= 2)
+ {
+ for (i = (LIST_NUM(o) - 2);i >= (int)pos;i--)
+ {
+ o->p[i + 1] = o->p[i];
+ }
+ }
+
+ o->p[pos] = p;
+
+ // KS
+ KS_INC(KS_INSERT_COUNT);
+}
+
+// Setting the sort flag
+void SetSortFlag(LIST *o, bool sorted)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ o->sorted = sorted;
+}
+
+// Sort the list
+void Sort(LIST *o)
+{
+ // Validate arguments
+ if (o == NULL || o->cmp == NULL)
+ {
+ return;
+ }
+
+ qsort(o->p, o->num_item, sizeof(void *), (int(*)(const void *, const void *))o->cmp);
+ o->sorted = true;
+
+ // KS
+ KS_INC(KS_SORT_COUNT);
+}
+void SortEx(LIST *o, COMPARE *cmp)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ qsort(o->p, o->num_item, sizeof(void *), (int(*)(const void *, const void *))cmp);
+ o->sorted = false;
+
+ // KS
+ KS_INC(KS_SORT_COUNT);
+}
+
+// Examine whether a certain string items are present in the list (Unicode version)
+bool IsInListUniStr(LIST *o, wchar_t *str)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ wchar_t *s = LIST_DATA(o, i);
+
+ if (UniStrCmpi(s, str) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Replace the pointer in the list
+bool ReplaceListPointer(LIST *o, void *oldptr, void *newptr)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || oldptr == NULL || newptr == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ void *p = LIST_DATA(o, i);
+
+ if (p == oldptr)
+ {
+ o->p[i] = newptr;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Examine whether a string items are present in the list
+bool IsInListStr(LIST *o, char *str)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char *s = LIST_DATA(o, i);
+
+ if (StrCmpi(s, str) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Get the pointer by scanning by UINT pointer in the list
+void *ListKeyToPointer(LIST *o, UINT key)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || key == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ void *p = LIST_DATA(o, i);
+
+ if (POINTER_TO_KEY(p) == key)
+ {
+ return p;
+ }
+ }
+
+ return NULL;
+}
+
+// Examine whether the key is present in the list
+bool IsInListKey(LIST *o, UINT key)
+{
+ void *p;
+ // Validate arguments
+ if (o == NULL || key == 0)
+ {
+ return false;
+ }
+
+ p = ListKeyToPointer(o, key);
+ if (p == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Examine whether the item exists in the list
+bool IsInList(LIST *o, void *p)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ void *q = LIST_DATA(o, i);
+ if (p == q)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Add an element to the list (Don't add if it already exists)
+void AddDistinct(LIST *o, void *p)
+{
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (IsInList(o, p))
+ {
+ return;
+ }
+
+ Add(o, p);
+}
+
+// Add an element to the list
+void Add(LIST *o, void *p)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return;
+ }
+
+ i = o->num_item;
+ o->num_item++;
+
+ if (o->num_item > o->num_reserved)
+ {
+ o->num_reserved = o->num_reserved * 2;
+ o->p = ReAlloc(o->p, sizeof(void *) * o->num_reserved);
+ }
+
+ o->p[i] = p;
+ o->sorted = false;
+
+ // KS
+ KS_INC(KS_INSERT_COUNT);
+}
+
+// Delete the elements specified by the key from the list
+bool DeleteKey(LIST *o, UINT key)
+{
+ void *p;
+ // Validate arguments
+ if (o == NULL || key == 0)
+ {
+ return false;
+ }
+
+ p = ListKeyToPointer(o, key);
+ if (p == NULL)
+ {
+ return false;
+ }
+
+ return Delete(o, p);
+}
+
+// Delete the element from the list
+bool Delete(LIST *o, void *p)
+{
+ UINT i, n;
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < o->num_item;i++)
+ {
+ if (o->p[i] == p)
+ {
+ break;
+ }
+ }
+ if (i == o->num_item)
+ {
+ return false;
+ }
+
+ n = i;
+ for (i = n;i < (o->num_item - 1);i++)
+ {
+ o->p[i] = o->p[i + 1];
+ }
+ o->num_item--;
+ if ((o->num_item * 2) <= o->num_reserved)
+ {
+ if (o->num_reserved > (INIT_NUM_RESERVED * 2))
+ {
+ o->num_reserved = o->num_reserved / 2;
+ o->p = ReAlloc(o->p, sizeof(void *) * o->num_reserved);
+ }
+ }
+
+ // KS
+ KS_INC(KS_DELETE_COUNT);
+
+ return true;
+}
+
+// Delete all elements from the list
+void DeleteAll(LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ o->num_item = 0;
+ o->num_reserved = INIT_NUM_RESERVED;
+ o->p = ReAlloc(o->p, sizeof(void *) * INIT_NUM_RESERVED);
+}
+
+// Lock the list
+void LockList(LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Lock(o->lock);
+}
+
+// Unlock the list
+void UnlockList(LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Unlock(o->lock);
+}
+
+// Release the list
+void ReleaseList(LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (o->ref == NULL || Release(o->ref) == 0)
+ {
+ CleanupList(o);
+ }
+}
+
+// Clean up the list
+void CleanupList(LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Free(o->p);
+ if (o->lock != NULL)
+ {
+ DeleteLock(o->lock);
+ }
+ Free(o);
+
+ // KS
+ KS_INC(KS_FREELIST_COUNT);
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackDeleteObj(POINTER_TO_UINT64(o));
+#endif // DONT_USE_KERNEL_STATUS
+}
+
+// Check whether the specified number is already in the list
+bool IsIntInList(LIST *o, UINT i)
+{
+ UINT j;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ UINT *p = LIST_DATA(o, j);
+
+ if (*p == i)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+bool IsInt64InList(LIST *o, UINT64 i)
+{
+ UINT j;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ UINT64 *p = LIST_DATA(o, j);
+
+ if (*p == i)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Remove all int from the interger list
+void DelAllInt(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ UINT *p = LIST_DATA(o, i);
+
+ Free(p);
+ }
+
+ DeleteAll(o);
+}
+
+// Release the integer list
+void ReleaseIntList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ UINT *p = LIST_DATA(o, i);
+
+ Free(p);
+ }
+
+ ReleaseList(o);
+}
+void ReleaseInt64List(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ UINT64 *p = LIST_DATA(o, i);
+
+ Free(p);
+ }
+
+ ReleaseList(o);
+}
+
+// Delete an integer from list
+void DelInt(LIST *o, UINT i)
+{
+ LIST *o2 = NULL;
+ UINT j;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ UINT *p = LIST_DATA(o, j);
+
+ if (*p == i)
+ {
+ if (o2 == NULL)
+ {
+ o2 = NewListFast(NULL);
+ }
+ Add(o2, p);
+ }
+ }
+
+ for (j = 0;j < LIST_NUM(o2);j++)
+ {
+ UINT *p = LIST_DATA(o2, j);
+
+ Delete(o, p);
+
+ Free(p);
+ }
+
+ if (o2 != NULL)
+ {
+ ReleaseList(o2);
+ }
+}
+void DelInt64(LIST *o, UINT64 i)
+{
+ LIST *o2 = NULL;
+ UINT j;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ UINT64 *p = LIST_DATA(o, j);
+
+ if (*p == i)
+ {
+ if (o2 == NULL)
+ {
+ o2 = NewListFast(NULL);
+ }
+ Add(o2, p);
+ }
+ }
+
+ for (j = 0;j < LIST_NUM(o2);j++)
+ {
+ UINT64 *p = LIST_DATA(o2, j);
+
+ Delete(o, p);
+
+ Free(p);
+ }
+
+ if (o2 != NULL)
+ {
+ ReleaseList(o2);
+ }
+}
+
+// Create a new list of integers
+LIST *NewIntList(bool sorted)
+{
+ LIST *o = NewList(sorted ? CompareInt : NULL);
+
+ return o;
+}
+LIST *NewInt64List(bool sorted)
+{
+ LIST *o = NewList(sorted ? CompareInt64 : NULL);
+
+ return o;
+}
+
+// Comparison of items in the list of integers
+int CompareInt(void *p1, void *p2)
+{
+ UINT *v1, *v2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+
+ v1 = *((UINT **)p1);
+ v2 = *((UINT **)p2);
+ if (v1 == NULL || v2 == NULL)
+ {
+ return 0;
+ }
+
+ return COMPARE_RET(*v1, *v2);
+}
+int CompareInt64(void *p1, void *p2)
+{
+ UINT64 *v1, *v2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+
+ v1 = *((UINT64 **)p1);
+ v2 = *((UINT64 **)p2);
+ if (v1 == NULL || v2 == NULL)
+ {
+ return 0;
+ }
+
+ return COMPARE_RET(*v1, *v2);
+}
+
+// Add an integer to the list
+void AddInt(LIST *o, UINT i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Add(o, Clone(&i, sizeof(UINT)));
+}
+void AddInt64(LIST *o, UINT64 i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Add(o, Clone(&i, sizeof(UINT64)));
+}
+void InsertInt(LIST *o, UINT i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Insert(o, Clone(&i, sizeof(UINT)));
+}
+void InsertInt64(LIST *o, UINT64 i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Insert(o, Clone(&i, sizeof(UINT64)));
+}
+
+// Add an integer to the list (no duplicates)
+void AddIntDistinct(LIST *o, UINT i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (IsIntInList(o, i) == false)
+ {
+ AddInt(o, i);
+ }
+}
+void AddInt64Distinct(LIST *o, UINT64 i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (IsInt64InList(o, i) == false)
+ {
+ AddInt64(o, i);
+ }
+}
+void InsertIntDistinct(LIST *o, UINT i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (IsIntInList(o, i) == false)
+ {
+ InsertInt(o, i);
+ }
+}
+void InsertInt64Distinct(LIST *o, UINT64 i)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (IsInt64InList(o, i) == false)
+ {
+ InsertInt64(o, i);
+ }
+}
+
+// String comparison function (Unicode)
+int CompareUniStr(void *p1, void *p2)
+{
+ wchar_t *s1, *s2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *(wchar_t **)p1;
+ s2 = *(wchar_t **)p2;
+
+ return UniStrCmp(s1, s2);
+}
+
+// Insert the string to the list
+bool InsertStr(LIST *o, char *str)
+{
+ // Validate arguments
+ if (o == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ if (Search(o, str) == NULL)
+ {
+ Insert(o, str);
+
+ return true;
+ }
+
+ return false;
+}
+
+// String comparison function
+int CompareStr(void *p1, void *p2)
+{
+ char *s1, *s2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *(char **)p1;
+ s2 = *(char **)p2;
+
+ return StrCmpi(s1, s2);
+}
+
+// Create a list with an item
+LIST *NewListSingle(void *p)
+{
+ LIST *o = NewListFast(NULL);
+
+ Add(o, p);
+
+ return o;
+}
+
+// Creating a high-speed list (without lock)
+LIST *NewListFast(COMPARE *cmp)
+{
+ return NewListEx(cmp, true);
+}
+
+// Creating a list
+LIST *NewList(COMPARE *cmp)
+{
+ return NewListEx(cmp, false);
+}
+LIST *NewListEx(COMPARE *cmp, bool fast)
+{
+ return NewListEx2(cmp, fast, false);
+}
+LIST *NewListEx2(COMPARE *cmp, bool fast, bool fast_malloc)
+{
+ LIST *o;
+
+ if (fast_malloc == false)
+ {
+ o = Malloc(sizeof(LIST));
+ }
+ else
+ {
+ o = MallocFast(sizeof(LIST));
+ }
+
+ if (fast == false)
+ {
+ o->lock = NewLock();
+ o->ref = NewRef();
+ }
+ else
+ {
+ o->lock = NULL;
+ o->ref = NULL;
+ }
+ o->num_item = 0;
+ o->num_reserved = INIT_NUM_RESERVED;
+ o->Param1 = 0;
+
+ if (fast_malloc == false)
+ {
+ o->p = Malloc(sizeof(void *) * o->num_reserved);
+ }
+ else
+ {
+ o->p = MallocFast(sizeof(void *) * o->num_reserved);
+ }
+
+ o->cmp = cmp;
+ o->sorted = true;
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackNewObj(POINTER_TO_UINT64(o), "LIST", 0);
+#endif //DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_NEWLIST_COUNT);
+
+ return o;
+}
+
+// Peek from the FIFO
+UINT PeekFifo(FIFO *f, void *p, UINT size)
+{
+ UINT read_size;
+ if (f == NULL || size == 0)
+ {
+ return 0;
+ }
+
+ // KS
+ KS_INC(KS_PEEK_FIFO_COUNT);
+
+ read_size = MIN(size, f->size);
+ if (read_size == 0)
+ {
+ return 0;
+ }
+
+ if (p != NULL)
+ {
+ Copy(p, (UCHAR *)f->p + f->pos, read_size);
+ }
+
+ return read_size;
+}
+
+// Read from the FIFO
+UINT ReadFifo(FIFO *f, void *p, UINT size)
+{
+ UINT read_size;
+ // Validate arguments
+ if (f == NULL || size == 0)
+ {
+ return 0;
+ }
+
+ read_size = MIN(size, f->size);
+ if (read_size == 0)
+ {
+ return 0;
+ }
+ if (p != NULL)
+ {
+ Copy(p, (UCHAR *)f->p + f->pos, read_size);
+ }
+ f->pos += read_size;
+ f->size -= read_size;
+
+ f->total_read_size += (UINT64)read_size;
+
+ if (f->size == 0)
+ {
+ f->pos = 0;
+ }
+
+ // Rearrange the memory
+ if (f->pos >= FIFO_INIT_MEM_SIZE &&
+ f->memsize >= f->realloc_mem_size &&
+ (f->memsize / 2) > f->size)
+ {
+ void *new_p;
+ UINT new_size;
+
+ new_size = MAX(f->memsize / 2, FIFO_INIT_MEM_SIZE);
+ new_p = Malloc(new_size);
+ Copy(new_p, (UCHAR *)f->p + f->pos, f->size);
+
+ Free(f->p);
+
+ f->memsize = new_size;
+ f->p = new_p;
+ f->pos = 0;
+ }
+
+ // KS
+ KS_INC(KS_READ_FIFO_COUNT);
+
+ return read_size;
+}
+
+// Write to the FIFO
+void WriteFifo(FIFO *f, void *p, UINT size)
+{
+ UINT i, need_size;
+ bool realloc_flag;
+ // Validate arguments
+ if (f == NULL || size == 0)
+ {
+ return;
+ }
+
+ i = f->size;
+ f->size += size;
+ need_size = f->pos + f->size;
+ realloc_flag = false;
+
+ // Memory expansion
+ while (need_size > f->memsize)
+ {
+ f->memsize = MAX(f->memsize, FIFO_INIT_MEM_SIZE) * 3;
+ realloc_flag = true;
+ }
+
+ if (realloc_flag)
+ {
+ f->p = ReAlloc(f->p, f->memsize);
+ }
+
+ // Write the data
+ if (p != NULL)
+ {
+ Copy((UCHAR *)f->p + f->pos + i, p, size);
+ }
+
+ f->total_write_size += (UINT64)size;
+
+ // KS
+ KS_INC(KS_WRITE_FIFO_COUNT);
+}
+
+// Clear the FIFO
+void ClearFifo(FIFO *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ f->size = f->pos = 0;
+ f->memsize = FIFO_INIT_MEM_SIZE;
+ f->p = ReAlloc(f->p, f->memsize);
+}
+
+// Get the current pointer of the FIFO
+UCHAR *GetFifoPointer(FIFO *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return NULL;
+ }
+
+ return ((UCHAR *)f->p) + f->pos;
+}
+UCHAR *FifoPtr(FIFO *f)
+{
+ return GetFifoPointer(f);
+}
+
+// Get the size of the FIFO
+UINT FifoSize(FIFO *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return 0;
+ }
+
+ return f->size;
+}
+
+// Lock the FIFO
+void LockFifo(FIFO *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ Lock(f->lock);
+}
+
+// Unlock the FIFO
+void UnlockFifo(FIFO *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ Unlock(f->lock);
+}
+
+// Release the FIFO
+void ReleaseFifo(FIFO *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ if (f->ref == NULL || Release(f->ref) == 0)
+ {
+ CleanupFifo(f);
+ }
+}
+
+// Clean-up the FIFO
+void CleanupFifo(FIFO *f)
+{
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ DeleteLock(f->lock);
+ Free(f->p);
+ Free(f);
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackDeleteObj(POINTER_TO_UINT64(f));
+#endif //DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_FREEFIFO_COUNT);
+}
+
+// Initialize the FIFO system
+void InitFifo()
+{
+ fifo_default_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;
+}
+
+// Create a FIFO
+FIFO *NewFifo()
+{
+ return NewFifoEx(0, false);
+}
+FIFO *NewFifoFast()
+{
+ return NewFifoEx(0, true);
+}
+FIFO *NewFifoEx(UINT realloc_mem_size, bool fast)
+{
+ FIFO *f;
+
+ // Memory allocation
+ f = ZeroMalloc(sizeof(FIFO));
+
+ if (fast == false)
+ {
+ f->lock = NewLock();
+ f->ref = NewRef();
+ }
+ else
+ {
+ f->lock = NULL;
+ f->ref = NULL;
+ }
+
+ f->size = f->pos = 0;
+ f->memsize = FIFO_INIT_MEM_SIZE;
+ f->p = Malloc(FIFO_INIT_MEM_SIZE);
+
+ if (realloc_mem_size == 0)
+ {
+ realloc_mem_size = fifo_default_realloc_mem_size;
+ }
+
+ f->realloc_mem_size = realloc_mem_size;
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackNewObj(POINTER_TO_UINT64(f), "FIFO", 0);
+#endif // DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_NEWFIFO_COUNT);
+
+ return f;
+}
+
+// Get the default memory reclaiming size of the FIFO
+UINT GetFifoDefaultReallocMemSize()
+{
+ return fifo_default_realloc_mem_size;
+}
+
+// Set the default memory reclaiming size of the FIFO
+void SetFifoDefaultReallocMemSize(UINT size)
+{
+ if (size == 0)
+ {
+ size = FIFO_REALLOC_MEM_SIZE;
+ }
+
+ fifo_default_realloc_mem_size = size;
+}
+
+// Read a buffer from a file
+BUF *FileToBuf(IO *o)
+{
+ UCHAR hash1[MD5_SIZE], hash2[MD5_SIZE];
+ UINT size;
+ void *buf;
+ BUF *b;
+
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ // Read the size
+ if (FileRead(o, &size, sizeof(size)) == false)
+ {
+ return NULL;
+ }
+ size = Endian32(size);
+
+ if (size > FileSize(o))
+ {
+ return NULL;
+ }
+
+ // Read a hash
+ if (FileRead(o, hash1, sizeof(hash1)) == false)
+ {
+ return NULL;
+ }
+
+ // Read from the buffer
+ buf = Malloc(size);
+ if (FileRead(o, buf, size) == false)
+ {
+ Free(buf);
+ return NULL;
+ }
+
+ // Take a hash
+ Hash(hash2, buf, size, false);
+
+ // Compare the hashes
+ if (Cmp(hash1, hash2, sizeof(hash1)) != 0)
+ {
+ // Hashes are different
+ Free(buf);
+ return NULL;
+ }
+
+ // Create a buffer
+ b = NewBuf();
+ WriteBuf(b, buf, size);
+ Free(buf);
+ b->Current = 0;
+
+ return b;
+}
+
+// Read a dump file into a buffer
+BUF *ReadDump(char *filename)
+{
+ return ReadDumpWithMaxSize(filename, 0);
+}
+BUF *ReadDumpWithMaxSize(char *filename, UINT max_size)
+{
+ IO *o;
+ BUF *b;
+ UINT size;
+ void *data;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ o = FileOpen(filename, false);
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ size = FileSize(o);
+
+ if (max_size != 0)
+ {
+ if (size > max_size)
+ {
+ size = max_size;
+ }
+ }
+
+ data = Malloc(size);
+ FileRead(o, data, size);
+ FileClose(o);
+
+ b = NewBuf();
+ WriteBuf(b, data, size);
+ b->Current = 0;
+ Free(data);
+
+ return b;
+}
+BUF *ReadDumpW(wchar_t *filename)
+{
+ return ReadDumpExW(filename, true);
+}
+BUF *ReadDumpExW(wchar_t *filename, bool read_lock)
+{
+ IO *o;
+ BUF *b;
+ UINT size;
+ void *data;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ o = FileOpenExW(filename, false, read_lock);
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ size = FileSize(o);
+ data = Malloc(size);
+ FileRead(o, data, size);
+ FileClose(o);
+
+ b = NewBuf();
+ WriteBuf(b, data, size);
+ b->Current = 0;
+ Free(data);
+
+ return b;
+}
+
+// Write down the data
+bool DumpDataW(void *data, UINT size, wchar_t *filename)
+{
+ IO *o;
+ // Validate arguments
+ if (filename == NULL || (size != 0 && data == NULL))
+ {
+ return false;
+ }
+
+ o = FileCreateW(filename);
+ if (o == NULL)
+ {
+ return false;
+ }
+ FileWrite(o, data, size);
+ FileClose(o);
+
+ return true;
+}
+bool DumpData(void *data, UINT size, char *filename)
+{
+ IO *o;
+ // Validate arguments
+ if (filename == NULL || (size != 0 && data == NULL))
+ {
+ return false;
+ }
+
+ o = FileCreate(filename);
+ if (o == NULL)
+ {
+ return false;
+ }
+ FileWrite(o, data, size);
+ FileClose(o);
+
+ return true;
+}
+
+// Dump the contents of the buffer to the file
+bool DumpBuf(BUF *b, char *filename)
+{
+ IO *o;
+ // Validate arguments
+ if (b == NULL || filename == NULL)
+ {
+ return false;
+ }
+
+ o = FileCreate(filename);
+ if (o == NULL)
+ {
+ return false;
+ }
+ FileWrite(o, b->Buf, b->Size);
+ FileClose(o);
+
+ return true;
+}
+bool DumpBufW(BUF *b, wchar_t *filename)
+{
+ IO *o;
+ // Validate arguments
+ if (b == NULL || filename == NULL)
+ {
+ return false;
+ }
+
+ o = FileCreateW(filename);
+ if (o == NULL)
+ {
+ return false;
+ }
+ FileWrite(o, b->Buf, b->Size);
+ FileClose(o);
+
+ return true;
+}
+
+// Write to the file only if the contents of the file is different
+bool DumpBufWIfNecessary(BUF *b, wchar_t *filename)
+{
+ BUF *now;
+ bool need = true;
+ // Validate arguments
+ if (b == NULL || filename == NULL)
+ {
+ return false;
+ }
+
+ now = ReadDumpW(filename);
+
+ if (now != NULL)
+ {
+ if (CompareBuf(now, b))
+ {
+ need = false;
+ }
+
+ FreeBuf(now);
+ }
+
+ if (need == false)
+ {
+ return true;
+ }
+ else
+ {
+ return DumpBufW(b, filename);
+ }
+}
+
+// Write the buffer to a file
+bool BufToFile(IO *o, BUF *b)
+{
+ UCHAR hash[MD5_SIZE];
+ UINT size;
+
+ // Validate arguments
+ if (o == NULL || b == NULL)
+ {
+ return false;
+ }
+
+ // Hash the data
+ Hash(hash, b->Buf, b->Size, false);
+
+ size = Endian32(b->Size);
+
+ // Write the size
+ if (FileWrite(o, &size, sizeof(size)) == false)
+ {
+ return false;
+ }
+
+ // Write a hash
+ if (FileWrite(o, hash, sizeof(hash)) == false)
+ {
+ return false;
+ }
+
+ // Write the data
+ if (FileWrite(o, b->Buf, b->Size) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Create a buffer from memory
+BUF *NewBufFromMemory(void *buf, UINT size)
+{
+ BUF *b;
+ // Validate arguments
+ if (buf == NULL && size != 0)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, buf, size);
+ SeekBufToBegin(b);
+
+ return b;
+}
+
+// Creating a buffer
+BUF *NewBuf()
+{
+ BUF *b;
+
+ // Memory allocation
+ b = Malloc(sizeof(BUF));
+ b->Buf = Malloc(INIT_BUF_SIZE);
+ b->Size = 0;
+ b->Current = 0;
+ b->SizeReserved = INIT_BUF_SIZE;
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackNewObj(POINTER_TO_UINT64(b), "BUF", 0);
+#endif // DONT_USE_KERNEL_STATUS
+
+ // KS
+ KS_INC(KS_NEWBUF_COUNT);
+ KS_INC(KS_CURRENT_BUF_COUNT);
+
+ return b;
+}
+
+// Clearing the buffer
+void ClearBuf(BUF *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ b->Size = 0;
+ b->Current = 0;
+}
+
+// Write to the buffer
+void WriteBuf(BUF *b, void *buf, UINT size)
+{
+ UINT new_size;
+ // Validate arguments
+ if (b == NULL || buf == NULL || size == 0)
+ {
+ return;
+ }
+
+ new_size = b->Current + size;
+ if (new_size > b->Size)
+ {
+ // Adjust the size
+ AdjustBufSize(b, new_size);
+ }
+ if (b->Buf != NULL)
+ {
+ Copy((UCHAR *)b->Buf + b->Current, buf, size);
+ }
+ b->Current += size;
+ b->Size = new_size;
+
+ // KS
+ KS_INC(KS_WRITE_BUF_COUNT);
+}
+
+// Append a string to the buffer
+void AddBufStr(BUF *b, char *str)
+{
+ // Validate arguments
+ if (b == NULL || str == NULL)
+ {
+ return;
+ }
+
+ WriteBuf(b, str, StrLen(str));
+}
+
+// Write a line to the buffer
+void WriteBufLine(BUF *b, char *str)
+{
+ char *crlf = "\r\n";
+ // Validate arguments
+ if (b == NULL || str == NULL)
+ {
+ return;
+ }
+
+ WriteBuf(b, str, StrLen(str));
+ WriteBuf(b, crlf, StrLen(crlf));
+}
+
+// Write a string to a buffer
+bool WriteBufStr(BUF *b, char *str)
+{
+ UINT len;
+ // Validate arguments
+ if (b == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ // String length
+ len = StrLen(str);
+ if (WriteBufInt(b, len + 1) == false)
+ {
+ return false;
+ }
+
+ // String body
+ WriteBuf(b, str, len);
+
+ return true;
+}
+
+// Read a string from the buffer
+bool ReadBufStr(BUF *b, char *str, UINT size)
+{
+ UINT len;
+ UINT read_size;
+ // Validate arguments
+ if (b == NULL || str == NULL || size == 0)
+ {
+ return false;
+ }
+
+ // Read the length of the string
+ len = ReadBufInt(b);
+ if (len == 0)
+ {
+ return false;
+ }
+ len--;
+ if (len <= (size - 1))
+ {
+ size = len + 1;
+ }
+
+ read_size = MIN(len, (size - 1));
+
+ // Read the string body
+ if (ReadBuf(b, str, read_size) != read_size)
+ {
+ return false;
+ }
+ if (read_size < len)
+ {
+ ReadBuf(b, NULL, len - read_size);
+ }
+ str[read_size] = 0;
+
+ return true;
+}
+
+// Write a 64 bit integer to the buffer
+bool WriteBufInt64(BUF *b, UINT64 value)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ value = Endian64(value);
+
+ WriteBuf(b, &value, sizeof(UINT64));
+ return true;
+}
+
+// Write an integer in the the buffer
+bool WriteBufInt(BUF *b, UINT value)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ value = Endian32(value);
+
+ WriteBuf(b, &value, sizeof(UINT));
+ return true;
+}
+
+// Write a UCHAR to the buffer
+bool WriteBufChar(BUF *b, UCHAR uc)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ WriteBuf(b, &uc, 1);
+
+ return true;
+}
+
+// Read a UCHAR from the buffer
+UCHAR ReadBufChar(BUF *b)
+{
+ UCHAR uc;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return 0;
+ }
+
+ if (ReadBuf(b, &uc, 1) != 1)
+ {
+ return 0;
+ }
+
+ return uc;
+}
+
+// Read a 64bit integer from the buffer
+UINT64 ReadBufInt64(BUF *b)
+{
+ UINT64 value;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return 0;
+ }
+
+ if (ReadBuf(b, &value, sizeof(UINT64)) != sizeof(UINT64))
+ {
+ return 0;
+ }
+ return Endian64(value);
+}
+
+// Read an integer from the buffer
+UINT ReadBufInt(BUF *b)
+{
+ UINT value;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return 0;
+ }
+
+ if (ReadBuf(b, &value, sizeof(UINT)) != sizeof(UINT))
+ {
+ return 0;
+ }
+ return Endian32(value);
+}
+
+// Write the buffer to a buffer
+void WriteBufBuf(BUF *b, BUF *bb)
+{
+ // Validate arguments
+ if (b == NULL || bb == NULL)
+ {
+ return;
+ }
+
+ WriteBuf(b, bb->Buf, bb->Size);
+}
+
+// Read into a buffer from the buffer
+BUF *ReadBufFromBuf(BUF *b, UINT size)
+{
+ BUF *ret;
+ UCHAR *data;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ data = Malloc(size);
+ if (ReadBuf(b, data, size) != size)
+ {
+ Free(data);
+ return NULL;
+ }
+
+ ret = NewBuf();
+ WriteBuf(ret, data, size);
+ SeekBuf(ret, 0, 0);
+
+ Free(data);
+
+ return ret;
+}
+
+// Read from the buffer
+UINT ReadBuf(BUF *b, void *buf, UINT size)
+{
+ UINT size_read;
+ // Validate arguments
+ if (b == NULL || size == 0)
+ {
+ return 0;
+ }
+
+ if (b->Buf == NULL)
+ {
+ Zero(buf, size);
+ return 0;
+ }
+ size_read = size;
+ if ((b->Current + size) >= b->Size)
+ {
+ size_read = b->Size - b->Current;
+ if (buf != NULL)
+ {
+ Zero((UCHAR *)buf + size_read, size - size_read);
+ }
+ }
+
+ if (buf != NULL)
+ {
+ Copy(buf, (UCHAR *)b->Buf + b->Current, size_read);
+ }
+
+ b->Current += size_read;
+
+ // KS
+ KS_INC(KS_READ_BUF_COUNT);
+
+ return size_read;
+}
+
+// Adjusting the buffer size
+void AdjustBufSize(BUF *b, UINT new_size)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ if (b->SizeReserved >= new_size)
+ {
+ return;
+ }
+
+ while (b->SizeReserved < new_size)
+ {
+ b->SizeReserved = b->SizeReserved * 2;
+ }
+ b->Buf = ReAlloc(b->Buf, b->SizeReserved);
+
+ // KS
+ KS_INC(KS_ADJUST_BUFSIZE_COUNT);
+}
+
+// Seek to the beginning of the buffer
+void SeekBufToBegin(BUF *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ SeekBuf(b, 0, 0);
+}
+
+// Seek to end of the buffer
+void SeekBufToEnd(BUF *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ SeekBuf(b, b->Size, 0);
+}
+
+// Seek of the buffer
+void SeekBuf(BUF *b, UINT offset, int mode)
+{
+ UINT new_pos;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ if (mode == 0)
+ {
+ // Absolute position
+ new_pos = offset;
+ }
+ else
+ {
+ if (mode > 0)
+ {
+ // Move Right
+ new_pos = b->Current + offset;
+ }
+ else
+ {
+ // Move Left
+ if (b->Current >= offset)
+ {
+ new_pos = b->Current - offset;
+ }
+ else
+ {
+ new_pos = 0;
+ }
+ }
+ }
+ b->Current = MAKESURE(new_pos, 0, b->Size);
+
+ KS_INC(KS_SEEK_BUF_COUNT);
+}
+
+// Free the buffer
+void FreeBuf(BUF *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ // Memory release
+ Free(b->Buf);
+ Free(b);
+
+ // KS
+ KS_INC(KS_FREEBUF_COUNT);
+ KS_DEC(KS_CURRENT_BUF_COUNT);
+
+#ifndef DONT_USE_KERNEL_STATUS
+// TrackDeleteObj(POINTER_TO_UINT64(b));
+#endif // DONT_USE_KERNEL_STATUS
+}
+
+// Compare BUFs whether two are identical
+bool CompareBuf(BUF *b1, BUF *b2)
+{
+ // Validate arguments
+ if (b1 == NULL && b2 == NULL)
+ {
+ return true;
+ }
+ if (b1 == NULL || b2 == NULL)
+ {
+ return false;
+ }
+
+ if (b1->Size != b2->Size)
+ {
+ return false;
+ }
+
+ if (Cmp(b1->Buf, b2->Buf, b1->Size) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Create a buffer from the memory area
+BUF *MemToBuf(void *data, UINT size)
+{
+ BUF *b;
+ // Validate arguments
+ if (data == NULL && size != 0)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, data, size);
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Creating a random number buffer
+BUF *RandBuf(UINT size)
+{
+ void *data = Malloc(size);
+ BUF *ret;
+
+ Rand(data, size);
+
+ ret = MemToBuf(data, size);
+
+ Free(data);
+
+ return ret;
+}
+
+// Read the rest part of the buffer
+BUF *ReadRemainBuf(BUF *b)
+{
+ UINT size;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ if (b->Size < b->Current)
+ {
+ return NULL;
+ }
+
+ size = b->Size - b->Current;
+
+ return ReadBufFromBuf(b, size);
+}
+
+// Clone the buffer
+BUF *CloneBuf(BUF *b)
+{
+ BUF *bb;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ bb = MemToBuf(b->Buf, b->Size);
+
+ return bb;
+}
+
+// Endian conversion of Unicode string
+void EndianUnicode(wchar_t *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ len = UniStrLen(str);
+
+ for (i = 0;i < len;i++)
+ {
+ str[i] = Endian16(str[i]);
+ }
+}
+
+// Endian conversion 16bit
+USHORT Endian16(USHORT src)
+{
+ int x = 1;
+ if (*((char *)&x))
+ {
+ return Swap16(src);
+ }
+ else
+ {
+ return src;
+ }
+}
+
+// Endian conversion 32bit
+UINT Endian32(UINT src)
+{
+ int x = 1;
+ if (*((char *)&x))
+ {
+ return Swap32(src);
+ }
+ else
+ {
+ return src;
+ }
+}
+
+// Endian conversion 64bit
+UINT64 Endian64(UINT64 src)
+{
+ int x = 1;
+ if (*((char *)&x))
+ {
+ return Swap64(src);
+ }
+ else
+ {
+ return src;
+ }
+}
+
+// Swap data of any
+void Swap(void *buf, UINT size)
+{
+ UCHAR *tmp, *src;
+ UINT i;
+ // Validate arguments
+ if (buf == NULL || size == 0)
+ {
+ return;
+ }
+
+ src = (UCHAR *)buf;
+ tmp = Malloc(size);
+ for (i = 0;i < size;i++)
+ {
+ tmp[size - i - 1] = src[i];
+ }
+
+ Copy(buf, tmp, size);
+ Free(buf);
+}
+
+// 16bit swap
+USHORT Swap16(USHORT value)
+{
+ USHORT r;
+ ((BYTE *)&r)[0] = ((BYTE *)&value)[1];
+ ((BYTE *)&r)[1] = ((BYTE *)&value)[0];
+ return r;
+}
+
+// 32bit swap
+UINT Swap32(UINT value)
+{
+ UINT r;
+ ((BYTE *)&r)[0] = ((BYTE *)&value)[3];
+ ((BYTE *)&r)[1] = ((BYTE *)&value)[2];
+ ((BYTE *)&r)[2] = ((BYTE *)&value)[1];
+ ((BYTE *)&r)[3] = ((BYTE *)&value)[0];
+ return r;
+}
+
+// 64-bit swap
+UINT64 Swap64(UINT64 value)
+{
+ UINT64 r;
+ ((BYTE *)&r)[0] = ((BYTE *)&value)[7];
+ ((BYTE *)&r)[1] = ((BYTE *)&value)[6];
+ ((BYTE *)&r)[2] = ((BYTE *)&value)[5];
+ ((BYTE *)&r)[3] = ((BYTE *)&value)[4];
+ ((BYTE *)&r)[4] = ((BYTE *)&value)[3];
+ ((BYTE *)&r)[5] = ((BYTE *)&value)[2];
+ ((BYTE *)&r)[6] = ((BYTE *)&value)[1];
+ ((BYTE *)&r)[7] = ((BYTE *)&value)[0];
+ return r;
+}
+
+// Base64 encode
+UINT Encode64(char *dst, char *src)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return 0;
+ }
+
+ return B64_Encode(dst, src, StrLen(src));
+}
+
+// Base64 decoding
+UINT Decode64(char *dst, char *src)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return 0;
+ }
+
+ return B64_Decode(dst, src, StrLen(src));
+}
+
+// Base64 encode
+int B64_Encode(char *set, char *source, int len)
+{
+ BYTE *src;
+ int i,j;
+ src = (BYTE *)source;
+ j = 0;
+ i = 0;
+ if (!len)
+ {
+ return 0;
+ }
+ while (TRUE)
+ {
+ if (i >= len)
+ {
+ return j;
+ }
+ if (set)
+ {
+ set[j] = B64_CodeToChar((src[i]) >> 2);
+ }
+ if (i + 1 >= len)
+ {
+ if (set)
+ {
+ set[j + 1] = B64_CodeToChar((src[i] & 0x03) << 4);
+ set[j + 2] = '=';
+ set[j + 3] = '=';
+ }
+ return j + 4;
+ }
+ if (set)
+ {
+ set[j + 1] = B64_CodeToChar(((src[i] & 0x03) << 4) + ((src[i + 1] >> 4)));
+ }
+ if (i + 2 >= len)
+ {
+ if (set)
+ {
+ set[j + 2] = B64_CodeToChar((src[i + 1] & 0x0f) << 2);
+ set[j + 3] = '=';
+ }
+ return j + 4;
+ }
+ if (set)
+ {
+ set[j + 2] = B64_CodeToChar(((src[i + 1] & 0x0f) << 2) + ((src[i + 2] >> 6)));
+ set[j + 3] = B64_CodeToChar(src[i + 2] & 0x3f);
+ }
+ i += 3;
+ j += 4;
+ }
+}
+
+// Base64 decode
+int B64_Decode(char *set, char *source, int len)
+{
+ int i,j;
+ char a1,a2,a3,a4;
+ char *src;
+ int f1,f2,f3,f4;
+ src = source;
+ i = 0;
+ j = 0;
+ while (TRUE)
+ {
+ f1 = f2 = f3 = f4 = 0;
+ if (i >= len)
+ {
+ break;
+ }
+ f1 = 1;
+ a1 = B64_CharToCode(src[i]);
+ if (a1 == -1)
+ {
+ f1 = 0;
+ }
+ if (i >= len + 1)
+ {
+ a2 = 0;
+ }
+ else
+ {
+ a2 = B64_CharToCode(src[i + 1]);
+ f2 = 1;
+ if (a2 == -1)
+ {
+ f2 = 0;
+ }
+ }
+ if (i >= len + 2)
+ {
+ a3 = 0;
+ }
+ else
+ {
+ a3 = B64_CharToCode(src[i + 2]);
+ f3 = 1;
+ if (a3 == -1)
+ {
+ f3 = 0;
+ }
+ }
+ if (i >= len + 3)
+ {
+ a4 = 0;
+ }
+ else
+ {
+ a4 = B64_CharToCode(src[i + 3]);
+ f4 = 1;
+ if (a4 == -1)
+ {
+ f4 = 0;
+ }
+ }
+ if (f1 && f2)
+ {
+ if (set)
+ {
+ set[j] = (a1 << 2) + (a2 >> 4);
+ }
+ j++;
+ }
+ if (f2 && f3)
+ {
+ if (set)
+ {
+ set[j] = (a2 << 4) + (a3 >> 2);
+ }
+ j++;
+ }
+ if (f3 && f4)
+ {
+ if (set)
+ {
+ set[j] = (a3 << 6) + a4;
+ }
+ j++;
+ }
+ i += 4;
+ }
+ return j;
+}
+
+// Base64 : Convert a code to a character
+char B64_CodeToChar(BYTE c)
+{
+ BYTE r;
+ r = '=';
+ if (c <= 0x19)
+ {
+ r = c + 'A';
+ }
+ if (c >= 0x1a && c <= 0x33)
+ {
+ r = c - 0x1a + 'a';
+ }
+ if (c >= 0x34 && c <= 0x3d)
+ {
+ r = c - 0x34 + '0';
+ }
+ if (c == 0x3e)
+ {
+ r = '+';
+ }
+ if (c == 0x3f)
+ {
+ r = '/';
+ }
+ return r;
+}
+
+// Base64 : Convert a character to a code
+char B64_CharToCode(char c)
+{
+ if (c >= 'A' && c <= 'Z')
+ {
+ return c - 'A';
+ }
+ if (c >= 'a' && c <= 'z')
+ {
+ return c - 'a' + 0x1a;
+ }
+ if (c >= '0' && c <= '9')
+ {
+ return c - '0' + 0x34;
+ }
+ if (c == '+')
+ {
+ return 0x3e;
+ }
+ if (c == '/')
+ {
+ return 0x3f;
+ }
+ if (c == '=')
+ {
+ return -1;
+ }
+ return 0;
+}
+
+// High-speed Malloc (currently not implemented)
+void *MallocFast(UINT size)
+{
+ return Malloc(size);
+}
+
+// Malloc
+void *Malloc(UINT size)
+{
+ return MallocEx(size, false);
+}
+void *MallocEx(UINT size, bool zero_clear_when_free)
+{
+ MEMTAG *tag;
+ UINT real_size;
+
+ real_size = CALC_MALLOCSIZE(size);
+
+ tag = InternalMalloc(real_size);
+
+ Zero(tag, sizeof(MEMTAG));
+ tag->Magic = MEMTAG_MAGIC;
+ tag->Size = size;
+ tag->ZeroFree = zero_clear_when_free;
+
+ return MEMTAG_TO_POINTER(tag);
+}
+
+// Get memory size
+UINT GetMemSize(void *addr)
+{
+ MEMTAG *tag;
+ // Validate arguments
+ if (IS_NULL_POINTER(addr))
+ {
+ return 0;
+ }
+
+ tag = POINTER_TO_MEMTAG(addr);
+ CheckMemTag(tag);
+
+ return tag->Size;
+}
+
+// ReAlloc
+void *ReAlloc(void *addr, UINT size)
+{
+ MEMTAG *tag;
+ bool zerofree;
+ // Validate arguments
+ if (IS_NULL_POINTER(addr))
+ {
+ return NULL;
+ }
+
+ tag = POINTER_TO_MEMTAG(addr);
+ CheckMemTag(tag);
+
+ zerofree = tag->ZeroFree;
+
+ if (tag->Size == size)
+ {
+ // No size change
+ return addr;
+ }
+ else
+ {
+ if (zerofree)
+ {
+ // Size changed (zero clearing required)
+ void *new_p = MallocEx(size, true);
+
+ if (tag->Size <= size)
+ {
+ // Size expansion
+ Copy(new_p, addr, tag->Size);
+ }
+ else
+ {
+ // Size reduction
+ Copy(new_p, addr, size);
+ }
+
+ // Release the old block
+ Free(addr);
+
+ return new_p;
+ }
+ else
+ {
+ // Size changed
+ MEMTAG *tag2 = InternalReAlloc(tag, CALC_MALLOCSIZE(size));
+
+ Zero(tag2, sizeof(MEMTAG));
+ tag2->Magic = MEMTAG_MAGIC;
+ tag2->Size = size;
+
+ return MEMTAG_TO_POINTER(tag2);
+ }
+ }
+}
+
+// Free
+void Free(void *addr)
+{
+ MEMTAG *tag;
+ // Validate arguments
+ if (IS_NULL_POINTER(addr))
+ {
+ return;
+ }
+
+ tag = POINTER_TO_MEMTAG(addr);
+ CheckMemTag(tag);
+
+ if (tag->ZeroFree)
+ {
+ // Zero clear
+ Zero(addr, tag->Size);
+ }
+
+ // Memory release
+ tag->Magic = 0;
+ InternalFree(tag);
+}
+
+// Check the memtag
+void CheckMemTag(MEMTAG *tag)
+{
+#ifndef DONT_CHECK_HEAP
+ // Validate arguments
+ if (tag == NULL)
+ {
+ AbortExitEx("CheckMemTag: tag == NULL");
+ return;
+ }
+
+ if (tag->Magic != MEMTAG_MAGIC)
+ {
+ AbortExitEx("CheckMemTag: tag->Magic != MEMTAG_MAGIC");
+ return;
+ }
+#endif // DONT_CHECK_HEAP
+}
+
+// ZeroMalloc
+void *ZeroMalloc(UINT size)
+{
+ return ZeroMallocEx(size, false);
+}
+void *ZeroMallocEx(UINT size, bool zero_clear_when_free)
+{
+ void *p = MallocEx(size, zero_clear_when_free);
+ Zero(p, size);
+ return p;
+}
+void *ZeroMallocFast(UINT size)
+{
+ void *p = MallocFast(size);
+ Zero(p, size);
+ return p;
+}
+
+// Memory allocation
+void *InternalMalloc(UINT size)
+{
+ void *addr;
+ UINT retry = 0;
+ size = MORE(size, 1);
+
+ // KS
+ KS_INC(KS_MALLOC_COUNT);
+ KS_INC(KS_TOTAL_MEM_COUNT);
+ KS_ADD(KS_TOTAL_MEM_SIZE, size);
+ KS_INC(KS_CURRENT_MEM_COUNT);
+
+ // Attempt to allocate memory until success
+ while (true)
+ {
+ if ((retry++) > MEMORY_MAX_RETRY)
+ {
+ AbortExitEx("InternalMalloc: error: malloc() failed.\n\n");
+ }
+ addr = OSMemoryAlloc(size);
+ if (addr != NULL)
+ {
+ break;
+ }
+
+ OSSleep(MEMORY_SLEEP_TIME);
+ }
+
+#ifndef DONT_USE_KERNEL_STATUS
+ TrackNewObj(POINTER_TO_UINT64(addr), "MEM", size);
+#endif //DONT_USE_KERNEL_STATUS
+
+ return addr;
+}
+
+// Memory release
+void InternalFree(void *addr)
+{
+ // Validate arguments
+ if (addr == NULL)
+ {
+ return;
+ }
+
+ // KS
+ KS_DEC(KS_CURRENT_MEM_COUNT);
+ KS_INC(KS_FREE_COUNT);
+
+#ifndef DONT_USE_KERNEL_STATUS
+ TrackDeleteObj(POINTER_TO_UINT64(addr));
+#endif // DONT_USE_KERNEL_STATUS
+
+ // Memory release
+ OSMemoryFree(addr);
+}
+
+// Memory reallocation
+void *InternalReAlloc(void *addr, UINT size)
+{
+ void *new_addr;
+ UINT retry = 0;
+ size = MORE(size, 1);
+
+ // KS
+ KS_INC(KS_REALLOC_COUNT);
+ KS_ADD(KS_TOTAL_MEM_SIZE, size);
+
+ // Attempt to allocate memory until success
+ while (true)
+ {
+ if ((retry++) > MEMORY_MAX_RETRY)
+ {
+ AbortExitEx("InternalReAlloc: error: realloc() failed.\n\n");
+ }
+ new_addr = OSMemoryReAlloc(addr, size);
+ if (new_addr != NULL)
+ {
+ break;
+ }
+
+ OSSleep(MEMORY_SLEEP_TIME);
+ }
+
+#ifndef DONT_USE_KERNEL_STATUS
+ TrackChangeObjSize((DWORD)addr, size, (DWORD)new_addr);
+#endif // DONT_USE_KERNEL_STATUS
+
+ return new_addr;
+}
+
+// Add the heading space to the memory area
+void *AddHead(void *src, UINT src_size, void *head, UINT head_size)
+{
+ void *ret;
+ UINT ret_size;
+ // Validate arguments
+ if ((src == NULL && src_size != 0) || (head == NULL && head_size != 0))
+ {
+ return NULL;
+ }
+
+ ret_size = src_size + head_size;
+
+ ret = Malloc(ret_size);
+
+ Copy(ret, head, head_size);
+
+ Copy(((UCHAR *)ret) + head_size, src, src_size);
+
+ return ret;
+}
+
+// Clone the memory area (only the tail)
+void *CloneTail(void *src, UINT src_size, UINT dst_size)
+{
+ // Validate arguments
+ if (src_size != 0 && src == NULL)
+ {
+ return NULL;
+ }
+
+ if (src_size >= dst_size)
+ {
+ return Clone(((UCHAR *)src) + (src_size - dst_size), dst_size);
+ }
+ else
+ {
+ return Clone(src, src_size);
+ }
+}
+
+// Clone the memory area
+void *Clone(void *addr, UINT size)
+{
+ void *ret;
+ // Validate arguments
+ if (addr == NULL)
+ {
+ return NULL;
+ }
+
+ ret = Malloc(size);
+ Copy(ret, addr, size);
+
+ return ret;
+}
+
+// Memory copy
+void Copy(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL || size == 0 || dst == src)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_COPY_COUNT);
+
+ memcpy(dst, src, size);
+}
+
+// Memory comparison
+int Cmp(void *p1, void *p2, UINT size)
+{
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL || size == 0)
+ {
+ return 0;
+ }
+
+ return memcmp(p1, p2, (size_t)size);
+}
+
+// Memory comparison (case-insensitive)
+int CmpCaseIgnore(void *p1, void *p2, UINT size)
+{
+ UINT i;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL || size == 0)
+ {
+ return 0;
+ }
+
+ for (i = 0;i < size;i++)
+ {
+ char c1 = (char)(*(((UCHAR *)p1) + i));
+ char c2 = (char)(*(((UCHAR *)p2) + i));
+
+ c1 = ToUpper(c1);
+ c2 = ToUpper(c2);
+
+ if (c1 != c2)
+ {
+ return COMPARE_RET(c1, c2);
+ }
+ }
+
+ return 0;
+}
+
+// Zero-clear of memory
+void Zero(void *addr, UINT size)
+{
+ // Validate arguments
+ if (addr == NULL || size == 0)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_ZERO_COUNT);
+
+ memset(addr, 0, size);
+}
+
+// Compare the string map entries
+int StrMapCmp(void *p1, void *p2)
+{
+ STRMAP_ENTRY *s1, *s2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *(STRMAP_ENTRY **)p1;
+ s2 = *(STRMAP_ENTRY **)p2;
+ if (s1 == NULL || s2 == NULL)
+ {
+ return 0;
+ }
+ return StrCmpi(s1->Name, s2->Name);
+}
+
+// Create a string map (the data that can be searched by the string)
+LIST *NewStrMap()
+{
+ return NewList(StrMapCmp);
+}
+
+// Search in string map
+void *StrMapSearch(LIST *map, char *key)
+{
+ STRMAP_ENTRY tmp, *result;
+ tmp.Name = key;
+ result = (STRMAP_ENTRY*)Search(map, &tmp);
+ if(result != NULL)
+ {
+ return result->Value;
+ }
+ return NULL;
+}
+
+// XOR the data
+void XorData(void *dst, void *src1, void *src2, UINT size)
+{
+ UINT i;
+ UCHAR *d, *c1, *c2;
+ // Validate arguments
+ if (dst == NULL || src1 == NULL || src2 == NULL || size == 0)
+ {
+ return;
+ }
+
+ d = (UCHAR *)dst;
+ c1 = (UCHAR *)src1;
+ c2 = (UCHAR *)src2;
+
+ for (i = 0;i < size;i++)
+ {
+ *d = (*c1) ^ (*c2);
+
+ d++;
+ c1++;
+ c2++;
+ }
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Memory.h b/src/Mayaqua/Memory.h
new file mode 100644
index 00000000..7ebc4dd6
--- /dev/null
+++ b/src/Mayaqua/Memory.h
@@ -0,0 +1,429 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Memory.h
+// Header of Memory.c
+
+#ifndef MEMORY_H
+#define MEMORY_H
+
+// Memory size that can be passed to the kernel at a time
+#define MAX_SEND_BUF_MEM_SIZE (10 * 1024 * 1024)
+
+// The magic number for memory tag
+#define MEMTAG_MAGIC 0x49414449
+
+#define CALC_MALLOCSIZE(size) ((MAX(size, 1)) + sizeof(MEMTAG))
+#define MEMTAG_TO_POINTER(p) ((void *)(((UCHAR *)(p)) + sizeof(MEMTAG)))
+#define POINTER_TO_MEMTAG(p) ((MEMTAG *)(((UCHAR *)(p)) - sizeof(MEMTAG)))
+#define IS_NULL_POINTER(p) (((p) == NULL) || ((POINTER_TO_UINT64(p) == (UINT64)sizeof(MEMTAG))))
+
+// Fixed size of a block of memory pool
+#define MEMPOOL_MAX_SIZE 3000
+
+
+// Memory tag
+struct MEMTAG
+{
+ UINT Magic;
+ UINT Size;
+ bool ZeroFree;
+ UINT Padding;
+};
+
+// Buffer
+struct BUF
+{
+ void *Buf;
+ UINT Size;
+ UINT SizeReserved;
+ UINT Current;
+};
+
+// FIFO
+struct FIFO
+{
+ REF *ref;
+ LOCK *lock;
+ void *p;
+ UINT pos, size, memsize;
+ UINT realloc_mem_size;
+ UINT64 total_read_size;
+ UINT64 total_write_size;
+};
+
+// List
+struct LIST
+{
+ REF *ref;
+ UINT num_item, num_reserved;
+ void **p;
+ LOCK *lock;
+ COMPARE *cmp;
+ bool sorted;
+ UINT64 Param1;
+};
+
+// Queue
+struct QUEUE
+{
+ REF *ref;
+ UINT num_item;
+ FIFO *fifo;
+ LOCK *lock;
+};
+
+// Stack
+struct SK
+{
+ REF *ref;
+ UINT num_item, num_reserved;
+ void **p;
+ LOCK *lock;
+ bool no_compact;
+};
+
+// Candidate list
+struct CANDIDATE
+{
+ wchar_t *Str; // String
+ UINT64 LastSelectedTime; // Date and time last selected
+};
+
+struct STRMAP_ENTRY
+{
+ char *Name;
+ void *Value;
+};
+
+// Shared buffer
+struct SHARED_BUFFER
+{
+ REF *Ref;
+ void *Data;
+ UINT Size;
+};
+
+// Macro
+#define LIST_DATA(o, i) (((o) != NULL) ? ((o)->p[(i)]) : NULL)
+#define LIST_NUM(o) (((o) != NULL) ? (o)->num_item : 0)
+
+
+// Function pointer type to get a hash function
+typedef UINT (GET_HASH)(void *p);
+
+// Hash list
+struct HASH_LIST
+{
+ UINT Bits;
+ UINT Size;
+ GET_HASH *GetHashProc;
+ COMPARE *CompareProc;
+ LOCK *Lock;
+ REF *Ref;
+ LIST **Entries;
+ UINT NumItems;
+ LIST *AllList;
+};
+
+// Function prototype
+HASH_LIST *NewHashList(GET_HASH *get_hash_proc, COMPARE *compare_proc, UINT bits, bool make_list);
+void ReleaseHashList(HASH_LIST *h);
+void CleanupHashList(HASH_LIST *h);
+void AddHash(HASH_LIST *h, void *p);
+bool DeleteHash(HASH_LIST *h, void *p);
+void *SearchHash(HASH_LIST *h, void *t);
+UINT CalcHashForHashList(HASH_LIST *h, void *p);
+void **HashListToArray(HASH_LIST *h, UINT *num);
+void LockHashList(HASH_LIST *h);
+void UnlockHashList(HASH_LIST *h);
+
+LIST *NewCandidateList();
+void FreeCandidateList(LIST *o);
+int ComapreCandidate(void *p1, void *p2);
+void AddCandidate(LIST *o, wchar_t *str, UINT num_max);
+BUF *CandidateToBuf(LIST *o);
+LIST *BufToCandidate(BUF *b);
+
+void *Malloc(UINT size);
+void *MallocEx(UINT size, bool zero_clear_when_free);
+void *MallocFast(UINT size);
+void *ZeroMalloc(UINT size);
+void *ZeroMallocFast(UINT size);
+void *ZeroMallocEx(UINT size, bool zero_clear_when_free);
+void *ReAlloc(void *addr, UINT size);
+void Free(void *addr);
+void CheckMemTag(MEMTAG *tag);
+UINT GetMemSize(void *addr);
+
+void *InternalMalloc(UINT size);
+void *InternalReAlloc(void *addr, UINT size);
+void InternalFree(void *addr);
+
+void Copy(void *dst, void *src, UINT size);
+int Cmp(void *p1, void *p2, UINT size);
+int CmpCaseIgnore(void *p1, void *p2, UINT size);
+void ZeroMem(void *addr, UINT size);
+void Zero(void *addr, UINT size);
+void *Clone(void *addr, UINT size);
+void *CloneTail(void *src, UINT src_size, UINT dst_size);
+void *AddHead(void *src, UINT src_size, void *head, UINT head_size);
+
+char B64_CodeToChar(BYTE c);
+char B64_CharToCode(char c);
+int B64_Encode(char *set, char *source, int len);
+int B64_Decode(char *set, char *source, int len);
+UINT Encode64(char *dst, char *src);
+UINT Decode64(char *dst, char *src);
+
+void Swap(void *buf, UINT size);
+USHORT Swap16(USHORT value);
+UINT Swap32(UINT value);
+UINT64 Swap64(UINT64 value);
+USHORT Endian16(USHORT src);
+UINT Endian32(UINT src);
+UINT64 Endian64(UINT64 src);
+void EndianUnicode(wchar_t *str);
+
+BUF *NewBuf();
+BUF *NewBufFromMemory(void *buf, UINT size);
+void ClearBuf(BUF *b);
+void WriteBuf(BUF *b, void *buf, UINT size);
+void WriteBufBuf(BUF *b, BUF *bb);
+UINT ReadBuf(BUF *b, void *buf, UINT size);
+BUF *ReadBufFromBuf(BUF *b, UINT size);
+void AdjustBufSize(BUF *b, UINT new_size);
+void SeekBuf(BUF *b, UINT offset, int mode);
+void SeekBufToEnd(BUF *b);
+void SeekBufToBegin(BUF *b);
+void FreeBuf(BUF *b);
+bool BufToFile(IO *o, BUF *b);
+BUF *FileToBuf(IO *o);
+UINT ReadBufInt(BUF *b);
+UINT64 ReadBufInt64(BUF *b);
+UCHAR ReadBufChar(BUF *b);
+bool WriteBufInt(BUF *b, UINT value);
+bool WriteBufInt64(BUF *b, UINT64 value);
+bool WriteBufChar(BUF *b, UCHAR uc);
+bool ReadBufStr(BUF *b, char *str, UINT size);
+bool WriteBufStr(BUF *b, char *str);
+void WriteBufLine(BUF *b, char *str);
+void AddBufStr(BUF *b, char *str);
+bool DumpBuf(BUF *b, char *filename);
+bool DumpBufW(BUF *b, wchar_t *filename);
+bool DumpBufWIfNecessary(BUF *b, wchar_t *filename);
+bool DumpData(void *data, UINT size, char *filename);
+bool DumpDataW(void *data, UINT size, wchar_t *filename);
+BUF *ReadDump(char *filename);
+BUF *ReadDumpWithMaxSize(char *filename, UINT max_size);
+BUF *ReadDumpW(wchar_t *filename);
+BUF *ReadDumpExW(wchar_t *filename, bool read_lock);
+BUF *CloneBuf(BUF *b);
+BUF *MemToBuf(void *data, UINT size);
+BUF *RandBuf(UINT size);
+BUF *ReadRemainBuf(BUF *b);
+bool CompareBuf(BUF *b1, BUF *b2);
+
+UINT PeekFifo(FIFO *f, void *p, UINT size);
+UINT ReadFifo(FIFO *f, void *p, UINT size);
+UCHAR *GetFifoPointer(FIFO *f);
+UCHAR *FifoPtr(FIFO *f);
+void WriteFifo(FIFO *f, void *p, UINT size);
+void ClearFifo(FIFO *f);
+UINT FifoSize(FIFO *f);
+void LockFifo(FIFO *f);
+void UnlockFifo(FIFO *f);
+void ReleaseFifo(FIFO *f);
+void CleanupFifo(FIFO *f);
+FIFO *NewFifo();
+FIFO *NewFifoFast();
+FIFO *NewFifoEx(UINT realloc_mem_size, bool fast);
+void InitFifo();
+UINT GetFifoDefaultReallocMemSize();
+void SetFifoDefaultReallocMemSize(UINT size);
+
+void *Search(LIST *o, void *target);
+void Sort(LIST *o);
+void SortEx(LIST *o, COMPARE *cmp);
+void Add(LIST *o, void *p);
+void AddDistinct(LIST *o, void *p);
+void Insert(LIST *o, void *p);
+void InsertDistinct(LIST *o, void *p);
+bool Delete(LIST *o, void *p);
+bool DeleteKey(LIST *o, UINT key);
+void DeleteAll(LIST *o);
+void LockList(LIST *o);
+void UnlockList(LIST *o);
+void ReleaseList(LIST *o);
+void CleanupList(LIST *o);
+LIST *NewList(COMPARE *cmp);
+LIST *NewListFast(COMPARE *cmp);
+LIST *NewListEx(COMPARE *cmp, bool fast);
+LIST *NewListEx2(COMPARE *cmp, bool fast, bool fast_malloc);
+LIST *NewListSingle(void *p);
+void CopyToArray(LIST *o, void *p);
+void *ToArray(LIST *o);
+void *ToArrayEx(LIST *o, bool fast);
+LIST *CloneList(LIST *o);
+void SetCmp(LIST *o, COMPARE *cmp);
+void SetSortFlag(LIST *o, bool sorted);
+int CompareStr(void *p1, void *p2);
+bool InsertStr(LIST *o, char *str);
+int CompareUniStr(void *p1, void *p2);
+bool IsInList(LIST *o, void *p);
+bool IsInListKey(LIST *o, UINT key);
+void *ListKeyToPointer(LIST *o, UINT key);
+bool IsInListStr(LIST *o, char *str);
+bool IsInListUniStr(LIST *o, wchar_t *str);
+bool ReplaceListPointer(LIST *o, void *oldptr, void *newptr);
+void AddInt(LIST *o, UINT i);
+void AddInt64(LIST *o, UINT64 i);
+void AddIntDistinct(LIST *o, UINT i);
+void AddInt64Distinct(LIST *o, UINT64 i);
+void DelInt(LIST *o, UINT i);
+void DelInt64(LIST *o, UINT64 i);
+void ReleaseIntList(LIST *o);
+void ReleaseInt64List(LIST *o);
+void DelAllInt(LIST *o);
+bool IsIntInList(LIST *o, UINT i);
+bool IsInt64InList(LIST *o, UINT64 i);
+LIST *NewIntList(bool sorted);
+LIST *NewInt64List(bool sorted);
+int CompareInt(void *p1, void *p2);
+int CompareInt64(void *p1, void *p2);
+void InsertInt(LIST *o, UINT i);
+void InsertInt64(LIST *o, UINT64 i);
+void InsertIntDistinct(LIST *o, UINT i);
+void InsertInt64Distinct(LIST *o, UINT64 i);
+
+void *GetNext(QUEUE *q);
+void *GetNextWithLock(QUEUE *q);
+void *PeekQueue(QUEUE *q);
+void InsertQueue(QUEUE *q, void *p);
+void InsertQueueWithLock(QUEUE *q, void *p);
+void InsertQueueInt(QUEUE *q, UINT value);
+void LockQueue(QUEUE *q);
+void UnlockQueue(QUEUE *q);
+void ReleaseQueue(QUEUE *q);
+void CleanupQueue(QUEUE *q);
+QUEUE *NewQueue();
+QUEUE *NewQueueFast();
+
+SK *NewSk();
+SK *NewSkEx(bool no_compact);
+void ReleaseSk(SK *s);
+void CleanupSk(SK *s);
+void LockSk(SK *s);
+void UnlockSk(SK *s);
+void Push(SK *s, void *p);
+void *Pop(SK *s);
+
+UINT Uncompress(void *dst, UINT dst_size, void *src, UINT src_size);
+UINT Compress(void *dst, UINT dst_size, void *src, UINT src_size);
+UINT CompressEx(void *dst, UINT dst_size, void *src, UINT src_size, UINT level);
+UINT CalcCompress(UINT src_size);
+BUF *CompressBuf(BUF *src_buf);
+BUF *UncompressBuf(BUF *src_buf);
+
+bool IsZero(void *data, UINT size);
+void FillBytes(void *data, UINT size, UCHAR c);
+
+LIST *NewStrMap();
+void *StrMapSearch(LIST *map, char *key);
+
+UINT SearchBin(void *data, UINT data_start, UINT data_size, void *key, UINT key_size);
+void CrashNow();
+UINT Power(UINT a, UINT b);
+
+void XorData(void *dst, void *src1, void *src2, UINT size);
+
+SHARED_BUFFER *NewSharedBuffer(void *data, UINT size);
+void ReleaseSharedBuffer(SHARED_BUFFER *b);
+void CleanupSharedBuffer(SHARED_BUFFER *b);
+
+void AppendBufUtf8(BUF *b, wchar_t *str);
+void AppendBufStr(BUF *b, char *str);
+
+#endif // MEMORY_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Microsoft.c b/src/Mayaqua/Microsoft.c
new file mode 100644
index 00000000..b03b826f
--- /dev/null
+++ b/src/Mayaqua/Microsoft.c
@@ -0,0 +1,14824 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Microsoft.c
+// For Microsoft Windows code
+// (not compiled on non-Windows environments)
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+
+#define MICROSOFT_C
+
+typedef enum _PNP_VETO_TYPE {
+ PNP_VetoTypeUnknown, // Name is unspecified
+ PNP_VetoLegacyDevice, // Name is an Instance Path
+ PNP_VetoPendingClose, // Name is an Instance Path
+ PNP_VetoWindowsApp, // Name is a Module
+ PNP_VetoWindowsService, // Name is a Service
+ PNP_VetoOutstandingOpen, // Name is an Instance Path
+ PNP_VetoDevice, // Name is an Instance Path
+ PNP_VetoDriver, // Name is a Driver Service Name
+ PNP_VetoIllegalDeviceRequest, // Name is an Instance Path
+ PNP_VetoInsufficientPower, // Name is unspecified
+ PNP_VetoNonDisableable, // Name is an Instance Path
+ PNP_VetoLegacyDriver, // Name is a Service
+ PNP_VetoInsufficientRights // Name is unspecified
+} PNP_VETO_TYPE, *PPNP_VETO_TYPE;
+
+#define _WIN32_IE 0x0600
+#define _WIN32_WINNT 0x0502
+#define WINVER 0x0502
+#define SECURITY_WIN32
+#include <winsock2.h>
+#include <windows.h>
+#include <Wintrust.h>
+#include <Softpub.h>
+#include <Iphlpapi.h>
+#include <ws2ipdef.h>
+#include <netioapi.h>
+#include <tlhelp32.h>
+#include <wincon.h>
+#include <Nb30.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <setupapi.h>
+#include <regstr.h>
+#include <process.h>
+#include <psapi.h>
+#include <wtsapi32.h>
+#include <Ntsecapi.h>
+#include <security.h>
+#include <Msi.h>
+#include <Msiquery.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <cfgmgr32.h>
+#include <sddl.h>
+#include <Aclapi.h>
+
+static MS *ms = NULL;
+
+// Function prototype
+UINT MsgBox(HWND hWnd, UINT flag, wchar_t *msg);
+UINT MsgBoxEx(HWND hWnd, UINT flag, wchar_t *msg, ...);
+void ShowTcpIpConfigUtil(HWND hWnd, bool util_mode);
+void CmTraffic(HWND hWnd);
+void CnStart();
+void InitCedar();
+void FreeCedar();
+void InitWinUi(wchar_t *software_name, char *font, UINT fontsize);
+void FreeWinUi();
+
+// Global variable
+UINT64 ms_uint64_1 = 0;
+
+// Adapter list related
+static LOCK *lock_adapter_list = NULL;
+static MS_ADAPTER_LIST *last_adapter_list = NULL;
+
+// Service related
+static SERVICE_STATUS_HANDLE ssh = NULL;
+static SERVICE_STATUS status = { 0 };
+static HANDLE service_stop_event = NULL;
+static BOOL (WINAPI *_StartServiceCtrlDispatcher)(CONST LPSERVICE_TABLE_ENTRY) = NULL;
+static SERVICE_STATUS_HANDLE (WINAPI *_RegisterServiceCtrlHandler)(LPCTSTR, LPHANDLER_FUNCTION) = NULL;
+static BOOL (WINAPI *_SetServiceStatus)(SERVICE_STATUS_HANDLE, LPSERVICE_STATUS) = NULL;
+static char g_service_name[MAX_SIZE];
+static SERVICE_FUNCTION *g_start, *g_stop;
+static bool exiting = false;
+static bool wnd_end;
+static bool is_usermode = false;
+static HICON tray_icon;
+static NOTIFYICONDATA nid;
+static NOTIFYICONDATAW nid_nt;
+static bool service_for_9x_mode = false;
+static THREAD *service_stopper_thread = NULL;
+static bool tray_inited = false;
+static HWND hWndUsermode = NULL;
+static HANDLE hLsa = NULL;
+static ULONG lsa_package_id = 0;
+static TOKEN_SOURCE lsa_token_source;
+static LOCK *vlan_lock = NULL;
+
+// msi.dll
+static HINSTANCE hMsi = NULL;
+static UINT (WINAPI *_MsiGetProductInfoW)(LPCWSTR, LPCWSTR, LPWSTR, LPDWORD) = NULL;
+static UINT (WINAPI *_MsiConfigureProductW)(LPCWSTR, int, INSTALLSTATE) = NULL;
+static INSTALLUILEVEL (WINAPI *_MsiSetInternalUI)(INSTALLUILEVEL, HWND *) = NULL;
+static INSTALLSTATE (WINAPI *_MsiLocateComponentW)(LPCWSTR, LPWSTR, LPDWORD) = NULL;
+
+#define SE_GROUP_INTEGRITY (0x00000020L)
+
+typedef enum _TOKEN_INFORMATION_CLASS_VISTA
+{
+ VistaTokenUser = 1,
+ VistaTokenGroups,
+ VistaTokenPrivileges,
+ VistaTokenOwner,
+ VistaTokenPrimaryGroup,
+ VistaTokenDefaultDacl,
+ VistaTokenSource,
+ VistaTokenType,
+ VistaTokenImpersonationLevel,
+ VistaTokenStatistics,
+ VistaTokenRestrictedSids,
+ VistaTokenSessionId,
+ VistaTokenGroupsAndPrivileges,
+ VistaTokenSessionReference,
+ VistaTokenSandBoxInert,
+ VistaTokenAuditPolicy,
+ VistaTokenOrigin,
+ VistaTokenElevationType,
+ VistaTokenLinkedToken,
+ VistaTokenElevation,
+ VistaTokenHasRestrictions,
+ VistaTokenAccessInformation,
+ VistaTokenVirtualizationAllowed,
+ VistaTokenVirtualizationEnabled,
+ VistaTokenIntegrityLevel,
+ VistaTokenUIAccess,
+ VistaTokenMandatoryPolicy,
+ VistaTokenLogonSid,
+ VistaMaxTokenInfoClass
+} TOKEN_INFORMATION_CLASS_VISTA, *PTOKEN_INFORMATION_CLASS_VISTA;
+
+typedef struct MS_MSCHAPV2_PARAMS
+{
+ wchar_t Username[MAX_SIZE];
+ wchar_t Workstation[MAX_SIZE];
+ wchar_t Domain[MAX_SIZE];
+ UCHAR ClientResponse24[24];
+ UCHAR ResponseBuffer[MAX_SIZE];
+} MS_MSCHAPV2_PARAMS;
+
+// Collect the information of the VPN software
+bool MsCollectVpnInfo(BUF *bat, char *tmpdir, char *svc_name, wchar_t *config_name, wchar_t *logdir_name)
+{
+ wchar_t *inst_dir;
+ char subkey[MAX_PATH];
+ bool ret = false;
+ wchar_t tmpdir_w[MAX_PATH];
+ // Validate arguments
+ if (bat == NULL || tmpdir == NULL || svc_name == NULL || config_name == NULL || logdir_name == NULL)
+ {
+ return false;
+ }
+
+ StrToUni(tmpdir_w, sizeof(tmpdir_w), tmpdir);
+
+ Format(subkey, sizeof(subkey), "SOFTWARE\\" GC_REG_COMPANY_NAME "\\Setup Wizard Settings\\%s", svc_name);
+ inst_dir = MsRegReadStrEx2W(REG_LOCAL_MACHINE, subkey, "InstalledDir", false, true);
+ if (UniIsEmptyStr(inst_dir) == false)
+ {
+ wchar_t config_src[MAX_PATH];
+ wchar_t config_dst[MAX_PATH];
+ wchar_t log_dir[MAX_PATH];
+ DIRLIST *dir;
+ UINT64 max_dt_file = 0;
+
+ // config file
+ CombinePathW(config_src, sizeof(config_src), inst_dir, config_name);
+ UniFormat(config_dst, sizeof(config_dst), L"%s\\%S_%s", tmpdir_w, svc_name, config_name);
+ ret = FileCopyExW(config_src, config_dst, false);
+
+ // Log file
+ CombinePathW(log_dir, sizeof(log_dir), inst_dir, logdir_name);
+
+ dir = EnumDirW(log_dir);
+
+ if (dir != NULL)
+ {
+ UINT i;
+ DIRENT *latest_log = NULL;
+
+ for (i = 0;i < dir->NumFiles;i++)
+ {
+ DIRENT *e = dir->File[i];
+
+ // Get the most recent file
+ if (max_dt_file <= e->UpdateDate)
+ {
+ max_dt_file = e->UpdateDate;
+
+ latest_log = e;
+ }
+ }
+
+ if (latest_log != NULL)
+ {
+ wchar_t fullpath[MAX_SIZE];
+ IO *f;
+
+ // Open the log file
+ CombinePathW(fullpath, sizeof(fullpath), log_dir, latest_log->FileNameW);
+ f = FileOpenExW(fullpath, false, false);
+
+ if (f != NULL)
+ {
+ UINT size = FileSize(f);
+
+ if (size >= 1)
+ {
+ UINT copy_size = 1024 * 1024;
+ UINT seek_size = 0;
+ UCHAR *buf;
+
+ if (copy_size < size)
+ {
+ seek_size = size - copy_size;
+ }
+ else
+ {
+ copy_size = size;
+ }
+
+ FileSeek(f, 0, seek_size);
+
+ buf = Malloc(copy_size + 3);
+ buf[0] = 0xEF;
+ buf[1] = 0xBB;
+ buf[2] = 0xBF;
+ if (FileRead(f, buf + 3, copy_size))
+ {
+ char log_dst_filename[MAX_PATH];
+
+ Format(log_dst_filename, sizeof(log_dst_filename), "%s\\lastlog_%s_%s",
+ tmpdir, svc_name, latest_log->FileName);
+
+ SaveFile(log_dst_filename, buf, copy_size + 3);
+ }
+
+ Free(buf);
+ }
+
+ FileClose(f);
+ }
+ }
+
+ FreeDir(dir);
+ }
+ }
+ Free(inst_dir);
+
+ return ret;
+}
+
+// Save the system information
+bool MsSaveSystemInfo(wchar_t *dst_filename)
+{
+ char tmpdir[MAX_PATH];
+ UCHAR rand_data[SHA1_SIZE];
+ char rand_str[MAX_SIZE];
+ char filename_bat[MAX_PATH];
+ BUF *bat;
+ char tmp[MAX_PATH];
+ char cmd[MAX_PATH];
+ char cmd_arg[MAX_PATH];
+ bool ret = false;
+ DIRLIST *dir;
+ UINT i;
+ // Validate arguments
+ if (dst_filename == NULL)
+ {
+ return false;
+ }
+ if (MsIsAdmin() == false || MsIsWin2000OrGreater() == false)
+ {
+ return false;
+ }
+
+ Rand(rand_data, sizeof(rand_data));
+ BinToStr(rand_str, sizeof(rand_str), rand_data, 4);
+
+ // Create a temporary directory
+ Format(tmpdir, sizeof(tmpdir), "%s\\Temp\\se_support_%s", MsGetWindowsDir(), rand_str);
+ MakeDirEx(tmpdir);
+
+ // Create a batch file
+ CombinePath(filename_bat, sizeof(filename_bat), tmpdir, "make_system_info.cmd");
+ bat = NewBuf();
+
+ Format(tmp, sizeof(tmp), "systeminfo > %s\\SystemInfo.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "ipconfig > %s\\ipconfig.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netsh dump > %s\\netsh.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "route print > %s\\route.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -nab > %s\\netstat_nab.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -nao > %s\\netstat_nao.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -na > %s\\netstat_na.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -fab > %s\\netstat_fab.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -fao > %s\\netstat_fao.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -fa > %s\\netstat_fa.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -ab > %s\\netstat_ab.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -ao > %s\\netstat_ao.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "netstat -a > %s\\netstat_a.txt", tmpdir);
+ WriteBufLine(bat, tmp);
+
+ Format(tmp, sizeof(tmp), "\"%s\\Common Files\\Microsoft Shared\\MSInfo\\msinfo32.exe\" /report %s\\SystemInfo.txt", MsGetProgramFilesDir(), tmpdir);
+ WriteBufLine(bat, tmp);
+
+ // Collect the information of the VPN software
+ MsCollectVpnInfo(bat, tmpdir, "vpnclient", L"vpn_client.config", L"client_log");
+ MsCollectVpnInfo(bat, tmpdir, "vpnserver", L"vpn_server.config", L"server_log");
+ MsCollectVpnInfo(bat, tmpdir, "vpnbridge", L"vpn_bridge.config", L"server_log");
+
+ MsCollectVpnInfo(bat, tmpdir, "sevpnclient", L"vpn_client.config", L"client_log");
+ MsCollectVpnInfo(bat, tmpdir, "sevpnserver", L"vpn_server.config", L"server_log");
+ MsCollectVpnInfo(bat, tmpdir, "sevpnbridge", L"vpn_bridge.config", L"server_log");
+
+ WriteBufLine(bat, "");
+
+ DumpBuf(bat, filename_bat);
+
+ FreeBuf(bat);
+
+ // Run the batch file
+ CombinePath(cmd, sizeof(cmd), MsGetSystem32Dir(), "cmd.exe");
+ Format(cmd_arg, sizeof(cmd_arg), "/C %s", filename_bat);
+ if (Win32Run(cmd, cmd_arg, false, true))
+ {
+ dir = EnumDir(tmpdir);
+ if (dir != NULL)
+ {
+ ZIP_PACKER *zip;
+ zip = NewZipPacker();
+
+ for (i = 0;i < dir->NumFiles;i++)
+ {
+ char *name = dir->File[i]->FileName;
+ char full[MAX_PATH];
+
+ CombinePath(full, sizeof(full), tmpdir, name);
+
+ ZipAddRealFile(zip, name, SystemTime64(), 0, full);
+ }
+ FreeDir(dir);
+
+ ret = ZipWriteW(zip, dst_filename);
+ FreeZipPacker(zip);
+ }
+ }
+
+ // Delete the temporary directory
+ dir = EnumDir(tmpdir);
+ if (dir != NULL)
+ {
+ for (i = 0;i < dir->NumFiles;i++)
+ {
+ char *name = dir->File[i]->FileName;
+ char full[MAX_PATH];
+
+ CombinePath(full, sizeof(full), tmpdir, name);
+
+ if (EndWith(full, ".txt") || EndWith(full, ".cmd") || EndWith(full, ".config") || EndWith(full, ".log"))
+ {
+ FileDelete(full);
+ }
+ }
+ FreeDir(dir);
+ }
+ DeleteDir(tmpdir);
+
+ return ret;
+}
+
+// Determine whether this is running in a VM
+bool MsIsInVmMain()
+{
+ char *bat_data = "On Error Resume Next\r\n\r\nDim str\r\n\r\nSet wmi_svc = GetObject(\"winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\cimv2\")\r\n\r\nSet items = wmi_svc.ExecQuery(\"Select * from Win32_BaseBoard\")\r\n\r\nFor Each item in items\r\n str = str & item.Manufacturer\r\nNext\r\n\r\nSet items = Nothing\r\n\r\nSet items = wmi_svc.ExecQuery(\"Select * from Win32_ComputerSystem\")\r\n\r\nFor Each item in items\r\n str = str & item.Manufacturer\r\nNext\r\n\r\nSet items = Nothing\r\n\r\nSet wmi_svc = Nothing\r\n\r\nstr = LCase(str)\r\n\r\nDim ret\r\n\r\nret = 0\r\n\r\nif InStr(str, \"microsoft corporation\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"vmware\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"virtualbox\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"virtualpc\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"xen\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"hvm\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"domu\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"kvm\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"oracle vm\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"qemu\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"parallels\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"xvm\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"virtual\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"bochs\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nwscript.quit ret\r\n\r\n";
+ wchar_t bat_filename[MAX_SIZE];
+ wchar_t cscript_exe[MAX_SIZE];
+ wchar_t tmp[MAX_SIZE];
+ void *process;
+ bool ret = false;
+
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ if (MsIsWin2000OrGreater() == false)
+ {
+ return false;
+ }
+
+ CombinePathW(bat_filename, sizeof(bat_filename), MsGetMyTempDirW(), L"detectvm.vbs");
+
+ if (DumpDataW(bat_data, StrLen(bat_data), bat_filename) == false)
+ {
+ return false;
+ }
+
+ CombinePathW(cscript_exe, sizeof(cscript_exe), MsGetSystem32DirW(), L"cscript.exe");
+
+ UniFormat(tmp, sizeof(tmp), L"\"%s\"", bat_filename);
+
+ process = Win32RunEx3W(cscript_exe, tmp, true, NULL, true);
+
+ if (process == NULL)
+ {
+ return false;
+ }
+
+ if (Win32WaitProcess(process, 30000))
+ {
+ DWORD exit_code = 0;
+
+ if (GetExitCodeProcess(process, &exit_code))
+ {
+ if (exit_code == 1)
+ {
+ ret = true;
+ }
+ }
+ }
+
+ Win32CloseProcess(process);
+
+ return ret;
+}
+bool MsIsInVm()
+{
+ static bool flag_detected = false;
+ static bool flag_is_vm = false;
+
+ if (flag_detected == false)
+ {
+ flag_is_vm = MsIsInVmMain();
+
+ flag_detected = true;
+ }
+
+ return flag_is_vm;
+}
+
+// Get the current module handle
+void *MsGetCurrentModuleHandle()
+{
+ return ms->hInst;
+}
+
+// Resource enumeration procedure
+bool CALLBACK MsEnumResourcesInternalProc(HMODULE hModule, const char *type, char *name, LONG_PTR lParam)
+{
+ LIST *o = (LIST *)lParam;
+ // Validate arguments
+ if (type == NULL || name == NULL || o == NULL)
+ {
+ return true;
+ }
+
+ Add(o, CopyStr(name));
+
+ return true;
+}
+
+// Enumeration of resources
+TOKEN_LIST *MsEnumResources(void *hModule, char *type)
+{
+ LIST *o;
+ TOKEN_LIST *ret;
+ // Validate arguments
+ if (hModule == NULL)
+ {
+ hModule = MsGetCurrentModuleHandle();
+ }
+ if (type == NULL)
+ {
+ return NullToken();
+ }
+
+ o = NewListFast(NULL);
+
+ if (EnumResourceNamesA(hModule, type, MsEnumResourcesInternalProc, (LONG_PTR)o) == false)
+ {
+ ReleaseList(o);
+ return NullToken();
+ }
+
+ ret = ListToTokenList(o);
+
+ FreeStrList(o);
+
+ return ret;
+}
+
+// Get whether the locale ID of the current user is Japanese
+bool MsIsCurrentUserLocaleIdJapanese()
+{
+ UINT lcid = MsGetUserLocaleId();
+
+ if (lcid == 1041)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Get the locale ID of the user
+UINT MsGetUserLocaleId()
+{
+ static UINT lcid_cache = 0;
+
+ if (lcid_cache == 0)
+ {
+ lcid_cache = (UINT)GetUserDefaultLCID();
+ }
+
+ return lcid_cache;
+}
+
+// Get the locale ID of the system
+UINT MsGetSystemLocaleId()
+{
+ static UINT lcid_cache = 0;
+
+ if (lcid_cache == 0)
+ {
+ lcid_cache = (UINT)GetSystemDefaultLCID();
+ }
+
+ return lcid_cache;
+}
+
+// Set a secure ACL to the specified file or directory
+bool MsSetFileSecureAcl(wchar_t *path)
+{
+ SID *sid_system;
+ SID *sid_admin;
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+ if (ms->nt == NULL)
+ {
+ return false;
+ }
+ if (ms->nt->SetNamedSecurityInfoW == NULL || ms->nt->AddAccessAllowedAceEx == NULL)
+ {
+ return false;
+ }
+
+ sid_system = MsGetSidFromAccountName("SYSTEM");
+ sid_admin = MsGetSidFromAccountName("Administrators");
+
+ if (sid_system != NULL && sid_admin != NULL)
+ {
+ UINT acl_size = 4096;
+ ACL *acl;
+
+ acl = ZeroMalloc(acl_size);
+
+ if (InitializeAcl(acl, acl_size, 2))
+ {
+ if (ms->nt->AddAccessAllowedAceEx(acl, 2, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, GENERIC_ALL, sid_system) &&
+ ms->nt->AddAccessAllowedAceEx(acl, 2, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, GENERIC_ALL, sid_admin))
+ {
+ if (ms->nt->SetNamedSecurityInfoW(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, NULL, NULL, acl, NULL) == ERROR_SUCCESS)
+ {
+ ret = true;
+ }
+ }
+ }
+
+ Free(acl);
+ }
+
+ MsFreeSid(sid_system);
+ MsFreeSid(sid_admin);
+
+ return ret;
+}
+
+// Disable the minimization function of the number of network connections by WCM
+void MsDisableWcmNetworkMinimize()
+{
+ MS_WCM_POLICY_VALUE v;
+ bool b;
+ if (ms->nt == NULL)
+ {
+ return;
+ }
+ if (ms->nt->WcmQueryProperty == NULL || ms->nt->WcmSetProperty == NULL || ms->nt->WcmFreeMemory == NULL || ms->nt->WcmGetProfileList == NULL)
+ {
+ return;
+ }
+
+ if (MsIsWindows8() == false)
+ {
+ return;
+ }
+
+ Zero(&v, sizeof(v));
+ v.fIsGroupPolicy = true;
+ v.fValue = false;
+ b = false;
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(v), (const BYTE *)&v);
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(b), (const BYTE *)&b);
+
+ Zero(&v, sizeof(v));
+ v.fIsGroupPolicy = true;
+ v.fValue = false;
+ b = false;
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(v), (const BYTE *)&v);
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(b), (const BYTE *)&b);
+
+ Zero(&v, sizeof(v));
+ v.fIsGroupPolicy = false;
+ v.fValue = false;
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(v), (const BYTE *)&v);
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(b), (const BYTE *)&b);
+
+ Zero(&v, sizeof(v));
+ v.fIsGroupPolicy = false;
+ v.fValue = false;
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(v), (const BYTE *)&v);
+ ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(b), (const BYTE *)&b);
+}
+
+// Request the MS-CHAPv2 authentication to the LSA
+bool MsPerformMsChapV2AuthByLsa(char *username, UCHAR *challenge8, UCHAR *client_response_24, UCHAR *ret_pw_hash_hash)
+{
+ bool ret = false;
+ char user[MAX_SIZE];
+ char domain[MAX_SIZE];
+ wchar_t workstation[MAX_SIZE + 1];
+ LSA_STRING origin;
+ MSV1_0_LM20_LOGON *m;
+ MS_MSCHAPV2_PARAMS *p;
+ UINT m_size;
+ DWORD sz;
+ void *profile_buffer = NULL;
+ LUID logon_id;
+ UINT profile_buffer_size = 0;
+ UINT i;
+ HANDLE hLogon = NULL;
+ QUOTA_LIMITS q;
+ char *origin_str = "SE-VPN";
+ NTSTATUS sub_status = 0;
+ // Validate arguments
+ if (username == NULL || challenge8 == NULL || client_response_24 == NULL || ret_pw_hash_hash == NULL)
+ {
+ return false;
+ }
+ if (hLsa == NULL)
+ {
+ return false;
+ }
+
+ ParseNtUsername(username, user, sizeof(user), domain, sizeof(domain), false);
+
+ // Get the machine name
+ Zero(workstation, sizeof(workstation));
+ sz = MAX_SIZE;
+ GetComputerNameW(workstation, &sz);
+
+ // Build a MSV1_0_INTERACTIVE_LOGON
+ m_size = sizeof(MSV1_0_LM20_LOGON) + sizeof(MS_MSCHAPV2_PARAMS);
+ m = ZeroMalloc(m_size);
+ p = (MS_MSCHAPV2_PARAMS *)(((UCHAR *)m) + sizeof(MSV1_0_LM20_LOGON));
+
+ StrToUni(p->Username, sizeof(p->Username), user);
+ StrToUni(p->Domain, sizeof(p->Domain), domain);
+ UniStrCpy(p->Workstation, sizeof(p->Workstation), workstation);
+ Copy(p->ClientResponse24, client_response_24, 24);
+
+ m->MessageType = MsV1_0Lm20Logon;
+
+ // User name
+ m->UserName.Length = m->UserName.MaximumLength = (USHORT)(UniStrLen(p->Username) * sizeof(wchar_t));
+ m->UserName.Buffer = p->Username;
+
+ // Workstation name
+ m->Workstation.Length = m->Workstation.MaximumLength = (USHORT)(UniStrLen(p->Workstation) * sizeof(wchar_t));
+ m->Workstation.Buffer = p->Workstation;
+
+ // Domain name
+ if (IsEmptyUniStr(p->Domain) == false)
+ {
+ m->LogonDomainName.Length = m->LogonDomainName.MaximumLength = (USHORT)(UniStrLen(p->Domain) * sizeof(wchar_t));
+ m->LogonDomainName.Buffer = p->Domain;
+ }
+
+ // Challenge
+ Copy(m->ChallengeToClient, challenge8, 8);
+
+ // Response
+ m->CaseInsensitiveChallengeResponse.Length = m->CaseInsensitiveChallengeResponse.MaximumLength = 24;
+ m->CaseInsensitiveChallengeResponse.Buffer = p->ClientResponse24;
+
+ m->CaseSensitiveChallengeResponse.Length = m->CaseSensitiveChallengeResponse.MaximumLength = sizeof(p->ResponseBuffer);
+ m->CaseSensitiveChallengeResponse.Buffer = p->ResponseBuffer;
+
+ m->ParameterControl = MSV1_0_ALLOW_MSVCHAPV2;
+
+ Zero(&origin, sizeof(origin));
+ origin.Length = origin.MaximumLength = StrLen(origin_str);
+ origin.Buffer = origin_str;
+
+ Zero(&logon_id, sizeof(logon_id));
+ Zero(&q, sizeof(q));
+
+ i = ms->nt->LsaLogonUser(hLsa, &origin, Network, lsa_package_id, m, m_size, NULL, &lsa_token_source,
+ &profile_buffer, &profile_buffer_size, &logon_id, &hLogon, &q, &sub_status);
+
+ if (i == 0)
+ {
+ if (profile_buffer != NULL)
+ {
+ MSV1_0_LM20_LOGON_PROFILE *response = (MSV1_0_LM20_LOGON_PROFILE *)profile_buffer;
+
+ Copy(ret_pw_hash_hash, response->UserSessionKey, 16);
+
+ ret = true;
+
+ ms->nt->LsaFreeReturnBuffer(profile_buffer);
+ }
+ CloseHandle(hLogon);
+ }
+
+ Free(m);
+
+ return ret;
+}
+
+// Send a pulse
+void MsSendGlobalPulse(void *p)
+{
+ HANDLE h;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ h = (HANDLE)p;
+
+ PulseEvent(h);
+}
+
+// Release a pulse
+void MsCloseGlobalPulse(void *p)
+{
+ HANDLE h;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ h = (HANDLE)p;
+
+ CloseHandle(h);
+}
+
+// Wait for arriving the pulse
+bool MsWaitForGlobalPulse(void *p, UINT timeout)
+{
+ HANDLE h;
+ UINT ret;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return false;
+ }
+ if (timeout == TIMEOUT_INFINITE)
+ {
+ timeout = INFINITE;
+ }
+
+ h = (HANDLE)p;
+
+ ret = WaitForSingleObject(h, timeout);
+
+ if (ret == WAIT_OBJECT_0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Open or create a pulse
+void *MsOpenOrCreateGlobalPulse(char *name)
+{
+ UCHAR hash[20];
+ char tmp[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ HANDLE h;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ StrCpy(tmp, sizeof(tmp), name);
+ Trim(tmp);
+ StrUpper(tmp);
+
+ HashSha1(hash, name, StrLen(name));
+
+ BinToStr(tmp, sizeof(tmp), hash, sizeof(hash));
+
+ Format(tmp2, sizeof(tmp2), "GlobalPulse_%s", tmp);
+
+ if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
+ {
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
+ GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
+ {
+ Format(tmp2, sizeof(tmp2), "Global\\GlobalPulse_%s", tmp);
+ }
+ }
+
+ h = CreateEvent(NULL, true, false, tmp2);
+
+ return (void *)h;
+}
+
+// Stop the IPsec service
+bool MsStopIPsecService()
+{
+ if (MsIsServiceRunning(MsGetIPsecServiceName()))
+ {
+ Debug("Stopping Windows Service: %s\n", MsGetIPsecServiceName());
+ if (MsStopService(MsGetIPsecServiceName()))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Start the IPsec service
+bool MsStartIPsecService()
+{
+ if (MsIsServiceRunning(MsGetIPsecServiceName()) == false)
+ {
+ Debug("Starting Windows Service: %s\n", MsGetIPsecServiceName());
+ return MsStartService(MsGetIPsecServiceName());
+ }
+
+ return false;
+}
+
+// Get the IPsec service name
+char *MsGetIPsecServiceName()
+{
+ char *svc_name = "PolicyAgent";
+
+ if (MsIsVista())
+ {
+ svc_name = "ikeext";
+ }
+
+ return svc_name;
+}
+
+// Initialize the global lock
+void *MsInitGlobalLock(char *name, bool ts_local)
+{
+ char tmp[MAX_SIZE];
+ HANDLE h;
+ // Validate arguments
+ if (name == NULL)
+ {
+ name = "default_global_lock";
+ }
+
+ if (ts_local)
+ {
+ HashInstanceNameLocal(tmp, sizeof(tmp), name);
+ }
+ else
+ {
+ HashInstanceName(tmp, sizeof(tmp), name);
+ }
+
+ h = CreateMutexA(NULL, false, tmp);
+ if (h == NULL || h == INVALID_HANDLE_VALUE)
+ {
+ return NULL;
+ }
+
+ return (void *)h;
+}
+
+// Get a global lock
+void MsGlobalLock(void *p)
+{
+ HANDLE h = (HANDLE)p;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ WaitForSingleObject(p, INFINITE);
+}
+
+// Unlock the global lock
+void MsGlobalUnlock(void *p)
+{
+ HANDLE h = (HANDLE)p;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ ReleaseMutex(h);
+}
+
+// Release the global lock
+void MsFreeGlobalLock(void *p)
+{
+ HANDLE h = (HANDLE)p;
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ CloseHandle(h);
+}
+
+
+// Set the mode not to show the errors
+void MsSetErrorModeToSilent()
+{
+ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
+}
+
+// Get the file information
+bool MsGetFileInformation(void *h, void *info)
+{
+ // Validate arguments
+ if (h == INVALID_HANDLE_VALUE || info == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ if (ms->nt->GetFileInformationByHandle == NULL)
+ {
+ return false;
+ }
+
+ return ms->nt->GetFileInformationByHandle(h, info);
+}
+
+// Set the shutdown parameters of the process
+void MsSetShutdownParameters(UINT level, UINT flag)
+{
+ if (MsIsNt() == false)
+ {
+ return;
+ }
+
+ if (ms->nt == false || ms->nt->SetProcessShutdownParameters == NULL)
+ {
+ return;
+ }
+
+ ms->nt->SetProcessShutdownParameters(level, flag);
+}
+
+// Get whether the version of the OS is Windows XP or Windows Vista or later
+bool MsIsWinXPOrWinVista()
+{
+ OS_INFO *info = GetOsInfo();
+ if (info == NULL)
+ {
+ return false;
+ }
+
+ if (OS_IS_WINDOWS_NT(info->OsType) == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) >= 3)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Write to the event log
+bool MsWriteEventLog(void *p, UINT type, wchar_t *str)
+{
+ MS_EVENTLOG *g = (MS_EVENTLOG *)p;
+ wchar_t *strings[2];
+ UINT id = 0;
+ UINT typeapi = 0;
+ // Validate arguments
+ if (g == NULL || type >= 5 || str == NULL)
+ {
+ return false;
+ }
+
+ strings[0] = str;
+
+ switch (type)
+ {
+ case MS_EVENTLOG_TYPE_INFORMATION:
+ id = MS_RC_EVENTLOG_TYPE_INFORMATION;
+ typeapi = EVENTLOG_INFORMATION_TYPE;
+ break;
+
+ case MS_EVENTLOG_TYPE_WARNING:
+ id = MS_RC_EVENTLOG_TYPE_WARNING;
+ typeapi = EVENTLOG_WARNING_TYPE;
+ break;
+
+ case MS_EVENTLOG_TYPE_ERROR:
+ id = MS_RC_EVENTLOG_TYPE_ERROR;
+ typeapi = EVENTLOG_ERROR_TYPE;
+ break;
+ }
+
+ return ms->nt->ReportEventW(g->hEventLog, typeapi, 0, id, NULL, 1, 0, strings, NULL);
+}
+
+// Release of the event log
+void MsFreeEventLog(void *p)
+{
+ MS_EVENTLOG *g = (MS_EVENTLOG *)p;
+ // Validate arguments
+ if (g == NULL)
+ {
+ return;
+ }
+
+ ms->nt->DeregisterEventSource(g->hEventLog);
+
+ Free(g);
+}
+
+// Initialization of the event log
+void *MsInitEventLog(wchar_t *src_name)
+{
+ MS_EVENTLOG *g;
+ HANDLE h;
+ wchar_t keyname[MAX_PATH];
+ char keyname_a[MAX_PATH];
+ wchar_t *exename;
+ // Validate arguments
+ if (src_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Write the key to the registry
+ exename = MsGetExeFileNameW();
+ UniFormat(keyname, sizeof(keyname),
+ L"SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application\\%s",
+ src_name);
+ UniToStr(keyname_a, sizeof(keyname_a), keyname);
+
+ MsRegWriteStrExpandExW(REG_LOCAL_MACHINE, keyname_a, "EventMessageFile",
+ exename, false);
+
+ MsRegWriteIntEx(REG_LOCAL_MACHINE, keyname_a, "TypesSupported", 7, false);
+
+ h = ms->nt->RegisterEventSourceW(NULL, src_name);
+ if (h == NULL)
+ {
+ return NULL;
+ }
+
+ g = ZeroMalloc(sizeof(MS_EVENTLOG));
+
+ g->hEventLog = h;
+
+ return (void *)g;
+}
+
+// Empty the clipboard
+void MsDeleteClipboard()
+{
+ OpenClipboard(NULL);
+
+ EmptyClipboard();
+
+ CloseClipboard();
+}
+
+// Get the process ID of the clipboard owner
+UINT MsGetClipboardOwnerProcessId()
+{
+ HWND hWnd = GetClipboardOwner();
+ DWORD pid = 0;
+
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ GetWindowThreadProcessId(hWnd, &pid);
+
+ return pid;
+}
+
+// Restart of MMCSS
+void MsRestartMMCSS()
+{
+ MsStopService("CTAudSvcService");
+ MsStopService("audiosrv");
+ MsStopService("MMCSS");
+ MsStartService("MMCSS");
+ MsStartService("audiosrv");
+ MsStartService("CTAudSvcService");
+}
+
+// Enable / disable network throttling by MMCSS
+void MsSetMMCSSNetworkThrottlingEnable(bool enable)
+{
+ UINT value;
+ if (MsIsVista() == false)
+ {
+ return;
+ }
+
+ if (enable)
+ {
+ value = 0x0000000a;
+ }
+ else
+ {
+ value = 0xffffffff;
+ }
+
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, MMCSS_PROFILE_KEYNAME, "NetworkThrottlingIndex",
+ value,
+ false, true);
+
+ MsRestartMMCSS();
+}
+
+// Examine whether the Network throttling by MMCSS is enabled
+bool MsIsMMCSSNetworkThrottlingEnabled()
+{
+ UINT value;
+ if (MsIsVista() == false)
+ {
+ return false;
+ }
+
+ if (MsRegIsKeyEx2(REG_LOCAL_MACHINE, MMCSS_PROFILE_KEYNAME, false, true) == false)
+ {
+ return false;
+ }
+
+ value = MsRegReadIntEx2(REG_LOCAL_MACHINE, MMCSS_PROFILE_KEYNAME,
+ "NetworkThrottlingIndex", false, true);
+
+ if (value == 0)
+ {
+ return false;
+ }
+
+ if (value == 0x0000000a)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Delete all the subkeys
+void MsRegDeleteSubkeys(UINT root, char *keyname, bool force32bit, bool force64bit)
+{
+ TOKEN_LIST *t;
+ UINT i;
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return;
+ }
+
+ t = MsRegEnumKeyEx2(root, keyname, force32bit, force64bit);
+ if (t == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char tmp[MAX_PATH];
+
+ Format(tmp, sizeof(tmp), "%s\\%s", keyname, t->Token[i]);
+
+ MsRegDeleteKeyEx2(root, tmp, force32bit, force64bit);
+ }
+
+ FreeToken(t);
+}
+
+// Convert the data in the buffer to the subkey of the registry
+void MsBufToRegSubkeys(UINT root, char *keyname, BUF *b, bool overwrite, bool force32bit, bool force64bit)
+{
+ UINT i;
+ UINT a;
+ UINT num_keys;
+ // Validate arguments
+ if (keyname == NULL || b == NULL)
+ {
+ return;
+ }
+
+ SeekBuf(b, 0, 0);
+
+ num_keys = ReadBufInt(b);
+
+ for (i = 0;i < num_keys;i++)
+ {
+ char subkeyname[MAX_PATH];
+ char fullkeyname[MAX_PATH];
+ UINT j;
+ UINT num_values;
+
+ Zero(subkeyname, sizeof(subkeyname));
+ ReadBufStr(b, subkeyname, sizeof(subkeyname));
+
+ Format(fullkeyname, sizeof(fullkeyname), "%s\\%s", keyname, subkeyname);
+
+ num_values = ReadBufInt(b);
+
+ for (j = 0;j < num_values;j++)
+ {
+ char valuename[MAX_PATH];
+ char data[MAX_SIZE];
+
+ Zero(valuename, sizeof(valuename));
+ ReadBufStr(b, valuename, sizeof(valuename));
+
+ a = ReadBufInt(b);
+
+ if (a == 0)
+ {
+ Zero(data, sizeof(data));
+ ReadBufStr(b, data, sizeof(data));
+
+ if (overwrite || MsRegIsValueEx2(root, fullkeyname, valuename, force32bit, force64bit) == false)
+ {
+ MsRegWriteStrEx2(root, fullkeyname, valuename, data, force32bit, force64bit);
+ }
+ }
+ else
+ {
+ if (overwrite || MsRegIsValueEx2(root, fullkeyname, valuename, force32bit, force64bit) == false)
+ {
+ MsRegWriteIntEx2(root, fullkeyname, valuename, ReadBufInt(b), force32bit, force64bit);
+ }
+ }
+ }
+ }
+}
+
+// Convert data in the registry subkey to the buffer
+BUF *MsRegSubkeysToBuf(UINT root, char *keyname, bool force32bit, bool force64bit)
+{
+ TOKEN_LIST *t;
+ UINT i;
+ BUF *b;
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return NULL;
+ }
+
+ t = MsRegEnumKeyEx2(root, keyname, force32bit, force64bit);
+
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+
+ WriteBufInt(b, t->NumTokens);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+ char tmp[MAX_PATH];
+ TOKEN_LIST *v;
+
+ Format(tmp, sizeof(tmp), "%s\\%s", keyname, name);
+
+ WriteBufStr(b, name);
+
+ v = MsRegEnumValueEx2(root, tmp, force32bit, force64bit);
+ if (v == NULL)
+ {
+ WriteBufInt(b, 0);
+ }
+ else
+ {
+ UINT j;
+
+ WriteBufInt(b, v->NumTokens);
+
+ for (j = 0;j < v->NumTokens;j++)
+ {
+ char *valuename = v->Token[j];
+ char *str;
+
+ WriteBufStr(b, valuename);
+
+ str = MsRegReadStrEx2(root, tmp, valuename, force32bit, force64bit);
+ if (str != NULL)
+ {
+ WriteBufInt(b, 0);
+ WriteBufStr(b, str);
+ Free(str);
+ }
+ else
+ {
+ WriteBufInt(b, 1);
+ WriteBufInt(b, MsRegReadIntEx2(root, tmp, valuename, force32bit, force64bit));
+ }
+ }
+
+ FreeToken(v);
+ }
+ }
+
+ FreeToken(t);
+
+ return b;
+}
+
+// Check whether the process of specified EXE file name exists
+bool MsIsProcessExists(char *exename)
+{
+ LIST *o;
+ bool ret = false;
+ UINT i;
+ // Validate arguments
+ if (exename == NULL)
+ {
+ return false;
+ }
+
+ o = MsGetProcessList();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MS_PROCESS *proc = LIST_DATA(o, i);
+ char exe[MAX_PATH];
+
+ GetFileNameFromFilePath(exe, sizeof(exe), proc->ExeFilename);
+
+ if (StrCmpi(exename, exe) == 0)
+ {
+ ret = true;
+ break;
+ }
+ }
+
+ MsFreeProcessList(o);
+
+ return ret;
+}
+bool MsIsProcessExistsW(wchar_t *exename)
+{
+ LIST *o;
+ bool ret = false;
+ UINT i;
+ // Validate arguments
+ if (exename == NULL)
+ {
+ return false;
+ }
+
+ o = MsGetProcessList();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MS_PROCESS *proc = LIST_DATA(o, i);
+ wchar_t exe[MAX_PATH];
+
+ GetFileNameFromFilePathW(exe, sizeof(exe), proc->ExeFilenameW);
+
+ if (UniStrCmpi(exename, exe) == 0)
+ {
+ ret = true;
+ break;
+ }
+ }
+
+ MsFreeProcessList(o);
+
+ return ret;
+}
+
+typedef struct _ASTAT_
+{
+ ADAPTER_STATUS adapt;
+ NAME_BUFFER NameBuff[30];
+} ASTAT, *PASTAT;
+
+// Get the precise time from the value of the high-resolution counter
+double MsGetHiResTimeSpan(UINT64 diff)
+{
+ LARGE_INTEGER t;
+ UINT64 freq;
+
+ if (QueryPerformanceFrequency(&t) == false)
+ {
+ freq = 1000ULL;
+ }
+ else
+ {
+ Copy(&freq, &t, sizeof(UINT64));
+ }
+
+ return (double)diff / (double)freq;
+}
+UINT64 MsGetHiResTimeSpanUSec(UINT64 diff)
+{
+ LARGE_INTEGER t;
+ UINT64 freq;
+
+ if (QueryPerformanceFrequency(&t) == false)
+ {
+ freq = 1000ULL;
+ }
+ else
+ {
+ Copy(&freq, &t, sizeof(UINT64));
+ }
+
+ return (UINT64)(diff) * 1000ULL * 1000ULL / (UINT64)freq;
+}
+
+// Get a high-resolution counter
+UINT64 MsGetHiResCounter()
+{
+ LARGE_INTEGER t;
+ UINT64 ret;
+
+ if (QueryPerformanceCounter(&t) == false)
+ {
+ return Tick64();
+ }
+
+ Copy(&ret, &t, sizeof(UINT64));
+
+ return ret;
+}
+
+// Whether the Welcome screen is used
+bool MsIsUseWelcomeLogin()
+{
+ UINT os_type;
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ os_type = GetOsInfo()->OsType;
+
+ if (OS_IS_WINDOWS_NT(os_type))
+ {
+ if (GET_KETA(os_type, 100) == 3)
+ {
+ if (MsRegReadIntEx2(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
+ "LogonType", false, true) == 0)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// Get a physical MAC address of the computer
+bool MsGetPhysicalMacAddress(void *address)
+{
+ // Validate arguments
+ if (address == NULL)
+ {
+ return false;
+ }
+
+ if (MsGetPhysicalMacAddressFromApi(address))
+ {
+ return true;
+ }
+
+ if (MsGetPhysicalMacAddressFromNetbios(address))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Get the physical MAC address (from API)
+bool MsGetPhysicalMacAddressFromApi(void *address)
+{
+ MS_ADAPTER_LIST *o;
+ UINT i;
+ bool ret = false;
+ // Validate arguments
+ if (address == NULL)
+ {
+ return false;
+ }
+
+ Zero(address, 6);
+
+ o = MsCreateAdapterList();
+
+ for (i = 0;i < o->Num;i++)
+ {
+ MS_ADAPTER *a = o->Adapters[i];
+
+ if (a->AddressSize == 6 && a->Mtu == 1500)
+ {
+ bool b = false;
+ switch (a->Type)
+ {
+ case MIB_IF_TYPE_OTHER:
+ case MIB_IF_TYPE_ETHERNET:
+ b = true;
+ break;
+
+ case MIB_IF_TYPE_TOKENRING:
+ case MIB_IF_TYPE_FDDI:
+ case MIB_IF_TYPE_PPP:
+ case MIB_IF_TYPE_LOOPBACK:
+ case MIB_IF_TYPE_SLIP:
+ b = false;
+ break;
+
+ default:
+ b = true;
+ break;
+ }
+
+ if (b)
+ {
+ if (SearchStrEx(a->Title, "WAN", 0, false) == INFINITE)
+ {
+ if (a->Status == MIB_IF_OPER_STATUS_CONNECTED || a->Status == MIB_IF_OPER_STATUS_OPERATIONAL)
+ {
+ if (a->AddressSize == 6)
+ {
+ if (IsZero(a->Address, 6) == false)
+ {
+ if (Cmp(address, a->Address, 6) <= 0)
+ {
+ Copy(address, a->Address, 6);
+ ret = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ MsFreeAdapterList(o);
+
+ return ret;
+}
+
+// Get the physical MAC address (from NetBIOS)
+bool MsGetPhysicalMacAddressFromNetbios(void *address)
+{
+ NCB ncb;
+ UCHAR ret;
+ LANA_ENUM lenum;
+ UINT i;
+ ASTAT adapter;
+ bool b = false;
+ // Validate arguments
+ if (address == NULL)
+ {
+ return false;
+ }
+
+ Zero(&ncb, sizeof(ncb));
+ Zero(&lenum, sizeof(lenum));
+
+ ncb.ncb_command = NCBENUM;
+ ncb.ncb_buffer = (UCHAR *)&lenum;
+ ncb.ncb_length = sizeof(lenum);
+ ret = Netbios(&ncb);
+
+ Zero(address, 6);
+
+ for (i = 0;i < lenum.length;i++)
+ {
+ Zero(&ncb, sizeof(ncb));
+ ncb.ncb_command = NCBRESET;
+ ncb.ncb_lana_num = lenum.lana[i];
+
+ ret = Netbios(&ncb);
+
+ Zero(&ncb, sizeof(ncb));
+ ncb.ncb_command = NCBASTAT;
+ ncb.ncb_lana_num = lenum.lana[i];
+
+ StrCpy(ncb.ncb_callname, sizeof(ncb.ncb_callname), "* ");
+ Zero(&adapter, sizeof(adapter));
+ ncb.ncb_buffer = (char *)&adapter;
+ ncb.ncb_length = sizeof(adapter);
+
+ ret = Netbios(&ncb);
+
+ if (ret == 0)
+ {
+ if (Cmp(address, adapter.adapt.adapter_address, 6) <= 0)
+ {
+ Copy(address, adapter.adapt.adapter_address, 6);
+ b = true;
+ }
+ }
+ }
+
+ return b;
+}
+
+// System-wide updating notification
+void MsUpdateSystem()
+{
+ static DWORD dw = 0;
+
+ SendMessageTimeoutA(HWND_BROADCAST, WM_WININICHANGE, 0, 0, SMTO_NORMAL, 1, (PDWORD_PTR)&dw);
+ SleepThread(25);
+ SendMessageTimeoutA(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)"Environment", SMTO_NORMAL, 1, (PDWORD_PTR)&dw);
+ SleepThread(25);
+ SHChangeNotify(SHCNE_GLOBALEVENTS, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT | SHCNF_NOTIFYRECURSIVE, NULL, NULL);
+ SleepThread(25);
+ SHChangeNotify(SHCNE_GLOBALEVENTS, SHCNF_IDLIST, NULL, NULL);
+ SleepThread(25);
+ SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT | SHCNF_NOTIFYRECURSIVE, NULL, NULL);
+ SleepThread(25);
+ SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
+ SleepThread(25);
+ SHChangeNotify(SHCNE_ALLEVENTS, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT | SHCNF_NOTIFYRECURSIVE, NULL, NULL);
+ SleepThread(25);
+ SHChangeNotify(SHCNE_ALLEVENTS, SHCNF_IDLIST, NULL, NULL);
+ SleepThread(25);
+}
+
+// Get whether the specified path points to a local drive
+bool MsIsLocalDrive(char *name)
+{
+ char tmp[MAX_PATH];
+ UINT ret;
+
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ Zero(tmp, sizeof(tmp));
+ InnerFilePath(tmp, sizeof(tmp), name);
+
+ if (StartWith(tmp, "\\\\"))
+ {
+ // Network directory
+ return false;
+ }
+
+ if (tmp[1] != ':' || tmp[2] != '\\')
+ {
+ // Not a drive letter
+ return false;
+ }
+
+ tmp[3] = 0;
+
+ ret = GetDriveType(tmp);
+
+ if (ret == DRIVE_REMOTE || ret == DRIVE_CDROM || ret == DRIVE_RAMDISK)
+ {
+ return false;
+ }
+
+ return true;
+}
+bool MsIsLocalDriveW(wchar_t *name)
+{
+ char name_a[MAX_PATH];
+
+ UniToStr(name_a, sizeof(name_a), name);
+
+ return MsIsLocalDrive(name_a);
+}
+
+// Get whether the specified file is locked
+bool MsIsFileLocked(char *name)
+{
+ HANDLE h;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePath(tmp, sizeof(tmp), name);
+
+ h = CreateFile(tmp, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return true;
+ }
+
+ CloseHandle(h);
+
+ return false;
+}
+bool MsIsFileLockedW(wchar_t *name)
+{
+ HANDLE h;
+ wchar_t tmp[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char name_a[MAX_SIZE];
+
+ UniToStr(name_a, sizeof(name_a), name);
+
+ return MsIsFileLocked(name_a);
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), name);
+
+ h = CreateFileW(tmp, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return true;
+ }
+
+ CloseHandle(h);
+
+ return false;
+}
+
+// Wait for the process termination
+UINT MsWaitProcessExit(void *process_handle)
+{
+ HANDLE h = (HANDLE)process_handle;
+ UINT ret = 1;
+
+ if (h == NULL)
+ {
+ return 1;
+ }
+
+ while (true)
+ {
+ WaitForSingleObject(h, INFINITE);
+
+ ret = 1;
+ if (GetExitCodeProcess(h, &ret) == false)
+ {
+ break;
+ }
+
+ if (ret != STILL_ACTIVE)
+ {
+ break;
+ }
+ }
+
+ CloseHandle(h);
+
+ return ret;
+}
+
+// Execution of the file (to get process handle)
+bool MsExecuteEx(char *exe, char *arg, void **process_handle)
+{
+ return MsExecuteEx2(exe, arg, process_handle, false);
+}
+bool MsExecuteEx2(char *exe, char *arg, void **process_handle, bool runas)
+{
+ SHELLEXECUTEINFO info;
+ HANDLE h;
+ // Validate arguments
+ if (exe == NULL || process_handle == NULL)
+ {
+ return false;
+ }
+
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.lpVerb = (runas ? "runas" : "open");
+ info.lpFile = exe;
+ info.fMask = SEE_MASK_NOCLOSEPROCESS;
+ info.lpParameters = arg;
+ info.nShow = SW_SHOWNORMAL;
+ if (ShellExecuteEx(&info) == false)
+ {
+ return false;
+ }
+
+ h = info.hProcess;
+
+ *process_handle = (void *)h;
+
+ return true;
+}
+bool MsExecuteExW(wchar_t *exe, wchar_t *arg, void **process_handle)
+{
+ return MsExecuteEx2W(exe, arg, process_handle, false);
+}
+bool MsExecuteEx2W(wchar_t *exe, wchar_t *arg, void **process_handle, bool runas)
+{
+ SHELLEXECUTEINFOW info;
+ HANDLE h;
+ // Validate arguments
+ if (exe == NULL || process_handle == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char exe_a[MAX_SIZE];
+ char arg_a[MAX_SIZE];
+
+ UniToStr(exe_a, sizeof(exe_a), exe);
+ UniToStr(arg_a, sizeof(arg_a), arg);
+
+ return MsExecuteEx(exe_a, arg_a, process_handle);
+ }
+
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.lpVerb = (runas ? L"runas" : L"open");
+ info.lpFile = exe;
+ info.fMask = SEE_MASK_NOCLOSEPROCESS;
+ info.lpParameters = arg;
+ info.nShow = SW_SHOWNORMAL;
+ if (ShellExecuteExW(&info) == false)
+ {
+ return false;
+ }
+
+ h = info.hProcess;
+
+ *process_handle = (void *)h;
+
+ return true;
+}
+
+// Close the handle
+void MsCloseHandle(void *handle)
+{
+ if (handle != NULL)
+ {
+ CloseHandle(handle);
+ }
+}
+
+// Execution of the file
+bool MsExecute(char *exe, char *arg)
+{
+ return MsExecute2(exe, arg, false);
+}
+bool MsExecute2(char *exe, char *arg, bool runas)
+{
+ DWORD d;
+ // Validate arguments
+ if (exe == NULL)
+ {
+ return false;
+ }
+
+ d = (DWORD)ShellExecuteA(NULL, (runas ? "runas" : "open"), exe, arg, MsGetExeDirName(), SW_SHOWNORMAL);
+
+ if (d > 32)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool MsExecuteW(wchar_t *exe, wchar_t *arg)
+{
+ return MsExecute2W(exe, arg, false);
+}
+bool MsExecute2W(wchar_t *exe, wchar_t *arg, bool runas)
+{
+ DWORD d;
+ // Validate arguments
+ if (exe == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char exe_a[MAX_SIZE];
+ char arg_a[MAX_SIZE];
+
+ UniToStr(exe_a, sizeof(exe_a), exe);
+ UniToStr(arg_a, sizeof(arg_a), arg);
+
+ return MsExecute(exe_a, arg_a);
+ }
+
+ d = (DWORD)ShellExecuteW(NULL, (runas ? L"runas" : L"open"), exe, arg, MsGetExeDirNameW(), SW_SHOWNORMAL);
+
+ if (d > 32)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Recursive directory creation
+void MsUniMakeDirEx(wchar_t *name)
+{
+ UINT wp;
+ wchar_t *tmp;
+ UINT i, len;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ tmp = ZeroMalloc(UniStrSize(name) * 2);
+ wp = 0;
+ len = UniStrLen(name);
+ for (i = 0;i < len;i++)
+ {
+ wchar_t c = name[i];
+
+ if (c == '\\')
+ {
+ if (UniStrCmpi(tmp, L"\\\\") != 0 && UniStrCmpi(tmp, L"\\") != 0)
+ {
+ MsUniMakeDir(tmp);
+ }
+ }
+
+ tmp[wp++] = c;
+ }
+
+ Free(tmp);
+
+ MsUniMakeDir(name);
+}
+void MsMakeDirEx(char *name)
+{
+ wchar_t *name_w = CopyStrToUni(name);
+
+ MsUniMakeDirEx(name_w);
+
+ Free(name_w);
+}
+
+// Create a directory
+bool MsUniMakeDir(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ char *s = CopyUniToStr(name);
+ bool ret = MsMakeDir(s);
+ Free(s);
+ return ret;
+ }
+
+ return CreateDirectoryW(name, NULL);
+}
+bool MsMakeDir(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ return CreateDirectoryA(name, NULL);
+}
+
+// Delete the directory
+bool MsUniDirectoryDelete(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ char *s = CopyUniToStr(name);
+ bool ret = MsDirectoryDelete(s);
+ Free(s);
+ return ret;
+ }
+
+ return RemoveDirectoryW(name);
+}
+bool MsDirectoryDelete(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ return RemoveDirectoryA(name);
+}
+
+// Delete the File
+bool MsUniFileDelete(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ bool ret;
+ char *s = CopyUniToStr(name);
+ ret = MsFileDelete(s);
+ Free(s);
+ return ret;
+ }
+
+ return DeleteFileW(name);
+}
+bool MsFileDelete(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ return DeleteFileA(name);
+}
+
+// Get whether the specified file name is a directory
+bool MsUniIsDirectory(wchar_t *name)
+{
+ DWORD ret;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ char *s = CopyUniToStr(name);
+ ret = MsIsDirectory(s);
+ Free(s);
+
+ return ret;
+ }
+
+ ret = GetFileAttributesW(name);
+ if (ret == 0xffffffff)
+ {
+ return false;
+ }
+
+ if (ret & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool MsIsDirectoryW(wchar_t *name)
+{
+ return MsUniIsDirectory(name);
+}
+bool MsIsDirectory(char *name)
+{
+ DWORD ret;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePath(tmp, sizeof(tmp), name);
+
+ ret = GetFileAttributesA(tmp);
+ if (ret == 0xffffffff)
+ {
+ return false;
+ }
+
+ if (ret & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Extract the Cabinet from the MSI file
+bool MsExtractCabFromMsi(char *msi, char *cab)
+{
+ wchar_t msi_w[MAX_PATH];
+ wchar_t cab_w[MAX_PATH];
+
+ StrToUni(msi_w, sizeof(msi_w), msi);
+ StrToUni(cab_w, sizeof(cab_w), cab);
+
+ return MsExtractCabFromMsiW(msi_w, cab_w);
+}
+bool MsExtractCabFromMsiW(wchar_t *msi, wchar_t *cab)
+{
+ BUF *b;
+ bool ret = false;
+ UINT i;
+ char sign[] = {'M', 'S', 'C', 'F', 0, 0, 0, 0,};
+ void *pointer = NULL;
+ UINT current_pos = 0;
+ UINT sign_size;
+ // Validate arguments
+ if (msi == NULL || cab == NULL)
+ {
+ return false;
+ }
+
+ // Read the MSI
+ b = ReadDumpW(msi);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (b->Size < 128)
+ {
+ FreeBuf(b);
+ return false;
+ }
+
+ sign_size = sizeof(sign);
+
+ // Search for "MSCF"
+ for (i = 0;i < (b->Size - sign_size);i++)
+ {
+ char *p = ((UCHAR *)b->Buf) + i;
+
+ if (Cmp(p, sign, sign_size) == 0)
+ {
+ pointer = p;
+ current_pos = i;
+ }
+ }
+
+ if (pointer != NULL)
+ {
+ UINT size = b->Size - current_pos;
+ BUF *b2 = NewBuf();
+
+ WriteBuf(b2, pointer, size);
+
+ ret = DumpBufW(b2, cab);
+
+ FreeBuf(b2);
+
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Retrieve a file from Cabinet file
+bool MsExtractCab(char *cab_name, char *dest_dir_name)
+{
+ wchar_t cab_name_w[MAX_SIZE];
+ wchar_t dest_dir_name_w[MAX_SIZE];
+
+ StrToUni(cab_name_w, sizeof(cab_name_w), cab_name);
+ StrToUni(dest_dir_name_w, sizeof(dest_dir_name_w), dest_dir_name);
+
+ return MsExtractCabW(cab_name_w, dest_dir_name_w);
+}
+bool MsExtractCabW(wchar_t *cab_name, wchar_t *dest_dir_name)
+{
+ wchar_t cabarc[MAX_PATH];
+ wchar_t arg[MAX_PATH * 2];
+ wchar_t tmp[MAX_PATH];
+
+ // Validate arguments
+ if (cab_name == NULL || dest_dir_name == NULL)
+ {
+ return false;
+ }
+
+ if (MsGetCabarcExeFilenameW(cabarc, sizeof(cabarc)) == false)
+ {
+ return false;
+ }
+
+ UniStrCpy(tmp, sizeof(tmp), dest_dir_name);
+ if (UniEndWith(tmp, L"\\"))
+ {
+ tmp[UniStrLen(tmp) - 1] = 0;
+ }
+
+ UniFormat(arg, sizeof(arg),
+ L"-o X \"%s\" * \"%s\"\\",
+ cab_name,
+ tmp);
+
+ MakeDirW(dest_dir_name);
+
+ if (RunW(cabarc, arg, true, true) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Extract of cabarc.exe
+bool MsGetCabarcExeFilename(char *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ ConbinePath(name, size, MsGetMyTempDir(), "cabarc.exe");
+
+ if (IsFileExists(name))
+ {
+ return true;
+ }
+
+ if (FileCopy("|cabarc.exe", name) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+bool MsGetCabarcExeFilenameW(wchar_t *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ ConbinePathW(name, size, MsGetMyTempDirW(), L"cabarc.exe");
+
+ if (IsFileExistsW(name))
+ {
+ return true;
+ }
+
+ if (FileCopyW(L"|cabarc.exe", name) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Extract the Cabinet file from EXE file
+bool MsExtractCabinetFileFromExe(char *exe, char *cab)
+{
+ BUF *b;
+ // Validate arguments
+ if (exe == NULL || cab == NULL)
+ {
+ return false;
+ }
+
+ b = MsExtractResourceFromExe(exe, RT_RCDATA, "CABINET");
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (DumpBuf(b, cab) == false)
+ {
+ FreeBuf(b);
+
+ return false;
+ }
+
+ FreeBuf(b);
+
+ return true;
+}
+bool MsExtractCabinetFileFromExeW(wchar_t *exe, wchar_t *cab)
+{
+ BUF *b;
+ // Validate arguments
+ if (exe == NULL || cab == NULL)
+ {
+ return false;
+ }
+
+ b = MsExtractResourceFromExeW(exe, RT_RCDATA, "CABINET");
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (DumpBufW(b, cab) == false)
+ {
+ FreeBuf(b);
+
+ return false;
+ }
+
+ FreeBuf(b);
+
+ return true;
+}
+
+// Extract the resource from EXE file
+BUF *MsExtractResourceFromExe(char *exe, char *type, char *name)
+{
+ HINSTANCE h;
+ HRSRC hr;
+ HGLOBAL hg;
+ UINT size;
+ void *data;
+ BUF *buf;
+ // Validate arguments
+ if (exe == NULL || type == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ h = LoadLibraryExA(exe, NULL, LOAD_LIBRARY_AS_DATAFILE);
+ if (h == NULL)
+ {
+ return NULL;
+ }
+
+ hr = FindResourceA(h, name, type);
+ if (hr == NULL)
+ {
+ FreeLibrary(h);
+ return NULL;
+ }
+
+ hg = LoadResource(h, hr);
+ if (hg == NULL)
+ {
+ FreeLibrary(h);
+ return NULL;
+ }
+
+ size = SizeofResource(h, hr);
+ data = (void *)LockResource(hg);
+
+ buf = NewBuf();
+ WriteBuf(buf, data, size);
+
+ FreeResource(hg);
+ FreeLibrary(h);
+
+ SeekBuf(buf, 0, 0);
+
+ return buf;
+}
+BUF *MsExtractResourceFromExeW(wchar_t *exe, char *type, char *name)
+{
+ HINSTANCE h;
+ HRSRC hr;
+ HGLOBAL hg;
+ UINT size;
+ void *data;
+ BUF *buf;
+ // Validate arguments
+ if (exe == NULL || type == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsNt() == false)
+ {
+ char exe_a[MAX_PATH];
+
+ UniToStr(exe_a, sizeof(exe_a), exe);
+
+ return MsExtractResourceFromExe(exe_a, type, name);
+ }
+
+ h = LoadLibraryExW(exe, NULL, LOAD_LIBRARY_AS_DATAFILE);
+ if (h == NULL)
+ {
+ return NULL;
+ }
+
+ hr = FindResource(h, name, type);
+ if (hr == NULL)
+ {
+ FreeLibrary(h);
+ return NULL;
+ }
+
+ hg = LoadResource(h, hr);
+ if (hg == NULL)
+ {
+ FreeLibrary(h);
+ return NULL;
+ }
+
+ size = SizeofResource(h, hr);
+ data = (void *)LockResource(hg);
+
+ buf = NewBuf();
+ WriteBuf(buf, data, size);
+
+ FreeResource(hg);
+ FreeLibrary(h);
+
+ SeekBuf(buf, 0, 0);
+
+ return buf;
+}
+
+// Get the version information of the file
+bool MsGetFileVersion(char *name, UINT *v1, UINT *v2, UINT *v3, UINT *v4)
+{
+ void *data;
+ UINT size;
+ DWORD h;
+ bool ret = false;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ h = 0;
+ size = GetFileVersionInfoSize(name, &h);
+ if (size == 0)
+ {
+ return false;
+ }
+
+ data = ZeroMalloc(size);
+
+ if (GetFileVersionInfoA(name, 0, size, data))
+ {
+ VS_FIXEDFILEINFO *info = NULL;
+ UINT info_size = 0;
+ if (VerQueryValueA(data, "\\", &info, &info_size))
+ {
+ if (v1 != NULL)
+ {
+ *v1 = HIWORD(info->dwFileVersionMS);
+ }
+
+ if (v2 != NULL)
+ {
+ *v2 = LOWORD(info->dwFileVersionMS);
+ }
+
+ if (v3 != NULL)
+ {
+ *v3 = HIWORD(info->dwFileVersionLS);
+ }
+
+ if (v4 != NULL)
+ {
+ *v4 = LOWORD(info->dwFileVersionLS);
+ }
+
+ ret = true;
+ }
+ }
+
+ Free(data);
+
+ return ret;
+}
+bool MsGetFileVersionW(wchar_t *name, UINT *v1, UINT *v2, UINT *v3, UINT *v4)
+{
+ void *data;
+ UINT size;
+ DWORD h;
+ bool ret = false;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char name_a[MAX_PATH];
+
+ UniToStr(name_a, sizeof(name_a), name);
+
+ return MsGetFileVersion(name_a, v1, v2, v3, v4);
+ }
+
+ h = 0;
+ size = GetFileVersionInfoSizeW(name, &h);
+ if (size == 0)
+ {
+ return false;
+ }
+
+ data = ZeroMalloc(size);
+
+ if (GetFileVersionInfoW(name, 0, size, data))
+ {
+ VS_FIXEDFILEINFO *info = NULL;
+ UINT info_size = 0;
+ if (VerQueryValue(data, "\\", &info, &info_size))
+ {
+ if (v1 != NULL)
+ {
+ *v1 = HIWORD(info->dwFileVersionMS);
+ }
+
+ if (v2 != NULL)
+ {
+ *v2 = LOWORD(info->dwFileVersionMS);
+ }
+
+ if (v3 != NULL)
+ {
+ *v3 = HIWORD(info->dwFileVersionLS);
+ }
+
+ if (v4 != NULL)
+ {
+ *v4 = LOWORD(info->dwFileVersionLS);
+ }
+
+ ret = true;
+ }
+ }
+
+ Free(data);
+
+ return ret;
+}
+
+// Set the file to a hidden file
+void MsSetFileToHidden(char *name)
+{
+ char tmp[MAX_PATH];
+ DWORD d;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ NormalizePath(tmp, sizeof(tmp), name);
+
+ d = GetFileAttributesA(tmp);
+ if (d != INVALID_FILE_ATTRIBUTES)
+ {
+ d |= FILE_ATTRIBUTE_HIDDEN;
+
+ SetFileAttributesA(tmp, d);
+ }
+}
+void MsSetFileToHiddenW(wchar_t *name)
+{
+ wchar_t tmp[MAX_PATH];
+ DWORD d;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ if (IsNt() == false)
+ {
+ char name_a[MAX_SIZE];
+
+ UniToStr(name_a, sizeof(name_a), name);
+
+ MsSetFileToHidden(name_a);
+
+ return;
+ }
+
+ NormalizePathW(tmp, sizeof(tmp), name);
+
+ d = GetFileAttributesW(tmp);
+ if (d != INVALID_FILE_ATTRIBUTES)
+ {
+ d |= FILE_ATTRIBUTE_HIDDEN;
+
+ SetFileAttributesW(tmp, d);
+ }
+}
+
+// Sleep prevention thread
+void MsNoSleepThread(THREAD *thread, void *param)
+{
+ MS_NOSLEEP *e;
+ EXECUTION_STATE (WINAPI *_SetThreadExecutionState)(EXECUTION_STATE);
+ HINSTANCE hKernel32;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ hKernel32 = LoadLibrary("kernel32.dll");
+
+ _SetThreadExecutionState =
+ (EXECUTION_STATE (__stdcall *)(EXECUTION_STATE))
+ GetProcAddress(hKernel32, "SetThreadExecutionState");
+
+ e = (MS_NOSLEEP *)param;
+
+ while (e->Halt == false)
+ {
+ DWORD flag = ES_SYSTEM_REQUIRED;
+
+ if (e->NoScreenSaver)
+ {
+ flag |= ES_DISPLAY_REQUIRED;
+ }
+
+ if (_SetThreadExecutionState != NULL)
+ {
+ _SetThreadExecutionState(flag);
+ }
+
+ Wait(e->HaltEvent, 30 * 1000);
+ }
+
+ FreeLibrary(hKernel32);
+}
+
+// Sleep prevention thread (for Windows Vista)
+void MsNoSleepThreadVista(THREAD *thread, void *param)
+{
+ MS_NOSLEEP *e;
+ char *key = "Control Panel\\Desktop";
+ UINT64 last_set_flag = 0;
+ UINT last_c_x = INFINITE, last_c_y = INFINITE;
+ UINT64 last_mouse_move_time = 0;
+ EXECUTION_STATE (WINAPI *_SetThreadExecutionState)(EXECUTION_STATE);
+ HINSTANCE hKernel32;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ hKernel32 = LoadLibrary("kernel32.dll");
+
+ _SetThreadExecutionState =
+ (EXECUTION_STATE (__stdcall *)(EXECUTION_STATE))
+ GetProcAddress(hKernel32, "SetThreadExecutionState");
+
+ e = (MS_NOSLEEP *)param;
+
+ while (e->Halt == false)
+ {
+ DWORD flag = ES_SYSTEM_REQUIRED;
+ UINT64 now = Tick64();
+ POINT p;
+ bool mouse_move = false;
+
+ Zero(&p, sizeof(p));
+ GetCursorPos(&p);
+
+ if (p.x != last_c_x || p.y != last_c_y)
+ {
+ if (last_c_x != INFINITE && last_c_y != INFINITE)
+ {
+ mouse_move = true;
+ }
+
+ last_c_x = p.x;
+ last_c_y = p.y;
+ }
+
+ if (mouse_move)
+ {
+ last_mouse_move_time = now;
+ }
+
+ if (last_mouse_move_time == 0 || (now > (last_mouse_move_time + 50000ULL)))
+ {
+ wchar_t *active;
+ wchar_t *exe;
+ // Remove the configuration of the screen saver If the mouse does not move more than 50 seconds
+
+ active = MsRegReadStrW(REG_CURRENT_USER, key, "ScreenSaveActive");
+ exe = MsRegReadStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE");
+
+ if (UniToInt(active) != 0 && UniIsEmptyStr(exe) == false)
+ {
+ // Screen saver is set
+ UniStrCpy(e->ScreenSaveActive, sizeof(e->ScreenSaveActive), active);
+ UniStrCpy(e->SCRNSAVE_EXE, sizeof(e->SCRNSAVE_EXE), exe);
+
+ MsRegWriteStrW(REG_CURRENT_USER, key, "ScreenSaveActive", L"0");
+ MsRegDeleteValue(REG_CURRENT_USER, key, "SCRNSAVE.EXE");
+
+ Debug("Push SS Settings.\n");
+ }
+
+ Free(active);
+ Free(exe);
+
+ last_mouse_move_time = now;
+ }
+ else
+ {
+ if (mouse_move)
+ {
+ if (UniIsEmptyStr(e->ScreenSaveActive) == false && UniIsEmptyStr(e->SCRNSAVE_EXE) == false)
+ {
+ // Restore the settings of screen saver if the screen saver
+ // is not set when the mouse is moved
+ wchar_t *active;
+ wchar_t *exe;
+
+ active = MsRegReadStrW(REG_CURRENT_USER, key, "ScreenSaveActive");
+ exe = MsRegReadStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE");
+
+ if (UniToInt(active) != 0 && UniIsEmptyStr(exe) == false)
+ {
+ }
+ else
+ {
+ MsRegWriteStrW(REG_CURRENT_USER, key, "ScreenSaveActive", e->ScreenSaveActive);
+ MsRegWriteStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE", e->SCRNSAVE_EXE);
+
+ Zero(e->ScreenSaveActive, sizeof(e->ScreenSaveActive));
+ Zero(e->SCRNSAVE_EXE, sizeof(e->SCRNSAVE_EXE));
+
+ Debug("Pop SS Settings.\n");
+ }
+
+ Free(active);
+ Free(exe);
+ }
+ }
+ }
+
+ if (last_set_flag == 0 || (now > (last_set_flag + 50000ULL)))
+ {
+ // Flag set (interval 50 seconds)
+ last_set_flag = now;
+
+ if (_SetThreadExecutionState != NULL)
+ {
+ _SetThreadExecutionState(flag);
+ }
+ }
+
+ Wait(e->HaltEvent, 512);
+ }
+
+ if (true)
+ {
+ // Restore the settings of the screen saver
+ wchar_t *active;
+ wchar_t *exe;
+
+ if (UniIsEmptyStr(e->ScreenSaveActive) == false && UniIsEmptyStr(e->SCRNSAVE_EXE) == false)
+ {
+ active = MsRegReadStrW(REG_CURRENT_USER, key, "ScreenSaveActive");
+ exe = MsRegReadStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE");
+
+ if (UniToInt(active) != 0 && UniIsEmptyStr(exe) != 0)
+ {
+ }
+ else
+ {
+ MsRegWriteStrW(REG_CURRENT_USER, key, "ScreenSaveActive", e->ScreenSaveActive);
+ MsRegWriteStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE", e->SCRNSAVE_EXE);
+
+ Zero(e->ScreenSaveActive, sizeof(e->ScreenSaveActive));
+ Zero(e->SCRNSAVE_EXE, sizeof(e->SCRNSAVE_EXE));
+
+ Debug("Pop SS Settings.\n");
+ }
+
+ Free(active);
+ Free(exe);
+ }
+ }
+
+ FreeLibrary(hKernel32);
+}
+
+// The start of the sleep prevention
+void *MsNoSleepStart(bool no_screensaver)
+{
+ MS_NOSLEEP *e;
+ bool is_vista = MsIsVista();
+ bool is_nt_4 = false;
+ UINT os_type = GetOsInfo()->OsType;
+
+ if (OS_IS_WINDOWS_NT(os_type))
+ {
+ if (GET_KETA(os_type, 100) == 1)
+ {
+ is_nt_4 = true;
+ }
+ }
+
+ e = ZeroMalloc(sizeof(MS_NOSLEEP));
+
+ e->HaltEvent = NewEvent();
+ e->NoScreenSaver = no_screensaver;
+
+ if (e->NoScreenSaver == false || (is_vista == false && is_nt_4 == false))
+ {
+ e->Thread = NewThread(MsNoSleepThread, e);
+ }
+ else
+ {
+ e->Thread = NewThread(MsNoSleepThreadVista, e);
+ }
+
+ return (void *)e;
+}
+
+// Stop the Sleep prevention
+void MsNoSleepEnd(void *p)
+{
+ MS_NOSLEEP *e;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ e = (MS_NOSLEEP *)p;
+
+ e->Halt = true;
+ Set(e->HaltEvent);
+
+ WaitThread(e->Thread, INFINITE);
+ ReleaseThread(e->Thread);
+ ReleaseEvent(e->HaltEvent);
+
+ Free(e);
+}
+
+static wchar_t ms_computer_name_full_cache[MAX_SIZE] = {0};
+
+// Get the full name of the computer
+void MsGetComputerNameFull(wchar_t *name, UINT size)
+{
+ MsGetComputerNameFullEx(name, size, false);
+}
+void MsGetComputerNameFullEx(wchar_t *name, UINT size, bool with_cache)
+{
+ UINT size2 = size;
+ // Validate arguments
+ UniStrCpy(name, size, L"");
+ if (name == NULL || size == 0)
+ {
+ return;
+ }
+
+ if (with_cache)
+ {
+ if (UniIsEmptyStr(ms_computer_name_full_cache) == false)
+ {
+ UniStrCpy(name, size, ms_computer_name_full_cache);
+ return;
+ }
+ }
+
+ if (MsIsNt() == false || ms->nt->GetComputerNameExW == NULL ||
+ ms->nt->GetComputerNameExW(ComputerNameDnsFullyQualified, name, &size2) == false)
+ {
+ char tmp[MAX_SIZE];
+
+ MsGetComputerName(tmp, sizeof(tmp));
+
+ StrToUni(name, size, tmp);
+ }
+
+ if (with_cache)
+ {
+ UniStrCpy(ms_computer_name_full_cache, sizeof(ms_computer_name_full_cache), name);
+ }
+}
+
+// Get the computer name
+void MsGetComputerName(char *name, UINT size)
+{
+ DWORD sz;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ sz = size;
+ GetComputerName(name, &sz);
+}
+
+// Get the hash value of the position of the mouse cursor
+UINT MsGetCursorPosHash()
+{
+ POINT p;
+
+ Zero(&p, sizeof(p));
+
+ if (GetCursorPos(&p) == false)
+ {
+ return 0;
+ }
+
+ return MAKELONG((USHORT)p.x, (USHORT)p.y);
+}
+
+// Start the process as a standard user privileges
+void *MsRunAsUserEx(char *filename, char *arg, bool hide)
+{
+ void *ret = MsRunAsUserExInner(filename, arg, hide);
+
+ if (ret == NULL)
+ {
+ Debug("MsRunAsUserExInner Failed.\n");
+ ret = Win32RunEx(filename, arg, hide);
+ }
+
+ return ret;
+}
+void *MsRunAsUserExW(wchar_t *filename, wchar_t *arg, bool hide)
+{
+ void *ret = MsRunAsUserExInnerW(filename, arg, hide);
+
+ if (ret == NULL)
+ {
+ Debug("MsRunAsUserExInner Failed.\n");
+ ret = Win32RunExW(filename, arg, hide);
+ }
+
+ return ret;
+}
+void *MsRunAsUserExInner(char *filename, char *arg, bool hide)
+{
+ void *ret;
+ wchar_t *filename_w;
+ wchar_t *arg_w;
+
+ filename_w = CopyStrToUni(filename);
+ arg_w = CopyStrToUni(arg);
+
+ ret = MsRunAsUserExInnerW(filename_w, arg_w, hide);
+
+ Free(filename_w);
+ Free(arg_w);
+
+ return ret;
+}
+void *MsRunAsUserExInnerW(wchar_t *filename, wchar_t *arg, bool hide)
+{
+ STARTUPINFOW info;
+ PROCESS_INFORMATION ret;
+ wchar_t cmdline[MAX_SIZE];
+ wchar_t name[MAX_PATH];
+ HANDLE hToken;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ if (MsIsVista() == false)
+ {
+ // Can not be used in non-Windows Vista
+ return NULL;
+ }
+
+ UniStrCpy(name, sizeof(name), filename);
+ UniTrim(name);
+
+ if (UniSearchStr(name, L"\"", 0) == INFINITE)
+ {
+ if (arg == NULL)
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"%s", name);
+ }
+ else
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"%s %s", name, arg);
+ }
+ }
+ else
+ {
+ if (arg == NULL)
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"\"%s\"", name);
+ }
+ else
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"\"%s\" %s", name, arg);
+ }
+ }
+
+ Zero(&info, sizeof(info));
+ Zero(&ret, sizeof(ret));
+ info.cb = sizeof(info);
+ info.dwFlags = STARTF_USESHOWWINDOW;
+ info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE);
+
+ UniTrim(cmdline);
+
+ hToken = MsCreateUserToken();
+
+ if (hToken == NULL)
+ {
+ return NULL;
+ }
+
+ if (ms->nt->CreateProcessAsUserW(hToken, NULL, cmdline, NULL, NULL, FALSE,
+ (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS,
+ NULL, NULL, &info, &ret) == FALSE)
+ {
+ return NULL;
+ }
+
+ CloseHandle(hToken);
+
+ CloseHandle(ret.hThread);
+ return ret.hProcess;
+}
+
+// Get the SID from the account name
+SID *MsGetSidFromAccountName(char *name)
+{
+ SID *sid;
+ UINT sid_size = 4096;
+ char *domain_name;
+ UINT domain_name_size = 4096;
+ SID_NAME_USE use = SidTypeUser;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return NULL;
+ }
+
+ sid = ZeroMalloc(sid_size);
+ domain_name = ZeroMalloc(domain_name_size);
+
+ if (ms->nt->LookupAccountNameA(NULL, name, sid, &sid_size, domain_name, &domain_name_size, &use) == false)
+ {
+ Free(sid);
+ Free(domain_name);
+ return NULL;
+ }
+
+ Free(domain_name);
+
+ return sid;
+}
+
+// Release the SID
+void MsFreeSid(SID *sid)
+{
+ // Validate arguments
+ if (sid == NULL)
+ {
+ return;
+ }
+
+ Free(sid);
+}
+
+// Create a token of standard user
+HANDLE MsCreateUserToken()
+{
+ char *medium_sid = "S-1-16-8192";
+ char *administrators_sid = "S-1-5-32-544";
+ SID *sid = NULL;
+ TOKEN_MANDATORY_LABEL til;
+ HANDLE hCurrentToken, hNewToken;
+ if (MsIsNt() == false)
+ {
+ return NULL;
+ }
+ if (ms->nt->ConvertStringSidToSidA == NULL ||
+ ms->nt->OpenProcessToken == NULL ||
+ ms->nt->DuplicateTokenEx == NULL ||
+ ms->nt->GetTokenInformation == NULL ||
+ ms->nt->SetTokenInformation == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&til, sizeof(til));
+
+ if (ms->nt->ConvertStringSidToSidA(medium_sid, &sid) == false)
+ {
+ return NULL;
+ }
+
+ til.Label.Attributes = SE_GROUP_INTEGRITY;
+ til.Label.Sid = sid;
+
+ if (ms->nt->OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &hCurrentToken) == false)
+ {
+ LocalFree(sid);
+ return NULL;
+ }
+
+ if (ms->nt->DuplicateTokenEx(hCurrentToken, MAXIMUM_ALLOWED, NULL,
+ SecurityImpersonation, TokenPrimary, &hNewToken) == false)
+ {
+ CloseHandle(hCurrentToken);
+ LocalFree(sid);
+ return NULL;
+ }
+
+ if (ms->nt->SetTokenInformation(hNewToken, VistaTokenIntegrityLevel, &til,
+ sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(sid)) == false)
+ {
+ CloseHandle(hNewToken);
+ CloseHandle(hCurrentToken);
+ LocalFree(sid);
+ return NULL;
+ }
+
+ CloseHandle(hCurrentToken);
+ LocalFree(sid);
+
+ return hNewToken;
+}
+
+
+// Check the digital signature of the file
+bool MsCheckFileDigitalSignature(HWND hWnd, char *name, bool *danger)
+{
+ wchar_t tmp[MAX_PATH];
+
+ swprintf(tmp, sizeof(tmp), L"%S", name);
+
+ return MsCheckFileDigitalSignatureW(hWnd, tmp, danger);
+}
+bool MsCheckFileDigitalSignatureW(HWND hWnd, wchar_t *name, bool *danger)
+{
+ HRESULT ret = S_OK;
+ wchar_t *tmp;
+ LONG (WINAPI *_WinVerifyTrust)(HWND, GUID *, LPVOID) = NULL;
+ HINSTANCE hDll;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (danger != NULL)
+ {
+ *danger = false;
+ }
+
+ tmp = name;
+
+ hDll = LoadLibrary("Wintrust.dll");
+ if (hDll == NULL)
+ {
+ return false;
+ }
+
+ _WinVerifyTrust =
+ (LONG (__stdcall *)(HWND,GUID *,LPVOID))
+ GetProcAddress(hDll, "WinVerifyTrust");
+ if (_WinVerifyTrust == NULL)
+ {
+ FreeLibrary(hDll);
+ return false;
+ }
+ else
+ {
+ GUID action_id = WINTRUST_ACTION_GENERIC_VERIFY_V2;
+ WINTRUST_FILE_INFO file;
+ WINTRUST_DATA data;
+
+ Zero(&file, sizeof(file));
+ file.cbStruct = sizeof(file);
+ file.pcwszFilePath = tmp;
+
+ Zero(&data, sizeof(data));
+ data.cbStruct = sizeof(data);
+ data.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
+ data.dwUIChoice = (hWnd != NULL ? WTD_UI_NOGOOD : WTD_UI_NONE);
+ data.dwProvFlags = WTD_REVOCATION_CHECK_CHAIN;
+ data.dwUnionChoice = WTD_CHOICE_FILE;
+ data.pFile = &file;
+
+ ret = _WinVerifyTrust(hWnd, &action_id, &data);
+
+ if (ret == ERROR_SUCCESS && danger != NULL)
+ {
+ if (hWnd != NULL)
+ {
+ if (MsCheckFileDigitalSignatureW(NULL, name, NULL) == false)
+ {
+ // It's a dangerous file, but the user had to select the [OK]
+ *danger = true;
+ }
+ }
+ }
+ }
+
+ FreeLibrary(hDll);
+
+ if (ret != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Enable or disable the WoW64 redirection
+void MsSetWow64FileSystemRedirectionEnable(bool enable)
+{
+ if (MsIs64BitWindows() == false)
+ {
+ return;
+ }
+
+ if (ms->nt->Wow64EnableWow64FsRedirection == NULL)
+ {
+ return;
+ }
+
+ ms->nt->Wow64EnableWow64FsRedirection(enable ? 1 : 0);
+}
+
+// Disable the WoW64 redirection
+void *MsDisableWow64FileSystemRedirection()
+{
+ void *p = NULL;
+ if (MsIs64BitWindows() == false)
+ {
+ return NULL;
+ }
+
+ if (ms->nt->Wow64DisableWow64FsRedirection == NULL ||
+ ms->nt->Wow64RevertWow64FsRedirection == NULL)
+ {
+ return NULL;
+ }
+
+ if (ms->nt->Wow64DisableWow64FsRedirection(&p) == false)
+ {
+ return NULL;
+ }
+
+ if (p == NULL)
+ {
+ p = (void *)0x12345678;
+ }
+
+ return p;
+}
+
+// Restore the WoW64 redirection
+void MsRestoreWow64FileSystemRedirection(void *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+ if (p == (void *)0x12345678)
+ {
+ p = NULL;
+ }
+ if (MsIs64BitWindows() == false)
+ {
+ return;
+ }
+
+ if (ms->nt->Wow64DisableWow64FsRedirection == NULL ||
+ ms->nt->Wow64RevertWow64FsRedirection == NULL)
+ {
+ return;
+ }
+
+ ms->nt->Wow64RevertWow64FsRedirection(p);
+}
+
+// Get whether the x64 version of Windows is currently running
+bool MsIsX64()
+{
+ SYSTEM_INFO info;
+
+ if (MsIs64BitWindows() == false)
+ {
+ return false;
+ }
+ if (ms->nt->GetNativeSystemInfo == NULL)
+ {
+ return false;
+ }
+
+ Zero(&info, sizeof(info));
+ ms->nt->GetNativeSystemInfo(&info);
+
+ if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Get whether the IA64 version of Windows is currently running
+bool MsIsIA64()
+{
+ if (MsIs64BitWindows() == false)
+ {
+ return false;
+ }
+
+ if (MsIsX64())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Acquisition whether it's a 64bit Windows
+bool MsIs64BitWindows()
+{
+ if (Is64())
+ {
+ return true;
+ }
+ else
+ {
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+ else
+ {
+ if (ms == NULL || ms->nt == NULL)
+ {
+ return false;
+ }
+
+ if (ms->nt->IsWow64Process == NULL)
+ {
+ return false;
+ }
+ else
+ {
+ bool b = false;
+ if (ms->nt->IsWow64Process(GetCurrentProcess(), &b) == false)
+ {
+ return false;
+ }
+ return b;
+ }
+ }
+ }
+}
+
+// Windows Firewall registration
+void MsRegistWindowsFirewallEx2(char *title, char *exe, char *dir)
+{
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (title == NULL || exe == NULL)
+ {
+ return;
+ }
+ if (dir == NULL || IsEmptyStr(dir))
+ {
+ dir = MsGetExeDirName();
+ }
+
+ ConbinePath(tmp, sizeof(tmp), dir, exe);
+
+ if (IsFileExists(tmp) == false)
+ {
+ return;
+ }
+
+ MsRegistWindowsFirewallEx(title, tmp);
+}
+void MsRegistWindowsFirewallEx(char *title, char *exe)
+{
+ char *data =
+ "Option Explicit\r\nConst NET_FW_PROFILE_DOMAIN = 0\r\nConst NET_FW_PROFILE_STANDARD = 1\r\n"
+ "Const NET_FW_SCOPE_ALL = 0\r\nConst NET_FW_IP_VERSION_ANY = 2\r\nDim fwMgr\r\n"
+ "Set fwMgr = CreateObject(\"HNetCfg.FwMgr\")\r\nDim profile\r\n"
+ "Set profile = fwMgr.LocalPolicy.CurrentProfile\r\nDim app\r\n"
+ "Set app = CreateObject(\"HNetCfg.FwAuthorizedApplication\")\r\n"
+ "app.ProcessImageFileName = \"$PATH$\"\r\napp.Name = \"$TITLE$\"\r\n"
+ "app.Scope = NET_FW_SCOPE_ALL\r\napp.IpVersion = NET_FW_IP_VERSION_ANY\r\n"
+ "app.Enabled = TRUE\r\nOn Error Resume Next\r\nprofile.AuthorizedApplications."
+ "Add app\r\n";
+ char *tmp;
+ UINT tmp_size;
+ char filename[MAX_PATH];
+ char cscript[MAX_PATH];
+ char arg[MAX_PATH];
+ UINT ostype;
+ IO *o;
+ char hash[MAX_PATH];
+ UCHAR hashbin[SHA1_SIZE];
+ UCHAR file_hash_bin[SHA1_SIZE];
+ char file_hash_str[MAX_SIZE];
+ // Validate arguments
+ if (title == NULL || exe == NULL)
+ {
+ return;
+ }
+
+ // OS check (This Is not performed except Windows XP, Windows Server 2003, Windows Vista or later)
+ ostype = GetOsInfo()->OsType;
+ if (OS_IS_WINDOWS_NT(ostype) == false)
+ {
+ return;
+ }
+ if (MsIsVista() == false && (GET_KETA(ostype, 100) != 3 && GET_KETA(ostype, 100) != 4 && GET_KETA(ostype, 100) != 5 && GET_KETA(ostype, 100) != 6 && GET_KETA(ostype, 100) != 7))
+ {
+ return;
+ }
+ if (MsIsAdmin() == false)
+ {
+ return;
+ }
+
+ if (MsIsVista())
+ {
+ data = "Option Explicit\r\n\r\nConst PROFILES_ALL = 7\r\nConst NET_FW_ACTION_ALLOWNET_FW_ACTION_ALLOW = 1\r\n"
+ "\r\nDim policy2\r\nDim rules\r\nDim new_rule\r\n\r\nOn Error Resume Next\r\n\r\n"
+ "Set policy2 = CreateObject(\"HNetCfg.FwPolicy2\")\r\nSet rules = policy2.Rules\r\n"
+ "Set new_rule = CreateObject(\"HNetCfg.FWRule\")\r\nnew_rule.Name = \"$TITLE$\"\r\n"
+ "new_rule.Description = \"$TITLE$\"\r\nnew_rule.ApplicationName = \"$PATH$\"\r\n"
+ "new_rule.Enabled = TRUE\r\nnew_rule.Profiles = PROFILES_ALL\r\nnew_rule.Action = "
+ "NET_FW_ACTION_ALLOWNET_FW_ACTION_ALLOW\r\nrules.Add new_rule\r\n\r\n";
+ }
+
+ tmp_size = StrLen(data) * 4;
+ tmp = ZeroMalloc(tmp_size);
+
+ HashSha1(hashbin, exe, StrLen(exe));
+ BinToStr(hash, sizeof(hash), hashbin, 6);
+
+ ReplaceStrEx(tmp, tmp_size, data, "$TITLE$", title, false);
+ ReplaceStrEx(tmp, tmp_size, tmp, "$PATH$", exe, false);
+
+ HashSha1(file_hash_bin, tmp, StrLen(tmp));
+ BinToStr(file_hash_str, sizeof(file_hash_str), file_hash_bin, sizeof(file_hash_bin));
+
+ if (MsIsVista() == false || MsRegReadIntEx2(REG_LOCAL_MACHINE, SOFTETHER_FW_SCRIPT_HASH, file_hash_str, false, true) == 0)
+ {
+ Format(filename, sizeof(filename), "%s\\winfire_%s.vbs", MsGetMyTempDir(), hash);
+ o = FileCreate(filename);
+ FileWrite(o, tmp, StrLen(tmp));
+ FileClose(o);
+
+ Format(cscript, sizeof(cscript), "%s\\cscript.exe", MsGetSystem32Dir());
+ Format(arg, sizeof(arg), "\"%s\"", filename);
+
+ if (Run(cscript, arg, true, false))
+ {
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, SOFTETHER_FW_SCRIPT_HASH, file_hash_str, 1, false, true);
+ }
+
+ Debug("cscript %s\n", arg);
+ }
+
+ Free(tmp);
+}
+
+// Run driver installer for Vista
+bool MsExecDriverInstaller(char *arg)
+{
+ wchar_t tmp[MAX_PATH];
+ wchar_t hamcore_dst[MAX_PATH];
+ wchar_t hamcore_src[MAX_PATH];
+ wchar_t lang_config_src[MAX_PATH];
+ wchar_t lang_config_dst[MAX_PATH];
+ HANDLE h;
+ UINT retcode;
+ SHELLEXECUTEINFOW info;
+ wchar_t *src_exe;
+ wchar_t *arg_w;
+ // Validate arguments
+ if (arg == NULL)
+ {
+ return false;
+ }
+
+ UniFormat(hamcore_dst, sizeof(hamcore_dst), L"%s\\hamcore.se2", MsGetMyTempDirW());
+ UniFormat(hamcore_src, sizeof(hamcore_src), L"%s\\hamcore.se2", MsGetExeDirNameW());
+
+ // Extract the File
+ src_exe = VISTA_DRIVER_INSTALLER_SRC;
+
+ if (MsIsX64())
+ {
+ src_exe = VISTA_DRIVER_INSTALLER_SRC_X64;
+ }
+ if (MsIsIA64())
+ {
+ src_exe = VISTA_DRIVER_INSTALLER_SRC_IA64;
+ }
+
+ UniFormat(tmp, sizeof(tmp), VISTA_DRIVER_INSTALLER_DST, MsGetMyTempDirW());
+
+ if (FileCopyW(src_exe, tmp) == false)
+ {
+ return false;
+ }
+
+ if (FileCopyW(hamcore_src, hamcore_dst) == false)
+ {
+ return false;
+ }
+
+ ConbinePathW(lang_config_src, sizeof(lang_config_src), MsGetExeDirNameW(), L"lang.config");
+ ConbinePathW(lang_config_dst, sizeof(lang_config_dst), MsGetMyTempDirW(), L"lang.config");
+ FileCopyW(lang_config_src, lang_config_dst);
+
+ arg_w = CopyStrToUni(arg);
+
+ // Run
+ Zero(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.lpVerb = L"open";
+ info.lpFile = tmp;
+ info.fMask = SEE_MASK_NOCLOSEPROCESS;
+ info.lpParameters = arg_w;
+ info.nShow = SW_SHOWNORMAL;
+ if (ShellExecuteExW(&info) == false)
+ {
+ Free(arg_w);
+ return false;
+ }
+
+ Free(arg_w);
+
+ h = info.hProcess;
+ retcode = 1;
+
+ while (true)
+ {
+ // Wait for completion
+ WaitForSingleObject(h, INFINITE);
+
+ // Get the exit code
+ retcode = 1;
+ if (GetExitCodeProcess(h, &retcode) == false)
+ {
+ break;
+ }
+
+ if (retcode != STILL_ACTIVE)
+ {
+ break;
+ }
+ }
+
+ CloseHandle(h);
+
+ if (retcode & 1)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the locale of the current thread
+UINT MsGetThreadLocale()
+{
+ return (UINT)GetThreadLocale();
+}
+
+// Set the width of the current console
+UINT MsSetConsoleWidth(UINT size)
+{
+ HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ COORD c;
+ UINT old_x, old_y;
+ // Validate arguments
+ if (size == 0)
+ {
+ return 0;
+ }
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return 0;
+ }
+
+ Zero(&info, sizeof(info));
+ if (GetConsoleScreenBufferInfo(h, &info) == false)
+ {
+ return 0;
+ }
+
+ old_x = info.dwSize.X;
+ old_y = info.dwSize.Y;
+
+ c.X = size;
+ c.Y = old_y;
+
+ SetConsoleScreenBufferSize(h, c);
+
+ return old_x;
+}
+
+// Get the width of the current console
+UINT MsGetConsoleWidth()
+{
+ HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
+ CONSOLE_SCREEN_BUFFER_INFO info;
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return 80;
+ }
+
+ Zero(&info, sizeof(info));
+ if (GetConsoleScreenBufferInfo(h, &info) == false)
+ {
+ return 80;
+ }
+
+ return info.dwSize.X;
+}
+
+// Disable the MS-IME
+bool MsDisableIme()
+{
+ HINSTANCE h;
+ bool ret = false;
+ char dll_name[MAX_PATH];
+ BOOL (WINAPI *_ImmDisableIME)(DWORD);
+
+ Format(dll_name, sizeof(dll_name), "%s\\imm32.dll", MsGetSystem32Dir());
+ h = MsLoadLibrary(dll_name);
+ if (h == NULL)
+ {
+ return false;
+ }
+
+ _ImmDisableIME = (BOOL (__stdcall *)(DWORD))GetProcAddress(h, "ImmDisableIME");
+
+ if (_ImmDisableIME != NULL)
+ {
+ ret = _ImmDisableIME(-1);
+ }
+
+ FreeLibrary(h);
+
+ return ret;
+}
+
+// Display the current time
+void MsPrintTick()
+{
+ UINT tick = timeGetTime();
+ static UINT tick_init = 0;
+ if (tick_init == 0)
+ {
+ tick_init = tick;
+ tick = 0;
+ }
+ else
+ {
+ tick -= tick_init;
+ }
+
+ printf("[%u]\n", tick);
+}
+
+// LoadLibrary compatible for hamcore (Read as a data file)
+void *MsLoadLibraryAsDataFileW(wchar_t *name)
+{
+ BUF *b;
+ wchar_t tmp_dll_name[MAX_SIZE];
+ char hash_str[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ Hash(hash, name, UniStrLen(name), true);
+
+ BinToStr(hash_str, sizeof(hash_str), hash, 4);
+
+ UniFormat(tmp_dll_name, sizeof(tmp_dll_name), L"%s\\%S.dll", MsGetMyTempDirW(), hash_str);
+
+ if (IsFileExistsW(tmp_dll_name) == false)
+ {
+ b = ReadDumpW(name);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ DumpBufW(b, tmp_dll_name);
+ FreeBuf(b);
+ }
+
+ return LoadLibraryExW(tmp_dll_name, NULL, LOAD_LIBRARY_AS_DATAFILE);
+}
+void *MsLoadLibraryAsDataFile(char *name)
+{
+ wchar_t name_w[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ StrToUni(name_w, sizeof(name_w), name);
+
+ return MsLoadLibraryAsDataFileW(name_w);
+}
+
+// Simple LoadLibaray
+void *MsLoadLibraryRawW(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (MsIsNt())
+ {
+ return LoadLibraryW(name);
+ }
+ else
+ {
+ char tmp[MAX_PATH];
+
+ UniToStr(tmp, sizeof(tmp), name);
+
+ return LoadLibraryA(tmp);
+ }
+}
+
+// LoadLibrary (compatible for Hamcore)
+void *MsLoadLibraryW(wchar_t *name)
+{
+ BUF *b;
+ wchar_t tmp_dll_name[MAX_SIZE];
+ char hash_str[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ Hash(hash, name, UniStrSize(name), true);
+
+ BinToStr(hash_str, sizeof(hash_str), hash, 4);
+
+ UniFormat(tmp_dll_name, sizeof(tmp_dll_name), L"%s\\%S.dll", MsGetMyTempDirW(), hash_str);
+
+ if (IsFileExistsW(tmp_dll_name) == false)
+ {
+ b = ReadDumpW(name);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ DumpBufW(b, tmp_dll_name);
+ FreeBuf(b);
+ }
+
+ if (IsNt())
+ {
+ return LoadLibraryW(tmp_dll_name);
+ }
+ else
+ {
+ char tmp_dll_name_a[MAX_SIZE];
+ HINSTANCE ret;
+
+ UniToStr(tmp_dll_name_a, sizeof(tmp_dll_name_a), tmp_dll_name);
+
+ ret = LoadLibraryA(tmp_dll_name_a);
+
+ return ret;
+ }
+}
+void *MsLoadLibrary(char *name)
+{
+ wchar_t name_w[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ StrToUni(name_w, sizeof(name_w), name);
+
+ return MsLoadLibraryW(name_w);
+}
+
+// Release of the library
+void MsFreeLibrary(void *h)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return;
+ }
+
+ FreeLibrary(h);
+}
+
+// Get the function pointer in the DLL
+void *MsGetProcAddress(void *h, char *name)
+{
+ // Validate arguments
+ if (h == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ return (void *)GetProcAddress(h, name);
+}
+
+// Search for the adapter by GUID
+MS_ADAPTER *MsGetAdapterByGuid(char *guid)
+{
+ MS_ADAPTER_LIST *o;
+ MS_ADAPTER *ret = NULL;
+ // Validate arguments
+ if (guid == NULL)
+ {
+ return NULL;
+ }
+
+ o = MsCreateAdapterList();
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ ret = MsGetAdapterByGuidFromList(o, guid);
+
+ MsFreeAdapterList(o);
+
+ return ret;
+}
+MS_ADAPTER *MsGetAdapterByGuidFromList(MS_ADAPTER_LIST *o, char *guid)
+{
+ MS_ADAPTER *ret = NULL;
+ UINT i;
+ // Validate arguments
+ if (o == NULL || guid == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < o->Num;i++)
+ {
+ if (StrCmpi(o->Adapters[i]->Guid, guid) == 0)
+ {
+ ret = MsCloneAdapter(o->Adapters[i]);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+// Get a single adapter
+MS_ADAPTER *MsGetAdapter(char *title)
+{
+ MS_ADAPTER_LIST *o;
+ MS_ADAPTER *ret = NULL;
+ UINT i;
+ // Validate arguments
+ if (title == NULL)
+ {
+ return NULL;
+ }
+
+ o = MsCreateAdapterList();
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < o->Num;i++)
+ {
+ if (StrCmpi(o->Adapters[i]->Title, title) == 0)
+ {
+ ret = MsCloneAdapter(o->Adapters[i]);
+ break;
+ }
+ }
+
+ MsFreeAdapterList(o);
+
+ return ret;
+}
+
+// 32-bit overflow checking
+#define CHECK_32BIT_OVERFLOW(old_value, new_value) \
+{ \
+ if ((old_value) > (new_value)) \
+ { \
+ (new_value) += ((UINT64)4294967296ULL); \
+ } \
+}
+
+// Get the TCP/IP information of the specified adapter
+void MsGetAdapterTcpIpInformation(MS_ADAPTER *a)
+{
+ IP_ADAPTER_INFO *info, *info_top;
+ UINT info_size;
+ UINT ret;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ if (w32net->GetAdaptersInfo == NULL)
+ {
+ return;
+ }
+
+ info_top = ZeroMalloc(sizeof(IP_ADAPTER_INFO));
+ info_size = sizeof(IP_ADAPTER_INFO);
+
+ ret = w32net->GetAdaptersInfo(info_top, &info_size);
+ if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW)
+ {
+ Free(info_top);
+ info_size *= 2;
+ info_top = ZeroMalloc(info_size);
+
+ if (w32net->GetAdaptersInfo(info_top, &info_size) != NO_ERROR)
+ {
+ Free(info_top);
+ return;
+ }
+ }
+ else if (ret != NO_ERROR)
+ {
+ Free(info_top);
+ return;
+ }
+
+ // Search for their own entry
+ info = info_top;
+
+ while (info != NULL)
+ {
+ if (info->Index == a->Index)
+ {
+ IP_ADDR_STRING *s;
+
+ // IP address
+ a->NumIpAddress = 0;
+ s = &info->IpAddressList;
+ while (s != NULL)
+ {
+ if (a->NumIpAddress < MAX_MS_ADAPTER_IP_ADDRESS)
+ {
+ StrToIP(&a->IpAddresses[a->NumIpAddress], s->IpAddress.String);
+ StrToIP(&a->SubnetMasks[a->NumIpAddress], s->IpMask.String);
+ a->NumIpAddress++;
+ }
+ s = s->Next;
+ }
+
+ // Gateway
+ a->NumGateway = 0;
+ s = &info->GatewayList;
+ while (s != NULL)
+ {
+ if (a->NumGateway < MAX_MS_ADAPTER_IP_ADDRESS)
+ {
+ StrToIP(&a->Gateways[a->NumGateway], s->IpAddress.String);
+ a->NumGateway++;
+ }
+ s = s->Next;
+ }
+
+ // DHCP Server
+ a->UseDhcp = (info->DhcpEnabled == 0 ? false : true);
+ if (a->UseDhcp)
+ {
+ SYSTEMTIME st;
+
+ StrToIP(&a->DhcpServer, info->DhcpServer.IpAddress.String);
+ TimeToSystem(&st, info->LeaseObtained);
+ a->DhcpLeaseStart = SystemToUINT64(&st);
+
+ TimeToSystem(&st, info->LeaseExpires);
+ a->DhcpLeaseExpires = SystemToUINT64(&st);
+ }
+
+ // WINS server
+ a->UseWins = info->HaveWins;
+ if (a->UseWins)
+ {
+ StrToIP(&a->PrimaryWinsServer, info->PrimaryWinsServer.IpAddress.String);
+ StrToIP(&a->SecondaryWinsServer, info->SecondaryWinsServer.IpAddress.String);
+ }
+
+ StrCpy(a->Guid, sizeof(a->Guid), info->AdapterName);
+
+ a->Info = true;
+
+ break;
+ }
+
+ info = info->Next;
+ }
+
+ Free(info_top);
+}
+
+// Generation of adapter list
+MS_ADAPTER_LIST *MsCreateAdapterList()
+{
+ return MsCreateAdapterListEx(false);
+}
+MS_ADAPTER_LIST *MsCreateAdapterListEx(bool no_info)
+{
+ MS_ADAPTER_LIST *ret;
+
+ if (no_info)
+ {
+ ret = MsCreateAdapterListInnerEx(true);
+
+ return ret;
+ }
+
+ Lock(lock_adapter_list);
+ {
+ MS_ADAPTER_LIST *old = last_adapter_list;
+ UINT i;
+
+ // Fetch a new adapter list
+ ret = MsCreateAdapterListInner();
+
+ if (ret == NULL)
+ {
+ Unlock(lock_adapter_list);
+ return NULL;
+ }
+
+ // Check whether the previously acquired item exists for each entry
+ // in the list of adapters have been taken
+ for (i = 0;i < ret->Num;i++)
+ {
+ UINT j;
+ for (j = 0;j < old->Num;j++)
+ {
+ MS_ADAPTER *o = old->Adapters[j];
+ MS_ADAPTER *n = ret->Adapters[i];
+
+ if (StrCmpi(o->Title, n->Title) == 0)
+ {
+ // If the value of older item is small, increment it
+ CHECK_32BIT_OVERFLOW(o->RecvBytes, n->RecvBytes);
+ CHECK_32BIT_OVERFLOW(o->RecvPacketsBroadcast, n->RecvPacketsBroadcast);
+ CHECK_32BIT_OVERFLOW(o->RecvPacketsUnicast, n->RecvPacketsUnicast);
+ CHECK_32BIT_OVERFLOW(o->SendBytes, n->SendBytes);
+ CHECK_32BIT_OVERFLOW(o->SendPacketsBroadcast, n->SendPacketsBroadcast);
+ CHECK_32BIT_OVERFLOW(o->SendPacketsUnicast, n->SendPacketsUnicast);
+ break;
+ }
+ }
+ }
+
+ // Release the old adapter list
+ MsFreeAdapterList(old);
+
+ // Save a clone of the adapter list that newly acquired
+ last_adapter_list = MsCloneAdapterList(ret);
+ }
+ Unlock(lock_adapter_list);
+
+ return ret;
+}
+
+// Initialization of the adapter module list
+void MsInitAdapterListModule()
+{
+ lock_adapter_list = NewLock(NULL);
+
+ last_adapter_list = MsCreateAdapterListInner();
+}
+
+// Release of the adapter module list
+void MsFreeAdapterListModule()
+{
+ if (last_adapter_list != NULL)
+ {
+ MsFreeAdapterList(last_adapter_list);
+ last_adapter_list = NULL;
+ }
+
+ DeleteLock(lock_adapter_list);
+ lock_adapter_list = NULL;
+}
+
+// Clone the adapter list
+MS_ADAPTER_LIST *MsCloneAdapterList(MS_ADAPTER_LIST *o)
+{
+ MS_ADAPTER_LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ ret->Num = o->Num;
+ ret->Adapters = ZeroMalloc(sizeof(MS_ADAPTER *) * ret->Num);
+
+ for (i = 0;i < ret->Num;i++)
+ {
+ ret->Adapters[i] = ZeroMalloc(sizeof(MS_ADAPTER));
+ Copy(ret->Adapters[i], o->Adapters[i], sizeof(MS_ADAPTER));
+ }
+
+ return ret;
+}
+
+// Clone the adapter
+MS_ADAPTER *MsCloneAdapter(MS_ADAPTER *a)
+{
+ MS_ADAPTER *ret;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(MS_ADAPTER));
+ Copy(ret, a, sizeof(MS_ADAPTER));
+
+ return ret;
+}
+
+// Creating an adapters list
+MS_ADAPTER_LIST *MsCreateAdapterListInner()
+{
+ return MsCreateAdapterListInnerEx(false);
+}
+MS_ADAPTER_LIST *MsCreateAdapterListInnerEx(bool no_info)
+{
+ LIST *o;
+ UINT i;
+ UINT retcode;
+ MIB_IFTABLE *table;
+ UINT table_size = sizeof(MIB_IFTABLE);
+ MS_ADAPTER_LIST *ret;
+
+ if (w32net->GetIfTable2 != NULL && w32net->FreeMibTable != NULL)
+ {
+ return MsCreateAdapterListInnerExVista(no_info);
+ }
+
+ if (w32net->GetIfTable == NULL)
+ {
+ return ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ }
+
+ table = ZeroMalloc(table_size);
+
+ retcode = w32net->GetIfTable(table, &table_size, TRUE);
+ if (retcode == ERROR_INSUFFICIENT_BUFFER || retcode == ERROR_BUFFER_OVERFLOW)
+ {
+ Free(table);
+ table_size *= 2;
+ table = ZeroMalloc(table_size);
+ if (w32net->GetIfTable(table, &table_size, TRUE) != NO_ERROR)
+ {
+ Free(table);
+ return ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ }
+ }
+ else if (retcode != NO_ERROR)
+ {
+ Free(table);
+ return ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ }
+
+ o = NewListFast(NULL);
+
+ for (i = 0;i < table->dwNumEntries;i++)
+ {
+ MIB_IFROW *r = &table->table[i];
+ char title[MAX_PATH];
+ UINT num = 0;
+ MS_ADAPTER *a;
+ UINT j;
+
+ //if (r->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || r->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL)
+ {
+ //if (r->dwType & IF_TYPE_ETHERNET_CSMACD)
+ {
+ for (j = 1;;j++)
+ {
+ UINT k;
+ bool exists;
+ if (j == 1)
+ {
+ StrCpy(title, sizeof(title), (char *)r->bDescr);
+ }
+ else
+ {
+ Format(title, sizeof(title), "%s (%u)", (char *)r->bDescr, j);
+ }
+
+ exists = false;
+
+ for (k = 0;k < LIST_NUM(o);k++)
+ {
+ MS_ADAPTER *a = LIST_DATA(o, k);
+
+ if (StrCmpi(a->Title, title) == 0)
+ {
+ exists = true;
+ break;
+ }
+ }
+
+ if (exists == false)
+ {
+ break;
+ }
+ }
+
+ a = ZeroMalloc(sizeof(MS_ADAPTER));
+
+ // Create an adapter information
+ StrCpy(a->Title, sizeof(a->Title), title);
+ StrToUni(a->TitleW, sizeof(a->TitleW), title);
+ a->Index = r->dwIndex;
+ a->Type = r->dwType;
+ a->Status = r->dwOperStatus;
+ a->Mtu = r->dwMtu;
+ a->Speed = r->dwSpeed;
+ a->AddressSize = MIN(sizeof(a->Address), r->dwPhysAddrLen);
+ Copy(a->Address, r->bPhysAddr, a->AddressSize);
+ a->RecvBytes = r->dwInOctets;
+ a->RecvPacketsBroadcast = r->dwInNUcastPkts;
+ a->RecvPacketsUnicast = r->dwInUcastPkts;
+ a->SendBytes = r->dwOutOctets;
+ a->SendPacketsBroadcast = r->dwOutNUcastPkts;
+ a->SendPacketsUnicast = r->dwOutUcastPkts;
+
+ if (a->Type != IF_TYPE_ETHERNET_CSMACD)
+ {
+ a->IsNotEthernetLan = true;
+ }
+
+ // TCP/IP information acquisition
+ if (no_info == false)
+ {
+ MsGetAdapterTcpIpInformation(a);
+ }
+
+ Add(o, a);
+ }
+ }
+ }
+
+ ret = ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ ret->Num = LIST_NUM(o);
+ ret->Adapters = ToArray(o);
+
+ ReleaseList(o);
+ Free(table);
+
+ return ret;
+}
+
+// Creating an adapters list (Windows Vista version)
+MS_ADAPTER_LIST *MsCreateAdapterListInnerExVista(bool no_info)
+{
+ LIST *o;
+ UINT i;
+ UINT retcode;
+ MIB_IF_TABLE2 *table;
+ UINT table_size = sizeof(MIB_IFTABLE);
+ MS_ADAPTER_LIST *ret;
+
+ if (w32net->GetIfTable2 == NULL || w32net->FreeMibTable == NULL)
+ {
+ return ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ }
+
+ retcode = w32net->GetIfTable2(&table);
+ if (retcode != NO_ERROR || table == NULL)
+ {
+ return ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ }
+
+ o = NewListFast(NULL);
+
+ for (i = 0;i < table->NumEntries;i++)
+ {
+ MIB_IF_ROW2 *r = &table->Table[i];
+ wchar_t title[MAX_PATH];
+ UINT num = 0;
+ MS_ADAPTER *a;
+ UINT j;
+
+ //if (r->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || r->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL)
+ {
+ //if (r->dwType & IF_TYPE_ETHERNET_CSMACD)
+ {
+ for (j = 1;;j++)
+ {
+ UINT k;
+ bool exists;
+ if (j == 1)
+ {
+ UniStrCpy(title, sizeof(title), r->Description);
+ }
+ else
+ {
+ UniFormat(title, sizeof(title), L"%s (%u)", r->Description, j);
+ }
+
+ exists = false;
+
+ for (k = 0;k < LIST_NUM(o);k++)
+ {
+ MS_ADAPTER *a = LIST_DATA(o, k);
+
+ if (UniStrCmpi(a->TitleW, title) == 0)
+ {
+ exists = true;
+ break;
+ }
+ }
+
+ if (exists == false)
+ {
+ break;
+ }
+ }
+
+ a = ZeroMalloc(sizeof(MS_ADAPTER));
+
+ // Create an adapter information
+ UniStrCpy(a->TitleW, sizeof(a->TitleW), title);
+ UniToStr(a->Title, sizeof(a->Title), title);
+ a->Index = r->InterfaceIndex;
+ a->Type = r->Type;
+ a->Status = ConvertMidStatusVistaToXp(r->OperStatus);
+ a->Mtu = r->Mtu;
+ a->Speed = MAX((UINT)r->TransmitLinkSpeed, (UINT)r->ReceiveLinkSpeed);
+ a->AddressSize = MIN(sizeof(a->Address), r->PhysicalAddressLength);
+ Copy(a->Address, r->PhysicalAddress, a->AddressSize);
+ a->RecvBytes = r->InOctets;
+ a->RecvPacketsBroadcast = r->InNUcastPkts;
+ a->RecvPacketsUnicast = r->InUcastPkts;
+ a->SendBytes = r->OutOctets;
+ a->SendPacketsBroadcast = r->OutNUcastPkts;
+ a->SendPacketsUnicast = r->OutUcastPkts;
+
+ if (r->MediaType == NdisMediumWirelessWan || r->PhysicalMediumType == NdisPhysicalMediumWirelessLan ||
+ r->PhysicalMediumType == NdisPhysicalMediumWirelessWan || r->PhysicalMediumType == NdisPhysicalMediumWiMax ||
+ r->Type == IF_TYPE_IEEE80211)
+ {
+ a->IsWireless = true;
+ }
+
+ if (a->IsWireless ||
+ r->Type != IF_TYPE_ETHERNET_CSMACD ||
+ r->MediaType != NdisMedium802_3 ||
+ (r->PhysicalMediumType != 0 && r->PhysicalMediumType != NdisPhysicalMedium802_3))
+ {
+ a->IsNotEthernetLan = true;
+ }
+
+ // TCP/IP information acquisition
+ if (no_info == false)
+ {
+ MsGetAdapterTcpIpInformation(a);
+ }
+
+ Add(o, a);
+ }
+ }
+ }
+
+ ret = ZeroMalloc(sizeof(MS_ADAPTER_LIST));
+ ret->Num = LIST_NUM(o);
+ ret->Adapters = ToArray(o);
+
+ ReleaseList(o);
+ w32net->FreeMibTable(table);
+
+ return ret;
+}
+
+// Convert the MIB Operational Status from Vista format to XP format
+UINT ConvertMidStatusVistaToXp(UINT st)
+{
+ switch (st)
+ {
+ case IfOperStatusUp:
+ return MIB_IF_OPER_STATUS_CONNECTED;
+
+ case IfOperStatusDown:
+ return MIB_IF_OPER_STATUS_DISCONNECTED;
+ }
+
+ return MIB_IF_OPER_STATUS_NON_OPERATIONAL;
+}
+
+// Release the adapter list
+void MsFreeAdapterList(MS_ADAPTER_LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < o->Num;i++)
+ {
+ MsFreeAdapter(o->Adapters[i]);
+ }
+ Free(o->Adapters);
+
+ Free(o);
+}
+
+// Release the adapter information
+void MsFreeAdapter(MS_ADAPTER *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ Free(a);
+}
+
+// Get the status string of the adapter
+wchar_t *MsGetAdapterStatusStr(UINT status)
+{
+ wchar_t *ret;
+
+ switch (status)
+ {
+ case MIB_IF_OPER_STATUS_NON_OPERATIONAL:
+ ret = _UU("MS_NON_OPERATIONAL");
+ break;
+
+ case MIB_IF_OPER_STATUS_UNREACHABLE:
+ ret = _UU("MS_UNREACHABLE");
+ break;
+
+ case MIB_IF_OPER_STATUS_DISCONNECTED:
+ ret = _UU("MS_DISCONNECTED");
+ break;
+
+ case MIB_IF_OPER_STATUS_CONNECTING:
+ ret = _UU("MS_CONNECTING");
+ break;
+
+ case MIB_IF_OPER_STATUS_CONNECTED:
+ ret = _UU("MS_CONNECTED");
+ break;
+
+ default:
+ ret = _UU("MS_OPERATIONAL");
+ break;
+ }
+
+ return ret;
+}
+
+// Get the type string of the adapter
+wchar_t *MsGetAdapterTypeStr(UINT type)
+{
+ wchar_t *ret;
+
+ switch (type)
+ {
+ case MIB_IF_TYPE_ETHERNET:
+ ret = _UU("MS_ETHERNET");
+ break;
+
+ case IF_TYPE_IEEE80211:
+ ret = _UU("MS_WLAN");
+ break;
+
+ case MIB_IF_TYPE_TOKENRING:
+ ret = _UU("MS_TOKENRING");
+ break;
+
+ case MIB_IF_TYPE_FDDI:
+ ret = _UU("MS_FDDI");
+ break;
+
+ case MIB_IF_TYPE_PPP:
+ ret = _UU("MS_PPP");
+ break;
+
+ case MIB_IF_TYPE_LOOPBACK:
+ ret = _UU("MS_LOOPBACK");
+ break;
+
+ case MIB_IF_TYPE_SLIP:
+ ret = _UU("MS_SLIP");
+ break;
+
+ default:
+ ret = _UU("MS_OTHER");
+ break;
+ }
+
+ return ret;
+}
+
+// Kill the process of specified EXE file name
+UINT MsKillProcessByExeName(wchar_t *name)
+{
+ LIST *o;
+ UINT me, i;
+ UINT num = 0;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return 0;
+ }
+
+ o = MsGetProcessList();
+ me = MsGetProcessId();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MS_PROCESS *p = LIST_DATA(o, i);
+ if (p->ProcessId != me)
+ {
+ if (UniStrCmpi(p->ExeFilenameW, name) == 0)
+ {
+ if (MsKillProcess(p->ProcessId))
+ {
+ num++;
+ }
+ }
+ }
+ }
+
+ MsFreeProcessList(o);
+
+ return num;
+}
+
+// Terminate all instances except the EXE itself
+void MsKillOtherInstance()
+{
+ MsKillOtherInstanceEx(NULL);
+}
+void MsKillOtherInstanceEx(char *exclude_svcname)
+{
+ UINT me, i;
+ wchar_t me_path[MAX_PATH];
+ wchar_t me_path_short[MAX_PATH];
+ LIST *o = MsGetProcessList();
+ UINT e_procid = 0;
+ UINT e_procid2 = 0;
+
+ if (exclude_svcname != NULL)
+ {
+ e_procid = MsReadCallingServiceManagerProcessId(exclude_svcname, false);
+ e_procid2 = MsReadCallingServiceManagerProcessId(exclude_svcname, true);
+ }
+
+ me = MsGetProcessId();
+
+ MsGetCurrentProcessExeNameW(me_path, sizeof(me_path));
+ MsGetShortPathNameW(me_path, me_path_short, sizeof(me_path_short));
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MS_PROCESS *p = LIST_DATA(o, i);
+ if (p->ProcessId != me)
+ {
+ if ((e_procid == 0 || (e_procid != p->ProcessId)) && (e_procid2 == 0 || (e_procid2 != p->ProcessId)))
+ {
+ wchar_t tmp[MAX_PATH];
+ MsGetShortPathNameW(p->ExeFilenameW, tmp, sizeof(tmp));
+ if (UniStrCmpi(me_path_short, tmp) == 0)
+ {
+ MsKillProcess(p->ProcessId);
+ }
+ }
+ }
+ }
+
+ MsFreeProcessList(o);
+}
+
+// Get the short file name
+bool MsGetShortPathNameA(char *long_path, char *short_path, UINT short_path_size)
+{
+ // Validate arguments
+ if (long_path == NULL || short_path == NULL)
+ {
+ return false;
+ }
+
+ if (GetShortPathNameA(long_path, short_path, short_path_size) == 0)
+ {
+ StrCpy(short_path, short_path_size, long_path);
+ return false;
+ }
+
+ return true;
+}
+bool MsGetShortPathNameW(wchar_t *long_path, wchar_t *short_path, UINT short_path_size)
+{
+ // Validate arguments
+ if (long_path == NULL || short_path == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char short_path_a[MAX_SIZE];
+ char long_path_a[MAX_SIZE];
+ bool ret;
+
+ UniToStr(long_path_a, sizeof(long_path_a), long_path);
+
+ ret = MsGetShortPathNameA(long_path_a, short_path_a, sizeof(short_path_a));
+
+ StrToUni(short_path, short_path_size, short_path_a);
+
+ return ret;
+ }
+
+ if (GetShortPathNameW(long_path, short_path, short_path_size) == 0)
+ {
+ UniStrCpy(short_path, short_path_size, long_path);
+ return false;
+ }
+
+ return true;
+}
+
+// Kill the specified process
+bool MsKillProcess(UINT id)
+{
+ HANDLE h;
+ // Validate arguments
+ if (id == 0)
+ {
+ return false;
+ }
+
+ h = OpenProcess(PROCESS_TERMINATE, FALSE, id);
+ if (h == NULL)
+ {
+ return false;
+ }
+
+ if (TerminateProcess(h, 0) == FALSE)
+ {
+ CloseHandle(h);
+ return false;
+ }
+
+ CloseHandle(h);
+
+ return true;
+}
+
+// Get the current EXE file name
+void MsGetCurrentProcessExeName(char *name, UINT size)
+{
+ UINT id;
+ LIST *o;
+ MS_PROCESS *p;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ id = MsGetCurrentProcessId();
+ o = MsGetProcessList();
+ p = MsSearchProcessById(o, id);
+ if (p != NULL)
+ {
+ p = MsSearchProcessById(o, id);
+ StrCpy(name, size, p->ExeFilename);
+ }
+ else
+ {
+ StrCpy(name, size, MsGetExeFileName());
+ }
+ MsFreeProcessList(o);
+}
+void MsGetCurrentProcessExeNameW(wchar_t *name, UINT size)
+{
+ UINT id;
+ LIST *o;
+ MS_PROCESS *p;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ id = MsGetCurrentProcessId();
+ o = MsGetProcessList();
+ p = MsSearchProcessById(o, id);
+ if (p != NULL)
+ {
+ p = MsSearchProcessById(o, id);
+ UniStrCpy(name, size, p->ExeFilenameW);
+ }
+ else
+ {
+ UniStrCpy(name, size, MsGetExeFileNameW());
+ }
+ MsFreeProcessList(o);
+}
+
+// Search the process by the process ID
+MS_PROCESS *MsSearchProcessById(LIST *o, UINT id)
+{
+ MS_PROCESS *p, t;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+ t.ProcessId = id;
+
+ p = Search(o, &t);
+
+ return p;
+}
+
+// Compare the Process List items
+int MsCompareProcessList(void *p1, void *p2)
+{
+ MS_PROCESS *e1, *e2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ e1 = *(MS_PROCESS **)p1;
+ e2 = *(MS_PROCESS **)p2;
+ if (e1 == NULL || e2 == NULL)
+ {
+ return 0;
+ }
+
+ if (e1->ProcessId > e2->ProcessId)
+ {
+ return 1;
+ }
+ else if (e1->ProcessId < e2->ProcessId)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// Display the process list
+void MsPrintProcessList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MS_PROCESS *p = LIST_DATA(o, i);
+ UniPrint(L"%-4u: %s\n", p->ProcessId, p->ExeFilenameW);
+ }
+}
+
+// Release of the process list
+void MsFreeProcessList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ MS_PROCESS *p = LIST_DATA(o, i);
+ Free(p);
+ }
+
+ ReleaseList(o);
+}
+
+// Get the Process List (for WinNT)
+LIST *MsGetProcessListNt()
+{
+ LIST *o;
+ UINT max = 16384;
+ DWORD *processes;
+ UINT needed, num;
+ UINT i;
+
+ o = NewListFast(MsCompareProcessList);
+
+ if (ms->nt->EnumProcesses == NULL)
+ {
+ return o;
+ }
+
+ processes = ZeroMalloc(sizeof(DWORD) * max);
+
+ if (ms->nt->EnumProcesses(processes, sizeof(DWORD) * max, &needed) == FALSE)
+ {
+ Free(processes);
+ return NULL;
+ }
+
+ num = needed / sizeof(DWORD);
+
+ for (i = 0;i < num;i++)
+ {
+ UINT id = processes[i];
+ HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
+ false, id);
+
+ if (h != NULL)
+ {
+ HINSTANCE hInst = NULL;
+ DWORD needed;
+ char exe[MAX_SIZE];
+ wchar_t exe_w[MAX_SIZE];
+ bool ok = false;
+ DWORD sz1, sz2;
+
+ sz1 = sizeof(exe) - 1;
+ sz2 = sizeof(exe_w) / sizeof(wchar_t) - 1;
+
+ if (ms->nt->EnumProcessModules(h, &hInst, sizeof(hInst), &needed) == false)
+ {
+ hInst = NULL;
+ }
+
+ if (ms->nt->GetModuleFileNameExA(h, hInst, exe, sizeof(exe) - 1) &&
+ ms->nt->GetModuleFileNameExW(h, hInst, exe_w, sizeof(exe_w) / sizeof(wchar_t) - 1))
+ {
+ ok = true;
+ }
+ else if (ms->nt->QueryFullProcessImageNameA != NULL &&
+ ms->nt->QueryFullProcessImageNameW != NULL &&
+ ms->nt->QueryFullProcessImageNameA(h, 0, exe, &sz1) &&
+ ms->nt->QueryFullProcessImageNameW(h, 0, exe_w, &sz2))
+ {
+ ok = true;
+ }
+
+ if (ok)
+ {
+ MS_PROCESS *p = ZeroMalloc(sizeof(MS_PROCESS));
+
+ StrCpy(p->ExeFilename, sizeof(p->ExeFilename), exe);
+ UniStrCpy(p->ExeFilenameW, sizeof(p->ExeFilenameW), exe_w);
+ p->ProcessId = id;
+
+ Add(o, p);
+ }
+
+ CloseHandle(h);
+ }
+ }
+
+ Sort(o);
+
+ Free(processes);
+
+ return o;
+}
+
+// Get the Process List (for Win9x)
+LIST *MsGetProcessList9x()
+{
+ HANDLE h;
+ LIST *o;
+ HANDLE (WINAPI *CreateToolhelp32Snapshot)(DWORD, DWORD);
+ BOOL (WINAPI *Process32First)(HANDLE, LPPROCESSENTRY32);
+ BOOL (WINAPI *Process32Next)(HANDLE, LPPROCESSENTRY32);
+
+ CreateToolhelp32Snapshot =
+ (HANDLE (__stdcall *)(DWORD,DWORD))
+ GetProcAddress(ms->hKernel32, "CreateToolhelp32Snapshot");
+ Process32First =
+ (BOOL (__stdcall *)(HANDLE,LPPROCESSENTRY32))
+ GetProcAddress(ms->hKernel32, "Process32First");
+ Process32Next =
+ (BOOL (__stdcall *)(HANDLE,LPPROCESSENTRY32))
+ GetProcAddress(ms->hKernel32, "Process32Next");
+
+ o = NewListFast(MsCompareProcessList);
+
+ if (CreateToolhelp32Snapshot != NULL && Process32First != NULL && Process32Next != NULL)
+ {
+ h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ PROCESSENTRY32 e;
+ Zero(&e, sizeof(e));
+ e.dwSize = sizeof(e);
+
+ if (Process32First(h, &e))
+ {
+ while (true)
+ {
+ MS_PROCESS *p = ZeroMalloc(sizeof(MS_PROCESS));
+ StrCpy(p->ExeFilename, sizeof(p->ExeFilename), e.szExeFile);
+ StrToUni(p->ExeFilenameW, sizeof(p->ExeFilenameW), p->ExeFilename);
+ p->ProcessId = e.th32ProcessID;
+ Add(o, p);
+ if (Process32Next(h, &e) == false)
+ {
+ break;
+ }
+ }
+ }
+ CloseHandle(h);
+ }
+ }
+
+ Sort(o);
+
+ return o;
+}
+
+// Get the Process List
+LIST *MsGetProcessList()
+{
+ if (MsIsNt() == false)
+ {
+ // Windows 9x
+ return MsGetProcessList9x();
+ }
+ else
+ {
+ // Windows NT, 2000, XP
+ return MsGetProcessListNt();
+ }
+}
+
+// Force to run the current thread on a single CPU
+void MsSetThreadSingleCpu()
+{
+ SetThreadAffinityMask(GetCurrentThread(), 1);
+}
+
+// Playback of sound
+void MsPlaySound(char *name)
+{
+ char tmp[MAX_SIZE];
+ char wav[MAX_SIZE];
+ char *temp;
+ BUF *b;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ Format(tmp, sizeof(tmp), "|%s", name);
+
+ b = ReadDump(tmp);
+ if (b == NULL)
+ {
+ return;
+ }
+
+ temp = MsGetMyTempDir();
+ Format(wav, sizeof(tmp), "%s\\%s", temp, name);
+ DumpBuf(b, wav);
+
+ PlaySound(wav, NULL, SND_ASYNC | SND_FILENAME | SND_NODEFAULT);
+
+ FreeBuf(b);
+}
+
+// Show an icon in the task tray
+bool MsShowIconOnTray(HWND hWnd, HICON icon, wchar_t *tooltip, UINT msg)
+{
+ bool ret = true;
+ // Validate arguments
+ if (hWnd == NULL || icon == NULL)
+ {
+ return true;
+ }
+
+ if (MsIsNt() == false)
+ {
+ Zero(&nid, sizeof(nid));
+ nid.cbSize = sizeof(nid);
+ nid.hWnd = hWnd;
+ nid.uID = 1;
+ nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
+ nid.uCallbackMessage = msg;
+ nid.hIcon = icon;
+ UniToStr(nid.szTip, sizeof(nid.szTip), tooltip);
+ ret = Shell_NotifyIcon(NIM_ADD, &nid);
+ }
+ else
+ {
+ Zero(&nid_nt, sizeof(nid_nt));
+ nid_nt.cbSize = sizeof(nid_nt);
+ nid_nt.hWnd = hWnd;
+ nid_nt.uID = 1;
+ nid_nt.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
+ nid_nt.uCallbackMessage = msg;
+ nid_nt.hIcon = icon;
+ UniStrCpy(nid_nt.szTip, sizeof(nid_nt.szTip), tooltip);
+
+ ret = Shell_NotifyIconW(NIM_ADD, &nid_nt);
+ }
+
+ tray_inited = true;
+
+ return ret;
+}
+
+// Check whether the task tray has been initialized
+bool MsIsTrayInited()
+{
+ return tray_inited;
+}
+
+// Restore the icon in the task tray
+void MsRestoreIconOnTray()
+{
+ if (tray_inited == false)
+ {
+ return;
+ }
+
+ if (MsIsNt() == false)
+ {
+ Shell_NotifyIcon(NIM_ADD, &nid);
+ }
+ else
+ {
+ Shell_NotifyIconW(NIM_ADD, &nid_nt);
+ }
+}
+
+// Change the icon in the task tray (go over!)
+void MsChangeIconOnTrayEx2(void *icon, wchar_t *tooltip, wchar_t *info_title, wchar_t *info, UINT info_flags)
+{
+ MsChangeIconOnTrayEx((HICON)icon, tooltip, info_title, info, info_flags, false);
+}
+
+// Change the icon in the task tray
+void MsChangeIconOnTray(HICON icon, wchar_t *tooltip)
+{
+ MsChangeIconOnTrayEx(icon, tooltip, NULL, NULL, NIIF_NONE, false);
+}
+bool MsChangeIconOnTrayEx(HICON icon, wchar_t *tooltip, wchar_t *info_title, wchar_t *info, UINT info_flags, bool add)
+{
+ bool changed = false;
+ bool ret = true;
+
+ if (tray_inited == false)
+ {
+ return ret;
+ }
+
+ if (icon != NULL)
+ {
+ if (MsIsNt() == false)
+ {
+ if (nid.hIcon != icon)
+ {
+ changed = true;
+ nid.hIcon = icon;
+ }
+ }
+ else
+ {
+ if (nid_nt.hIcon != icon)
+ {
+ changed = true;
+ nid_nt.hIcon = icon;
+ }
+ }
+ }
+
+ if (tooltip != NULL)
+ {
+ if (MsIsNt() == false)
+ {
+ char tmp[MAX_SIZE];
+
+ UniToStr(tmp, sizeof(tmp), tooltip);
+
+ if (StrCmp(nid.szTip, tmp) != 0)
+ {
+ StrCpy(nid.szTip, sizeof(nid.szTip), tmp);
+ changed = true;
+ }
+ }
+ else
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ UniStrCpy(tmp, sizeof(tmp), tooltip);
+
+ if (UniStrCmp(nid_nt.szTip, tmp) != 0)
+ {
+ UniStrCpy(nid_nt.szTip, sizeof(nid_nt.szTip), tmp);
+ changed = true;
+ }
+ }
+ }
+
+ if (info_title != NULL && info != NULL)
+ {
+ if (MsIsNt() == false)
+ {
+ char tmp1[MAX_SIZE];
+ char tmp2[MAX_PATH];
+
+ UniToStr(tmp1, sizeof(tmp1), info_title);
+ UniToStr(tmp2, sizeof(tmp2), info);
+
+ if (StrCmp(nid.szInfo, tmp1) != 0 ||
+ StrCmp(nid.szInfoTitle, tmp2) != 0)
+ {
+ StrCpy(nid.szInfo, sizeof(nid.szInfo), tmp1);
+ StrCpy(nid.szInfoTitle, sizeof(nid.szInfoTitle), tmp2);
+ nid.dwInfoFlags = info_flags;
+
+ changed = true;
+ }
+ }
+ else
+ {
+ wchar_t tmp1[MAX_SIZE];
+ wchar_t tmp2[MAX_PATH];
+
+ UniStrCpy(tmp1, sizeof(tmp1), info_title);
+ UniStrCpy(tmp2, sizeof(tmp2), info);
+
+ if (UniStrCmp(nid_nt.szInfo, tmp1) != 0 ||
+ UniStrCmp(nid_nt.szInfoTitle, tmp2) != 0)
+ {
+ UniStrCpy(nid_nt.szInfo, sizeof(nid_nt.szInfo), tmp1);
+ UniStrCpy(nid_nt.szInfoTitle, sizeof(nid_nt.szInfoTitle), tmp2);
+ nid_nt.dwInfoFlags = info_flags;
+
+ changed = true;
+ }
+ }
+ }
+
+ if (changed || add)
+ {
+ UINT op = (add ? NIM_ADD : NIM_MODIFY);
+ if (MsIsNt() == false)
+ {
+ ret = Shell_NotifyIcon(op, &nid);
+ }
+ else
+ {
+ ret = Shell_NotifyIconW(op, &nid_nt);
+ }
+ }
+
+ return ret;
+}
+
+// Remove the icon in the task tray
+void MsHideIconOnTray()
+{
+ if (MsIsNt() == false)
+ {
+ Shell_NotifyIcon(NIM_DELETE, &nid);
+ }
+ else
+ {
+ Shell_NotifyIconW(NIM_DELETE, &nid_nt);
+ }
+
+ tray_inited = false;
+}
+
+// Insert a menu item
+bool MsInsertMenu(HMENU hMenu, UINT pos, UINT flags, UINT_PTR id_new_item, wchar_t *lp_new_item)
+{
+ bool ret;
+
+ if (MsIsNt())
+ {
+ ret = InsertMenuW(hMenu, pos, flags, id_new_item, lp_new_item);
+ }
+ else
+ {
+ char *s = CopyUniToStr(lp_new_item);
+ ret = InsertMenuA(hMenu, pos, flags, id_new_item, s);
+ Free(s);
+ }
+
+ return ret;
+}
+
+// Adding a menu item
+bool MsAppendMenu(HMENU hMenu, UINT flags, UINT_PTR id, wchar_t *str)
+{
+ bool ret;
+
+ if (MsIsNt())
+ {
+ ret = AppendMenuW(hMenu, flags, id, str);
+ }
+ else
+ {
+ char *s = CopyUniToStr(str);
+ ret = AppendMenuA(hMenu, flags, id, s);
+ Free(s);
+ }
+
+ return ret;
+}
+
+// Display the menu
+void MsUserModeTrayMenu(HWND hWnd)
+{
+ HMENU h;
+ POINT p;
+ wchar_t tmp[MAX_SIZE];
+ wchar_t caption[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ // Create a menu
+ h = CreatePopupMenu();
+ MsAppendMenu(h, MF_ENABLED | MF_STRING, 10001, _UU("SVC_USERMODE_MENU_1"));
+ MsAppendMenu(h, MF_SEPARATOR, 10002, NULL);
+
+ if (MsIsNt())
+ {
+ GetWindowTextW(hWnd, caption, sizeof(caption));
+ }
+ else
+ {
+ char tmp[MAX_SIZE];
+ GetWindowTextA(hWnd, tmp, sizeof(tmp));
+ StrToUni(caption, sizeof(caption), tmp);
+ }
+
+ UniFormat(tmp, sizeof(tmp), _UU("SVC_USERMODE_MENU_2"), caption);
+ MsAppendMenu(h, MF_ENABLED | MF_STRING, 10003, tmp);
+
+ // Display the menu
+ GetCursorPos(&p);
+
+ SetForegroundWindow(hWnd);
+ TrackPopupMenu(h, TPM_LEFTALIGN, p.x, p.y, 0, hWnd, NULL);
+ PostMessage(hWnd, WM_NULL, 0, 0);
+
+ DestroyMenu(h);
+}
+
+// Window procedure for the user mode
+LRESULT CALLBACK MsUserModeWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ wchar_t tmp[MAX_SIZE];
+ char title[MAX_SIZE];
+ wchar_t title_w[MAX_SIZE];
+ char value_name[MAX_SIZE];
+ static UINT taskbar_msg = 0;
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return 0;
+ }
+
+ if (msg == taskbar_msg && taskbar_msg != 0)
+ {
+ // The taskbar was regenerated
+ if (MsRegReadInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, value_name) == 0 &&
+ service_for_9x_mode == false)
+ {
+ MsRestoreIconOnTray();
+ }
+ }
+
+ switch (msg)
+ {
+ case WM_ENDSESSION:
+ // Resume
+ if (wParam == false)
+ {
+ break;
+ }
+ case WM_CREATE:
+ // Start
+ exiting = false;
+ g_start();
+ GetWindowText(hWnd, title, sizeof(title));
+ StrToUni(title_w, sizeof(title_w), title);
+ UniFormat(tmp, sizeof(tmp), _UU("SVC_TRAY_TOOLTIP"), title);
+
+ if (taskbar_msg == 0)
+ {
+ taskbar_msg = RegisterWindowMessage("TaskbarCreated");
+ }
+
+ Format(value_name, sizeof(value_name), SVC_HIDETRAY_REG_VALUE, title_w);
+ if (MsRegReadInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, value_name) == 0 &&
+ service_for_9x_mode == false)
+ {
+ MsShowIconOnTray(hWnd, tray_icon, tmp, WM_APP + 33);
+ }
+
+ break;
+ case WM_APP + 33:
+ if (wParam == 1)
+ {
+ // The operation to the icon in the task tray
+ switch (lParam)
+ {
+ case WM_RBUTTONDOWN:
+ // Right click
+ MsUserModeTrayMenu(hWnd);
+ break;
+ case WM_LBUTTONDBLCLK:
+ // Left double-click
+ break;
+ }
+ }
+ break;
+ case WM_LBUTTONDOWN:
+ MsUserModeTrayMenu(hWnd);
+ break;
+ case WM_QUERYENDSESSION:
+ if (exiting == false)
+ {
+ exiting = true;
+ MsHideIconOnTray();
+ g_stop();
+ DestroyWindow(hWnd);
+ }
+ return TRUE;
+ case WM_CLOSE:
+ // Stop
+ if (exiting == false)
+ {
+ exiting = true;
+ g_stop();
+ MsHideIconOnTray();
+ DestroyWindow(hWnd);
+ }
+ break;
+ case WM_DESTROY:
+ wnd_end = true;
+ break;
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case 10001:
+ GetWindowText(hWnd, title, sizeof(title));
+ StrToUni(title_w, sizeof(title_w), title);
+ // Display a confirmation message
+ if (MsgBoxEx(hWnd, MB_ICONINFORMATION | MB_OKCANCEL | MB_DEFBUTTON2 |
+ MB_SYSTEMMODAL, _UU("SVC_HIDE_TRAY_MSG"), title, title) == IDOK)
+ {
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), SVC_HIDETRAY_REG_VALUE, title_w);
+ // Write to the registry
+ MsRegWriteInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, tmp, 1);
+ // Hide the icon
+ MsHideIconOnTray();
+ }
+ break;
+ case 10003:
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+ break;
+ }
+ break;
+ }
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+}
+
+// Get the name of PenCore.dll
+char *MsGetPenCoreDllFileName()
+{
+ /*if (Is64())
+ {
+ if (IsX64())
+ {
+ return PENCORE_DLL_NAME_X64;
+ }
+ else
+ {
+ return PENCORE_DLL_NAME_IA64;
+ }
+ }
+ else*/
+ {
+ return PENCORE_DLL_NAME;
+ }
+}
+
+// Get whether this instance is in user mode
+bool MsIsUserMode()
+{
+ return is_usermode;
+}
+
+// Command to terminate the user-mode from the service side
+void MsStopUserModeFromService()
+{
+ if (hWndUsermode != NULL)
+ {
+ PostMessage(hWndUsermode, WM_CLOSE, 0, 0);
+ }
+}
+
+// Only run the test (for debugging)
+void MsTestOnly()
+{
+ g_start();
+ GetLine(NULL, 0);
+ g_stop();
+
+ _exit(0);
+}
+
+// Stop the user-mode service
+void MsStopUserModeSvc(char *svc_name)
+{
+ void *p;
+ // Validate arguments
+ if (svc_name == NULL)
+ {
+ return;
+ }
+
+ p = MsCreateUserModeSvcGlocalPulse(svc_name);
+ if (p == NULL)
+ {
+ return;
+ }
+
+ MsSendGlobalPulse(p);
+
+ MsCloseGlobalPulse(p);
+}
+
+// Creating a global pulse for user-mode service
+void *MsCreateUserModeSvcGlocalPulse(char *svc_name)
+{
+ char name[MAX_SIZE];
+ // Validate arguments
+ if (svc_name == NULL)
+ {
+ return NULL;
+ }
+
+ MsGenerateUserModeSvcGlobalPulseName(name, sizeof(name), svc_name);
+
+ return MsOpenOrCreateGlobalPulse(name);
+}
+
+// Get the global pulse name for the user-mode service
+void MsGenerateUserModeSvcGlobalPulseName(char *name, UINT size, char *svc_name)
+{
+ wchar_t tmp[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (name == NULL || svc_name == NULL)
+ {
+ return;
+ }
+
+ UniFormat(tmp, sizeof(tmp), L"usersvc_%S_@_%s", svc_name, MsGetUserNameW());
+
+ UniTrim(tmp);
+ UniStrUpper(tmp);
+
+ HashSha1(hash, tmp, UniStrLen(tmp) * sizeof(wchar_t));
+
+ BinToStr(name, size, hash, sizeof(hash));
+}
+
+// Start in user mode
+void MsUserMode(char *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon)
+{
+ wchar_t *title_w = CopyStrToUni(title);
+
+ MsUserModeW(title_w, start, stop, icon);
+
+ Free(title_w);
+}
+void MsUserModeW(wchar_t *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon)
+{
+ WNDCLASS wc;
+ HINSTANCE hDll;
+ HWND hWnd;
+ MSG msg;
+ INSTANCE *inst;
+ char title_a[MAX_PATH];
+ MS_USERMODE_SVC_PULSE_THREAD_PARAM p;
+ THREAD *recv_thread = NULL;
+ // Validate arguments
+ if (title == NULL || start == NULL || stop == NULL)
+ {
+ return;
+ }
+
+ UniToStr(title_a, sizeof(title_a), title);
+
+ is_usermode = true;
+ g_start = start;
+ g_stop = stop;
+
+ inst = NewSingleInstance(NULL);
+ if (inst == NULL)
+ {
+ if (service_for_9x_mode == false)
+ {
+ // Do not display an error if Win9x service mode
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_USERMODE_MUTEX"), ms->ExeFileNameW);
+ }
+ return;
+ }
+
+ if (Is64())
+ {
+ hDll = MsLoadLibraryAsDataFile(MsGetPenCoreDllFileName());
+ }
+ else
+ {
+ hDll = MsLoadLibrary(MsGetPenCoreDllFileName());
+ }
+
+ // Read icon
+ tray_icon = LoadImage(hDll, MAKEINTRESOURCE(icon), IMAGE_ICON, 16, 16,
+ (MsIsNt() ? LR_SHARED : 0) | LR_VGACOLOR);
+
+ // Creating the main window
+ Zero(&wc, sizeof(wc));
+ wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
+ wc.hCursor = LoadCursor(NULL,IDC_ARROW);
+ wc.hIcon = LoadIcon(hDll, MAKEINTRESOURCE(icon));
+ wc.hInstance = ms->hInst;
+ wc.lpfnWndProc = MsUserModeWindowProc;
+ wc.lpszClassName = title_a;
+ if (RegisterClass(&wc) == 0)
+ {
+ return;
+ }
+
+ hWnd = CreateWindow(title_a, title_a, WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, NULL, ms->hInst, NULL);
+
+ if (hWnd == NULL)
+ {
+ return;
+ }
+
+ Zero(&p, sizeof(p));
+ p.hWnd = hWnd;
+ p.GlobalPulse = MsCreateUserModeSvcGlocalPulse(g_service_name);
+
+ if (p.GlobalPulse != NULL)
+ {
+ // Start the global pulse monitoring thread for termination
+ p.Halt = false;
+
+ recv_thread = NewThread(MsUserModeGlobalPulseRecvThread, &p);
+ }
+
+ hWndUsermode = hWnd;
+
+ wnd_end = false;
+ // Window loop
+ while (wnd_end == false)
+ {
+ GetMessage(&msg, NULL, 0, 0);
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ FreeSingleInstance(inst);
+
+ p.hWnd = NULL;
+
+ hWndUsermode = NULL;
+
+ if (p.GlobalPulse != NULL)
+ {
+ // Terminate the monitoring thread of termination global pulse
+ p.Halt = true;
+ MsSendGlobalPulse(p.GlobalPulse);
+
+ WaitThread(recv_thread, INFINITE);
+ ReleaseThread(recv_thread);
+
+ MsCloseGlobalPulse(p.GlobalPulse);
+ }
+
+ // Might abort
+ _exit(0);
+}
+
+// The thread that wait for global pulse to stop the user mode service
+void MsUserModeGlobalPulseRecvThread(THREAD *thread, void *param)
+{
+ MS_USERMODE_SVC_PULSE_THREAD_PARAM *p = (MS_USERMODE_SVC_PULSE_THREAD_PARAM *)param;
+ // Validate arguments
+ if (thread == NULL || p == NULL)
+ {
+ return;
+ }
+
+ while (p->Halt == false)
+ {
+ if (MsWaitForGlobalPulse(p->GlobalPulse, INFINITE))
+ {
+ break;
+ }
+ }
+
+ if (p->hWnd != NULL)
+ {
+ PostMessageA(p->hWnd, WM_CLOSE, 0, 0);
+ }
+}
+
+// Service stopping procedure main thread
+void MsServiceStoperMainThread(THREAD *t, void *p)
+{
+ // Stopping procedure
+ g_stop();
+}
+
+// Service stop procedure
+bool MsServiceStopProc()
+{
+ THREAD *thread;
+ bool ret = true;
+ UINT64 selfkill_timeout = Tick64() + SVC_SELFKILL_TIMEOUT;
+
+ thread = NewThread(MsServiceStoperMainThread, NULL);
+
+ while (WaitThread(thread, 250) == false)
+ {
+ if (Tick64() >= selfkill_timeout)
+ {
+ // Suicide when it freezes
+ ret = false;
+ break;
+ }
+ // During stopping procedure to complete, call the SetServiceStatus periodically
+ status.dwWin32ExitCode = 0;
+ status.dwWaitHint = 100000;
+ status.dwCheckPoint++;
+ status.dwCurrentState = SERVICE_STOP_PENDING;
+ _SetServiceStatus(ssh, &status);
+ }
+
+ // Report that the stopping is complete
+ status.dwWin32ExitCode = 0;
+ status.dwWaitHint = 0;
+ status.dwCheckPoint = 0;
+ status.dwCurrentState = SERVICE_STOPPED;
+ _SetServiceStatus(ssh, &status);
+
+ if (ret == false)
+ {
+ // Force termination here if this has committed suicide
+ _exit(-1);
+ }
+ else
+ {
+ ReleaseThread(thread);
+ }
+
+ return ret;
+}
+
+// Service handler
+void CALLBACK MsServiceHandler(DWORD opcode)
+{
+ switch (opcode)
+ {
+ case SERVICE_CONTROL_SHUTDOWN:
+ case SERVICE_CONTROL_STOP:
+ // Stopping request
+ status.dwWin32ExitCode = 0;
+ status.dwWaitHint = 100000;
+ status.dwCheckPoint = 0;
+ status.dwCurrentState = SERVICE_STOP_PENDING;
+
+ // Set the stopping event
+ if (service_stop_event != NULL)
+ {
+ SetEvent(service_stop_event);
+ }
+ break;
+ }
+
+ _SetServiceStatus(ssh, &status);
+}
+
+// Dispatch function of the service
+void CALLBACK MsServiceDispatcher(DWORD argc, LPTSTR *argv)
+{
+ // Creating a stopping event
+ service_stop_event = CreateEventA(NULL, true, false, NULL);
+
+ // Preparing for the service
+ Zero(&status, sizeof(status));
+ status.dwServiceType = SERVICE_WIN32;
+ status.dwCurrentState = SERVICE_START_PENDING;
+ status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
+
+ ssh = _RegisterServiceCtrlHandler(g_service_name, MsServiceHandler);
+
+ if (ssh == NULL)
+ {
+ MessageBox(NULL, "RegisterServiceCtrlHandler() Failed.", "MsServiceDispatcher()", MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION);
+ return;
+ }
+
+ status.dwWaitHint = 300000;
+ status.dwCheckPoint = 0;
+ status.dwCheckPoint++;
+ status.dwCurrentState = SERVICE_START_PENDING;
+ _SetServiceStatus(ssh, &status);
+
+ // Report the start completion
+ status.dwWaitHint = 0;
+ status.dwCheckPoint = 0;
+ status.dwCurrentState = SERVICE_RUNNING;
+ _SetServiceStatus(ssh, &status);
+
+ //// Initialization
+ // Start of the Mayaqua
+ InitMayaqua(false, false, 0, NULL);
+
+ // Stop the MS-IME
+ MsDisableIme();
+
+ // Service operation start
+ g_start();
+ MsUpdateServiceConfig(g_service_name);
+
+ // Wait for the stopping event to be signaled state
+ WaitForSingleObject(service_stop_event, INFINITE);
+
+ // Service operation stop
+ MsServiceStopProc();
+}
+
+// Start as a test mode
+void MsTestMode(char *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
+{
+ wchar_t *title_w = CopyStrToUni(title);
+
+ MsTestModeW(title_w, start, stop);
+ Free(title_w);
+}
+void MsTestModeW(wchar_t *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
+{
+ INSTANCE *inst;
+ // Validate arguments
+ if (title == NULL || start == NULL || stop == NULL)
+ {
+ return;
+ }
+
+ is_usermode = true;
+
+ inst = NewSingleInstance(NULL);
+ if (inst == NULL)
+ {
+ // Already started
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_TEST_MUTEX"), ms->ExeFileNameW);
+ return;
+ }
+
+ // Start
+ start();
+
+ // Display the message
+ MsgBoxEx(NULL, MB_ICONINFORMATION | MB_SYSTEMMODAL, _UU("SVC_TEST_MSG"), title);
+
+ // Stop
+ stop();
+
+ FreeSingleInstance(inst);
+}
+
+// Write the process ID of the process which is calling the service manager
+void MsWriteCallingServiceManagerProcessId(char *svcname, UINT pid)
+{
+ char tmp[MAX_PATH];
+
+ Format(tmp, sizeof(tmp), SVC_CALLING_SM_PROCESS_ID_KEY, svcname);
+
+ if (pid != 0)
+ {
+ MsRegWriteInt(REG_LOCAL_MACHINE, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE, pid);
+ MsRegWriteInt(REG_CURRENT_USER, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE, pid);
+ }
+ else
+ {
+ MsRegDeleteValue(REG_LOCAL_MACHINE, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE);
+ MsRegDeleteKey(REG_LOCAL_MACHINE, tmp);
+
+ MsRegDeleteValue(REG_CURRENT_USER, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE);
+ MsRegDeleteKey(REG_CURRENT_USER, tmp);
+ }
+}
+
+// Get the process ID of the process which is calling the service manager
+UINT MsReadCallingServiceManagerProcessId(char *svcname, bool current_user)
+{
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (svcname == NULL)
+ {
+ return 0;
+ }
+
+ Format(tmp, sizeof(tmp), SVC_CALLING_SM_PROCESS_ID_KEY, svcname);
+
+ return MsRegReadInt(current_user ? REG_CURRENT_USER : REG_LOCAL_MACHINE, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE);
+}
+
+// Dispatch function of the service
+void CALLBACK MsScmDispatcher(DWORD argc, LPTSTR *argv)
+{
+}
+
+// Service main function
+UINT MsService(char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon, char *cmd_line)
+{
+ UINT mode;
+ UINT ret = 0;
+ char *arg;
+ wchar_t *arg_w;
+ TOKEN_LIST *t = NULL;
+ UNI_TOKEN_LIST *ut = NULL;
+ char *service_name;
+ wchar_t *service_title;
+ wchar_t *service_description;
+ wchar_t *service_title_uni;
+ char tmp[MAX_SIZE];
+ bool restoreReg = false;
+ bool silent = false;
+ bool is_win32_service_mode = false;
+ // Validate arguments
+ if (name == NULL || start == NULL || stop == NULL)
+ {
+ return ret;
+ }
+
+ g_start = start;
+ g_stop = stop;
+ StrCpy(g_service_name, sizeof(g_service_name), name);
+ StrLower(g_service_name);
+
+ // Determine whether it's in Win32 service mode
+ if (cmd_line != NULL && lstrcmpiA(cmd_line, SVC_ARG_SERVICE) == 0)
+ {
+ HINSTANCE h_advapi32 = LoadLibraryA("advapi32.dll");
+
+ if (h_advapi32 != NULL)
+ {
+ // Check whether there is the SCM in the service mode
+ _StartServiceCtrlDispatcher =
+ (BOOL (__stdcall *)(const LPSERVICE_TABLE_ENTRY))
+ GetProcAddress(h_advapi32, "StartServiceCtrlDispatcherW");
+
+ _RegisterServiceCtrlHandler =
+ (SERVICE_STATUS_HANDLE (__stdcall *)(LPCTSTR,LPHANDLER_FUNCTION))
+ GetProcAddress(h_advapi32, "RegisterServiceCtrlHandlerW");
+
+ _SetServiceStatus =
+ (BOOL (__stdcall *)(SERVICE_STATUS_HANDLE,LPSERVICE_STATUS))
+ GetProcAddress(h_advapi32, "SetServiceStatus");
+
+ if (_StartServiceCtrlDispatcher != NULL &&
+ _RegisterServiceCtrlHandler != NULL &&
+ _SetServiceStatus != NULL)
+ {
+ is_win32_service_mode = true;
+ }
+ }
+ }
+
+ // Run the service using the SCM in the case of Win32 service mode
+ if (is_win32_service_mode)
+ {
+ SERVICE_TABLE_ENTRY dispatch_table[] =
+ {
+ {"", MsServiceDispatcher},
+ {NULL, NULL},
+ };
+
+ MsSetErrorModeToSilent();
+
+ if (_StartServiceCtrlDispatcher(dispatch_table) == false)
+ {
+ MessageBox(NULL, "StartServiceCtrlDispatcher() Failed.", "MsServiceMode()", MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION);
+ }
+ else
+ {
+ MsUpdateServiceConfig(g_service_name);
+ }
+
+ // Abort here in the case of using the SCM
+ _exit(0);
+ return 0;
+ }
+
+ // Start of the Mayaqua
+ InitMayaqua(false, false, 0, NULL);
+
+ // Stop the MS-IME
+ MsDisableIme();
+
+ // Get the information about the service from the string table
+ Format(tmp, sizeof(tmp), SVC_NAME, name);
+ service_name = _SS(tmp);
+ Format(tmp, sizeof(tmp), SVC_TITLE, name);
+ service_title = _UU(tmp);
+ service_title_uni = _UU(tmp);
+ Format(tmp, sizeof(tmp), SVC_DESCRIPT, name);
+ service_description = _UU(tmp);
+
+ if (StrLen(service_name) == 0 || UniStrLen(service_title) == 0)
+ {
+ // The service information isn't found
+ MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_NOT_FOUND"), name);
+ }
+ else
+ {
+ wchar_t path[MAX_SIZE];
+ // Check the argument
+ mode = SVC_MODE_NONE;
+
+ t = GetCommandLineToken();
+ arg = NULL;
+
+ ut = GetCommandLineUniToken();
+ arg_w = NULL;
+
+ if (t->NumTokens >= 1)
+ {
+ arg = t->Token[0];
+ }
+ if(t->NumTokens >= 2)
+ {
+ if(StrCmpi(t->Token[1], SVC_ARG_SILENT) == 0)
+ {
+ silent = true;
+ }
+ }
+
+ if (ut->NumTokens >= 1)
+ {
+ arg_w = ut->Token[0];
+ }
+
+ if (arg != NULL)
+ {
+ if (StrCmpi(arg, SVC_ARG_INSTALL) == 0)
+ {
+ mode = SVC_MODE_INSTALL;
+ }
+ if (StrCmpi(arg, SVC_ARG_UNINSTALL) == 0)
+ {
+ mode = SVC_MODE_UNINSTALL;
+ }
+ if (StrCmpi(arg, SVC_ARG_START) == 0)
+ {
+ mode = SVC_MODE_START;
+ }
+ if (StrCmpi(arg, SVC_ARG_STOP) == 0)
+ {
+ mode = SVC_MODE_STOP;
+ }
+ if (StrCmpi(arg, SVC_ARG_TEST) == 0)
+ {
+ mode = SVC_MODE_TEST;
+ }
+ if (StrCmpi(arg, SVC_ARG_USERMODE) == 0)
+ {
+ mode = SVC_MODE_USERMODE;
+ }
+ if (StrCmpi(arg, SVC_ARG_SETUP_INSTALL) == 0)
+ {
+ mode = SVC_MODE_SETUP_INSTALL;
+ }
+ if (StrCmpi(arg, SVC_ARG_SETUP_UNINSTALL) == 0)
+ {
+ mode = SVC_MODE_SETUP_UNINSTALL;
+ }
+ if (StrCmpi(arg, SVC_ARG_WIN9X_SERVICE) == 0)
+ {
+ mode = SVC_MODE_WIN9X_SERVICE;
+ }
+ if (StrCmpi(arg, SVC_ARG_WIN9X_INSTALL) == 0)
+ {
+ mode = SVC_MODE_WIN9X_INSTALL;
+ }
+ if (StrCmpi(arg, SVC_ARG_WIN9X_UNINSTALL) == 0)
+ {
+ mode = SVC_MODE_WIN9X_UNINSTALL;
+ }
+ if (StrCmpi(arg, SVC_ARG_TCP) == 0)
+ {
+ mode = SVC_MODE_TCP;
+ }
+ if (StrCmpi(arg, SVC_ARG_TCP_UAC) == 0)
+ {
+ mode = SVC_MODE_TCP_UAC;
+ }
+ if (StrCmpi(arg, SVC_ARG_TCP_SETUP) == 0)
+ {
+ mode = SVC_MODE_TCPSETUP;
+ }
+ if (StrCmpi(arg, SVC_ARG_TRAFFIC) == 0)
+ {
+ mode = SVC_MODE_TRAFFIC;
+ }
+ if (StrCmpi(arg, SVC_ARG_UIHELP) == 0)
+ {
+ mode = SVC_MODE_UIHELP;
+ }
+ if (StrCmpi(arg, SVC_ARG_USERMODE_SHOWTRAY) == 0)
+ {
+ char tmp[MAX_SIZE];
+ mode = SVC_MODE_USERMODE;
+ Format(tmp, sizeof(tmp), SVC_HIDETRAY_REG_VALUE, service_title);
+ MsRegDeleteValue(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, tmp);
+ }
+ if (StrCmpi(arg, SVC_ARG_USERMODE_HIDETRAY) == 0)
+ {
+ char tmp[MAX_SIZE];
+ mode = SVC_MODE_USERMODE;
+ Format(tmp, sizeof(tmp), SVC_HIDETRAY_REG_VALUE, service_title);
+ MsRegWriteInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, tmp, 1);
+ }
+ if (StrCmpi(arg, SVC_ARG_SERVICE) == 0)
+ {
+ mode = SVC_MODE_SERVICE;
+ }
+
+ if (mode != SVC_MODE_NONE)
+ {
+ // Network Config
+ MsInitGlobalNetworkConfig();
+ }
+ }
+
+ // Get the command-line name when running as a service
+ UniFormat(path, sizeof(path), SVC_RUN_COMMANDLINE, ms->ExeFileNameW);
+
+ if ((mode == SVC_MODE_INSTALL || mode == SVC_MODE_UNINSTALL || mode == SVC_MODE_START ||
+ mode == SVC_MODE_STOP || mode == SVC_MODE_SERVICE) &&
+ (ms->IsNt == false))
+ {
+ // Tried to use the command for the NT in non-WindowsNT system
+ MsgBox(NULL, MB_ICONSTOP, _UU("SVC_NT_ONLY"));
+ }
+ else if ((mode == SVC_MODE_INSTALL || mode == SVC_MODE_UNINSTALL || mode == SVC_MODE_START ||
+ mode == SVC_MODE_STOP || mode == SVC_MODE_SERVICE) &&
+ (ms->IsAdmin == false))
+ {
+ // Do not have Administrators privillage
+ MsgBox(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_ADMIN"));
+ }
+ else
+ {
+ // Performs processing depend on mode
+ switch (mode)
+ {
+ case SVC_MODE_NONE:
+ // Exit by showing a guidance message
+ if (arg_w != NULL && UniEndWith(arg_w, L".vpn"))
+ {
+ if (MsgBox(NULL, MB_ICONQUESTION | MB_YESNO, _UU("CM_VPN_FILE_CLICKED")) == IDYES)
+ {
+ wchar_t vpncmgr[MAX_PATH];
+ wchar_t filename[MAX_PATH];
+
+ UniFormat(filename, sizeof(filename), L"\"%s\"", arg_w);
+
+ if (Is64() == false)
+ {
+ UniFormat(vpncmgr, sizeof(vpncmgr), L"%s\\vpncmgr.exe", MsGetExeDirNameW());
+ }
+ else
+ {
+ UniFormat(vpncmgr, sizeof(vpncmgr), L"%s\\vpncmgr_x64.exe", MsGetExeDirNameW());
+ }
+
+ RunW(vpncmgr, filename, false, false);
+ }
+ }
+ else
+ {
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_HELP"),
+ service_title, service_name, service_title, service_title, service_name, service_title, service_name, service_title, service_name, service_title, service_name, service_title, service_title);
+ }
+ break;
+
+ case SVC_MODE_SETUP_INSTALL:
+ // Setup.exe installation mode
+ // Uninstall the old version
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsServiceInstalled(service_name))
+ {
+ if (MsIsServiceRunning(service_name))
+ {
+ MsStopService(service_name);
+ }
+ MsUninstallService(service_name);
+ }
+ if (MsInstallServiceW(service_name, service_title, service_description, path) == false)
+ {
+ ret = 1;
+ }
+ MsStartService(service_name);
+ MsWriteCallingServiceManagerProcessId(service_name, 0);
+ break;
+
+ case SVC_MODE_SETUP_UNINSTALL:
+ // Setup.exe uninstall mode
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsServiceInstalled(service_name))
+ {
+ if (MsIsServiceRunning(service_name))
+ {
+ MsStopService(service_name);
+ }
+ if (MsUninstallService(service_name) == false)
+ {
+ ret = 1;
+ }
+ }
+ break;
+
+ case SVC_MODE_INSTALL:
+ // Install the service
+ // Check whether it is already installed
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsServiceInstalled(service_name))
+ {
+ // Already installed
+ // Show a message asking if you want to uninstall
+ if(silent == true)
+ {
+ // Always cancel the operation
+ break;
+ }
+ if (MsgBoxEx(NULL, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("SVC_ALREADY_INSTALLED"),
+ service_title, service_name) == IDNO)
+ {
+ // Cancel the operation
+ break;
+ }
+ else
+ {
+ // Whether the existing service is working?
+ if (MsIsServiceRunning(service_name))
+ {
+ // Try to stop
+ if (MsStopService(service_name) == false)
+ {
+ // Failed to stop
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_STOP_FAILED"),
+ service_title, service_name);
+ }
+ break;
+ }
+ }
+ // Uninstall
+ if (MsUninstallService(service_name) == false)
+ {
+ // Failed to uninstall
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_UNINSTALL_FAILED"),
+ service_title, service_name);
+ }
+ break;
+ }
+ }
+ }
+
+ // Do the installation
+ if (MsInstallServiceW(service_name, service_title, service_description, path) == false)
+ {
+ // Failed to install
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_INSTALL_FAILED"),
+ service_title, service_name);
+ }
+ break;
+ }
+
+ // Start the service
+ if (MsStartService(service_name) == false)
+ {
+ // Failed to start
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_INSTALL_FAILED_2"),
+ service_title, service_name, path);
+ }
+ break;
+ }
+
+ // All successful
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_INSTALL_OK"),
+ service_title, service_name, path);
+ }
+ break;
+
+ case SVC_MODE_UNINSTALL:
+ // Uninstall the service
+ // Check whether it is already installed
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsServiceInstalled(service_name) == false)
+ {
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_INSTALLED"),
+ service_title, service_name, path);
+ }
+ break;
+ }
+
+ // If the service is currently running, stop it
+ if (MsIsServiceRunning(service_name))
+ {
+ // Stop the service
+ if (MsStopService(service_name) == false)
+ {
+ // Failed to stop
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_STOP_FAILED"),
+ service_title, service_name);
+ }
+ break;
+ }
+ }
+
+ // Uninstall the service
+ if (MsUninstallService(service_name) == false)
+ {
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_UNINSTALL_FAILED"),
+ service_title, service_name);
+ }
+ break;
+ }
+
+ // All successful
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_UNINSTALL_OK"),
+ service_title, service_name);
+ }
+ break;
+
+ case SVC_MODE_START:
+ // Start the service
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsServiceInstalled(service_name) == false)
+ {
+ // Service is not installed
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_INSTALLED"),
+ service_title, service_name);
+ }
+ break;
+ }
+
+ // Confirm whether the service is running
+ if (MsIsServiceRunning(service_name))
+ {
+ // Service is running
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVR_ALREADY_START"),
+ service_title, service_name);
+ }
+ break;
+ }
+
+ // Start the service
+ if (MsStartService(service_name) == false)
+ {
+ // Failed to start
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_START_FAILED"),
+ service_title, service_name);
+ }
+ break;
+ }
+
+ // All successful
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_START_OK"),
+ service_title, service_name);
+ }
+ break;
+
+ case SVC_MODE_STOP:
+ // Stop the service
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsServiceInstalled(service_name) == false)
+ {
+ // Service is not installed
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_INSTALLED"),
+ service_title, service_name);
+ }
+ break;
+ }
+
+ // Confirm whether the service is running
+ if (MsIsServiceRunning(service_name) == false)
+ {
+ // The service is stopped
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_ALREADY_STOP"),
+ service_title, service_name);
+ }
+ break;
+ }
+ // Stop the service
+ if (MsStopService(service_name) == false)
+ {
+ // Failed to stop
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_STOP_FAILED"),
+ service_title, service_name);
+ }
+ break;
+ }
+
+ // All successful
+ if(silent == false)
+ {
+ MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_STOP_OK"),
+ service_title, service_name);
+ }
+ break;
+
+ case SVC_MODE_TEST:
+ // Test mode
+ MsTestModeW(service_title, start, stop);
+ break;
+
+ case SVC_MODE_WIN9X_SERVICE:
+ // Win9x service mode (hide icon in the task tray unconditionally)
+ if (MsIsNt())
+ {
+ // Don't do this on Windows 2000 or later
+ break;
+ }
+ service_for_9x_mode = true;
+ // Not a oblivion to break
+ case SVC_MODE_USERMODE:
+ // User mode
+ MsUserModeW(service_title, start, stop, icon);
+ break;
+
+ case SVC_MODE_WIN9X_INSTALL:
+ // Win9x installation mode
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsNt() == false)
+ {
+ // Adding a registry key
+ char cmdline[MAX_PATH];
+ Format(cmdline, sizeof(cmdline), "\"%s\" %s",
+ MsGetExeFileName(), SVC_ARG_WIN9X_SERVICE);
+ MsRegWriteStr(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_1,
+ name, cmdline);
+ MsRegWriteStr(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_2,
+ name, cmdline);
+
+ // Start
+ //Run(MsGetExeFileName(), SVC_ARG_WIN9X_SERVICE, false, false);
+ }
+ break;
+
+ case SVC_MODE_WIN9X_UNINSTALL:
+ // Win9x uninstall mode
+ MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
+ restoreReg = true;
+
+ if (MsIsNt() == false)
+ {
+ // Delete the registry key
+ MsRegDeleteValue(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_1,
+ name);
+ MsRegDeleteValue(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_2,
+ name);
+
+ // Terminate all the processes of PacketiX VPN Client other than itself
+ MsKillOtherInstance();
+ }
+ break;
+
+ case SVC_MODE_SERVICE:
+ // Run as a service
+ // Obsolated (2012.12.31) (Do this in the above code)
+ //MsServiceMode(start, stop);
+ break;
+
+ case SVC_MODE_TCP:
+ case SVC_MODE_TCP_UAC:
+ // TCP Utility
+ InitCedar();
+ InitWinUi(service_title_uni, NULL, 0);
+
+ if (MsIsVista() && MsIsAdmin() == false && mode != SVC_MODE_TCP_UAC)
+ {
+ void *handle = NULL;
+ if (MsExecuteEx2W(ms->ExeFileNameW, SVC_ARG_TCP_UAC_W, &handle, true) == false)
+ {
+ ShowTcpIpConfigUtil(NULL, true);
+ }
+ else
+ {
+ MsWaitProcessExit(handle);
+ }
+ }
+ else
+ {
+ ShowTcpIpConfigUtil(NULL, true);
+ }
+
+ FreeWinUi();
+ FreeCedar();
+ break;
+
+ case SVC_MODE_TCPSETUP:
+ // TCP optimization mode (This is called by the installer)
+ InitCedar();
+ InitWinUi(service_title_uni, NULL, 0);
+
+ if (MsIsVista() && MsIsAdmin() == false)
+ {
+ void *handle = NULL;
+ if (MsExecuteEx2W(ms->ExeFileNameW, arg_w, &handle, true) == false)
+ {
+ ShowTcpIpConfigUtil(NULL, false);
+ }
+ else
+ {
+ MsWaitProcessExit(handle);
+ }
+ }
+ else
+ {
+ ShowTcpIpConfigUtil(NULL, false);
+ }
+
+ FreeWinUi();
+ FreeCedar();
+ break;
+
+ case SVC_MODE_TRAFFIC:
+ // Communication throughput measurement tool
+ InitCedar();
+ InitWinUi(service_title_uni, NULL, 0);
+ CmTraffic(NULL);
+ FreeWinUi();
+ FreeCedar();
+ break;
+
+ case SVC_MODE_UIHELP:
+ // Starting the UI Helper
+ CnStart();
+ break;
+ }
+
+ }
+ FreeToken(t);
+ UniFreeToken(ut);
+
+ if (restoreReg)
+ {
+ MsWriteCallingServiceManagerProcessId(service_name, 0);
+ }
+ }
+
+ FreeMayaqua();
+
+ return 0;
+}
+
+// Get the user name of the specified session
+wchar_t *MsGetSessionUserName(UINT session_id)
+{
+ if (MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled())
+ {
+ wchar_t *ret;
+ wchar_t *name;
+ UINT size = 0;
+ if (ms->nt->WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session_id,
+ WTSUserName, (wchar_t *)&name, &size) == false)
+ {
+ return NULL;
+ }
+
+ if (name == NULL || UniStrLen(name) == 0)
+ {
+ ret = NULL;
+ }
+ else
+ {
+ ret = UniCopyStr(name);
+ }
+
+ ms->nt->WTSFreeMemory(name);
+
+ return ret;
+ }
+ return NULL;
+}
+
+// Get whether the current desktop is available for the VNC
+bool MsIsCurrentDesktopAvailableForVnc()
+{
+ if (MsIsNt() == false)
+ {
+ return true;
+ }
+
+ if (MsIsCurrentTerminalSessionActive() == false)
+ {
+ return false;
+ }
+
+ if (ms->nt->OpenDesktopA == NULL ||
+ ms->nt->CloseDesktop == NULL ||
+ ms->nt->SwitchDesktop == NULL)
+ {
+ return true;
+ }
+ else
+ {
+ HDESK hDesk = ms->nt->OpenDesktopA("default", 0, false, DESKTOP_SWITCHDESKTOP);
+ bool ret;
+
+ if (hDesk == NULL)
+ {
+ return false;
+ }
+
+ ret = ms->nt->SwitchDesktop(hDesk);
+ ms->nt->CloseDesktop(hDesk);
+
+ return ret;
+ }
+}
+
+// Get whether the current terminal session is active
+bool MsIsCurrentTerminalSessionActive()
+{
+ return MsIsTerminalSessionActive(MsGetCurrentTerminalSessionId());
+}
+
+// Get whether the specified terminal session is active
+bool MsIsTerminalSessionActive(UINT session_id)
+{
+ if (MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled())
+ {
+ UINT *status = NULL;
+ UINT size = sizeof(status);
+ bool active = true;
+
+ if (ms->nt->WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session_id,
+ WTSConnectState, (wchar_t *)&status, &size) == false)
+ {
+ return true;
+ }
+
+ switch (*status)
+ {
+ case WTSDisconnected:
+ case WTSShadow:
+ case WTSIdle:
+ case WTSDown:
+ case WTSReset:
+ active = false;
+ break;
+ }
+
+ ms->nt->WTSFreeMemory(status);
+
+ return active;
+ }
+
+ return true;
+}
+
+// Get the current terminal session ID
+UINT MsGetCurrentTerminalSessionId()
+{
+ if (MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled())
+ {
+ UINT ret;
+ UINT *session_id = NULL;
+ UINT size = sizeof(session_id);
+ if (ms->nt->WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION,
+ WTSSessionId, (wchar_t *)&session_id, &size) == false)
+ {
+ return 0;
+ }
+
+ ret = *session_id;
+
+ ms->nt->WTSFreeMemory(session_id);
+
+ return ret;
+ }
+
+ return 0;
+}
+
+// Examine whether the Terminal Services is installed and the multiple sessions can log in
+bool MsIsTerminalServiceMultiUserInstalled()
+{
+ OS_INFO *info = GetOsInfo();
+ OSVERSIONINFOEX i;
+ if (MsIsTerminalServiceInstalled() == false)
+ {
+ return false;
+ }
+
+ if (OS_IS_SERVER(info->OsType) == false)
+ {
+ return false;
+ }
+
+ Zero(&i, sizeof(i));
+ i.dwOSVersionInfoSize = sizeof(i);
+ if (GetVersionEx((OSVERSIONINFO *)&i) == false)
+ {
+ return false;
+ }
+
+ if (i.wSuiteMask & VER_SUITE_SINGLEUSERTS)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Examine whether the user switching is installed
+bool MsIsUserSwitchingInstalled()
+{
+ OS_INFO *info = GetOsInfo();
+ OSVERSIONINFOEX i;
+
+ if (OS_IS_WINDOWS_NT(info->OsType) == false)
+ {
+ return false;
+ }
+
+ if (ms->nt->WTSDisconnectSession == NULL ||
+ ms->nt->WTSFreeMemory == NULL ||
+ ms->nt->WTSQuerySessionInformation == NULL)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) < 2)
+ {
+ return false;
+ }
+
+ Zero(&i, sizeof(i));
+ i.dwOSVersionInfoSize = sizeof(i);
+ if (GetVersionEx((OSVERSIONINFO *)&i) == false)
+ {
+ return false;
+ }
+
+ if (i.wSuiteMask & VER_SUITE_SINGLEUSERTS)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Enable the remote desktop
+bool MsEnableRemoteDesktop()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (MsIsRemoteDesktopAvailable() == false)
+ {
+ return false;
+ }
+
+ if (MsIsRemoteDesktopEnabled())
+ {
+ return true;
+ }
+
+ if (GET_KETA(info->OsType, 100) == 2)
+ {
+ // Windows 2000
+ return false;
+ }
+
+ if (MsRegWriteInt(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Terminal Server",
+ "fDenyTSConnections", 0) == false)
+ {
+ return false;
+ }
+
+ if (MsIsVista())
+ {
+ if (MsRegWriteInt(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp",
+ "UserAuthentication", 0) == false)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Examine whether the Remote Desktop is enabled
+bool MsIsRemoteDesktopEnabled()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (MsIsRemoteDesktopAvailable() == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) == 2)
+ {
+ // Windows 2000
+ return MsIsServiceRunning("TermService");
+ }
+ else
+ {
+ // Windows XP or later
+ bool b = MsRegReadInt(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Terminal Server",
+ "fDenyTSConnections");
+
+ if (MsIsVista() == false)
+ {
+ return b ? false : true;
+ }
+ else
+ {
+ if (b)
+ {
+ return false;
+ }
+ else
+ {
+ if (MsRegReadInt(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp",
+ "UserAuthentication"))
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+ }
+}
+
+// Examine whether the remote desktop becomes available by registry operation
+bool MsIsRemoteDesktopCanEnableByRegistory()
+{
+ OS_INFO *info = GetOsInfo();
+ if (MsIsRemoteDesktopAvailable() == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) == 2)
+ {
+ // Windows 2000
+ return false;
+ }
+ else
+ {
+ // Others
+ return true;
+ }
+}
+
+// Examine whether it's running on Windows 2000
+bool MsIsWin2000()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (OS_IS_WINDOWS_NT(info->OsType) == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) == 2)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Examine whether Windows 2000 or later
+bool MsIsWin2000OrGreater()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (OS_IS_WINDOWS_NT(info->OsType) == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) >= 2)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Examine whether Windows XP or later
+bool MsIsWinXPOrGreater()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (OS_IS_WINDOWS_NT(info->OsType) == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) >= 3)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Examine whether the remote desktop is available
+bool MsIsRemoteDesktopAvailable()
+{
+ OS_INFO *info = GetOsInfo();
+ if (MsIsTerminalServiceInstalled() == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) == 2)
+ {
+ // Windows 2000
+ if (info->OsType == 2200)
+ {
+ // Windows 2000 Professional
+ return false;
+ }
+ else
+ {
+ // Windows 2000 server series
+ return true;
+ }
+ }
+ else if (GET_KETA(info->OsType, 100) == 3)
+ {
+ // Windows XP
+ if (info->OsType == OSTYPE_WINDOWS_XP_HOME)
+ {
+ // Home Edition
+ return false;
+ }
+ else
+ {
+ // Professional Edition
+ return true;
+ }
+ }
+ else if (GET_KETA(info->OsType, 100) == 4)
+ {
+ // Windows Server 2003
+ return true;
+ }
+ else if (GET_KETA(info->OsType, 100) >= 5)
+ {
+ // Windows Vista or later
+ OSVERSIONINFOEX i;
+
+ Zero(&i, sizeof(i));
+ i.dwOSVersionInfoSize = sizeof(i);
+ if (GetVersionEx((OSVERSIONINFO *)&i) == false)
+ {
+ return false;
+ }
+
+ if (i.wSuiteMask & VER_SUITE_PERSONAL)
+ {
+ // Home series
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Examine whether the Terminal Services is installed
+bool MsIsTerminalServiceInstalled()
+{
+ OS_INFO *info = GetOsInfo();
+ OSVERSIONINFOEX i;
+
+ if (OS_IS_WINDOWS_NT(info->OsType) == false)
+ {
+ return false;
+ }
+
+ if (ms->nt->WTSDisconnectSession == NULL ||
+ ms->nt->WTSFreeMemory == NULL ||
+ ms->nt->WTSQuerySessionInformation == NULL)
+ {
+ return false;
+ }
+
+ if (GET_KETA(info->OsType, 100) < 2)
+ {
+ return false;
+ }
+
+ Zero(&i, sizeof(i));
+ i.dwOSVersionInfoSize = sizeof(i);
+ if (GetVersionEx((OSVERSIONINFO *)&i) == false)
+ {
+ return false;
+ }
+
+ if (i.wSuiteMask & VER_SUITE_TERMINAL || i.wSuiteMask & VER_SUITE_SINGLEUSERTS)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Stop the service
+bool MsStopService(char *name)
+{
+ SC_HANDLE sc, service;
+ bool ret = false;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+ if (ms->IsNt == false)
+ {
+ return false;
+ }
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (sc == NULL)
+ {
+ return false;
+ }
+
+ service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS);
+ if (service != NULL)
+ {
+ SERVICE_STATUS st;
+ ret = ms->nt->ControlService(service, SERVICE_CONTROL_STOP, &st);
+
+ ms->nt->CloseServiceHandle(service);
+ }
+
+ if (ret)
+ {
+ UINT64 end = Tick64() + 10000ULL;
+ while (Tick64() < end)
+ {
+ if (MsIsServiceRunning(name) == false)
+ {
+ break;
+ }
+
+ SleepThread(250);
+ }
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+ return ret;
+}
+
+// Start the service
+bool MsStartService(char *name)
+{
+ return MsStartServiceEx(name, NULL);
+}
+bool MsStartServiceEx(char *name, UINT *error_code)
+{
+ SC_HANDLE sc, service;
+ bool ret = false;
+ static UINT dummy = 0;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+ if (ms->IsNt == false)
+ {
+ return false;
+ }
+ if (error_code == NULL)
+ {
+ error_code = &dummy;
+ }
+
+ *error_code = 0;
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (sc == NULL)
+ {
+ *error_code = GetLastError();
+ return false;
+ }
+
+ service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS);
+ if (service != NULL)
+ {
+ ret = ms->nt->StartService(service, 0, NULL);
+
+ ms->nt->CloseServiceHandle(service);
+ }
+ else
+ {
+ *error_code = GetLastError();
+ }
+
+ if (ret)
+ {
+ UINT64 end = Tick64() + 10000ULL;
+ while (Tick64() < end)
+ {
+ if (MsIsServiceRunning(name))
+ {
+ break;
+ }
+
+ SleepThread(250);
+ }
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+ return ret;
+}
+
+// Get whether the service is running
+bool MsIsServiceRunning(char *name)
+{
+ SC_HANDLE sc, service;
+ bool ret = false;
+ // Validate arguments
+ if (name == NULL || IsEmptyStr(name))
+ {
+ return false;
+ }
+ if (ms->IsNt == false)
+ {
+ return false;
+ }
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, GENERIC_READ);
+ if (sc == NULL)
+ {
+ return false;
+ }
+
+ service = ms->nt->OpenService(sc, name, GENERIC_READ);
+ if (service != NULL)
+ {
+ SERVICE_STATUS st;
+ Zero(&st, sizeof(st));
+ if (ms->nt->QueryServiceStatus(service, &st))
+ {
+ switch (st.dwCurrentState)
+ {
+ case SERVICE_CONTINUE_PENDING:
+ case SERVICE_PAUSE_PENDING:
+ case SERVICE_PAUSED:
+ case SERVICE_RUNNING:
+ case SERVICE_START_PENDING:
+ case SERVICE_STOP_PENDING:
+ ret = true;
+ break;
+ }
+ }
+
+ ms->nt->CloseServiceHandle(service);
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+ return ret;
+}
+
+// Uninstall the service
+bool MsUninstallService(char *name)
+{
+ SC_HANDLE sc, service;
+ bool ret = false;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+ if (ms->IsNt == false)
+ {
+ return false;
+ }
+
+ MsStopService(name);
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (sc == NULL)
+ {
+ return false;
+ }
+
+ service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS);
+ if (service != NULL)
+ {
+ if (ms->nt->DeleteService(service))
+ {
+ ret = true;
+ }
+ ms->nt->CloseServiceHandle(service);
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+
+ if (ret)
+ {
+ SleepThread(2000);
+ }
+
+ return ret;
+}
+
+// Update the title and description of the service
+bool MsSetServiceDescription(char *name, wchar_t *description)
+{
+ SC_HANDLE sc, service;
+ // Validate arguments
+ if (name == NULL || description == NULL)
+ {
+ return false;
+ }
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (sc == NULL)
+ {
+ return false;
+ }
+
+ service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS);
+ if (service != NULL)
+ {
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
+ {
+ SERVICE_DESCRIPTIONW d;
+
+ if (UniIsEmptyStr(description) == false)
+ {
+ Zero(&d, sizeof(d));
+ d.lpDescription = description;
+ ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &d);
+ }
+ }
+
+ ms->nt->CloseServiceHandle(service);
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+
+ return true;
+}
+
+// Update the service setting
+bool MsUpdateServiceConfig(char *name)
+{
+ SC_HANDLE sc, service;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ // Whether just after Windows startup (deadlock prevention)
+ if (timeGetTime() <= (60 * 30 * 1000))
+ {
+ if (MsRegReadInt(REG_LOCAL_MACHINE, "Software\\" GC_REG_COMPANY_NAME "\\Update Service Config", name) != 0)
+ {
+ return false;
+ }
+ }
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (sc == NULL)
+ {
+ return false;
+ }
+
+ service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS);
+ if (service != NULL)
+ {
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
+ {
+ SERVICE_FAILURE_ACTIONS action;
+ SC_ACTION *e;
+ Zero(&action, sizeof(action));
+ e = ZeroMalloc(sizeof(SC_ACTION) * 3);
+ e[0].Delay = 10000; e[0].Type = SC_ACTION_RESTART;
+ e[1].Delay = 10000; e[1].Type = SC_ACTION_RESTART;
+ e[2].Delay = 10000; e[2].Type = SC_ACTION_RESTART;
+ action.cActions = 3;
+ action.lpsaActions = e;
+ action.dwResetPeriod = 1 * 60 * 60 * 24;
+ ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_FAILURE_ACTIONS, &action);
+
+ MsRegWriteInt(REG_LOCAL_MACHINE, "Software\\" GC_REG_COMPANY_NAME "\\Update Service Config", name, 1);
+ }
+
+
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
+ {
+ SERVICE_DESCRIPTIONW d;
+ wchar_t *description;
+ char dname[MAX_SIZE];
+
+ Format(dname, sizeof(dname), "SVC_%s_DESCRIPT", name);
+
+ description = _UU(dname);
+
+ if (UniIsEmptyStr(description) == false)
+ {
+ Zero(&d, sizeof(d));
+ d.lpDescription = description;
+ ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &d);
+ }
+ }
+
+ ms->nt->CloseServiceHandle(service);
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+
+ return true;
+}
+
+// Install the device driver
+bool MsInstallDeviceDriverW(char *name, wchar_t *title, wchar_t *path, UINT *error_code)
+{
+ SC_HANDLE sc, service;
+ bool ret = false;
+ wchar_t name_w[MAX_SIZE];
+ static UINT temp_int = 0;
+ // Validate arguments
+ if (name == NULL || title == NULL || path == NULL)
+ {
+ return false;
+ }
+ if (ms->IsNt == false)
+ {
+ return false;
+ }
+ if (error_code == NULL)
+ {
+ error_code = &temp_int;
+ }
+
+ *error_code = 0;
+
+ StrToUni(name_w, sizeof(name_w), name);
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (sc == NULL)
+ {
+ *error_code = GetLastError();
+ return false;
+ }
+
+ service = ms->nt->CreateServiceW(sc, name_w, title, SERVICE_ALL_ACCESS,
+ SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
+ SERVICE_ERROR_NORMAL, path, NULL, NULL, NULL, NULL, NULL);
+
+ if (service != NULL)
+ {
+ ret = true;
+
+ ms->nt->CloseServiceHandle(service);
+ }
+ else
+ {
+ *error_code = GetLastError();
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+
+ if (ret)
+ {
+ SleepThread(2000);
+ }
+
+ return ret;
+}
+
+// Install the service
+bool MsInstallService(char *name, char *title, wchar_t *description, char *path)
+{
+ wchar_t title_w[MAX_PATH];
+ wchar_t path_w[MAX_PATH];
+ // Validate arguments
+ if (name == NULL || title == NULL || path == NULL)
+ {
+ return false;
+ }
+
+ StrToUni(title_w, sizeof(title_w), title);
+ StrToUni(path_w, sizeof(path_w), path);
+
+ return MsInstallServiceW(name, title_w, description, path_w);
+}
+bool MsInstallServiceW(char *name, wchar_t *title, wchar_t *description, wchar_t *path)
+{
+ return MsInstallServiceExW(name, title, description, path, NULL);
+}
+bool MsInstallServiceExW(char *name, wchar_t *title, wchar_t *description, wchar_t *path, UINT *error_code)
+{
+ SC_HANDLE sc, service;
+ bool ret = false;
+ wchar_t name_w[MAX_SIZE];
+ static UINT temp_int = 0;
+ // Validate arguments
+ if (name == NULL || title == NULL || path == NULL)
+ {
+ return false;
+ }
+ if (ms->IsNt == false)
+ {
+ return false;
+ }
+ if (error_code == NULL)
+ {
+ error_code = &temp_int;
+ }
+
+ *error_code = 0;
+
+ StrToUni(name_w, sizeof(name_w), name);
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (sc == NULL)
+ {
+ *error_code = GetLastError();
+ return false;
+ }
+
+ service = ms->nt->CreateServiceW(sc, name_w, title, SERVICE_ALL_ACCESS,
+ SERVICE_WIN32_OWN_PROCESS | (MsIsVista() ? 0 : SERVICE_INTERACTIVE_PROCESS), SERVICE_AUTO_START,
+ SERVICE_ERROR_NORMAL, path, NULL, NULL, NULL, NULL, NULL);
+
+ if (service != NULL)
+ {
+ ret = true;
+
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
+ {
+ SERVICE_DESCRIPTIONW d;
+ SERVICE_FAILURE_ACTIONS action;
+ SC_ACTION *e;
+ Zero(&d, sizeof(d));
+ d.lpDescription = description;
+ ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &d);
+ Zero(&action, sizeof(action));
+ e = ZeroMalloc(sizeof(SC_ACTION) * 3);
+ e[0].Delay = 10000; e[0].Type = SC_ACTION_RESTART;
+ e[1].Delay = 10000; e[1].Type = SC_ACTION_RESTART;
+ e[2].Delay = 10000; e[2].Type = SC_ACTION_RESTART;
+ action.cActions = 3;
+ action.lpsaActions = e;
+ action.dwResetPeriod = 1 * 60 * 60 * 24;
+ ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_FAILURE_ACTIONS, &action);
+
+ Free(e);
+ }
+
+ ms->nt->CloseServiceHandle(service);
+ }
+ else
+ {
+ *error_code = GetLastError();
+ }
+
+ ms->nt->CloseServiceHandle(sc);
+
+ if (ret)
+ {
+ SleepThread(2000);
+ }
+
+ return ret;
+}
+
+// Check whether the specified service is installed
+bool MsIsServiceInstalled(char *name)
+{
+ SC_HANDLE sc;
+ SC_HANDLE service;
+ bool ret = false;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+ if (ms->IsNt == false)
+ {
+ return false;
+ }
+
+ sc = ms->nt->OpenSCManager(NULL, NULL, GENERIC_READ);
+ if (sc == NULL)
+ {
+ return false;
+ }
+
+ service = ms->nt->OpenService(sc, name, GENERIC_READ);
+ if (service != NULL)
+ {
+ ret = true;
+ }
+
+ ms->nt->CloseServiceHandle(service);
+ ms->nt->CloseServiceHandle(sc);
+
+ return ret;
+}
+
+// Kill the process
+void MsTerminateProcess()
+{
+ TerminateProcess(GetCurrentProcess(), 0);
+ _exit(0);
+}
+
+// Get the Process ID
+UINT MsGetProcessId()
+{
+ return GetCurrentProcessId();
+}
+
+// Get the MS structure
+MS *MsGetMs()
+{
+ return ms;
+}
+
+// Lower the priority of the thread to lowest
+void MsSetThreadPriorityIdle()
+{
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE);
+}
+
+// Raise the priority of a thread
+void MsSetThreadPriorityHigh()
+{
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
+}
+
+// Lower the priority of the thread
+void MsSetThreadPriorityLow()
+{
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
+}
+
+// Raise the priority of the thread to highest
+void MsSetThreadPriorityRealtime()
+{
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+}
+
+// Restore the priority of the thread
+void MsRestoreThreadPriority()
+{
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
+}
+
+// Check whether should show the TCP setting application
+bool MsIsShouldShowTcpConfigApp()
+{
+ MS_TCP tcp1, tcp2;
+ if (MsIsTcpConfigSupported() == false)
+ {
+ return false;
+ }
+
+ MsGetTcpConfig(&tcp1);
+ if (MsLoadTcpConfigReg(&tcp2) == false)
+ {
+ return true;
+ }
+
+ if (Cmp(&tcp1, &tcp2, sizeof(MS_TCP) != 0))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Apply the temporary settings data of registry to the TCP parameter of the Windows
+void MsApplyTcpConfig()
+{
+ if (MsIsTcpConfigSupported())
+ {
+ MS_TCP tcp;
+
+ if (MsLoadTcpConfigReg(&tcp))
+ {
+ MsSetTcpConfig(&tcp);
+ }
+ }
+}
+
+// Check whether the dynamic configuration of TCP is supported in current state
+bool MsIsTcpConfigSupported()
+{
+ if (MsIsNt() && MsIsAdmin())
+ {
+ UINT type = GetOsInfo()->OsType;
+
+ if (GET_KETA(type, 100) >= 2)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Read the TCP settings from the registry setting
+bool MsLoadTcpConfigReg(MS_TCP *tcp)
+{
+ // Validate arguments
+ if (tcp == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt())
+ {
+ Zero(tcp, sizeof(MS_TCP));
+
+ if (MsRegIsValueEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "RecvWindowSize", true) == false ||
+ MsRegIsValueEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "SendWindowSize", true) == false)
+ {
+ return false;
+ }
+
+ tcp->RecvWindowSize = MsRegReadIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "RecvWindowSize", true);
+ tcp->SendWindowSize = MsRegReadIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "SendWindowSize", true);
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Remove the TCP settings from the registry
+void MsDeleteTcpConfigReg()
+{
+ if (MsIsNt() && MsIsAdmin())
+ {
+ MsRegDeleteKeyEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, true);
+ }
+}
+
+// Write the TCP settings to the registry setting
+void MsSaveTcpConfigReg(MS_TCP *tcp)
+{
+ // Validate arguments
+ if (tcp == NULL)
+ {
+ return;
+ }
+
+ if (MsIsNt() && MsIsAdmin())
+ {
+ MsRegWriteIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "RecvWindowSize", tcp->RecvWindowSize, true);
+ MsRegWriteIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "SendWindowSize", tcp->SendWindowSize, true);
+ }
+}
+
+// Get the current TCP settings
+void MsGetTcpConfig(MS_TCP *tcp)
+{
+ // Validate arguments
+ if (tcp == NULL)
+ {
+ return;
+ }
+
+ Zero(tcp, sizeof(MS_TCP));
+
+ if (MsIsNt())
+ {
+ UINT v;
+ // Initialize the network setting
+ MsInitGlobalNetworkConfig();
+
+ // Read the value of TcpWindowSize or GlobalMaxTcpWindowSize if there is
+ v = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "TcpWindowSize");
+ tcp->RecvWindowSize = MAX(tcp->RecvWindowSize, v);
+
+ v = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "GlobalMaxTcpWindowSize");
+ tcp->RecvWindowSize = MAX(tcp->RecvWindowSize, v);
+
+ v = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", "DefaultReceiveWindow");
+ tcp->RecvWindowSize = MAX(tcp->RecvWindowSize, v);
+
+ // Read the value of DefaultSendWindow if there is
+ tcp->SendWindowSize = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", "DefaultSendWindow");
+ }
+}
+
+// Write the TCP settings
+void MsSetTcpConfig(MS_TCP *tcp)
+{
+ // Validate arguments
+ if (tcp == NULL)
+ {
+ return;
+ }
+
+ if (MsIsNt() && MsIsAdmin())
+ {
+ bool window_scaling = false;
+ UINT tcp1323opts;
+
+ if (tcp->RecvWindowSize >= 65536 || tcp->SendWindowSize >= 65536)
+ {
+ window_scaling = true;
+ }
+
+ // Set the Tcp1323Opts
+ tcp1323opts = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "Tcp1323Opts");
+ if (window_scaling)
+ {
+ if (tcp1323opts == 0)
+ {
+ tcp1323opts = 1;
+ }
+ if (tcp1323opts == 2)
+ {
+ tcp1323opts = 3;
+ }
+ }
+ else
+ {
+ if (tcp1323opts == 1)
+ {
+ tcp1323opts = 0;
+ }
+ if (tcp1323opts == 3)
+ {
+ tcp1323opts = 2;
+ }
+ }
+ MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "Tcp1323Opts", tcp1323opts);
+
+ // Set the Receive Window
+ if (tcp->RecvWindowSize == 0)
+ {
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
+ "DefaultReceiveWindow");
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "TcpWindowSize");
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "GlobalMaxTcpWindowSize");
+ }
+ else
+ {
+ MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
+ "DefaultReceiveWindow", tcp->RecvWindowSize);
+ MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "TcpWindowSize", tcp->RecvWindowSize);
+ MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "GlobalMaxTcpWindowSize", tcp->RecvWindowSize);
+ }
+
+ // Setting the Send Window
+ if (tcp->SendWindowSize == 0)
+ {
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
+ "DefaultSendWindow");
+ }
+ else
+ {
+ MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
+ "DefaultSendWindow", tcp->SendWindowSize);
+ }
+ }
+}
+
+// Initialize the global network settings
+void MsInitGlobalNetworkConfig()
+{
+ if (MsIsNt())
+ {
+ UINT current_window_size;
+ current_window_size = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "TcpWindowSize");
+
+ if (current_window_size == 65535 || current_window_size == 5980160 ||
+ current_window_size == 16777216 || current_window_size == 16777214)
+ {
+ // Remove the strange value which is written by older version of PacketiX VPN
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
+ "DefaultReceiveWindow");
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
+ "DefaultSendWindow");
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "Tcp1323Opts");
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "TcpWindowSize");
+ MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "GlobalMaxTcpWindowSize");
+
+ // Set vpn_no_change = true
+ MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "vpn_no_change", 1);
+ MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", "vpn_no_change", 1);
+ }
+ }
+ else
+ {
+ if (MsRegReadInt(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\VxD\\MSTCP",
+ "packetix_no_optimize") == 0)
+ {
+ // Disable the DeadGWDetect
+ MsRegWriteStr(REG_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\VxD\\MSTCP",
+ "DeadGWDetect", "0");
+ }
+ }
+
+ MsApplyTcpConfig();
+}
+
+// Process disabling other off-loading of network and others
+void MsDisableNetworkOffloadingEtc()
+{
+ wchar_t netsh[MAX_SIZE];
+ UINT exec_timeout = 10000;
+ if (MsIsNt() == false)
+ {
+ return;
+ }
+
+ // Get the path of netsh.exe
+ CombinePathW(netsh, sizeof(netsh), MsGetSystem32DirW(), L"netsh.exe");
+
+ // Registry settings
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "DisableTaskOffload", 1, false, true);
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "TcpNumConnections", TCP_MAX_NUM_CONNECTIONS, false, true);
+
+ if (MsIsVista() == false)
+ {
+ // Windows Server 2003 or earlier
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "EnableRSS", 1, false, true);
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "EnableTCPChimney", 1, false, true);
+ MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "EnableTCPA", 1, false, true);
+
+ Win32RunAndWaitProcess(netsh, L"netsh int ip set chimney disabled", true, true, exec_timeout);
+ SleepThread(250);
+ }
+ else
+ {
+ // Windows Vista or later
+ Win32RunAndWaitProcess(netsh, L"int ipv4 set global taskoffload=disabled", true, true, exec_timeout);
+ SleepThread(250);
+ Win32RunAndWaitProcess(netsh, L"int ipv6 set global taskoffload=disabled", true, true, exec_timeout);
+ SleepThread(250);
+ Win32RunAndWaitProcess(netsh, L"int tcp set global chimney=disabled", true, true, exec_timeout);
+ SleepThread(250);
+ }
+}
+
+// Upgrade the virtual LAN card
+bool MsUpgradeVLan(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver)
+{
+ bool ret;
+
+ Lock(vlan_lock);
+ {
+ ret = MsUpgradeVLanWithoutLock(tag_name, connection_tag_name, instance_name, ver);
+ }
+ Unlock(vlan_lock);
+
+ return ret;
+}
+bool MsUpgradeVLanWithoutLock(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver)
+{
+ wchar_t infpath[MAX_PATH];
+ char hwid[MAX_PATH];
+ wchar_t hwid_w[MAX_PATH];
+ bool ret = false;
+ bool need_reboot;
+ bool before_status;
+ UCHAR old_mac_address[6];
+ UCHAR new_mac_address[6];
+ char *s;
+ NO_WARNING *nw;
+ char neo_sys[MAX_PATH];
+ char *reg_key;
+ UINT i;
+ // Validate arguments
+ if (instance_name == NULL || tag_name == NULL || connection_tag_name == NULL || ver == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ // Can not be upgraded in Windows 9x
+ return false;
+ }
+
+ if (MsIsInfCatalogRequired())
+ {
+ if (MsIsValidVLanInstanceNameForInfCatalog(instance_name) == false)
+ {
+ return false;
+ }
+
+ StrUpper(instance_name);
+ }
+
+ Zero(hwid, sizeof(hwid));
+ Format(hwid, sizeof(hwid), DRIVER_DEVICE_ID_TAG, instance_name);
+ StrToUni(hwid_w, sizeof(hwid_w), hwid);
+
+ // Examine whether the virtual LAN card with the specified name has already registered
+ if (MsIsVLanExists(tag_name, instance_name) == false)
+ {
+ // Not registered
+ return false;
+ }
+
+ reg_key = MsGetNetCfgRegKeyName(tag_name, instance_name);
+
+ if (IsEmptyStr(reg_key) == false)
+ {
+ // Add a value to the registry key
+ MsRegWriteInt(REG_LOCAL_MACHINE, reg_key, "*IfType", 6);
+ MsRegWriteInt(REG_LOCAL_MACHINE, reg_key, "*MediaType", 0);
+ MsRegWriteInt(REG_LOCAL_MACHINE, reg_key, "*PhysicalMediaType", 0);
+ }
+ Free(reg_key);
+
+ // Get the .sys file name that is currently being used
+ if (MsGetNeoDeiverFilename(neo_sys, sizeof(neo_sys), instance_name) == false)
+ {
+ if (MsIsInfCatalogRequired())
+ {
+ // Can not be upgraded if getting current .sys file name failed
+ // in the Windows 8 or later
+ return false;
+ }
+
+ // Create a new file name because it is unknown
+ if (MsMakeNewNeoDriverFilename(neo_sys, sizeof(neo_sys)) == false)
+ {
+ // Failure
+ return false;
+ }
+ }
+
+ // Get the current operating status
+ before_status = MsIsVLanEnabled(instance_name);
+
+ // Get the previous MAC address
+ s = MsGetMacAddress(tag_name, instance_name);
+ if (s == NULL)
+ {
+ Zero(old_mac_address, 6);
+ }
+ else
+ {
+ BUF *b;
+ b = StrToBin(s);
+ Free(s);
+
+ if (b->Size == 6)
+ {
+ Copy(old_mac_address, b->Buf, b->Size);
+ }
+ else
+ {
+ Zero(old_mac_address, 6);
+ }
+
+ FreeBuf(b);
+ }
+
+ // Starting the installation
+ if (MsStartDriverInstall(instance_name, IsZero(old_mac_address, 6) ? NULL : old_mac_address, neo_sys,
+ new_mac_address, ver) == false)
+ {
+ return false;
+ }
+ MsGetDriverPath(instance_name, NULL, NULL, infpath, NULL, NULL, NULL, neo_sys);
+
+ nw = NULL;
+
+ //if (MsIsVista() == false)
+ {
+ nw = MsInitNoWarning();
+ }
+
+ // Do the installation
+ if (ms->nt->UpdateDriverForPlugAndPlayDevicesW(
+ NULL, hwid_w, infpath, 1, &need_reboot))
+ {
+ ret = true;
+ }
+ MsFreeNoWarning(nw);
+
+ // Installation complete
+ MsFinishDriverInstall(instance_name, neo_sys);
+
+ for (i = 0;i < 5;i++)
+ {
+ MsInitNetworkConfig(tag_name, instance_name, connection_tag_name);
+ if (MsIsInfCatalogRequired())
+ {
+ // Write the MAC address
+ char mac_address_str[MAX_SIZE];
+ BinToStr(mac_address_str, sizeof(mac_address_str), new_mac_address, sizeof(new_mac_address));
+ MsSetMacAddress(VLAN_ADAPTER_NAME_TAG, instance_name, mac_address_str);
+ }
+
+ SleepThread(MsIsVista() ? 1000 : 300);
+ }
+
+ SleepThread(MsIsVista() ? 1000 : 300);
+
+ // Restore operation
+ if (before_status)
+ {
+ MsEnableVLan(instance_name);
+ }
+ else
+ {
+ MsDisableVLan(instance_name);
+ }
+
+ return ret;
+}
+
+// Test for Windows 9x
+void MsWin9xTest()
+{
+}
+
+// Update the CompatibleIDs of virtual LAN card
+void MsUpdateCompatibleIDs(char *instance_name)
+{
+ TOKEN_LIST *t;
+ char id[MAX_SIZE];
+ char device_title[MAX_SIZE];
+ char device_title_old[MAX_SIZE];
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return;
+ }
+
+ Format(id, sizeof(id), DRIVER_DEVICE_ID_TAG, instance_name);
+ Format(device_title, sizeof(device_title), VLAN_ADAPTER_NAME_TAG, instance_name);
+ Format(device_title_old, sizeof(device_title_old), VLAN_ADAPTER_NAME_TAG_OLD, instance_name);
+
+ t = MsRegEnumKey(REG_LOCAL_MACHINE, "Enum\\Root\\Net");
+ if (t != NULL)
+ {
+ UINT i;
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char keyname[MAX_PATH];
+ char *str;
+ char *title;
+
+ Format(keyname, sizeof(keyname), "Enum\\Root\\Net\\%s", t->Token[i]);
+
+ title = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "DeviceDesc");
+
+ if (title != NULL)
+ {
+ if (StrCmpi(title, device_title) == 0 || StrCmpi(title, device_title_old) == 0)
+ {
+ Format(keyname, sizeof(keyname), "Enum\\Root\\Net\\%s",t->Token[i]);
+ str = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "CompatibleIDs");
+ if (str != NULL)
+ {
+ Free(str);
+ }
+ else
+ {
+ MsRegWriteStr(REG_LOCAL_MACHINE, keyname, "CompatibleIDs", id);
+ }
+ }
+ Free(title);
+ }
+ }
+
+ FreeToken(t);
+ }
+
+ MsRegWriteStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup", "SourcePath",
+ ms->System32Dir);
+}
+
+// Installing the virtual LAN card (for Win9x)
+bool MsInstallVLan9x(char *instance_name, MS_DRIVER_VER *ver)
+{
+ char sysdir[MAX_PATH];
+ char infdir[MAX_PATH];
+ char otherdir[MAX_PATH];
+ char syspath[MAX_PATH];
+ char syspath2[MAX_PATH];
+ char infpath[MAX_PATH];
+ char vpn16[MAX_PATH];
+ char infpath_src[MAX_PATH];
+ char syspath_src[MAX_PATH];
+ char neo_sys[MAX_PATH];
+ // Validate arguments
+ if (instance_name == NULL || ver == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(sysdir, sizeof(sysdir), MsGetSystem32Dir());
+ Format(infdir, sizeof(infdir), "%s\\inf", MsGetWindowsDir());
+ Format(otherdir, sizeof(otherdir), "%s\\other", infdir);
+ Format(syspath, sizeof(syspath), "%s\\Neo_%s.sys", sysdir, instance_name);
+ Format(syspath2, sizeof(syspath2), "%s\\Neo_%s.sys", infdir, instance_name);
+ Format(infpath, sizeof(infpath), "%s\\Neo_%s.inf", infdir, instance_name);
+ Format(vpn16, sizeof(vpn16), "%s\\vpn16.exe", MsGetMyTempDir());
+
+ MakeDir(otherdir);
+
+ Format(neo_sys, sizeof(neo_sys), DRIVER_INSTALL_SYS_NAME_TAG, instance_name);
+
+ // Copy of vpn16.exe
+ FileCopy("|vpn16.exe", vpn16);
+
+ // Starting the installation
+ if (MsStartDriverInstall(instance_name, NULL, neo_sys, NULL, ver) == false)
+ {
+ return false;
+ }
+ MsGetDriverPathA(instance_name, NULL, NULL, infpath_src, syspath_src, NULL, NULL, neo_sys);
+
+ // Copy of the inf file
+ FileCopy(infpath_src, infpath);
+
+ // Copy of the sys file
+ FileCopy(syspath_src, syspath);
+
+ // Install the device driver
+ if (Run(vpn16, instance_name, false, true) == false)
+ {
+ return false;
+ }
+
+ // Update the CompatibleIDs
+ MsUpdateCompatibleIDs(instance_name);
+
+ return true;
+}
+
+// Child window enumeration procedure
+bool CALLBACK MsEnumChildWindowProc(HWND hWnd, LPARAM lParam)
+{
+ LIST *o = (LIST *)lParam;
+
+ if (o != NULL)
+ {
+ MsEnumChildWindows(o, hWnd);
+ }
+
+ return true;
+}
+
+// Enumerate specified window and all the its child windows
+LIST *MsEnumChildWindows(LIST *o, HWND hWnd)
+{
+ // Validate arguments
+ if (hWnd == NULL)
+ {
+ return NULL;
+ }
+
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ MsAddWindowToList(o, hWnd);
+
+ EnumChildWindows(hWnd, MsEnumChildWindowProc, (LPARAM)o);
+
+ return o;
+}
+
+// Add a window to the list
+void MsAddWindowToList(LIST *o, HWND hWnd)
+{
+ // Validate arguments
+ if (o == NULL || hWnd == NULL)
+ {
+ return;
+ }
+
+ if (IsInList(o, hWnd) == false)
+ {
+ Add(o, hWnd);
+ }
+}
+
+// Enumeration of the window that the thread owns
+bool CALLBACK MsEnumThreadWindowProc(HWND hWnd, LPARAM lParam)
+{
+ LIST *o = (LIST *)lParam;
+
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ MsEnumChildWindows(o, hWnd);
+
+ return true;
+}
+
+// Window enumeration procedure
+BOOL CALLBACK EnumTopWindowProc(HWND hWnd, LPARAM lParam)
+{
+ LIST *o = (LIST *)lParam;
+ HWND hParent;
+ char c1[MAX_SIZE], c2[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || o == NULL)
+ {
+ return TRUE;
+ }
+
+ Zero(c1, sizeof(c1));
+ Zero(c2, sizeof(c2));
+
+ hParent = GetParent(hWnd);
+
+ GetClassName(hWnd, c1, sizeof(c1));
+
+ if (hParent != NULL)
+ {
+ GetClassName(hParent, c2, sizeof(c2));
+ }
+
+ if (StrCmpi(c1, "SysIPAddress32") != 0 && (IsEmptyStr(c2) || StrCmpi(c2, "SysIPAddress32") != 0))
+ {
+ AddWindow(o, hWnd);
+ }
+
+ return TRUE;
+}
+
+// Child window enumeration procedure
+BOOL CALLBACK EnumChildWindowProc(HWND hWnd, LPARAM lParam)
+{
+ ENUM_CHILD_WINDOW_PARAM *p = (ENUM_CHILD_WINDOW_PARAM *)lParam;
+ LIST *o;
+ HWND hParent;
+ char c1[MAX_SIZE], c2[MAX_SIZE];
+ // Validate arguments
+ if (hWnd == NULL || p == NULL)
+ {
+ return TRUE;
+ }
+
+ o = p->o;
+
+ Zero(c1, sizeof(c1));
+ Zero(c2, sizeof(c2));
+
+ hParent = GetParent(hWnd);
+
+ GetClassName(hWnd, c1, sizeof(c1));
+
+ if (hParent != NULL)
+ {
+ GetClassName(hParent, c2, sizeof(c2));
+ }
+
+ if (p->include_ipcontrol || (StrCmpi(c1, "SysIPAddress32") != 0 && (IsEmptyStr(c2) || StrCmpi(c2, "SysIPAddress32") != 0)))
+ {
+ AddWindow(o, hWnd);
+
+ if (p->no_recursion == false)
+ {
+ EnumChildWindows(hWnd, EnumChildWindowProc, (LPARAM)p);
+ }
+ }
+
+ return TRUE;
+}
+LIST *EnumAllWindow()
+{
+ return EnumAllWindowEx(false, false);
+}
+LIST *EnumAllWindowEx(bool no_recursion, bool include_ipcontrol)
+{
+ ENUM_CHILD_WINDOW_PARAM p;
+ LIST *o = NewWindowList();
+
+ Zero(&p, sizeof(p));
+ p.o = o;
+ p.no_recursion = no_recursion;
+ p.include_ipcontrol = include_ipcontrol;
+
+ EnumWindows(EnumChildWindowProc, (LPARAM)&p);
+
+ return o;
+}
+LIST *EnumAllTopWindow()
+{
+ LIST *o = NewWindowList();
+
+ EnumWindows(EnumTopWindowProc, (LPARAM)o);
+
+ return o;
+}
+
+// Enumerate the child windows of all that is in the specified window
+LIST *EnumAllChildWindow(HWND hWnd)
+{
+ return EnumAllChildWindowEx(hWnd, false, false, false);
+}
+LIST *EnumAllChildWindowEx(HWND hWnd, bool no_recursion, bool include_ipcontrol, bool no_self)
+{
+ ENUM_CHILD_WINDOW_PARAM p;
+ LIST *o = NewWindowList();
+
+ Zero(&p, sizeof(p));
+ p.include_ipcontrol = include_ipcontrol;
+ p.no_recursion = no_recursion;
+ p.o = o;
+
+ if (no_self == false)
+ {
+ AddWindow(o, hWnd);
+ }
+
+ EnumChildWindows(hWnd, EnumChildWindowProc, (LPARAM)&p);
+
+ return o;
+}
+
+// Release of the window list
+void FreeWindowList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HWND *e = LIST_DATA(o, i);
+
+ Free(e);
+ }
+
+ ReleaseList(o);
+}
+
+// Add a window to the window list
+void AddWindow(LIST *o, HWND hWnd)
+{
+ HWND t, *e;
+ // Validate arguments
+ if (o == NULL || hWnd == NULL)
+ {
+ return;
+ }
+
+ t = hWnd;
+
+ if (Search(o, &t) != NULL)
+ {
+ return;
+ }
+
+ e = ZeroMalloc(sizeof(HWND));
+ *e = hWnd;
+
+ Insert(o, e);
+}
+
+// Comparison of the window list items
+int CmpWindowList(void *p1, void *p2)
+{
+ HWND *h1, *h2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ h1 = *(HWND **)p1;
+ h2 = *(HWND **)p2;
+ if (h1 == NULL || h2 == NULL)
+ {
+ return 0;
+ }
+
+ return Cmp(h1, h2, sizeof(HWND));
+}
+
+// Creating a new window list
+LIST *NewWindowList()
+{
+ return NewListFast(CmpWindowList);
+}
+
+// Determine whether it's Windows Vista or later
+bool MsIsVista()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (info == NULL)
+ {
+ return false;
+ }
+
+ if (OS_IS_WINDOWS_NT(info->OsType))
+ {
+ if (GET_KETA(info->OsType, 100) >= 5)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Determine whether it's Windows 7 or later
+bool MsIsWindows7()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (info == NULL)
+ {
+ return false;
+ }
+
+ if (OS_IS_WINDOWS_NT(info->OsType))
+ {
+ if (GET_KETA(info->OsType, 100) >= 6)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Determine whether it's Windows 8 later
+bool MsIsWindows8()
+{
+ OS_INFO *info = GetOsInfo();
+
+ if (info == NULL)
+ {
+ return false;
+ }
+
+ if (OS_IS_WINDOWS_NT(info->OsType))
+ {
+ if (GET_KETA(info->OsType, 100) >= 7)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Whether INF catalog signature is required
+bool MsIsInfCatalogRequired()
+{
+ return MsIsWindows8();
+}
+
+// Get the process path of the owner of the window
+bool MsGetWindowOwnerProcessExeName(char *path, UINT size, HWND hWnd)
+{
+ DWORD procId = 0;
+ // Validate arguments
+ if (path == NULL || hWnd == NULL)
+ {
+ return false;
+ }
+
+ GetWindowThreadProcessId(hWnd, &procId);
+ if (procId == 0)
+ {
+ return false;
+ }
+
+ if (MsGetProcessExeName(path, size, procId) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+bool MsGetWindowOwnerProcessExeNameW(wchar_t *path, UINT size, HWND hWnd)
+{
+ DWORD procId = 0;
+ // Validate arguments
+ if (path == NULL || hWnd == NULL)
+ {
+ return false;
+ }
+
+ GetWindowThreadProcessId(hWnd, &procId);
+ if (procId == 0)
+ {
+ return false;
+ }
+
+ if (MsGetProcessExeNameW(path, size, procId) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the process path from process ID
+bool MsGetProcessExeName(char *path, UINT size, UINT id)
+{
+ LIST *o;
+ MS_PROCESS *proc;
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ o = MsGetProcessList();
+ proc = MsSearchProcessById(o, id);
+
+ if (proc != NULL)
+ {
+ ret = true;
+ StrCpy(path, size, proc->ExeFilename);
+ }
+
+ MsFreeProcessList(o);
+
+ return ret;
+}
+bool MsGetProcessExeNameW(wchar_t *path, UINT size, UINT id)
+{
+ LIST *o;
+ MS_PROCESS *proc;
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ o = MsGetProcessList();
+ proc = MsSearchProcessById(o, id);
+
+ if (proc != NULL)
+ {
+ ret = true;
+ UniStrCpy(path, size, proc->ExeFilenameW);
+ }
+
+ MsFreeProcessList(o);
+
+ return ret;
+}
+
+// Close the alert dialog
+bool MsCloseWarningWindow(NO_WARNING *nw, UINT thread_id)
+{
+ UINT i;
+ LIST *o;
+ bool ret = false;
+ bool press = false;
+
+ if (MsIsVista() == false || nw->StartTimer == 0)
+ {
+ press = true;
+ }
+
+ if (nw->StartTick != 0 && nw->StartTick <= Tick64())
+ {
+ press = true;
+ }
+
+ if (MsIsVista() == false)
+ {
+ o = NewListFast(NULL);
+ EnumThreadWindows(thread_id, MsEnumThreadWindowProc, (LPARAM)o);
+ }
+ else
+ {
+ o = EnumAllTopWindow();
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HWND hWnd;
+
+ if (MsIsVista() == false)
+ {
+ hWnd = LIST_DATA(o, i);
+ }
+ else
+ {
+ hWnd = *((HWND *)LIST_DATA(o, i));
+ }
+
+ if (hWnd != NULL)
+ {
+ OS_INFO *info = GetOsInfo();
+
+ if (MsIsNt())
+ {
+ // Get whether this window is a warning screen of driver
+ if (MsIsVista() == false)
+ {
+ // Other than Windows Vista
+ HWND hStatic, hOk, hCancel, hDetail;
+
+ hStatic = GetDlgItem(hWnd, 0x14C1);
+ hOk = GetDlgItem(hWnd, 0x14B7);
+ hCancel = GetDlgItem(hWnd, 0x14BA);
+ hDetail = GetDlgItem(hWnd, 0x14B9);
+
+ if ((hStatic != NULL || hDetail != NULL) && hOk != NULL && hCancel != NULL)
+ {
+ char tmp[MAX_SIZE];
+ bool b = false;
+
+ if (GetClassName(hStatic, tmp, sizeof(tmp)) != 0)
+ {
+ if (StrCmpi(tmp, "static") == 0)
+ {
+ b = true;
+ }
+ }
+
+ if (GetClassName(hDetail, tmp, sizeof(tmp)) != 0)
+ {
+ if (StrCmpi(tmp, "button") == 0)
+ {
+ b = true;
+ }
+ }
+
+ if (b)
+ {
+ if (GetClassName(hOk, tmp, sizeof(tmp)) != 0)
+ {
+ if (StrCmpi(tmp, "button") == 0)
+ {
+ if (GetClassName(hCancel, tmp, sizeof(tmp)) != 0)
+ {
+ if (StrCmpi(tmp, "button") == 0)
+ {
+ // Press the OK button since it was found
+ PostMessage(hWnd, WM_COMMAND, 0x14B7, 0);
+
+ ret = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // Windows Vista
+ char exe[MAX_PATH];
+
+ if (MsGetWindowOwnerProcessExeName(exe, sizeof(exe), hWnd))
+ {
+ if (EndWith(exe, "rundll32.exe"))
+ {
+ LIST *o;
+ HWND h;
+ UINT i;
+
+ o = EnumAllChildWindow(hWnd);
+
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char tmp[MAX_SIZE];
+
+ h = *((HWND *)LIST_DATA(o, i));
+
+ Zero(tmp, sizeof(tmp));
+ GetClassNameA(h, tmp, sizeof(tmp));
+
+ if (StrCmpi(tmp, "DirectUIHWND") == 0)
+ {
+ LIST *o = EnumAllChildWindow(h);
+
+ if (o != NULL)
+ {
+ UINT j;
+ UINT numDirectUIHWND = 0;
+ UINT numButton = 0;
+ HWND hButton1 = NULL;
+ HWND hButton2 = NULL;
+
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ HWND hh;
+ char tmp[MAX_SIZE];
+
+ hh = *((HWND *)LIST_DATA(o, j));
+
+ Zero(tmp, sizeof(tmp));
+ GetClassNameA(hh, tmp, sizeof(tmp));
+
+ if (StrCmpi(tmp, "DirectUIHWND") == 0)
+ {
+ numDirectUIHWND++;
+ }
+
+ if (StrCmpi(tmp, "button") == 0)
+ {
+ numButton++;
+ if (hButton1 == NULL)
+ {
+ hButton1 = hh;
+ }
+ else
+ {
+ hButton2 = hh;
+ }
+ }
+ }
+
+ if ((numDirectUIHWND == 1 || numDirectUIHWND == 2) && numButton == 2)
+ {
+ if (hButton1 != NULL && hButton2 != NULL)
+ {
+ HWND hButton;
+ HWND hParent;
+ RECT r1, r2;
+
+ GetWindowRect(hButton1, &r1);
+ GetWindowRect(hButton2, &r2);
+
+ hButton = hButton1;
+
+ if (numDirectUIHWND == 1)
+ {
+ // Warning that there is no signature
+ if (r1.top < r2.top)
+ {
+ hButton = hButton2;
+ }
+ }
+ else
+ {
+ // Notification that there is signature
+ if (r1.left >= r2.left)
+ {
+ hButton = hButton2;
+ }
+ }
+
+ hParent = GetParent(hButton);
+
+ // Press the OK button since it was found
+ if (press)
+ {
+ PostMessage(hParent, WM_COMMAND, 1, 0);
+ }
+
+ ret = true;
+ }
+ }
+
+ FreeWindowList(o);
+ }
+ }
+ }
+
+ FreeWindowList(o);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (MsIsVista() == false)
+ {
+ ReleaseList(o);
+ }
+ else
+ {
+ FreeWindowList(o);
+ }
+
+ if (press == false)
+ {
+ if (ret)
+ {
+ ret = false;
+
+ if (nw->StartTick == 0)
+ {
+ nw->StartTick = Tick64() + nw->StartTimer;
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Thread to suppress a warning message
+void MsNoWarningThreadProc(THREAD *thread, void *param)
+{
+ NO_WARNING *nw;
+ UINT interval;
+ UINT i;
+ bool found0 = false;
+ // Validate arguments
+ if (thread == NULL)
+ {
+ return;
+ }
+
+ nw = (NO_WARNING *)param;
+
+ nw->NoWarningThread = thread;
+ AddRef(thread->ref);
+
+ NoticeThreadInit(thread);
+
+ interval = 50;
+
+ if (MsIsVista())
+ {
+ interval = 1000;
+ }
+
+ i = 0;
+
+ while (nw->Halt == false)
+ {
+ bool found = false;
+
+ // Close the alert dialog
+ found = MsCloseWarningWindow(nw, nw->ThreadId);
+ if (i == 0)
+ {
+ found0 = found;
+ }
+ else
+ {
+ if (found0 == false && found)
+ {
+ break;
+ }
+ }
+ i++;
+
+ // Loop until the command incomes from parent thread
+ Wait(nw->HaltEvent, interval);
+ }
+}
+
+// Initialize the procedure to turn off the warning sound
+char *MsNoWarningSoundInit()
+{
+ char *ret = MsRegReadStr(REG_CURRENT_USER, "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current", "");
+
+ if (IsEmptyStr(ret))
+ {
+ Free(ret);
+ ret = NULL;
+ }
+ else
+ {
+ MsRegWriteStr(REG_CURRENT_USER,
+ "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current",
+ "", "");
+ }
+
+ return ret;
+}
+
+// Release of procedure to turn off the warning sound
+void MsNoWarningSoundFree(char *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ MsRegWriteStrExpand(REG_CURRENT_USER,
+ "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current",
+ "", s);
+
+ Free(s);
+}
+
+// The start of the procedure to suppress the warning
+NO_WARNING *MsInitNoWarning()
+{
+ return MsInitNoWarningEx(0);
+}
+NO_WARNING *MsInitNoWarningEx(UINT start_timer)
+{
+ THREAD *thread;
+ NO_WARNING *nw = ZeroMalloc(sizeof(NO_WARNING));
+
+ nw->StartTimer = (UINT64)start_timer;
+
+ // Get the current sound file name
+ if (MsIsVista() == false)
+ {
+ wchar_t *tmp;
+
+ // Turn off the unnecessary warning tone in Windows XP or earlier
+ tmp = MsRegReadStrW(REG_CURRENT_USER, "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current", "");
+ if (UniIsEmptyStr(tmp) == false)
+ {
+ nw->SoundFileName = CopyUniStr(tmp);
+
+ MsRegWriteStrW(REG_CURRENT_USER,
+ "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current",
+ "", L"");
+ }
+
+ Free(tmp);
+ }
+
+ nw->ThreadId = GetCurrentThreadId();
+ nw->HaltEvent = NewEvent();
+
+ thread = NewThread(MsNoWarningThreadProc, nw);
+ WaitThreadInit(thread);
+
+ ReleaseThread(thread);
+
+ return nw;
+}
+
+// End of the procedure to suppress the warning
+void MsFreeNoWarning(NO_WARNING *nw)
+{
+ // Validate arguments
+ if (nw == NULL)
+ {
+ return;
+ }
+
+ nw->Halt = true;
+ Set(nw->HaltEvent);
+
+ WaitThread(nw->NoWarningThread, INFINITE);
+ ReleaseThread(nw->NoWarningThread);
+
+ ReleaseEvent(nw->HaltEvent);
+
+ if (MsIsVista() == false)
+ {
+ if (nw->SoundFileName != NULL)
+ {
+ MsRegWriteStrExpandW(REG_CURRENT_USER,
+ "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current",
+ "", nw->SoundFileName);
+
+ Free(nw->SoundFileName);
+ }
+ }
+
+ Free(nw);
+}
+
+// Obtain the name of the directory that the inf catalog file is stored
+void MsGetInfCatalogDir(char *dst, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL)
+ {
+ return;
+ }
+
+ Format(dst, size, "|inf\\%s", (MsIsX64() ? "x64" : "x86"));
+}
+
+// Examine whether the virtual LAN card name can be used as a instance name of the VLAN
+bool MsIsValidVLanInstanceNameForInfCatalog(char *instance_name)
+{
+ char src_dir[MAX_SIZE];
+ char tmp[MAX_SIZE];
+ bool ret;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return false;
+ }
+
+ MsGetInfCatalogDir(src_dir, sizeof(src_dir));
+
+ Format(tmp, sizeof(tmp), "%s\\INF_%s.inf", src_dir, instance_name);
+ ret = IsFile(tmp);
+
+ return ret;
+}
+
+// Delete the device information that is about the device which failed during the installation of the same name before installing the virtual LAN card
+void MsDeleteTroubleVLAN(char *tag_name, char *instance_name)
+{
+ HDEVINFO dev_info;
+ SP_DEVINFO_LIST_DETAIL_DATA detail_data;
+ SP_DEVINFO_DATA data;
+ UINT i;
+ char target_name[MAX_SIZE];
+ LIST *o;
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return;
+ }
+
+ Format(target_name, sizeof(target_name), DRIVER_DEVICE_ID_TAG, instance_name);
+
+ // Create a device information list
+ dev_info = SetupDiGetClassDevsEx(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT, NULL, NULL, NULL);
+ if (dev_info == NULL)
+ {
+ return;
+ }
+
+ Zero(&detail_data, sizeof(detail_data));
+ detail_data.cbSize = sizeof(detail_data);
+ if (SetupDiGetDeviceInfoListDetail(dev_info, &detail_data) == false)
+ {
+ MsDestroyDevInfo(dev_info);
+ return;
+ }
+
+ Zero(&data, sizeof(data));
+ data.cbSize = sizeof(data);
+
+ // Enumeration start
+ o = NewListFast(NULL);
+
+ for (i = 0;SetupDiEnumDeviceInfo(dev_info, i, &data);i++)
+ {
+ char *buffer;
+ UINT buffer_size = 8092;
+ DWORD data_type;
+
+ buffer = ZeroMalloc(buffer_size);
+
+ if (SetupDiGetDeviceRegistryProperty(dev_info, &data, SPDRP_HARDWAREID, &data_type, (PBYTE)buffer, buffer_size, NULL))
+ {
+ if (StrCmpi(buffer, target_name) == 0)
+ {
+ // Found
+ SP_DEVINFO_DATA *data2 = Clone(&data, sizeof(SP_DEVINFO_DATA));
+
+ Add(o, data2);
+ }
+ }
+
+ Free(buffer);
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SP_DEVINFO_DATA *data = LIST_DATA(o, i);
+ bool ret;
+
+ ret = SetupDiRemoveDevice(dev_info, data);
+
+ Debug("Deleting Troubled NIC %u: %u\n", i, ret);
+
+ Free(data);
+ }
+
+ ReleaseList(o);
+
+ MsDestroyDevInfo(dev_info);
+}
+
+// Install a virtual LAN card
+bool MsInstallVLan(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver)
+{
+ bool ret;
+
+ Lock(vlan_lock);
+ {
+ ret = MsInstallVLanWithoutLock(tag_name, connection_tag_name, instance_name, ver);
+ }
+ Unlock(vlan_lock);
+
+ return ret;
+}
+bool MsInstallVLanWithoutLock(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver)
+{
+ wchar_t infpath[MAX_PATH];
+ char hwid[MAX_PATH];
+ wchar_t hwid_w[MAX_PATH];
+ bool ret = false;
+ char neo_sys[MAX_PATH];
+ UCHAR new_mac_address[6];
+ UINT i;
+ // Validate arguments
+ if (instance_name == NULL || tag_name == NULL || connection_tag_name == NULL || ver == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ // For Windows 9x
+ return MsInstallVLan9x(instance_name, ver);
+ }
+
+ if (MsIsInfCatalogRequired())
+ {
+ if (MsIsValidVLanInstanceNameForInfCatalog(instance_name) == false)
+ {
+ Debug("MsIsValidVLanInstanceNameForInfCatalog() returns false.\n");
+ return false;
+ }
+
+ StrUpper(instance_name);
+ }
+
+ Zero(hwid, sizeof(hwid));
+ Format(hwid, sizeof(hwid), DRIVER_DEVICE_ID_TAG, instance_name);
+ StrToUni(hwid_w, sizeof(hwid_w), hwid);
+
+ // Examine whether the virtual LAN card with the specified name has already registered
+ if (MsIsVLanExists(tag_name, instance_name))
+ {
+ // Already be registered
+ Debug("MsIsVLanExists() returns true.\n");
+ return false;
+ }
+
+ // Determining destination .sys file name of the installation
+ if (MsIsInfCatalogRequired() == false)
+ {
+ if (MsMakeNewNeoDriverFilename(neo_sys, sizeof(neo_sys)) == false)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ Format(neo_sys, sizeof(neo_sys), DRIVER_INSTALL_SYS_NAME_TAG, instance_name);
+ }
+
+ // Starting the Installation
+ if (MsStartDriverInstall(instance_name, NULL, neo_sys, new_mac_address, ver) == false)
+ {
+ return false;
+ }
+ MsGetDriverPath(instance_name, NULL, NULL, infpath, NULL, NULL, NULL, neo_sys);
+
+ // Delete the device information that is left on fail of installation
+ if (MsIsNt())
+ {
+ MsDeleteTroubleVLAN(tag_name, instance_name);
+ }
+
+ // Call the Win32 API
+ ret = MsInstallVLanInternal(infpath, hwid_w, hwid);
+
+ // Installation complete
+ MsFinishDriverInstall(instance_name, neo_sys);
+
+ for (i = 0;i < 5;i++)
+ {
+ MsInitNetworkConfig(tag_name, instance_name, connection_tag_name);
+ if (MsIsInfCatalogRequired())
+ {
+ // Write the MAC address
+ char mac_address_str[MAX_SIZE];
+ BinToStr(mac_address_str, sizeof(mac_address_str), new_mac_address, sizeof(new_mac_address));
+ MsSetMacAddress(VLAN_ADAPTER_NAME_TAG, instance_name, mac_address_str);
+ }
+
+ SleepThread(MsIsVista() ? 1000 : 300);
+ }
+
+ if (ret)
+ {
+ MsDisableVLan(instance_name);
+ SleepThread(MsIsVista() ? 1000 : 300);
+ MsEnableVLan(instance_name);
+ }
+
+ return ret;
+}
+
+// Test function
+void MsTest()
+{
+}
+
+// Install a virtual LAN card (by calling Win32 API)
+bool MsInstallVLanInternal(wchar_t *infpath, wchar_t *hwid_w, char *hwid)
+{
+ bool need_reboot;
+ bool ret = false;
+ wchar_t inf_class_name[MAX_PATH];
+ GUID inf_class_guid;
+ HDEVINFO device_info;
+ SP_DEVINFO_DATA device_info_data;
+ // Validate arguments
+ if (infpath == NULL || hwid_w == NULL || hwid == NULL)
+ {
+ return false;
+ }
+
+ Debug("MsInstallVLanInternal('%S', '%S', '%s');\n",
+ infpath, hwid_w, hwid);
+
+ Zero(&inf_class_guid, sizeof(inf_class_guid));
+ Zero(&device_info, sizeof(device_info));
+ Zero(&device_info_data, sizeof(device_info_data));
+ Zero(inf_class_name, sizeof(inf_class_name));
+
+ // Get the class GUID of the inf file
+ if (SetupDiGetINFClassW(infpath, &inf_class_guid, inf_class_name, sizeof(inf_class_name), NULL))
+ {
+ // Get the device information set
+ device_info = SetupDiCreateDeviceInfoList(&inf_class_guid, NULL);
+ if (device_info != INVALID_HANDLE_VALUE)
+ {
+ // Windows 2000 or later
+ Zero(&device_info_data, sizeof(device_info_data));
+ device_info_data.cbSize = sizeof(device_info_data);
+ if (SetupDiCreateDeviceInfoW(device_info, inf_class_name, &inf_class_guid,
+ NULL, NULL, DICD_GENERATE_ID, &device_info_data))
+ {
+ char hwid_copy[MAX_SIZE];
+ Zero(hwid_copy, sizeof(hwid_copy));
+ StrCpy(hwid_copy, sizeof(hwid_copy), hwid);
+
+ // Set the registry information
+ if (SetupDiSetDeviceRegistryProperty(device_info, &device_info_data,
+ SPDRP_HARDWAREID, (BYTE *)hwid_copy, sizeof(hwid_copy)))
+ {
+ NO_WARNING *nw = NULL;
+
+ //if (MsIsVista() == false)
+ {
+ nw = MsInitNoWarning();
+ }
+
+ // Start the class installer
+ if (SetupDiCallClassInstaller(DIF_REGISTERDEVICE, device_info,
+ &device_info_data))
+ {
+ // Do the installation
+ if (ms->nt->UpdateDriverForPlugAndPlayDevicesW(
+ NULL, hwid_w, infpath, 1, &need_reboot))
+ {
+ ret = true;
+ }
+ else
+ {
+ // Installation Failed
+ Debug("UpdateDriverForPlugAndPlayDevicesW Error: %X\n", GetLastError());
+ if (SetupDiCallClassInstaller(DIF_REMOVE, device_info,
+ &device_info_data) == false)
+ {
+ Debug("SetupDiCallClassInstaller for Delete Failed. Err=%X\n", GetLastError());
+ }
+
+ if (SetupDiRemoveDevice(device_info, &device_info_data) == false)
+ {
+ Debug("SetupDiRemoveDevice for Delete Failed. Err=%X\n", GetLastError());
+ }
+ }
+ }
+ else
+ {
+ Debug("SetupDiCallClassInstaller for Create Error: %X\n", GetLastError());
+ }
+
+ MsFreeNoWarning(nw);
+ }
+ else
+ {
+ Debug("SetupDiSetDeviceRegistryProperty Error: %X\n", GetLastError());
+ }
+ }
+ else
+ {
+ Debug("SetupDiCreateDeviceInfoW Error: %X\n", GetLastError());
+ }
+ // Remove the device information set
+ SetupDiDestroyDeviceInfoList(device_info);
+ }
+ else
+ {
+ Debug("SetupDiCreateDeviceInfoList Error: %X\n", GetLastError());
+ }
+ }
+ else
+ {
+ Debug("SetupDiGetINFClassW Error: %X\n", GetLastError());
+ }
+
+ return ret;
+}
+
+// Get the device information from the device ID
+HDEVINFO MsGetDevInfoFromDeviceId(SP_DEVINFO_DATA *dev_info_data, char *device_id)
+{
+ HDEVINFO dev_info;
+ SP_DEVINFO_LIST_DETAIL_DATA detail_data;
+ SP_DEVINFO_DATA data;
+ UINT i;
+ bool found;
+ char target_name[MAX_SIZE];
+ // Validate arguments
+ if (dev_info_data == NULL || device_id == NULL)
+ {
+ return NULL;
+ }
+
+ StrCpy(target_name, sizeof(target_name), device_id);
+
+ // Create a device information list
+ dev_info = SetupDiGetClassDevsEx(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT, NULL, NULL, NULL);
+ if (dev_info == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&detail_data, sizeof(detail_data));
+ detail_data.cbSize = sizeof(detail_data);
+ if (SetupDiGetDeviceInfoListDetail(dev_info, &detail_data) == false)
+ {
+ MsDestroyDevInfo(dev_info);
+ return NULL;
+ }
+
+ Zero(&data, sizeof(data));
+ data.cbSize = sizeof(data);
+
+ // Enumeration start
+ found = false;
+ for (i = 0;SetupDiEnumDeviceInfo(dev_info, i, &data);i++)
+ {
+ char *buffer;
+ UINT buffer_size = 8092;
+ DWORD data_type;
+
+ buffer = ZeroMalloc(buffer_size);
+
+ if (SetupDiGetDeviceRegistryProperty(dev_info, &data, SPDRP_HARDWAREID, &data_type, (PBYTE)buffer, buffer_size, NULL))
+ {
+ if (StrCmpi(buffer, target_name) == 0)
+ {
+ // Found
+ found = true;
+ }
+ }
+
+ Free(buffer);
+
+ if (found)
+ {
+ break;
+ }
+ }
+
+ if (found == false)
+ {
+ MsDestroyDevInfo(dev_info);
+ return NULL;
+ }
+ else
+ {
+ Copy(dev_info_data, &data, sizeof(data));
+ return dev_info;
+ }
+}
+
+// Examine whether the specified device is operating
+bool MsIsDeviceRunning(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data)
+{
+ SP_DEVINFO_LIST_DETAIL_DATA detail;
+ UINT status = 0, problem = 0;
+ // Validate arguments
+ if (info == NULL || dev_info_data == NULL)
+ {
+ return false;
+ }
+
+ Zero(&detail, sizeof(detail));
+ detail.cbSize = sizeof(detail);
+
+ if (SetupDiGetDeviceInfoListDetail(info, &detail) == false ||
+ ms->nt->CM_Get_DevNode_Status_Ex(&status, &problem, dev_info_data->DevInst,
+ 0, detail.RemoteMachineHandle) != CR_SUCCESS)
+ {
+ return false;
+ }
+
+ if (status & 8)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Start the specified device
+bool MsStartDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data)
+{
+ SP_PROPCHANGE_PARAMS p;
+ // Validate arguments
+ if (info == NULL || dev_info_data == NULL)
+ {
+ return false;
+ }
+
+ Zero(&p, sizeof(p));
+ p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ p.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
+ p.StateChange = DICS_ENABLE;
+ p.Scope = DICS_FLAG_GLOBAL;
+ if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p)))
+ {
+ SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, info, dev_info_data);
+ }
+
+ Zero(&p, sizeof(p));
+ p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ p.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
+ p.StateChange = DICS_ENABLE;
+ p.Scope = DICS_FLAG_CONFIGSPECIFIC;
+
+ if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p)) == false ||
+ SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, info, dev_info_data) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Stop the specified device
+bool MsStopDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data)
+{
+ SP_PROPCHANGE_PARAMS p;
+ // Validate arguments
+ if (info == NULL || dev_info_data == NULL)
+ {
+ return false;
+ }
+
+ Zero(&p, sizeof(p));
+ p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ p.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
+ p.StateChange = DICS_DISABLE;
+ p.Scope = DICS_FLAG_CONFIGSPECIFIC;
+
+ if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p)) == false ||
+ SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, info, dev_info_data) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Remove the specified device
+bool MsDeleteDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data)
+{
+ SP_REMOVEDEVICE_PARAMS p;
+ SP_DEVINFO_LIST_DETAIL_DATA detail;
+ char device_id[MAX_PATH];
+ CONFIGRET ret;
+ // Validate arguments
+ if (info == NULL || dev_info_data == NULL)
+ {
+ return false;
+ }
+
+ Zero(&detail, sizeof(detail));
+ detail.cbSize = sizeof(detail);
+
+ if (SetupDiGetDeviceInfoListDetail(info, &detail) == false)
+ {
+ Debug("SetupDiGetDeviceInfoListDetail Failed. Err=0x%X\n", GetLastError());
+ return false;
+ }
+
+ ret = ms->nt->CM_Get_Device_ID_Ex(dev_info_data->DevInst, device_id, sizeof(device_id),
+ 0, detail.RemoteMachineHandle);
+ if (ret != CR_SUCCESS)
+ {
+ Debug("CM_Get_Device_ID_Ex Failed. Err=0x%X\n", ret);
+ return false;
+ }
+
+ Zero(&p, sizeof(p));
+ p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ p.ClassInstallHeader.InstallFunction = DIF_REMOVE;
+ p.Scope = DI_REMOVEDEVICE_GLOBAL;
+
+ if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p)) == false)
+ {
+ Debug("SetupDiSetClassInstallParams Failed. Err=0x%X\n", GetLastError());
+ return false;
+ }
+
+ if (SetupDiCallClassInstaller(DIF_REMOVE, info, dev_info_data) == false)
+ {
+ Debug("SetupDiCallClassInstaller Failed. Err=0x%X\n", GetLastError());
+ return false;
+ }
+
+ return true;
+}
+
+// Enable the virtual LAN card
+bool MsEnableVLan(char *instance_name)
+{
+ bool ret;
+
+ Lock(vlan_lock);
+ {
+ ret = MsEnableVLanWithoutLock(instance_name);
+ }
+ Unlock(vlan_lock);
+
+ return ret;
+}
+bool MsEnableVLanWithoutLock(char *instance_name)
+{
+ char tmp[MAX_PATH];
+ HDEVINFO h;
+ bool ret;
+ SP_DEVINFO_DATA data;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name);
+
+ h = MsGetDevInfoFromDeviceId(&data, tmp);
+ if (h == NULL)
+ {
+ return false;
+ }
+
+ ret = MsStartDevice(h, &data);
+
+ MsDestroyDevInfo(h);
+
+ return ret;
+}
+
+// Disable the virtual LAN card
+bool MsDisableVLan(char *instance_name)
+{
+ bool ret;
+
+ Lock(vlan_lock);
+ {
+ ret = MsDisableVLanWithoutLock(instance_name);
+ }
+ Unlock(vlan_lock);
+
+ return ret;
+}
+bool MsDisableVLanWithoutLock(char *instance_name)
+{
+ char tmp[MAX_PATH];
+ HDEVINFO h;
+ bool ret;
+ SP_DEVINFO_DATA data;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name);
+
+ h = MsGetDevInfoFromDeviceId(&data, tmp);
+ if (h == NULL)
+ {
+ return false;
+ }
+
+ ret = MsStopDevice(h, &data);
+
+ MsDestroyDevInfo(h);
+
+ return ret;
+}
+
+// Restart the virtual LAN card
+void MsRestartVLan(char *instance_name)
+{
+ Lock(vlan_lock);
+ {
+ MsRestartVLanWithoutLock(instance_name);
+ }
+ Unlock(vlan_lock);
+}
+void MsRestartVLanWithoutLock(char *instance_name)
+{
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return;
+ }
+
+ if (MsIsVLanEnabled(instance_name) == false)
+ {
+ return;
+ }
+
+ MsDisableVLan(instance_name);
+ MsEnableVLan(instance_name);
+}
+
+// Get whether the virtual LAN card is working
+bool MsIsVLanEnabled(char *instance_name)
+{
+ bool ret;
+
+ Lock(vlan_lock);
+ {
+ ret = MsIsVLanEnabledWithoutLock(instance_name);
+ }
+ Unlock(vlan_lock);
+
+ return ret;
+}
+bool MsIsVLanEnabledWithoutLock(char *instance_name)
+{
+ char tmp[MAX_PATH];
+ HDEVINFO h;
+ bool ret;
+ SP_DEVINFO_DATA data;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return true;
+ }
+
+ Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name);
+
+ h = MsGetDevInfoFromDeviceId(&data, tmp);
+ if (h == NULL)
+ {
+ return false;
+ }
+
+ ret = MsIsDeviceRunning(h, &data);
+
+ MsDestroyDevInfo(h);
+
+ return ret;
+}
+
+// Uninstall the virtual LAN card
+bool MsUninstallVLan(char *instance_name)
+{
+ bool ret;
+
+ Lock(vlan_lock);
+ {
+ ret = MsUninstallVLanWithoutLock(instance_name);
+ }
+ Unlock(vlan_lock);
+
+ return ret;
+}
+bool MsUninstallVLanWithoutLock(char *instance_name)
+{
+ char tmp[MAX_PATH];
+ HDEVINFO h;
+ bool ret;
+ SP_DEVINFO_DATA data;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return false;
+ }
+
+ Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name);
+
+ h = MsGetDevInfoFromDeviceId(&data, tmp);
+ if (h == NULL)
+ {
+ return false;
+ }
+
+ ret = MsDeleteDevice(h, &data);
+
+ MsDestroyDevInfo(h);
+
+ return ret;
+}
+
+// Dispose the device information
+void MsDestroyDevInfo(HDEVINFO info)
+{
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ SetupDiDestroyDeviceInfoList(info);
+}
+
+// Start the driver installation
+bool MsStartDriverInstall(char *instance_name, UCHAR *mac_address, char *neo_sys, UCHAR *ret_mac_address, MS_DRIVER_VER *ver)
+{
+ wchar_t src_inf[MAX_PATH];
+ wchar_t src_sys[MAX_PATH];
+ wchar_t dest_inf[MAX_PATH];
+ wchar_t dest_sys[MAX_PATH];
+ wchar_t src_cat[MAX_PATH];
+ wchar_t dst_cat[MAX_PATH];
+ UCHAR mac_address_bin[6];
+ char mac_address_str[32];
+ UINT size;
+ char *tmp;
+ BUF *b;
+ IO *io;
+ char str_year[16];
+ char str_month[16];
+ char str_day[16];
+ char str_major[16];
+ char str_minor[16];
+ char str_build[16];
+ // Validate arguments
+ if (instance_name == NULL || neo_sys == NULL || ver == NULL)
+ {
+ return false;
+ }
+
+ Format(str_year, sizeof(str_year), "%04d", ver->Year);
+ Format(str_month, sizeof(str_month), "%02d", ver->Month);
+ Format(str_day, sizeof(str_day), "%02d", ver->Day);
+
+ ToStr(str_major, ver->Major);
+ ToStr(str_minor, ver->Minor);
+ ToStr(str_build, ver->Build);
+
+ MsGetDriverPath(instance_name, src_inf, src_sys, dest_inf, dest_sys, src_cat, dst_cat, neo_sys);
+ Debug("MsStartDriverInstall\n");
+ Debug(" instance_name: %s\n", instance_name);
+ Debug(" src_inf: %S\n", src_inf);
+ Debug(" src_sys: %S\n", src_sys);
+ Debug(" dest_inf: %S\n", dest_inf);
+ Debug(" dest_sys: %S\n", dest_sys);
+ Debug(" src_cat: %S\n", src_cat);
+ Debug(" dst_cat: %S\n", dst_cat);
+ Debug(" neo_sys: %s\n", neo_sys);
+
+ // Processing INF file
+ io = FileOpenW(src_inf, false);
+ if (io == NULL)
+ {
+ return false;
+ }
+
+ size = FileSize(io);
+ tmp = ZeroMalloc(size * 2);
+ if (FileRead(io, tmp, size) == false)
+ {
+ FileClose(io);
+ Free(tmp);
+ return false;
+ }
+
+ FileClose(io);
+
+ if (mac_address == NULL)
+ {
+ MsGenMacAddress(mac_address_bin);
+ }
+ else
+ {
+ Copy(mac_address_bin, mac_address, 6);
+ }
+
+ BinToStr(mac_address_str, sizeof(mac_address_str), mac_address_bin, sizeof(mac_address_bin));
+
+ //ReplaceStrEx(tmp, size * 2, tmp, "$TAG_DRIVER_VER$", DRIVER_VER_STR, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$TAG_INSTANCE_NAME$", instance_name, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$TAG_MAC_ADDRESS$", mac_address_str, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$TAG_SYS_NAME$", neo_sys, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$YEAR$", str_year, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$MONTH$", str_month, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$DAY$", str_day, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$VER_MAJOR$", str_major, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$VER_MINOR$", str_minor, false);
+ ReplaceStrEx(tmp, size * 2, tmp, "$VER_BUILD$", str_build, false);
+
+ if (MsIsVista())
+ {
+ //ReplaceStrEx(tmp, size * 2, tmp, "\"100\"", "\"2000\"", false);
+ }
+
+ io = FileCreateW(dest_inf);
+ if (io == NULL)
+ {
+ Free(tmp);
+ return false;
+ }
+
+ FileWrite(io, tmp, StrLen(tmp));
+ FileClose(io);
+
+ Free(tmp);
+
+ // Processing the SYS file
+ b = ReadDumpW(src_sys);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (DumpBufW(b, dest_sys) == false)
+ {
+ FreeBuf(b);
+ return false;
+ }
+
+ FreeBuf(b);
+
+ // Copy of the catalog file
+ if (IsEmptyUniStr(src_cat) == false && IsEmptyUniStr(dst_cat) == false)
+ {
+ if (FileCopyW(src_cat, dst_cat) == false)
+ {
+ return false;
+ }
+ }
+
+ if (ret_mac_address != NULL)
+ {
+ Copy(ret_mac_address, mac_address_bin, 6);
+ }
+
+ return true;
+}
+
+// Generation of the MAC address
+void MsGenMacAddress(UCHAR *mac)
+{
+ UCHAR hash_src[40];
+ UCHAR hash[20];
+ UINT64 now;
+ // Validate arguments
+ if (mac == NULL)
+ {
+ return;
+ }
+
+ Rand(hash_src, 40);
+ now = SystemTime64();
+ Copy(hash_src, &now, sizeof(now));
+
+ Hash(hash, hash_src, sizeof(hash_src), true);
+
+ mac[0] = 0x00;
+ mac[1] = 0xAC;
+ mac[2] = hash[0];
+ mac[3] = hash[1];
+ mac[4] = hash[2];
+ mac[5] = hash[3];
+}
+
+// Finish the driver installation
+void MsFinishDriverInstall(char *instance_name, char *neo_sys)
+{
+ wchar_t src_inf[MAX_PATH];
+ wchar_t src_sys[MAX_PATH];
+ wchar_t dest_inf[MAX_PATH];
+ wchar_t dest_sys[MAX_PATH];
+ wchar_t src_cat[MAX_SIZE];
+ wchar_t dst_cat[MAX_SIZE];
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return;
+ }
+
+ MsGetDriverPath(instance_name, src_inf, src_sys, dest_inf, dest_sys, src_cat, dst_cat, neo_sys);
+
+ // Delete the files
+ FileDeleteW(dest_inf);
+ FileDeleteW(dest_sys);
+
+ if (IsEmptyUniStr(dst_cat) == false)
+ {
+ FileDeleteW(dst_cat);
+ }
+}
+
+// Get the path to the driver file
+void MsGetDriverPath(char *instance_name, wchar_t *src_inf, wchar_t *src_sys, wchar_t *dest_inf, wchar_t *dest_sys, wchar_t *src_cat, wchar_t *dest_cat, char *neo_sys)
+{
+ wchar_t *src_filename;
+ wchar_t *src_sys_filename;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return;
+ }
+
+ src_filename = DRIVER_INF_FILE_NAME;
+ src_sys_filename = DRIVER_SYS_FILE_NAME;
+
+ if (MsIsNt() == false)
+ {
+ src_filename = DRIVER_INF_FILE_NAME_9X;
+ src_sys_filename = DRIVER_SYS_FILE_NAME_9X;
+ }
+ else if (MsIsIA64() || MsIsX64())
+ {
+ if (MsIsX64())
+ {
+ src_filename = DRIVER_INF_FILE_NAME_X64;
+ src_sys_filename = DRIVER_SYS_FILE_NAME_X64;
+ }
+ else
+ {
+ src_filename = DRIVER_INF_FILE_NAME_IA64;
+ src_sys_filename = DRIVER_SYS_FILE_NAME_IA64;
+ }
+ }
+
+ if (MsIsWindows7())
+ {
+ // Use the NDIS 6.2 driver for Windows 7 or later
+ if (MsIsX64())
+ {
+ src_sys_filename = DRIVER_SYS6_FILE_NAME_X64;
+ }
+ else if (MsIsIA64())
+ {
+ src_sys_filename = DRIVER_SYS6_FILE_NAME_IA64;
+ }
+ else
+ {
+ src_sys_filename = DRIVER_SYS6_FILE_NAME;
+ }
+ }
+
+ if (src_inf != NULL)
+ {
+ if (MsIsInfCatalogRequired() == false)
+ {
+ UniStrCpy(src_inf, MAX_PATH, src_filename);
+ }
+ else
+ {
+ char tmp[MAX_SIZE];
+
+ MsGetInfCatalogDir(tmp, sizeof(tmp));
+
+ UniFormat(src_inf, MAX_PATH, L"%S\\INF_%S.inf", tmp, instance_name);
+ }
+ }
+
+ if (src_sys != NULL)
+ {
+ UniStrCpy(src_sys, MAX_PATH, src_sys_filename);
+ }
+
+ if (dest_inf != NULL)
+ {
+ char inf_name[MAX_PATH];
+ Format(inf_name, sizeof(inf_name), DRIVER_INSTALL_INF_NAME_TAG, instance_name);
+ UniFormat(dest_inf, MAX_PATH, L"%s\\%S", ms->MyTempDirW, inf_name);
+ }
+
+ if (dest_sys != NULL)
+ {
+ char sys_name[MAX_PATH];
+ StrCpy(sys_name, sizeof(sys_name), neo_sys);
+ UniFormat(dest_sys, MAX_PATH, L"%s\\%S", ms->MyTempDirW, sys_name);
+ }
+
+ if (src_cat != NULL)
+ {
+ if (MsIsInfCatalogRequired())
+ {
+ char tmp[MAX_SIZE];
+
+ MsGetInfCatalogDir(tmp, sizeof(tmp));
+ UniFormat(src_cat, MAX_PATH, L"%S\\inf.cat", tmp);
+ }
+ else
+ {
+ UniStrCpy(src_cat, MAX_PATH, L"");
+ }
+ }
+
+ if (dest_cat != NULL)
+ {
+ if (MsIsInfCatalogRequired())
+ {
+ UniFormat(dest_cat, MAX_PATH, L"%s\\inf_%S.cat", ms->MyTempDirW, instance_name);
+ }
+ else
+ {
+ UniStrCpy(dest_cat, MAX_PATH, L"");
+ }
+ }
+}
+void MsGetDriverPathA(char *instance_name, char *src_inf, char *src_sys, char *dest_inf, char *dest_sys, char *src_cat, char *dst_cat, char *neo_sys)
+{
+ wchar_t src_inf_w[MAX_PATH];
+ wchar_t src_sys_w[MAX_PATH];
+ wchar_t dest_inf_w[MAX_PATH];
+ wchar_t dest_sys_w[MAX_PATH];
+ wchar_t src_cat_w[MAX_PATH];
+ wchar_t dst_cat_w[MAX_PATH];
+
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ return;
+ }
+
+ MsGetDriverPath(instance_name, src_inf_w, src_sys_w, dest_inf_w, dest_sys_w, src_cat_w, dst_cat_w, neo_sys);
+
+ UniToStr(src_inf, MAX_PATH, src_inf_w);
+ UniToStr(src_sys, MAX_PATH, src_sys_w);
+ UniToStr(dest_inf, MAX_PATH, dest_inf_w);
+ UniToStr(dest_sys, MAX_PATH, dest_sys_w);
+ UniToStr(src_cat, MAX_PATH, src_cat_w);
+ UniToStr(dst_cat, MAX_PATH, dst_cat_w);
+}
+
+// Examine whether the virtual LAN card with the specified name has already registered
+bool MsIsVLanExists(char *tag_name, char *instance_name)
+{
+ char *guid;
+ // Validate arguments
+ if (instance_name == NULL || tag_name == NULL)
+ {
+ return false;
+ }
+
+ guid = MsGetNetworkAdapterGuid(tag_name, instance_name);
+ if (guid == NULL)
+ {
+ return false;
+ }
+
+ Free(guid);
+ return true;
+}
+
+// Create a temporary file based on the extension
+IO *MsCreateTempFileByExt(char *ext)
+{
+ char *tmp = MsCreateTempFileNameByExt(ext);
+ IO *ret;
+
+ if (tmp == NULL)
+ {
+ return NULL;
+ }
+
+ ret = FileCreate(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Create a temporary file with the specified extension
+char *MsCreateTempFileNameByExt(char *ext)
+{
+ UCHAR rand[2];
+ char *ret = NULL;
+ // Validate arguments
+ if (ext == NULL)
+ {
+ ext = "tmp";
+ }
+ if (ext[0] == '.')
+ {
+ ext++;
+ }
+ if (StrLen(ext) == 0)
+ {
+ ext = "tmp";
+ }
+
+ while (true)
+ {
+ char new_filename[MAX_PATH];
+ char *fullpath;
+ char rand_str[MAX_PATH];
+ IO *io;
+ Rand(rand, sizeof(rand));
+
+ BinToStr(rand_str, sizeof(rand_str), rand, sizeof(rand));
+ Format(new_filename, sizeof(new_filename), "__%s.%s", rand_str, ext);
+
+ fullpath = MsCreateTempFileName(new_filename);
+ io = FileOpen(fullpath, false);
+ if (io == NULL)
+ {
+ ret = fullpath;
+ break;
+ }
+ FileClose(io);
+
+ Free(fullpath);
+ }
+
+ return ret;
+}
+
+// Create a temporary file
+IO *MsCreateTempFile(char *name)
+{
+ IO *ret;
+ char *tmp;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ tmp = MsCreateTempFileName(name);
+ if (tmp == NULL)
+ {
+ return NULL;
+ }
+
+ ret = FileCreate(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Create a temporary file name
+char *MsCreateTempFileName(char *name)
+{
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ Format(tmp, sizeof(tmp), "%s\\%s", ms->MyTempDir, name);
+
+ return CopyStr(tmp);
+}
+
+// Delete VPN temporary directories that remain in the system but not used
+void MsDeleteTempDir()
+{
+ HANDLE h;
+ wchar_t dir_mask[MAX_PATH];
+ WIN32_FIND_DATAA data_a;
+ WIN32_FIND_DATAW data_w;
+
+ Zero(&data_a, sizeof(data_a));
+ Zero(&data_w, sizeof(data_w));
+
+ UniFormat(dir_mask, sizeof(dir_mask), L"%s\\*", ms->TempDirW);
+
+ if (IsNt())
+ {
+ h = FindFirstFileW(dir_mask, &data_w);
+ }
+ else
+ {
+ char *tmp_a = CopyUniToStr(dir_mask);
+
+ h = FindFirstFileA(tmp_a, &data_a);
+
+ Free(tmp_a);
+ }
+
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ bool b = true;
+
+ do
+ {
+ if (IsNt() == false)
+ {
+ Zero(&data_w, sizeof(data_w));
+ StrToUni(data_w.cFileName, sizeof(data_w.cFileName), data_a.cFileName);
+ data_w.dwFileAttributes = data_a.dwFileAttributes;
+ data_w.ftCreationTime = data_a.ftCreationTime;
+ data_w.ftLastWriteTime = data_a.ftLastWriteTime;
+ data_w.nFileSizeHigh = data_a.nFileSizeHigh;
+ data_w.nFileSizeLow = data_a.nFileSizeLow;
+ }
+
+ if (UniStrCmpi(data_w.cFileName, L".") != 0 &&
+ UniStrCmpi(data_w.cFileName, L"..") != 0)
+ {
+ if (data_w.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ if (UniStartWith(data_w.cFileName, L"VPN_") && UniStrLen(data_w.cFileName) == 8)
+ {
+ wchar_t lock_file_name[MAX_PATH];
+ wchar_t dir_name[MAX_PATH];
+ bool delete_now = false;
+ IO *io;
+
+ UniFormat(dir_name, sizeof(dir_name), L"%s\\%s",
+ ms->TempDirW, data_w.cFileName);
+ MsGenLockFile(lock_file_name, sizeof(lock_file_name), dir_name);
+
+ io = FileOpenExW(lock_file_name, false, false);
+ if (io != NULL)
+ {
+ // Mark to delete if the lock file is not locked
+ FileClose(io);
+ io = FileOpenW(lock_file_name, true);
+ if (io != NULL)
+ {
+ delete_now = true;
+ FileClose(io);
+ }
+ }
+ else
+ {
+ DIRLIST *d;
+
+ // Mark to delete if all files in this folder are not locked
+ delete_now = true;
+
+ d = EnumDirW(dir_name);
+ if (d != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < d->NumFiles;i++)
+ {
+ wchar_t full_path[MAX_PATH];
+
+ UniFormat(full_path, sizeof(full_path), L"%s\\%s", dir_name, d->File[i]->FileNameW);
+
+ io = FileOpenW(full_path, true);
+ if (io != NULL)
+ {
+ delete_now = true;
+ FileClose(io);
+ }
+ }
+ FreeDir(d);
+ }
+ }
+ if (delete_now)
+ {
+ MsDeleteAllFileW(dir_name);
+
+ Win32DeleteDirW(dir_name);
+ }
+ }
+ }
+ }
+
+
+ Zero(&data_w, sizeof(data_w));
+ Zero(&data_a, sizeof(data_a));
+
+ if (IsNt())
+ {
+ b = FindNextFileW(h, &data_w);
+ }
+ else
+ {
+ b = FindNextFileA(h, &data_a);
+ }
+ }
+ while (b);
+
+ FindClose(h);
+ }
+}
+
+// Delete all the files in the specified directory
+void MsDeleteAllFile(char *dir)
+{
+ HANDLE h;
+ char file_mask[MAX_PATH];
+ WIN32_FIND_DATA data;
+ // Validate arguments
+ if (dir == NULL || IsEmptyStr(dir))
+ {
+ return;
+ }
+
+ Format(file_mask, sizeof(file_mask), "%s\\*.*", dir);
+
+ h = FindFirstFile(file_mask, &data);
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ if (StrCmpi(data.cFileName, ".") != 0 &&
+ StrCmpi(data.cFileName, "..") != 0)
+ {
+ char fullpath[MAX_PATH];
+ Format(fullpath, sizeof(fullpath), "%s\\%s", dir, data.cFileName);
+ if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == false)
+ {
+ DeleteFile(fullpath);
+ }
+ else
+ {
+ MsDeleteAllFile(fullpath);
+ RemoveDirectory(fullpath);
+ }
+ }
+ }
+ while (FindNextFile(h, &data));
+
+ FindClose(h);
+ }
+}
+void MsDeleteAllFileW(wchar_t *dir)
+{
+ HANDLE h;
+ wchar_t file_mask[MAX_PATH];
+ WIN32_FIND_DATAW data;
+ // Validate arguments
+ if (dir == NULL || UniIsEmptyStr(dir))
+ {
+ return;
+ }
+
+ if (IsNt() == false)
+ {
+ char *dir_a = CopyUniToStr(dir);
+
+ MsDeleteAllFile(dir_a);
+
+ Free(dir_a);
+
+ return;
+ }
+
+ UniFormat(file_mask, sizeof(file_mask), L"%s\\*.*", dir);
+
+ h = FindFirstFileW(file_mask, &data);
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ if (UniStrCmpi(data.cFileName, L".") != 0 &&
+ UniStrCmpi(data.cFileName, L"..") != 0)
+ {
+ wchar_t fullpath[MAX_PATH];
+
+ UniFormat(fullpath, sizeof(fullpath), L"%s\\%s", dir, data.cFileName);
+
+ if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == false)
+ {
+ DeleteFileW(fullpath);
+ }
+ else
+ {
+ MsDeleteAllFileW(fullpath);
+ RemoveDirectoryW(fullpath);
+ }
+ }
+ }
+ while (FindNextFileW(h, &data));
+
+ FindClose(h);
+ }
+}
+
+// Initialize the temporary directory
+void MsInitTempDir()
+{
+ wchar_t tmp[MAX_PATH];
+ wchar_t tmp2[16];
+ UCHAR random[2];
+ wchar_t lockfilename[MAX_PATH];
+ UINT num = 0;
+
+ // Delete the unused temporary directory
+ MsDeleteTempDir();
+
+ // Determine the name of the temporary directory
+ while (true)
+ {
+ random[0] = rand() % 256;
+ random[1] = rand() % 256;
+ BinToStrW(tmp2, sizeof(tmp2), random, sizeof(random));
+
+ UniFormat(tmp, sizeof(tmp), L"%s\\VPN_%s", ms->TempDirW, tmp2);
+
+ // Create Directory
+ if (MakeDirW(tmp))
+ {
+ break;
+ }
+
+ if ((num++) >= 100)
+ {
+ // Failed many times
+ char msg[MAX_SIZE];
+ Format(msg, sizeof(msg),
+ "Couldn't create Temporary Directory: %s\r\n\r\n"
+ "Please contact your system administrator.",
+ tmp);
+ exit(0);
+ }
+ }
+
+ ms->MyTempDirW = CopyUniStr(tmp);
+ ms->MyTempDir = CopyUniToStr(tmp);
+
+ // Create a lock file
+ MsGenLockFile(lockfilename, sizeof(lockfilename), ms->MyTempDirW);
+ ms->LockFile = FileCreateW(lockfilename);
+}
+
+// Release the temporary directory
+void MsFreeTempDir()
+{
+ wchar_t lock_file_name[MAX_SIZE];
+
+ // Delete the lock file
+ MsGenLockFile(lock_file_name, sizeof(lock_file_name), ms->MyTempDirW);
+ FileClose(ms->LockFile);
+
+ // Memory release
+ Free(ms->MyTempDir);
+ Free(ms->MyTempDirW);
+ ms->MyTempDir = NULL;
+ ms->MyTempDirW = NULL;
+
+ // Delete directory
+ MsDeleteTempDir();
+}
+
+// Generation of the name of the lock file
+void MsGenLockFile(wchar_t *name, UINT size, wchar_t *temp_dir)
+{
+ // Validate arguments
+ if (name == NULL || temp_dir == NULL)
+ {
+ return;
+ }
+
+ UniFormat(name, size, L"%s\\VPN_Lock.dat", temp_dir);
+}
+
+// Normalization of the configuration of the interface metric of the default gateway in the network configuration
+void MsNormalizeInterfaceDefaultGatewaySettings(char *tag_name, char *instance_name)
+{
+ char tmp[MAX_SIZE];
+ char netsh[MAX_PATH];
+ char *config_str;
+ char tmp2[MAX_SIZE];
+ UINT if_index;
+ UINT if_metric;
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return;
+ }
+
+ Debug("MsNormalizeInterfaceDefaultGatewaySettings()\n");
+
+ if (MsIsVista() == false)
+ {
+ Debug("MsIsVista() == false\n");
+ return;
+ }
+
+ Format(tmp2, sizeof(tmp2), tag_name, instance_name);
+ if_index = Win32GetVLanInterfaceID(tmp2);
+ Debug("if_index=%u\n", if_index);
+
+ if (if_index == 0)
+ {
+ return;
+ }
+
+ CombinePath(netsh, sizeof(netsh), MsGetSystem32Dir(), "netsh.exe");
+
+ // Set the interface metric value
+ config_str = MsGetNetworkAdapterGuid(tag_name, instance_name);
+ if (config_str != NULL)
+ {
+ LIST *o;
+ LIST *o2;
+
+ Debug("MsNormalizeInterfaceDefaultGatewaySettings()\n");
+ Debug("if_index(%s) = %u\n", instance_name, if_index);
+
+ Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s",
+ config_str);
+
+ o = MsRegReadStrList(REG_LOCAL_MACHINE, tmp, "DefaultGateway");
+ o2 = MsRegReadStrList(REG_LOCAL_MACHINE, tmp, "DefaultGatewayMetric");
+
+ if_metric = MsRegReadInt(REG_LOCAL_MACHINE, tmp, "InterfaceMetric");
+ Debug("if_metric = %u\n", if_metric);
+
+ if (if_metric != 0)
+ {
+ if (o != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char *s = LIST_DATA(o, i);
+ char tmp[MAX_SIZE];
+
+ char *cm = NULL;
+ UINT current_metric;
+
+ if (o2 != NULL)
+ {
+ if (LIST_NUM(o2) > i)
+ {
+ current_metric = ToInt(LIST_DATA(o2, i));
+ }
+ }
+
+ Debug("gateway[%u] = %s\n", i, s);
+ Debug("current_metric[%u] = %u\n", i, current_metric);
+
+ if (current_metric == 0)
+ {
+ if (IsEmptyStr(s) == false)
+ {
+ Format(tmp, sizeof(tmp), "int ipv4 delete route prefix=0.0.0.0/0 interface=%u nexthop=%s",
+ if_index, s);
+ Debug("netsh %s\n", tmp);
+ Run(netsh, tmp, true, true);
+
+ Format(tmp, sizeof(tmp), "int ipv4 add route prefix=0.0.0.0/0 interface=%u nexthop=%s metric=%u",
+ if_index, s, if_metric);
+ Debug("netsh %s\n", tmp);
+ Run(netsh, tmp, true, true);
+ }
+ }
+ }
+ }
+ }
+
+ FreeStrList(o);
+ FreeStrList(o2);
+
+ Free(config_str);
+ }
+}
+
+// Initialization of the network configuration
+void MsInitNetworkConfig(char *tag_name, char *instance_name, char *connection_tag_name)
+{
+ char tmp[MAX_SIZE];
+ char *config_str;
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL || connection_tag_name == NULL)
+ {
+ return;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return;
+ }
+
+ // Settings such as string
+ Format(tmp, sizeof(tmp), connection_tag_name, instance_name);
+ MsSetNetworkConfig(tag_name, instance_name, tmp, true);
+
+ // Set the interface metric value
+ config_str = MsGetNetworkAdapterGuid(tag_name, instance_name);
+ if (config_str != NULL)
+ {
+ Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s",
+ config_str);
+
+ MsRegWriteInt(REG_LOCAL_MACHINE, tmp, "InterfaceMetric", 1);
+ MsRegWriteInt(REG_LOCAL_MACHINE, tmp, "EnableDeadGWDetect", 0);
+
+ if (MsRegReadInt(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "packetix_no_optimize") == 0)
+ {
+ MsRegWriteInt(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ "EnableDeadGWDetect",
+ 0);
+ }
+
+ Free(config_str);
+ }
+}
+
+// Configure the network settings
+void MsSetNetworkConfig(char *tag_name, char *instance_name, char *friendly_name, bool show_icon)
+{
+ char *key;
+ char *old_name;
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL || friendly_name == NULL)
+ {
+ return;
+ }
+
+ key = MsGetNetworkConfigRegKeyNameFromInstanceName(tag_name, instance_name);
+ if (key == NULL)
+ {
+ return;
+ }
+
+ old_name = MsRegReadStr(REG_LOCAL_MACHINE, key, "Name");
+ if (old_name != NULL)
+ {
+ if (MsIsVista())
+ {
+ char arg[MAX_PATH];
+ char netsh[MAX_PATH];
+
+ Format(netsh, sizeof(netsh), "%s\\netsh.exe", MsGetSystem32Dir());
+
+ if (StrCmp(old_name, friendly_name) != 0)
+ {
+ Format(arg, sizeof(arg), "interface set interface name=\"%s\" newname=\"%s\"",
+ old_name, friendly_name);
+
+ Run(netsh, arg, true, true);
+ }
+
+ Format(arg, sizeof(arg), "netsh interface ipv4 set interface interface=\"%s\" metric=1",
+ friendly_name);
+
+ Run(netsh, arg, true, true);
+ }
+ }
+
+ if (StrCmp(old_name, friendly_name) != 0)
+ {
+ MsRegWriteStr(REG_LOCAL_MACHINE, key, "Name", friendly_name);
+ }
+
+ MsRegWriteInt(REG_LOCAL_MACHINE, key, "ShowIcon", show_icon ? 1 : 0);
+
+ Free(key);
+
+ Free(old_name);
+}
+
+// Get the network configuration key name by the instance name
+char *MsGetNetworkConfigRegKeyNameFromInstanceName(char *tag_name, char *instance_name)
+{
+ char *guid, *ret;
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return NULL;
+ }
+
+ guid = MsGetNetworkAdapterGuid(tag_name, instance_name);
+ if (guid == NULL)
+ {
+ return NULL;
+ }
+
+ ret = MsGetNetworkConfigRegKeyNameFromGuid(guid);
+
+ Free(guid);
+
+ return ret;
+}
+
+// Get the network configuration key name by the GUID
+char *MsGetNetworkConfigRegKeyNameFromGuid(char *guid)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (guid == NULL)
+ {
+ return NULL;
+ }
+
+ Format(tmp, sizeof(tmp),
+ "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection",
+ guid);
+
+ return CopyStr(tmp);
+}
+
+// Configuring the MAC address
+void MsSetMacAddress(char *tag_name, char *instance_name, char *mac_address)
+{
+ TOKEN_LIST *key_list;
+ UINT i;
+ char dest_name[MAX_SIZE];
+ char mac_str[MAX_SIZE];
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return;
+ }
+
+ // Normalization of the MAC address
+ if (NormalizeMacAddress(mac_str, sizeof(mac_str), mac_address) == false)
+ {
+ return;
+ }
+
+ // Generate the desired name
+ Format(dest_name, sizeof(dest_name), tag_name, instance_name);
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+ if (key_list == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ if (StrCmpi(dest_name, driver_desc) == 0)
+ {
+ // Writing of the MAC address
+ MsRegWriteStr(REG_LOCAL_MACHINE, full_key_name, "NetworkAddress", mac_str);
+ Free(driver_desc);
+
+ // Restarting the driver
+ MsRestartVLan(instance_name);
+ break;
+ }
+ Free(driver_desc);
+ }
+ }
+
+ FreeToken(key_list);
+
+ return;
+}
+
+// Get the file name of the device driver
+char *MsGetDriverFileName(char *tag_name, char *instance_name)
+{
+ TOKEN_LIST *key_list;
+ UINT i;
+ char *ret = NULL;
+ char dest_name[MAX_SIZE];
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Generate the desired name
+ Format(dest_name, sizeof(dest_name), tag_name, instance_name);
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+ if (key_list == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ if (StrCmpi(dest_name, driver_desc) == 0)
+ {
+ // Read the file name
+ ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DeviceVxDs");
+ Free(driver_desc);
+ break;
+ }
+ Free(driver_desc);
+ }
+ }
+
+ FreeToken(key_list);
+
+ return ret;
+}
+
+// Get the version of the device driver
+char *MsGetDriverVersion(char *tag_name, char *instance_name)
+{
+ TOKEN_LIST *key_list;
+ TOKEN_LIST *t;
+ UINT i;
+ char *ret = NULL;
+ char dest_name[MAX_SIZE];
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Generate the desired name
+ Format(dest_name, sizeof(dest_name), tag_name, instance_name);
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+ if (key_list == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ if (StrCmpi(dest_name, driver_desc) == 0)
+ {
+ // Read the version information
+ ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverVersion");
+ if (ret == NULL)
+ {
+ ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "NeoVersion");
+ }
+ Free(driver_desc);
+ break;
+ }
+ Free(driver_desc);
+ }
+ }
+
+ FreeToken(key_list);
+
+ if (ret == NULL)
+ {
+ return NULL;
+ }
+
+ t = ParseToken(ret, ", ");
+ if (t->NumTokens == 2)
+ {
+ Free(ret);
+ ret = CopyStr(t->Token[1]);
+ }
+ FreeToken(t);
+
+ return ret;
+}
+
+// Get the registry key of the NETCFG of the virtual LAN card
+char *MsGetNetCfgRegKeyName(char *tag_name, char *instance_name)
+{
+ TOKEN_LIST *key_list;
+ UINT i;
+ char *ret = NULL;
+ char dest_name[MAX_SIZE];
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Generate the desired name
+ Format(dest_name, sizeof(dest_name), tag_name, instance_name);
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+
+ if (key_list == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ if (StrCmpi(dest_name, driver_desc) == 0)
+ {
+ ret = CopyStr(full_key_name);
+
+ Free(driver_desc);
+ break;
+ }
+ Free(driver_desc);
+ }
+ }
+
+ FreeToken(key_list);
+
+ return ret;
+}
+
+// Get the MAC address
+char *MsGetMacAddress(char *tag_name, char *instance_name)
+{
+ TOKEN_LIST *key_list;
+ UINT i;
+ char *ret = NULL;
+ char dest_name[MAX_SIZE];
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Generate the desired name
+ Format(dest_name, sizeof(dest_name), tag_name, instance_name);
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+
+ if (key_list == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ if (StrCmpi(dest_name, driver_desc) == 0)
+ {
+ // Read the MAC address
+ ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "NetworkAddress");
+
+ if (IsEmptyStr(ret) == false)
+ {
+ // Insert hyphens between the MAC address elements
+ BUF *b = StrToBin(ret);
+ if (b != NULL && b->Size == 6)
+ {
+ char tmp[MAX_SIZE];
+ MacToStr(tmp, sizeof(tmp), b->Buf);
+
+ Free(ret);
+ ret = CopyStr(tmp);
+ }
+ FreeBuf(b);
+ }
+
+ Free(driver_desc);
+ break;
+ }
+ Free(driver_desc);
+ }
+ }
+
+ FreeToken(key_list);
+
+ return ret;
+}
+
+// Check whether the device name of the virtual LAN card exists really
+bool MsCheckVLanDeviceIdFromRootEnum(char *name)
+{
+ TOKEN_LIST *t;
+ char *root;
+ char *keyname;
+ UINT i;
+ bool ret;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt())
+ {
+ root = "SYSTEM\\CurrentControlSet\\Enum\\Root\\NET";
+ keyname = "HardwareID";
+ }
+ else
+ {
+ root = "Enum\\Root\\Net";
+ keyname = "CompatibleIDs";
+ }
+
+ t = MsRegEnumKey(REG_LOCAL_MACHINE, root);
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ ret = false;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *subname = t->Token[i];
+ char fullname[MAX_SIZE];
+ char *value;
+
+ Format(fullname, sizeof(fullname), "%s\\%s", root, subname);
+
+ value = MsRegReadStr(REG_LOCAL_MACHINE, fullname, keyname);
+ if (value != NULL)
+ {
+ if (StrCmpi(value, name) == 0)
+ {
+ ret = true;
+ }
+ Free(value);
+ }
+
+ if (ret)
+ {
+ break;
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+// Get the GUID of the network adapter
+char *MsGetNetworkAdapterGuid(char *tag_name, char *instance_name)
+{
+ TOKEN_LIST *key_list;
+ UINT i;
+ char *ret = NULL;
+ char dest_name[MAX_SIZE];
+ // Validate arguments
+ if (tag_name == NULL || instance_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Generate the desired name
+ Format(dest_name, sizeof(dest_name), tag_name, instance_name);
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+ if (key_list == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+ char *device_id;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ device_id = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "MatchingDeviceId");
+
+ if (device_id != NULL)
+ {
+ if (MsCheckVLanDeviceIdFromRootEnum(device_id))
+ {
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ if (StrCmpi(dest_name, driver_desc) == 0)
+ {
+ // Read the NetCfgInstanceId
+ if (MsIsNt())
+ {
+ ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "NetCfgInstanceId");
+ }
+ else
+ {
+ ret = CopyStr("");
+ }
+ Free(driver_desc);
+ Free(device_id);
+ break;
+ }
+ Free(driver_desc);
+ }
+ }
+ Free(device_id);
+ }
+ }
+
+ FreeToken(key_list);
+
+ return ret;
+}
+// Get the network connection name
+wchar_t *MsGetNetworkConnectionName(char *guid)
+{
+ wchar_t *ncname = NULL;
+ // Validate arguments
+ if (guid == NULL)
+ {
+ return NULL;
+ }
+
+ // Get the network connection name
+ if (IsNt() != false && GetOsInfo()->OsType >= OSTYPE_WINDOWS_2000_PROFESSIONAL)
+ {
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", guid);
+ ncname = MsRegReadStrW(REG_LOCAL_MACHINE, tmp, "Name");
+ }
+
+ return ncname;
+}
+
+// Generate driver file name for the new Neo
+bool MsMakeNewNeoDriverFilename(char *name, UINT size)
+{
+ TOKEN_LIST *t = MsEnumNeoDriverFilenames();
+ UINT i;
+ bool ret = false;
+
+ i = 0;
+ while (true)
+ {
+ char tmp[MAX_PATH];
+ UINT n;
+
+ i++;
+ if (i >= 10000)
+ {
+ break;
+ }
+
+ n = Rand32() % DRIVER_INSTALL_SYS_NAME_TAG_MAXID;
+
+ MsGenerateNeoDriverFilenameFromInt(tmp, sizeof(tmp), n);
+
+ if (IsInToken(t, tmp) == false)
+ {
+ StrCpy(name, size, tmp);
+ ret = true;
+ break;
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+// Generate the driver file name of Neo from a integer
+void MsGenerateNeoDriverFilenameFromInt(char *name, UINT size, UINT n)
+{
+ Format(name, size, DRIVER_INSTALL_SYS_NAME_TAG_NEW, n);
+}
+
+// Enumeration of the driver file names of installed Neo
+TOKEN_LIST *MsEnumNeoDriverFilenames()
+{
+ TOKEN_LIST *neos = MsEnumNetworkAdaptersNeo();
+ LIST *o = NewListFast(NULL);
+ TOKEN_LIST *ret;
+ UINT i;
+
+ for (i = 0;i < neos->NumTokens;i++)
+ {
+ char filename[MAX_PATH];
+ if (MsGetNeoDeiverFilename(filename, sizeof(filename), neos->Token[i]))
+ {
+ Add(o, CopyStr(filename));
+ }
+ }
+
+ FreeToken(neos);
+
+ ret = ListToTokenList(o);
+ FreeStrList(o);
+
+ return ret;
+}
+
+// Get the driver file name of Neo
+bool MsGetNeoDeiverFilename(char *name, UINT size, char *instance_name)
+{
+ char tmp[MAX_SIZE];
+ char *ret;
+ // Validate arguments
+ if (name == NULL || instance_name == NULL)
+ {
+ return false;
+ }
+
+ Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Services\\Neo_%s", instance_name);
+
+ ret = MsRegReadStr(REG_LOCAL_MACHINE, tmp, "ImagePath");
+ if (ret == NULL)
+ {
+ return false;
+ }
+
+ GetFileNameFromFilePath(name, size, ret);
+ Free(ret);
+
+ return true;
+}
+
+// Enumeration of the network adapter (only Neo)
+TOKEN_LIST *MsEnumNetworkAdaptersNeo()
+{
+ TOKEN_LIST *key_list;
+ TOKEN_LIST *ret;
+ LIST *o;
+ UINT i;
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+ if (key_list == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(CompareStr);
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+ char *device_id;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ // Check whether it starts with the specific name
+ device_id = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "MatchingDeviceId");
+
+ if (device_id != NULL)
+ {
+ if (MsCheckVLanDeviceIdFromRootEnum(device_id))
+ {
+ char *tag = "neoadapter_";
+ if (StartWith(device_id, tag))
+ {
+ char tmp[MAX_SIZE];
+ StrCpy(tmp, sizeof(tmp), &device_id[StrLen(tag)]);
+
+ Add(o, CopyStr(tmp));
+ }
+ }
+ Free(device_id);
+ }
+
+ Free(driver_desc);
+ }
+ }
+
+ FreeToken(key_list);
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->NumTokens = LIST_NUM(o);
+ ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ ret->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+
+ return ret;
+}
+
+// Enumeration of the network adapter
+TOKEN_LIST *MsEnumNetworkAdapters(char *start_with_name, char *start_with_name_2)
+{
+ TOKEN_LIST *key_list;
+ TOKEN_LIST *ret;
+ LIST *o;
+ UINT i;
+
+ // Enumerate the key
+ if (MsIsNt())
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
+ }
+ else
+ {
+ key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Services\\Class\\Net");
+ }
+ if (key_list == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(CompareStr);
+
+ for (i = 0;i < key_list->NumTokens;i++)
+ {
+ char *key_name = key_list->Token[i];
+ char full_key_name[MAX_SIZE];
+ char *driver_desc;
+ char *device_id;
+
+ if (MsIsNt())
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
+ key_name);
+ }
+ else
+ {
+ Format(full_key_name, sizeof(full_key_name),
+ "System\\CurrentControlSet\\Services\\Class\\Net\\%s",
+ key_name);
+ }
+
+ // Read the DriverDesc
+ driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
+ if (driver_desc != NULL)
+ {
+ // Check whether it starts with the specific name
+ if ((IsEmptyStr(start_with_name) && IsEmptyStr(start_with_name_2)) ||
+ (StartWith(driver_desc, start_with_name) || StartWith(driver_desc, start_with_name_2)))
+ {
+ device_id = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "MatchingDeviceId");
+
+ if (device_id != NULL)
+ {
+ if (MsCheckVLanDeviceIdFromRootEnum(device_id))
+ {
+ char instance_name[MAX_SIZE];
+ // Extract only the instance name from the name
+ if (StartWith(driver_desc, start_with_name))
+ {
+ if (StrLen(driver_desc) > (StrLen(start_with_name) + 3))
+ {
+ StrCpy(instance_name, sizeof(instance_name),
+ driver_desc + StrLen(start_with_name) + 3);
+ Add(o, CopyStr(instance_name));
+ }
+ }
+ else
+ {
+ if (StrLen(driver_desc) > (StrLen(start_with_name_2) + 3))
+ {
+ StrCpy(instance_name, sizeof(instance_name),
+ driver_desc + StrLen(start_with_name_2) + 3);
+ Add(o, CopyStr(instance_name));
+ }
+ }
+ }
+ Free(device_id);
+ }
+ }
+
+ Free(driver_desc);
+ }
+ }
+
+ FreeToken(key_list);
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->NumTokens = LIST_NUM(o);
+ ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ ret->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+
+ return ret;
+}
+
+// Attempt to logon to the domain
+bool MsCheckLogon(wchar_t *username, char *password)
+{
+ wchar_t password_unicode[MAX_SIZE];
+ HANDLE h;
+ // Validate arguments
+ if (username == NULL || password == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ StrToUni(password_unicode, sizeof(password_unicode), password);
+
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
+ {
+ if (ms->nt->LogonUserW(username, NULL, password_unicode, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false)
+ {
+ // Logon failure
+ return false;
+ }
+ }
+ else
+ {
+ char username_ansi[MAX_SIZE];
+ UniToStr(username_ansi, sizeof(username_ansi), username);
+
+ if (ms->nt->LogonUserA(username_ansi, NULL, password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false)
+ {
+ // Logon failure
+ return false;
+ }
+ }
+
+ CloseHandle(h);
+
+ return true;
+}
+
+// Attempt to logon to the domain
+bool MsIsPasswordEmpty(wchar_t *username)
+{
+ HANDLE h;
+ // Validate arguments
+ if (username == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
+ {
+ if (ms->nt->LogonUserW(username, NULL, L"", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false)
+ {
+ // Logon failure
+ if (GetLastError() == 1327)
+ {
+ // Password is empty
+ return true;
+ }
+ else
+ {
+ // The password is not correct
+ return false;
+ }
+ }
+ }
+ else
+ {
+ char username_ansi[MAX_SIZE];
+ UniToStr(username_ansi, sizeof(username_ansi), username);
+
+ if (ms->nt->LogonUserA(username_ansi, NULL, "", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false)
+ {
+ // Logon failure
+ if (GetLastError() == 1327)
+ {
+ // Password is empty
+ return true;
+ }
+ else
+ {
+ // The password is not correct
+ return false;
+ }
+ }
+ }
+
+ CloseHandle(h);
+
+ // Since successful logon, the password should be empty
+ return false;
+}
+
+// Execution of shutdown (NT)
+bool MsShutdownEx(bool reboot, bool force, UINT time_limit, char *message)
+{
+ if (MsIsNt() == false)
+ {
+ return MsShutdown(reboot, force);
+ }
+
+ // Get the privilege
+ if (MsEnablePrivilege(SE_SHUTDOWN_NAME, true) == false)
+ {
+ return false;
+ }
+
+ // Execute the shutdown
+ if (ms->nt->InitiateSystemShutdown(NULL, message, time_limit, force, reboot) == false)
+ {
+ MsEnablePrivilege(SE_SHUTDOWN_NAME, false);
+ return false;
+ }
+
+ // Release of privilege
+ MsEnablePrivilege(SE_SHUTDOWN_NAME, false);
+
+ return true;
+}
+
+// Execute the shutdown
+bool MsShutdown(bool reboot, bool force)
+{
+ UINT flag = 0;
+ // Get the privilege
+ if (MsEnablePrivilege(SE_SHUTDOWN_NAME, true) == false)
+ {
+ return false;
+ }
+
+ flag |= (reboot ? EWX_REBOOT : EWX_SHUTDOWN);
+ flag |= (force ? EWX_FORCE : 0);
+
+ // Execute the shutdown
+ if (ExitWindowsEx(flag, 0) == false)
+ {
+ MsEnablePrivilege(SE_SHUTDOWN_NAME, false);
+ return false;
+ }
+
+ // Release of privilege
+ MsEnablePrivilege(SE_SHUTDOWN_NAME, false);
+
+ return true;
+}
+
+// Enable or disable the privilege
+bool MsEnablePrivilege(char *name, bool enable)
+{
+ HANDLE hToken;
+ NT_API *nt = ms->nt;
+ LUID luid;
+ TOKEN_PRIVILEGES *tp;
+ bool ret;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+ if (MsIsNt() == false)
+ {
+ return true;
+ }
+
+ // Open the process token
+ if (nt->OpenProcessToken(ms->hCurrentProcess, TOKEN_ADJUST_PRIVILEGES, &hToken) == false)
+ {
+ return false;
+ }
+
+ // Get a local unique identifier
+ if (nt->LookupPrivilegeValue(NULL, name, &luid) == FALSE)
+ {
+ CloseHandle(hToken);
+ return false;
+ }
+
+ // Create a structure to enable / disable the privilege
+ tp = ZeroMalloc(sizeof(TOKEN_PRIVILEGES));
+ tp->PrivilegeCount = 1;
+ tp->Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
+ Copy(&tp->Privileges[0].Luid, &luid, sizeof(LUID));
+
+ // Manipulate the privilege
+ ret = nt->AdjustTokenPrivileges(hToken, false, tp, sizeof(TOKEN_PRIVILEGES), 0, 0);
+
+ Free(tp);
+ CloseHandle(hToken);
+
+ return ret;
+}
+
+// Get whether the current OS is a NT system
+bool MsIsNt()
+{
+ if (ms == NULL)
+ {
+ OSVERSIONINFO os;
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+ GetVersionEx(&os);
+ if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return ms->IsNt;
+}
+
+// Get whether the current user is an Admin
+bool MsIsAdmin()
+{
+ return ms->IsAdmin;
+}
+
+// Load the NT system function
+NT_API *MsLoadNtApiFunctions()
+{
+ NT_API *nt = ZeroMalloc(sizeof(NT_API));
+ OSVERSIONINFO info;
+
+ Zero(&info, sizeof(info));
+ info.dwOSVersionInfoSize = sizeof(info);
+ GetVersionEx(&info);
+
+ nt->hKernel32 = LoadLibrary("kernel32.dll");
+ if (nt->hKernel32 == NULL)
+ {
+ Free(nt);
+ return NULL;
+ }
+
+ nt->hAdvapi32 = LoadLibrary("advapi32.dll");
+ if (nt->hAdvapi32 == NULL)
+ {
+ Free(nt);
+ return NULL;
+ }
+
+ nt->hShell32 = LoadLibrary("shell32.dll");
+ if (nt->hShell32 == NULL)
+ {
+ FreeLibrary(nt->hAdvapi32);
+ Free(nt);
+ return NULL;
+ }
+
+ nt->hPsApi = LoadLibrary("psapi.dll");
+
+ if (info.dwMajorVersion >= 5)
+ {
+ nt->hNewDev = LoadLibrary("newdev.dll");
+ if (nt->hNewDev == NULL)
+ {
+ FreeLibrary(nt->hShell32);
+ FreeLibrary(nt->hAdvapi32);
+ Free(nt);
+ return NULL;
+ }
+
+ nt->hSetupApi = LoadLibrary("setupapi.dll");
+ }
+
+ nt->hSecur32 = LoadLibrary("secur32.dll");
+
+ nt->hUser32 = LoadLibrary("user32.dll");
+
+ nt->hDbgHelp = LoadLibrary("dbghelp.dll");
+
+ nt->hWcmapi = LoadLibrary("wcmapi.dll");
+
+ nt->hDwmapi = LoadLibrary("dwmapi.dll");
+
+ // Read the function
+ nt->GetComputerNameExW =
+ (BOOL (__stdcall *)(COMPUTER_NAME_FORMAT,LPWSTR,LPDWORD))
+ GetProcAddress(nt->hKernel32, "GetComputerNameExW");
+
+ nt->IsWow64Process =
+ (BOOL (__stdcall *)(HANDLE,BOOL *))
+ GetProcAddress(nt->hKernel32, "IsWow64Process");
+
+ nt->GetFileInformationByHandle =
+ (BOOL (__stdcall *)(HANDLE,LPBY_HANDLE_FILE_INFORMATION))
+ GetProcAddress(nt->hKernel32, "GetFileInformationByHandle");
+
+ nt->GetProcessHeap =
+ (HANDLE (__stdcall *)())
+ GetProcAddress(nt->hKernel32, "GetProcessHeap");
+
+ nt->SetProcessShutdownParameters =
+ (BOOL (__stdcall *)(DWORD,DWORD))
+ GetProcAddress(nt->hKernel32, "SetProcessShutdownParameters");
+
+ nt->GetNativeSystemInfo =
+ (void (__stdcall *)(SYSTEM_INFO *))
+ GetProcAddress(nt->hKernel32, "GetNativeSystemInfo");
+
+ nt->AdjustTokenPrivileges =
+ (BOOL (__stdcall *)(HANDLE,BOOL,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD))
+ GetProcAddress(nt->hAdvapi32, "AdjustTokenPrivileges");
+
+ nt->LookupPrivilegeValue =
+ (BOOL (__stdcall *)(char *,char *,PLUID))
+ GetProcAddress(nt->hAdvapi32, "LookupPrivilegeValueA");
+
+ nt->OpenProcessToken =
+ (BOOL (__stdcall *)(HANDLE,DWORD,PHANDLE))
+ GetProcAddress(nt->hAdvapi32, "OpenProcessToken");
+
+ nt->InitiateSystemShutdown =
+ (BOOL (__stdcall *)(LPTSTR,LPTSTR,DWORD,BOOL,BOOL))
+ GetProcAddress(nt->hAdvapi32, "InitiateSystemShutdownA");
+
+ nt->LogonUserW =
+ (BOOL (__stdcall *)(wchar_t *,wchar_t *,wchar_t *,DWORD,DWORD,HANDLE *))
+ GetProcAddress(nt->hAdvapi32, "LogonUserW");
+
+ nt->LogonUserA =
+ (BOOL (__stdcall *)(char *,char *,char *,DWORD,DWORD,HANDLE * ))
+ GetProcAddress(nt->hAdvapi32, "LogonUserA");
+
+ nt->DuplicateTokenEx =
+ (BOOL (__stdcall *)(HANDLE,DWORD,SECURITY_ATTRIBUTES *,SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,HANDLE *))
+ GetProcAddress(nt->hAdvapi32, "DuplicateTokenEx");
+
+ nt->ConvertStringSidToSidA =
+ (BOOL (__stdcall *)(LPCSTR,PSID *))
+ GetProcAddress(nt->hAdvapi32, "ConvertStringSidToSidA");
+
+ nt->GetTokenInformation =
+ (BOOL (__stdcall *)(HANDLE,TOKEN_INFORMATION_CLASS,void *,DWORD,PDWORD))
+ GetProcAddress(nt->hAdvapi32, "GetTokenInformation");
+
+ nt->SetTokenInformation =
+ (BOOL (__stdcall *)(HANDLE,TOKEN_INFORMATION_CLASS,void *,DWORD))
+ GetProcAddress(nt->hAdvapi32, "SetTokenInformation");
+
+ nt->CreateProcessAsUserA =
+ (BOOL (__stdcall *)(HANDLE,LPCSTR,LPSTR,LPSECURITY_ATTRIBUTES,LPSECURITY_ATTRIBUTES,BOOL,DWORD,void *,LPCSTR,LPSTARTUPINFOA,LPPROCESS_INFORMATION))
+ GetProcAddress(nt->hAdvapi32, "CreateProcessAsUserA");
+
+ nt->CreateProcessAsUserW =
+ (BOOL (__stdcall *)(HANDLE,LPCWSTR,LPWSTR,LPSECURITY_ATTRIBUTES,LPSECURITY_ATTRIBUTES,BOOL,DWORD,void *,LPCWSTR,LPSTARTUPINFOW,LPPROCESS_INFORMATION))
+ GetProcAddress(nt->hAdvapi32, "CreateProcessAsUserW");
+
+ nt->LookupAccountSidA =
+ (BOOL (__stdcall *)(LPCSTR,PSID,LPSTR,LPDWORD,LPSTR,LPDWORD,PSID_NAME_USE))
+ GetProcAddress(nt->hAdvapi32, "LookupAccountSidA");
+
+ nt->LookupAccountNameA =
+ (BOOL (__stdcall *)(LPCSTR,LPCSTR,PSID,LPDWORD,LPSTR,LPDWORD,PSID_NAME_USE))
+ GetProcAddress(nt->hAdvapi32, "LookupAccountNameA");
+
+ nt->SetNamedSecurityInfoW =
+ (DWORD (__stdcall *)(LPWSTR,UINT,SECURITY_INFORMATION,PSID,PSID,PACL,PACL))
+ GetProcAddress(nt->hAdvapi32, "SetNamedSecurityInfoW");
+
+ nt->AddAccessAllowedAceEx =
+ (BOOL (__stdcall *)(PACL,DWORD,DWORD,DWORD,PSID))
+ GetProcAddress(nt->hAdvapi32, "AddAccessAllowedAceEx");
+
+ nt->QueryFullProcessImageNameA =
+ (BOOL (__stdcall *)(HANDLE,DWORD,LPSTR,PDWORD))
+ GetProcAddress(nt->hKernel32, "QueryFullProcessImageNameA");
+
+ nt->QueryFullProcessImageNameW =
+ (BOOL (__stdcall *)(HANDLE,DWORD,LPWSTR,PDWORD))
+ GetProcAddress(nt->hKernel32, "QueryFullProcessImageNameW");
+
+ if (info.dwMajorVersion >= 5)
+ {
+ nt->UpdateDriverForPlugAndPlayDevicesW =
+ (BOOL (__stdcall *)(HWND,wchar_t *,wchar_t *,UINT,BOOL *))
+ GetProcAddress(nt->hNewDev, "UpdateDriverForPlugAndPlayDevicesW");
+
+ nt->CM_Get_Device_ID_ExA =
+ (UINT (__stdcall *)(DWORD,char *,UINT,UINT,HANDLE))
+ GetProcAddress(nt->hSetupApi, "CM_Get_Device_ID_ExA");
+
+ nt->CM_Get_DevNode_Status_Ex =
+ (UINT (__stdcall *)(UINT *,UINT *,DWORD,UINT,HANDLE))
+ GetProcAddress(nt->hSetupApi, "CM_Get_DevNode_Status_Ex");
+ }
+
+ nt->hWtsApi32 = LoadLibrary("wtsapi32.dll");
+ if (nt->hWtsApi32 != NULL)
+ {
+ // Terminal Services related API
+ nt->WTSQuerySessionInformation =
+ (UINT (__stdcall *)(HANDLE,DWORD,WTS_INFO_CLASS,wchar_t *,DWORD *))
+ GetProcAddress(nt->hWtsApi32, "WTSQuerySessionInformationW");
+ nt->WTSFreeMemory =
+ (void (__stdcall *)(void *))
+ GetProcAddress(nt->hWtsApi32, "WTSFreeMemory");
+ nt->WTSDisconnectSession =
+ (BOOL (__stdcall *)(HANDLE,DWORD,BOOL))
+ GetProcAddress(nt->hWtsApi32, "WTSDisconnectSession");
+ nt->WTSEnumerateSessionsA =
+ (BOOL (__stdcall *)(HANDLE,DWORD,DWORD,PWTS_SESSION_INFOA *,DWORD *))
+ GetProcAddress(nt->hWtsApi32, "WTSEnumerateSessionsA");
+ }
+
+ // Service related API
+ nt->OpenSCManager =
+ (SC_HANDLE (__stdcall *)(LPCTSTR,LPCTSTR,DWORD))
+ GetProcAddress(nt->hAdvapi32, "OpenSCManagerA");
+ nt->CreateServiceA =
+ (SC_HANDLE (__stdcall *)(SC_HANDLE,LPCTSTR,LPCTSTR,DWORD,DWORD,DWORD,DWORD,LPCTSTR,LPCTSTR,LPDWORD,LPCTSTR,LPCTSTR,LPCTSTR))
+ GetProcAddress(nt->hAdvapi32, "CreateServiceA");
+ nt->CreateServiceW =
+ (SC_HANDLE (__stdcall *)(SC_HANDLE,LPCWSTR,LPCWSTR,DWORD,DWORD,DWORD,DWORD,LPCWSTR,LPCWSTR,LPDWORD,LPCWSTR,LPCWSTR,LPCWSTR))
+ GetProcAddress(nt->hAdvapi32, "CreateServiceW");
+ nt->ChangeServiceConfig2 =
+ (BOOL (__stdcall *)(SC_HANDLE,DWORD,LPVOID))
+ GetProcAddress(nt->hAdvapi32, "ChangeServiceConfig2W");
+ nt->CloseServiceHandle =
+ (BOOL (__stdcall *)(SC_HANDLE))
+ GetProcAddress(nt->hAdvapi32, "CloseServiceHandle");
+ nt->OpenService =
+ (SC_HANDLE (__stdcall *)(SC_HANDLE,LPCTSTR,DWORD))
+ GetProcAddress(nt->hAdvapi32, "OpenServiceA");
+ nt->QueryServiceStatus =
+ (BOOL (__stdcall *)(SC_HANDLE,LPSERVICE_STATUS))
+ GetProcAddress(nt->hAdvapi32, "QueryServiceStatus");
+ nt->StartService =
+ (BOOL (__stdcall *)(SC_HANDLE,DWORD,LPCTSTR))
+ GetProcAddress(nt->hAdvapi32, "StartServiceA");
+ nt->ControlService =
+ (BOOL (__stdcall *)(SC_HANDLE,DWORD,LPSERVICE_STATUS))
+ GetProcAddress(nt->hAdvapi32, "ControlService");
+ nt->SetServiceStatus =
+ (BOOL (__stdcall *)(SERVICE_STATUS_HANDLE,LPSERVICE_STATUS))
+ GetProcAddress(nt->hAdvapi32, "SetServiceStatus");
+ nt->RegisterServiceCtrlHandler =
+ (SERVICE_STATUS_HANDLE (__stdcall *)(LPCTSTR,LPHANDLER_FUNCTION))
+ GetProcAddress(nt->hAdvapi32, "RegisterServiceCtrlHandlerW");
+ nt->StartServiceCtrlDispatcher =
+ (BOOL (__stdcall *)(const LPSERVICE_TABLE_ENTRY))
+ GetProcAddress(nt->hAdvapi32, "StartServiceCtrlDispatcherW");
+ nt->DeleteService =
+ (BOOL (__stdcall *)(SC_HANDLE))
+ GetProcAddress(nt->hAdvapi32, "DeleteService");
+ nt->RegisterEventSourceW =
+ (HANDLE (__stdcall *)(LPCWSTR,LPCWSTR))
+ GetProcAddress(nt->hAdvapi32, "RegisterEventSourceW");
+ nt->ReportEventW =
+ (BOOL (__stdcall *)(HANDLE,WORD,WORD,DWORD,PSID,WORD,DWORD,LPCWSTR *,LPVOID))
+ GetProcAddress(nt->hAdvapi32, "ReportEventW");
+ nt->DeregisterEventSource =
+ (BOOL (__stdcall *)(HANDLE))
+ GetProcAddress(nt->hAdvapi32, "DeregisterEventSource");
+ nt->Wow64DisableWow64FsRedirection =
+ (BOOL (__stdcall *)(void **))
+ GetProcAddress(nt->hKernel32, "Wow64DisableWow64FsRedirection");
+ nt->Wow64EnableWow64FsRedirection =
+ (BOOLEAN (__stdcall *)(BOOLEAN))
+ GetProcAddress(nt->hKernel32, "Wow64EnableWow64FsRedirection");
+ nt->Wow64RevertWow64FsRedirection =
+ (BOOL (__stdcall *)(void *))
+ GetProcAddress(nt->hKernel32, "Wow64RevertWow64FsRedirection");
+
+ if (nt->hPsApi != NULL)
+ {
+ // Process related API
+ nt->EnumProcesses =
+ (BOOL (__stdcall *)(DWORD *,DWORD,DWORD *))
+ GetProcAddress(nt->hPsApi, "EnumProcesses");
+
+ nt->EnumProcessModules =
+ (BOOL (__stdcall *)(HANDLE,HMODULE * ,DWORD,DWORD *))
+ GetProcAddress(nt->hPsApi, "EnumProcessModules");
+
+ nt->GetModuleFileNameExA =
+ (DWORD (__stdcall *)(HANDLE,HMODULE,LPSTR,DWORD))
+ GetProcAddress(nt->hPsApi, "GetModuleFileNameExA");
+
+ nt->GetModuleFileNameExW =
+ (DWORD (__stdcall *)(HANDLE,HMODULE,LPWSTR,DWORD))
+ GetProcAddress(nt->hPsApi, "GetModuleFileNameExW");
+
+ nt->GetProcessImageFileNameA =
+ (DWORD (__stdcall *)(HANDLE,LPSTR,DWORD))
+ GetProcAddress(nt->hPsApi, "GetProcessImageFileNameA");
+
+ nt->GetProcessImageFileNameW =
+ (DWORD (__stdcall *)(HANDLE,LPWSTR,DWORD))
+ GetProcAddress(nt->hPsApi, "GetProcessImageFileNameW");
+ }
+
+ // Registry related API
+ nt->RegDeleteKeyExA =
+ (LONG (__stdcall *)(HKEY,LPCTSTR,REGSAM,DWORD))
+ GetProcAddress(nt->hAdvapi32, "RegDeleteKeyExA");
+
+ // Security related API
+ if (nt->hSecur32 != NULL)
+ {
+ nt->GetUserNameExA =
+ (BOOL (__stdcall *)(EXTENDED_NAME_FORMAT,LPSTR,PULONG))
+ GetProcAddress(nt->hSecur32, "GetUserNameExA");
+
+ nt->GetUserNameExW =
+ (BOOL (__stdcall *)(EXTENDED_NAME_FORMAT,LPWSTR,PULONG))
+ GetProcAddress(nt->hSecur32, "GetUserNameExW");
+
+ nt->LsaConnectUntrusted =
+ (NTSTATUS (__stdcall *)(PHANDLE))
+ GetProcAddress(nt->hSecur32, "LsaConnectUntrusted");
+
+ nt->LsaLookupAuthenticationPackage =
+ (NTSTATUS (__stdcall *)(HANDLE,PLSA_STRING,PULONG))
+ GetProcAddress(nt->hSecur32, "LsaLookupAuthenticationPackage");
+
+ nt->LsaLogonUser =
+ (NTSTATUS (__stdcall *)(HANDLE,PLSA_STRING,SECURITY_LOGON_TYPE,ULONG,PVOID,ULONG,PTOKEN_GROUPS,PTOKEN_SOURCE,PVOID,PULONG,PLUID,PHANDLE,PQUOTA_LIMITS,PNTSTATUS))
+ GetProcAddress(nt->hSecur32, "LsaLogonUser");
+
+ nt->LsaDeregisterLogonProcess =
+ (NTSTATUS (__stdcall *)(HANDLE))
+ GetProcAddress(nt->hSecur32, "LsaDeregisterLogonProcess");
+
+ nt->LsaFreeReturnBuffer =
+ (NTSTATUS (__stdcall *)(PVOID))
+ GetProcAddress(nt->hSecur32, "LsaFreeReturnBuffer");
+ }
+
+ // WCM related API of Windows 8
+ if (nt->hWcmapi != NULL)
+ {
+ nt->WcmQueryProperty =
+ (DWORD (__stdcall *)(const GUID *,LPCWSTR,MS_WCM_PROPERTY,PVOID,PDWORD,PBYTE *))
+ GetProcAddress(nt->hWcmapi, "WcmQueryProperty");
+
+ nt->WcmSetProperty =
+ (DWORD (__stdcall *)(const GUID *,LPCWSTR,MS_WCM_PROPERTY,PVOID,DWORD,const BYTE *))
+ GetProcAddress(nt->hWcmapi, "WcmSetProperty");
+
+ nt->WcmFreeMemory =
+ (void (__stdcall *)(PVOID))
+ GetProcAddress(nt->hWcmapi, "WcmFreeMemory");
+
+ nt->WcmGetProfileList =
+ (DWORD (__stdcall *)(PVOID,MS_WCM_PROFILE_INFO_LIST **))
+ GetProcAddress(nt->hWcmapi, "WcmGetProfileList");
+ }
+
+ nt->AllocateLocallyUniqueId =
+ (BOOL (__stdcall *)(PLUID))
+ GetProcAddress(nt->hAdvapi32, "AllocateLocallyUniqueId");
+
+ // Desktop related API
+ if (nt->hUser32 != NULL)
+ {
+ nt->SwitchDesktop =
+ (BOOL (__stdcall *)(HDESK))
+ GetProcAddress(nt->hUser32, "SwitchDesktop");
+ nt->OpenDesktopA =
+ (HDESK (__stdcall *)(LPTSTR,DWORD,BOOL,ACCESS_MASK))
+ GetProcAddress(nt->hUser32, "OpenDesktopA");
+ nt->CloseDesktop =
+ (BOOL (__stdcall *)(HDESK))
+ GetProcAddress(nt->hUser32, "CloseDesktop");
+ }
+
+ // DWM API
+ if (nt->hDwmapi)
+ {
+ nt->DwmIsCompositionEnabled =
+ (HRESULT (__stdcall *)(BOOL *))
+ GetProcAddress(nt->hDwmapi, "DwmIsCompositionEnabled");
+ }
+
+ // Debug related API
+ if (nt->hDbgHelp != NULL)
+ {
+ nt->MiniDumpWriteDump =
+ (BOOL (__stdcall *)(HANDLE,DWORD,HANDLE,MINIDUMP_TYPE,PMINIDUMP_EXCEPTION_INFORMATION,PMINIDUMP_USER_STREAM_INFORMATION,PMINIDUMP_CALLBACK_INFORMATION))
+ GetProcAddress(nt->hDbgHelp, "MiniDumpWriteDump");
+ }
+
+ return nt;
+}
+
+// Release of NT system function
+void MsFreeNtApiFunctions(NT_API *nt)
+{
+ // Validate arguments
+ if (nt == NULL)
+ {
+ return;
+ }
+
+ if (nt->hSecur32 != NULL)
+ {
+ FreeLibrary(nt->hSecur32);
+ }
+
+ if (nt->hNewDev != NULL)
+ {
+ FreeLibrary(nt->hSetupApi);
+ FreeLibrary(nt->hNewDev);
+ }
+
+ FreeLibrary(nt->hAdvapi32);
+
+ FreeLibrary(nt->hShell32);
+
+ if (nt->hWtsApi32 != NULL)
+ {
+ FreeLibrary(nt->hWtsApi32);
+ }
+
+ if (nt->hPsApi != NULL)
+ {
+ FreeLibrary(nt->hPsApi);
+ }
+
+ if (nt->hUser32 != NULL)
+ {
+ FreeLibrary(nt->hUser32);
+ }
+
+ if (nt->hDbgHelp != NULL)
+ {
+ FreeLibrary(nt->hDbgHelp);
+ }
+
+ if (nt->hWcmapi != NULL)
+ {
+ FreeLibrary(nt->hWcmapi);
+ }
+
+ if (nt->hDwmapi != NULL)
+ {
+ FreeLibrary(nt->hDwmapi);
+ }
+
+ FreeLibrary(nt->hKernel32);
+
+ Free(nt);
+}
+
+// Get whether the screen color is like to Aero of Windows Vista or later
+bool MsIsAeroColor()
+{
+ UINT r;
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ if (MsIsVista() == false)
+ {
+ return false;
+ }
+
+ r = GetSysColor(COLOR_MENU);
+ if (r == 0xFFFFFF || r == 0xF0F0F0 || r >= 0xF00000)
+ {
+ return true;
+ }
+
+ if (MsIsAeroEnabled())
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Get whether Aero is enabled
+bool MsIsAeroEnabled()
+{
+ bool ret;
+ if (MsIsNt() == false)
+ {
+ return false;
+ }
+
+ if (ms->nt->DwmIsCompositionEnabled == NULL)
+ {
+ return false;
+ }
+
+ ret = false;
+
+ if (ms->nt->DwmIsCompositionEnabled(&ret) != S_OK)
+ {
+ return false;
+ }
+
+ return ret;
+}
+
+// Generate an access mask to force accessing to the 32 bit registry key for 64 bit application
+DWORD MsRegAccessMaskFor64Bit(bool force32bit)
+{
+ return MsRegAccessMaskFor64BitEx(force32bit, false);
+}
+DWORD MsRegAccessMaskFor64BitEx(bool force32bit, bool force64bit)
+{
+ if (MsIs64BitWindows() == false)
+ {
+ return 0;
+ }
+ if (force32bit)
+ {
+ return KEY_WOW64_32KEY;
+ }
+ if (force64bit)
+ {
+ return KEY_WOW64_64KEY;
+ }
+
+ return 0;
+}
+
+// Delete the value
+bool MsRegDeleteValue(UINT root, char *keyname, char *valuename)
+{
+ return MsRegDeleteValueEx(root, keyname, valuename, false);
+}
+bool MsRegDeleteValueEx(UINT root, char *keyname, char *valuename, bool force32bit)
+{
+ return MsRegDeleteValueEx2(root, keyname, valuename, force32bit, false);
+}
+bool MsRegDeleteValueEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ bool ret;
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return false;
+ }
+
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ if (RegDeleteValue(h, valuename) != ERROR_SUCCESS)
+ {
+ ret = false;
+ }
+ else
+ {
+ ret = true;
+ }
+
+ RegCloseKey(h);
+
+ return ret;
+}
+
+// Delete the key
+bool MsRegDeleteKey(UINT root, char *keyname)
+{
+ return MsRegDeleteKeyEx(root, keyname, false);
+}
+bool MsRegDeleteKeyEx(UINT root, char *keyname, bool force32bit)
+{
+ return MsRegDeleteKeyEx2(root, keyname, force32bit, false);
+}
+bool MsRegDeleteKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit)
+{
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return false;
+ }
+
+ if (MsIsNt() && ms->nt->RegDeleteKeyExA != NULL)
+ {
+ if (ms->nt->RegDeleteKeyExA(MsGetRootKeyFromInt(root), keyname, MsRegAccessMaskFor64BitEx(force32bit, force64bit), 0) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (RegDeleteKey(MsGetRootKeyFromInt(root), keyname) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Enumeration of values
+TOKEN_LIST *MsRegEnumValue(UINT root, char *keyname)
+{
+ return MsRegEnumValueEx(root, keyname, false);
+}
+TOKEN_LIST *MsRegEnumValueEx(UINT root, char *keyname, bool force32bit)
+{
+ return MsRegEnumValueEx2(root, keyname, force32bit, false);
+}
+TOKEN_LIST *MsRegEnumValueEx2(UINT root, char *keyname, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ UINT i;
+ TOKEN_LIST *t;
+ LIST *o;
+
+ if (keyname == NULL)
+ {
+ h = MsGetRootKeyFromInt(root);
+ }
+ else
+ {
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return NULL;
+ }
+ }
+
+ o = NewListFast(CompareStr);
+
+ for (i = 0;;i++)
+ {
+ char tmp[MAX_SIZE];
+ UINT ret;
+ UINT size = sizeof(tmp);
+
+ Zero(tmp, sizeof(tmp));
+ ret = RegEnumValue(h, i, tmp, &size, NULL, NULL, NULL, NULL);
+ if (ret == ERROR_NO_MORE_ITEMS)
+ {
+ break;
+ }
+ else if (ret != ERROR_SUCCESS)
+ {
+ break;
+ }
+
+ Add(o, CopyStr(tmp));
+ }
+
+ Sort(o);
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+
+ if (keyname != NULL)
+ {
+ RegCloseKey(h);
+ }
+
+ return t;
+}
+
+// Enumeration of the keys
+TOKEN_LIST *MsRegEnumKey(UINT root, char *keyname)
+{
+ return MsRegEnumKeyEx(root, keyname, false);
+}
+TOKEN_LIST *MsRegEnumKeyEx(UINT root, char *keyname, bool force32bit)
+{
+ return MsRegEnumKeyEx2(root, keyname, force32bit, false);
+}
+TOKEN_LIST *MsRegEnumKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ UINT i;
+ TOKEN_LIST *t;
+ LIST *o;
+
+ if (keyname == NULL)
+ {
+ h = MsGetRootKeyFromInt(root);
+ }
+ else
+ {
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return NULL;
+ }
+ }
+
+ o = NewListFast(CompareStr);
+
+ for (i = 0;;i++)
+ {
+ char tmp[MAX_SIZE];
+ UINT ret;
+ UINT size = sizeof(tmp);
+ FILETIME ft;
+
+ Zero(tmp, sizeof(tmp));
+ ret = RegEnumKeyEx(h, i, tmp, &size, NULL, NULL, NULL, &ft);
+ if (ret == ERROR_NO_MORE_ITEMS)
+ {
+ break;
+ }
+ else if (ret != ERROR_SUCCESS)
+ {
+ break;
+ }
+
+ Add(o, CopyStr(tmp));
+ }
+
+ Sort(o);
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+
+ if (keyname != NULL)
+ {
+ RegCloseKey(h);
+ }
+
+ return t;
+}
+
+// Set the binary data
+bool MsRegWriteBin(UINT root, char *keyname, char *valuename, void *data, UINT size)
+{
+ return MsRegWriteBinEx(root, keyname, valuename, data, size, false);
+}
+bool MsRegWriteBinEx(UINT root, char *keyname, char *valuename, void *data, UINT size, bool force32bit)
+{
+ return MsRegWriteBinEx2(root, keyname, valuename, data, size, force32bit, false);
+}
+bool MsRegWriteBinEx2(UINT root, char *keyname, char *valuename, void *data, UINT size, bool force32bit, bool force64bit)
+{
+ // Validate arguments
+ if (keyname == NULL || (size != 0 && data == NULL))
+ {
+ return false;
+ }
+
+ return MsRegWriteValueEx2(root, keyname, valuename, REG_BINARY, data, size, force32bit, force64bit);
+}
+
+// Set the integer value
+bool MsRegWriteInt(UINT root, char *keyname, char *valuename, UINT value)
+{
+ return MsRegWriteIntEx(root, keyname, valuename, value, false);
+}
+bool MsRegWriteIntEx(UINT root, char *keyname, char *valuename, UINT value, bool force32bit)
+{
+ return MsRegWriteIntEx2(root, keyname, valuename, value, force32bit, false);
+}
+bool MsRegWriteIntEx2(UINT root, char *keyname, char *valuename, UINT value, bool force32bit, bool force64bit)
+{
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return false;
+ }
+
+ // Endian correction
+ if (IsBigEndian())
+ {
+ value = Swap32(value);
+ }
+
+ return MsRegWriteValueEx2(root, keyname, valuename, REG_DWORD_LITTLE_ENDIAN, &value, sizeof(UINT), force32bit, force64bit);
+}
+
+// Set the string
+bool MsRegWriteStrExpand(UINT root, char *keyname, char *valuename, char *str)
+{
+ return MsRegWriteStrExpandEx(root, keyname, valuename, str, false);
+}
+bool MsRegWriteStrExpandEx(UINT root, char *keyname, char *valuename, char *str, bool force32bit)
+{
+ return MsRegWriteStrExpandEx2(root, keyname, valuename, str, force32bit, false);
+}
+bool MsRegWriteStrExpandEx2(UINT root, char *keyname, char *valuename, char *str, bool force32bit, bool force64bit)
+{
+ // Validate arguments
+ if (keyname == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ return MsRegWriteValueEx2(root, keyname, valuename, REG_EXPAND_SZ, str, StrSize(str), force32bit, force64bit);
+}
+bool MsRegWriteStrExpandW(UINT root, char *keyname, char *valuename, wchar_t *str)
+{
+ return MsRegWriteStrExpandExW(root, keyname, valuename, str, false);
+}
+bool MsRegWriteStrExpandExW(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit)
+{
+ return MsRegWriteStrExpandEx2W(root, keyname, valuename, str, force32bit, false);
+}
+bool MsRegWriteStrExpandEx2W(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit, bool force64bit)
+{
+ // Validate arguments
+ if (keyname == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ return MsRegWriteValueEx2W(root, keyname, valuename, REG_EXPAND_SZ, str, UniStrSize(str), force32bit, force64bit);
+}
+
+bool MsRegWriteStr(UINT root, char *keyname, char *valuename, char *str)
+{
+ return MsRegWriteStrEx(root, keyname, valuename, str, false);
+}
+bool MsRegWriteStrEx(UINT root, char *keyname, char *valuename, char *str, bool force32bit)
+{
+ return MsRegWriteStrEx2(root, keyname, valuename, str, force32bit, false);
+}
+bool MsRegWriteStrEx2(UINT root, char *keyname, char *valuename, char *str, bool force32bit, bool force64bit)
+{
+ // Validate arguments
+ if (keyname == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ return MsRegWriteValueEx2(root, keyname, valuename, REG_SZ, str, StrSize(str), force32bit, force64bit);
+}
+bool MsRegWriteStrW(UINT root, char *keyname, char *valuename, wchar_t *str)
+{
+ return MsRegWriteStrExW(root, keyname, valuename, str, false);
+}
+bool MsRegWriteStrExW(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit)
+{
+ return MsRegWriteStrEx2W(root, keyname, valuename, str, force32bit, false);
+}
+bool MsRegWriteStrEx2W(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit, bool force64bit)
+{
+ // Validate arguments
+ if (keyname == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ return MsRegWriteValueEx2W(root, keyname, valuename, REG_SZ, str, UniStrSize(str), force32bit, force64bit);
+}
+
+// Set the value
+bool MsRegWriteValue(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size)
+{
+ return MsRegWriteValueEx(root, keyname, valuename, type, data, size, false);
+}
+bool MsRegWriteValueEx(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit)
+{
+ return MsRegWriteValueEx2(root, keyname, valuename, type, data, size, force32bit, false);
+}
+bool MsRegWriteValueEx2(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ // Validate arguments
+ if (keyname == NULL || (size != 0 && data == NULL))
+ {
+ return false;
+ }
+
+ // Create a key
+ MsRegNewKeyEx2(root, keyname, force32bit, force64bit);
+
+ // Open the key
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ // Write the value
+ if (RegSetValueEx(h, valuename, 0, type, data, size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(h);
+ return false;
+ }
+
+ // Close the key
+ RegCloseKey(h);
+
+ return true;
+}
+bool MsRegWriteValueW(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size)
+{
+ return MsRegWriteValueExW(root, keyname, valuename, type, data, size, false);
+}
+bool MsRegWriteValueExW(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit)
+{
+ return MsRegWriteValueEx2W(root, keyname, valuename, type, data, size, force32bit, false);
+}
+bool MsRegWriteValueEx2W(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ wchar_t *valuename_w;
+ // Validate arguments
+ if (keyname == NULL || (size != 0 && data == NULL))
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ UINT size_a;
+ void *data_a;
+ bool ret;
+
+ if (type == REG_SZ || type == REG_MULTI_SZ || type == REG_EXPAND_SZ)
+ {
+ data_a = CopyUniToStr(data);
+ size_a = StrSize(data_a);
+ }
+ else
+ {
+ data_a = Clone(data, size);
+ size_a = size;
+ }
+
+ ret = MsRegWriteValueEx2(root, keyname, valuename, type, data_a, size_a, force32bit, force64bit);
+
+ Free(data_a);
+
+ return ret;
+ }
+
+ // Create a key
+ MsRegNewKeyEx2(root, keyname, force32bit, force64bit);
+
+ // Open the key
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ valuename_w = CopyStrToUni(valuename);
+
+ // Write the value
+ if (RegSetValueExW(h, valuename_w, 0, type, data, size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(h);
+ Free(valuename_w);
+ return false;
+ }
+
+ // Close the key
+ RegCloseKey(h);
+ Free(valuename_w);
+
+ return true;
+}
+
+// Get the binary data
+BUF *MsRegReadBin(UINT root, char *keyname, char *valuename)
+{
+ return MsRegReadBinEx(root, keyname, valuename, false);
+}
+BUF *MsRegReadBinEx(UINT root, char *keyname, char *valuename, bool force32bit)
+{
+ return MsRegReadBinEx2(root, keyname, valuename, force32bit, false);
+}
+BUF *MsRegReadBinEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
+{
+ char *ret;
+ UINT type, size;
+ BUF *b;
+ // Validate arguments
+ if (keyname == NULL || valuename == NULL)
+ {
+ return 0;
+ }
+
+ // Read the value
+ if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false)
+ {
+ return 0;
+ }
+
+ b = NewBuf();
+
+ WriteBuf(b, ret, size);
+ SeekBuf(b, 0, 0);
+
+ Free(ret);
+
+ return b;
+}
+
+// Get an integer value
+UINT MsRegReadInt(UINT root, char *keyname, char *valuename)
+{
+ return MsRegReadIntEx(root, keyname, valuename, false);
+}
+UINT MsRegReadIntEx(UINT root, char *keyname, char *valuename, bool force32bit)
+{
+ return MsRegReadIntEx2(root, keyname, valuename, force32bit, false);
+}
+UINT MsRegReadIntEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
+{
+ char *ret;
+ UINT type, size;
+ UINT value;
+ // Validate arguments
+ if (keyname == NULL || valuename == NULL)
+ {
+ return 0;
+ }
+
+ // Read the value
+ if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false)
+ {
+ return 0;
+ }
+
+ // Check the type
+ if (type != REG_DWORD_LITTLE_ENDIAN && type != REG_DWORD_BIG_ENDIAN)
+ {
+ // It is not a DWORD
+ Free(ret);
+ return 0;
+ }
+
+ // Check the size
+ if (size != sizeof(UINT))
+ {
+ Free(ret);
+ return 0;
+ }
+
+ Copy(&value, ret, sizeof(UINT));
+
+ Free(ret);
+
+ // Endian conversion
+ if (IsLittleEndian())
+ {
+#ifdef REG_DWORD_BIG_ENDIAN
+ if (type == REG_DWORD_BIG_ENDIAN)
+ {
+ value = Swap32(value);
+ }
+#endif // REG_DWORD_BIG_ENDIAN
+ }
+ else
+ {
+#ifdef REG_DWORD_LITTLE_ENDIAN_FLAG
+ if (type == REG_DWORD_LITTLE_ENDIAN_FLAG)
+ {
+ value = Swap32(value);
+ }
+#endif // REG_DWORD_LITTLE_ENDIAN_FLAG
+ }
+
+ return value;
+}
+
+// Get a string list
+LIST *MsRegReadStrList(UINT root, char *keyname, char *valuename)
+{
+ return MsRegReadStrListEx(root, keyname, valuename, false);
+}
+LIST *MsRegReadStrListEx(UINT root, char *keyname, char *valuename, bool force32bit)
+{
+ return MsRegReadStrListEx2(root, keyname, valuename, force32bit, false);
+}
+LIST *MsRegReadStrListEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
+{
+ LIST *o;
+ char *ret;
+ UINT type, size;
+ // Validate arguments
+ if (keyname == NULL || valuename == NULL)
+ {
+ return NULL;
+ }
+
+ // Read the value
+ if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false)
+ {
+ return NULL;
+ }
+
+ // Check the type
+ if (type != REG_MULTI_SZ)
+ {
+ // It is not a string list
+ Free(ret);
+ return NULL;
+ }
+
+ if (size < 2)
+ {
+ // Invalid size
+ Free(ret);
+ return NULL;
+ }
+
+ if (ret[size - 1] != 0)
+ {
+ // Invalid data
+ Free(ret);
+ return NULL;
+ }
+
+ // Creating a list
+ o = StrToStrList(ret, size);
+
+ Free(ret);
+
+ return o;
+}
+
+// Get a string
+char *MsRegReadStr(UINT root, char *keyname, char *valuename)
+{
+ return MsRegReadStrEx(root, keyname, valuename, false);
+}
+char *MsRegReadStrEx(UINT root, char *keyname, char *valuename, bool force32bit)
+{
+ return MsRegReadStrEx2(root, keyname, valuename, force32bit, false);
+}
+char *MsRegReadStrEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
+{
+ char *ret;
+ UINT type, size;
+ // Validate arguments
+ if (keyname == NULL || valuename == NULL)
+ {
+ return NULL;
+ }
+
+ // Read the value
+ if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false)
+ {
+ return NULL;
+ }
+
+ // Check the type
+ if (type != REG_SZ && type != REG_EXPAND_SZ && type != REG_MULTI_SZ)
+ {
+ // It is not a string
+ Free(ret);
+
+ if (type == REG_MULTI_SZ)
+ {
+ // It is a string list
+ LIST *o = MsRegReadStrList(root, keyname, valuename);
+ if (o != NULL)
+ {
+ if (LIST_NUM(o) >= 1)
+ {
+ ret = CopyStr(LIST_DATA(o, 0));
+ FreeStrList(o);
+ return ret;
+ }
+ }
+ }
+ return NULL;
+ }
+
+ if (size == 0)
+ {
+ // Invalid size
+ Free(ret);
+
+ return CopyStr("");
+ }
+
+ if (ret[size - 1] != 0)
+ {
+ // Invalid data
+ Free(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+wchar_t *MsRegReadStrW(UINT root, char *keyname, char *valuename)
+{
+ return MsRegReadStrExW(root, keyname, valuename, false);
+}
+wchar_t *MsRegReadStrExW(UINT root, char *keyname, char *valuename, bool force32bit)
+{
+ return MsRegReadStrEx2W(root, keyname, valuename, force32bit, false);
+}
+wchar_t *MsRegReadStrEx2W(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
+{
+ wchar_t *ret;
+ UINT type, size;
+ // Validate arguments
+ if (keyname == NULL || valuename == NULL)
+ {
+ return NULL;
+ }
+
+ // Read the value
+ if (MsRegReadValueEx2W(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false)
+ {
+ return NULL;
+ }
+
+ // Check the type
+ if (type != REG_SZ && type != REG_EXPAND_SZ)
+ {
+ // It is not a string
+ Free(ret);
+
+ return NULL;
+ }
+
+ if (ret[size / sizeof(wchar_t) - 1] != 0)
+ {
+ // Invalid data
+ Free(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+// Read the value
+bool MsRegReadValue(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size)
+{
+ return MsRegReadValueEx(root, keyname, valuename, data, type, size, false);
+}
+bool MsRegReadValueEx(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit)
+{
+ return MsRegReadValueEx2(root, keyname, valuename, data, type, size, force32bit, false);
+}
+bool MsRegReadValueEx2(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ UINT ret;
+ // Validate arguments
+ if (keyname == NULL || data == NULL || type == NULL || size == NULL)
+ {
+ return false;
+ }
+ *type = 0;
+ *size = 0;
+
+ // Open the key
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ // Open up the value
+ *data = ZeroMalloc(*size);
+ ret = RegQueryValueEx(h, valuename, 0, type, *data, size);
+
+ if (ret == ERROR_SUCCESS)
+ {
+ // Reading is complete
+ RegCloseKey(h);
+ return true;
+ }
+
+ if (ret != ERROR_MORE_DATA)
+ {
+ // Strange error occurs
+ Free(*data);
+ *data = NULL;
+ RegCloseKey(h);
+ return false;
+ }
+
+ // Get the data by re-allocating memory
+ *data = ReAlloc(*data, *size);
+ ret = RegQueryValueEx(h, valuename, 0, type, *data, size);
+ if (ret != ERROR_SUCCESS)
+ {
+ // An error has occured
+ Free(*data);
+ *data = NULL;
+ RegCloseKey(h);
+ }
+
+ RegCloseKey(h);
+
+ return true;
+}
+bool MsRegReadValueW(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size)
+{
+ return MsRegReadValueExW(root, keyname, valuename, data, type, size, false);
+}
+bool MsRegReadValueExW(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit)
+{
+ return MsRegReadValueEx2W(root, keyname, valuename, data, type, size, force32bit, false);
+}
+bool MsRegReadValueEx2W(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ UINT ret;
+ wchar_t *valuename_w;
+ // Validate arguments
+ if (keyname == NULL || data == NULL || type == NULL || size == NULL)
+ {
+ return false;
+ }
+ *type = 0;
+ *size = 0;
+
+ if (IsNt() == false)
+ {
+ bool ret;
+ void *data_a = NULL;
+ UINT type_a = 0, size_a = 0;
+
+ ret = MsRegReadValueEx2(root, keyname, valuename, &data_a, &type_a, &size_a, force32bit, force64bit);
+
+ if (ret != false)
+ {
+ if (type_a == REG_SZ || type_a == REG_MULTI_SZ || type_a == REG_EXPAND_SZ)
+ {
+ *data = CopyStrToUni(data_a);
+ Free(data_a);
+
+ size_a = UniStrSize(*data);
+ }
+ else
+ {
+ *data = data_a;
+ }
+
+ *type = type_a;
+ *size = size_a;
+ }
+
+ return ret;
+ }
+
+ // Open the key
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ valuename_w = CopyStrToUni(valuename);
+
+ // Open up the value
+ *data = ZeroMalloc(*size);
+ ret = RegQueryValueExW(h, valuename_w, 0, type, *data, size);
+
+ if (ret == ERROR_SUCCESS)
+ {
+ // Reading is complete
+ RegCloseKey(h);
+ Free(valuename_w);
+ return true;
+ }
+
+ if (ret != ERROR_MORE_DATA)
+ {
+ // Strange error occurs
+ Free(*data);
+ *data = NULL;
+ Free(valuename_w);
+ RegCloseKey(h);
+ return false;
+ }
+
+ // Get the data by re-allocating memory
+ *data = ReAlloc(*data, *size);
+ ret = RegQueryValueExW(h, valuename_w, 0, type, *data, size);
+ if (ret != ERROR_SUCCESS)
+ {
+ // An error has occured
+ Free(*data);
+ *data = NULL;
+ Free(valuename_w);
+ RegCloseKey(h);
+ }
+
+ Free(valuename_w);
+
+ RegCloseKey(h);
+
+ return true;
+}
+
+// Get the size and type of value
+bool MsRegGetValueTypeAndSize(UINT root, char *keyname, char *valuename, UINT *type, UINT *size)
+{
+ return MsRegGetValueTypeAndSizeEx(root, keyname, valuename, type, size, false);
+}
+bool MsRegGetValueTypeAndSizeEx(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit)
+{
+ return MsRegGetValueTypeAndSizeEx2(root, keyname, valuename, type, size, force32bit, false);
+}
+bool MsRegGetValueTypeAndSizeEx2(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ UINT ret;
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return false;
+ }
+ if (type != NULL)
+ {
+ *type = 0;
+ }
+ if (size != NULL)
+ {
+ *size = 0;
+ }
+
+ // Open the key
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ // Open up the value
+ ret = RegQueryValueEx(h, valuename, 0, type, NULL, size);
+
+ if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA)
+ {
+ RegCloseKey(h);
+ return true;
+ }
+
+ RegCloseKey(h);
+
+ return false;
+}
+bool MsRegGetValueTypeAndSizeW(UINT root, char *keyname, char *valuename, UINT *type, UINT *size)
+{
+ return MsRegGetValueTypeAndSizeExW(root, keyname, valuename, type, size, false);
+}
+bool MsRegGetValueTypeAndSizeExW(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit)
+{
+ return MsRegGetValueTypeAndSizeEx2W(root, keyname, valuename, type, size, force32bit, false);
+}
+bool MsRegGetValueTypeAndSizeEx2W(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ UINT ret;
+ wchar_t *valuename_w;
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return false;
+ }
+ if (type != NULL)
+ {
+ *type = 0;
+ }
+ if (size != NULL)
+ {
+ *size = 0;
+ }
+ if (IsNt() == false)
+ {
+ UINT type_a = 0;
+ UINT size_a = 0;
+
+ bool ret = MsRegGetValueTypeAndSizeEx2(root, keyname, valuename, &type_a, &size_a, force32bit, force64bit);
+
+ if (type_a == REG_SZ || type_a == REG_MULTI_SZ || type_a == REG_EXPAND_SZ)
+ {
+ size_a = size_a * sizeof(wchar_t);
+ }
+
+ if (type != NULL)
+ {
+ *type = type_a;
+ }
+
+ if (size != NULL)
+ {
+ *size = size_a;
+ }
+
+ return ret;
+ }
+
+ // Open the key
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ valuename_w = CopyStrToUni(valuename);
+
+ // Open up the value
+ ret = RegQueryValueExW(h, valuename_w, 0, type, NULL, size);
+
+ Free(valuename_w);
+
+ if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA)
+ {
+ RegCloseKey(h);
+ return true;
+ }
+
+ RegCloseKey(h);
+
+ return false;
+}
+
+// Confirm that the specified value exists on the registry
+bool MsRegIsValue(UINT root, char *keyname, char *valuename)
+{
+ return MsRegIsValueEx(root, keyname, valuename, false);
+}
+bool MsRegIsValueEx(UINT root, char *keyname, char *valuename, bool force32bit)
+{
+ return MsRegIsValueEx2(root, keyname, valuename, force32bit, false);
+}
+bool MsRegIsValueEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ UINT type, size;
+ UINT ret;
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return false;
+ }
+
+ // Open the key
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ // Open up the value
+ size = 0;
+ ret = RegQueryValueEx(h, valuename, 0, &type, NULL, &size);
+
+ if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA)
+ {
+ RegCloseKey(h);
+ return true;
+ }
+
+ RegCloseKey(h);
+
+ return false;
+}
+
+// Create a key in the registry
+bool MsRegNewKey(UINT root, char *keyname)
+{
+ return MsRegNewKeyEx(root, keyname, false);
+}
+bool MsRegNewKeyEx(UINT root, char *keyname, bool force32bit)
+{
+ return MsRegNewKeyEx2(root, keyname, force32bit, false);
+}
+bool MsRegNewKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ // Validate arguments
+ if (keyname == NULL)
+ {
+ return false;
+ }
+
+ // Confirm whether there is the key
+ if (MsRegIsKeyEx2(root, keyname, force32bit, force64bit))
+ {
+ // Already exists
+ return true;
+ }
+
+ // Create a key
+ if (RegCreateKeyEx(MsGetRootKeyFromInt(root), keyname, 0, NULL, REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), NULL, &h, NULL) != ERROR_SUCCESS)
+ {
+ // Failed
+ return false;
+ }
+
+ RegCloseKey(h);
+
+ return true;
+}
+
+// Confirm the specified key exists on the registry
+bool MsRegIsKey(UINT root, char *name)
+{
+ return MsRegIsKeyEx(root, name, false);
+}
+bool MsRegIsKeyEx(UINT root, char *name, bool force32bit)
+{
+ return MsRegIsKeyEx2(root, name, force32bit, false);
+}
+bool MsRegIsKeyEx2(UINT root, char *name, bool force32bit, bool force64bit)
+{
+ HKEY h;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (RegOpenKeyEx(MsGetRootKeyFromInt(root), name, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ RegCloseKey(h);
+
+ return true;
+}
+
+// Getting root key handle
+HKEY MsGetRootKeyFromInt(UINT root)
+{
+ switch (root)
+ {
+ case REG_CLASSES_ROOT:
+ return HKEY_CLASSES_ROOT;
+
+ case REG_LOCAL_MACHINE:
+ return HKEY_LOCAL_MACHINE;
+
+ case REG_CURRENT_USER:
+ return HKEY_CURRENT_USER;
+
+ case REG_USERS:
+ return HKEY_USERS;
+ }
+
+ return NULL;
+}
+
+// Cut the executable file name from the command line string (Unicode version)
+wchar_t *MsCutExeNameFromUniCommandLine(wchar_t *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ if (str[0] != L'\"')
+ {
+ UINT i = UniSearchStrEx(str, L" ", 0, true);
+ if (i == INFINITE)
+ {
+ return str + UniStrLen(str);
+ }
+ else
+ {
+ return str + i + 1;
+ }
+ }
+ else
+ {
+ str++;
+ while (true)
+ {
+ if ((*str) == 0)
+ {
+ return str + UniStrLen(str);
+ }
+ if ((*str) == L'\"')
+ {
+ break;
+ }
+ str++;
+ }
+
+ while (true)
+ {
+ if ((*str) == 0)
+ {
+ return str + UniStrLen(str);
+ }
+ if ((*str) == L' ')
+ {
+ return str + 1;
+ }
+ str++;
+ }
+ }
+}
+
+// Cut the executable file name from the command line string
+char *MsCutExeNameFromCommandLine(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ if (str[0] != '\"')
+ {
+ UINT i = SearchStrEx(str, " ", 0, true);
+ if (i == INFINITE)
+ {
+ return str + StrLen(str);
+ }
+ else
+ {
+ return str + i + 1;
+ }
+ }
+ else
+ {
+ str++;
+ while (true)
+ {
+ if ((*str) == 0)
+ {
+ return str + StrLen(str);
+ }
+ if ((*str) == '\"')
+ {
+ break;
+ }
+ str++;
+ }
+
+ while (true)
+ {
+ if ((*str) == 0)
+ {
+ return str + StrLen(str);
+ }
+ if ((*str) == ' ')
+ {
+ return str + 1;
+ }
+ str++;
+ }
+ }
+}
+
+// Get the Process handle
+void *MsGetCurrentProcess()
+{
+ return ms->hCurrentProcess;
+}
+
+// Get the Process ID
+UINT MsGetCurrentProcessId()
+{
+ return ms->CurrentProcessId;
+}
+
+// Get the EXE file name
+char *MsGetExeFileName()
+{
+ return ms == NULL ? "Unknown" : ms->ExeFileName;
+}
+
+// Get the name of the directory where the EXE file is in
+char *MsGetExeDirName()
+{
+ return ms->ExeFileDir;
+}
+wchar_t *MsGetExeDirNameW()
+{
+ return ms->ExeFileDirW;
+}
+
+// Get the special directory name
+char *MsGetSpecialDir(int id)
+{
+ LPITEMIDLIST t = NULL;
+ char tmp[MAX_PATH];
+
+ if (SHGetSpecialFolderLocation(NULL, id, &t) != S_OK)
+ {
+ return CopyStr(ms->ExeFileDir);
+ }
+
+ if (SHGetPathFromIDList(t, tmp) == false)
+ {
+ return CopyStr(ms->ExeFileDir);
+ }
+
+ Win32NukuEn(tmp, sizeof(tmp), tmp);
+
+ return CopyStr(tmp);
+}
+wchar_t *MsGetSpecialDirW(int id)
+{
+ LPITEMIDLIST t = NULL;
+ wchar_t tmp[MAX_PATH];
+
+ if (IsNt() == false)
+ {
+ char *tmp = MsGetSpecialDir(id);
+ wchar_t *ret = CopyStrToUni(tmp);
+
+ Free(tmp);
+
+ return ret;
+ }
+
+ if (SHGetSpecialFolderLocation(NULL, id, &t) != S_OK)
+ {
+ return UniCopyStr(ms->ExeFileDirW);
+ }
+
+ if (SHGetPathFromIDListW(t, tmp) == false)
+ {
+ return UniCopyStr(ms->ExeFileDirW);
+ }
+
+ Win32NukuEnW(tmp, sizeof(tmp), tmp);
+
+ return UniCopyStr(tmp);
+}
+
+// Get all the special directory
+void MsGetSpecialDirs()
+{
+ char tmp[MAX_PATH];
+
+ // System32
+ GetSystemDirectory(tmp, sizeof(tmp));
+ Win32NukuEn(tmp, sizeof(tmp), tmp);
+ ms->System32Dir = CopyStr(tmp);
+ ms->System32DirW = CopyStrToUni(tmp);
+
+ // The Windows directory is parent of the System32 directory
+ Win32GetDirFromPath(tmp, sizeof(tmp), tmp);
+ Win32NukuEn(tmp, sizeof(tmp), tmp);
+ ms->WindowsDir = CopyStr(tmp);
+ ms->WindowsDirW = CopyStrToUni(tmp);
+
+ // Temp directory under the Windows directory
+ Format(tmp, sizeof(tmp), "%s\\Temp", ms->WindowsDir);
+ ms->WinTempDir = CopyStr(tmp);
+ ms->WinTempDirW = CopyStrToUni(tmp);
+ MsUniMakeDirEx(ms->WinTempDirW);
+
+ // System drive
+ tmp[2] = 0;
+ ms->WindowsDrive = CopyStr(tmp);
+ ms->WindowsDriveW = CopyStrToUni(tmp);
+
+ // Temp
+ GetTempPath(MAX_PATH, tmp);
+ Win32NukuEn(tmp, sizeof(tmp), tmp);
+ ms->TempDir = CopyStr(tmp);
+
+ // Get the Temp (Unicode)
+ if (IsNt())
+ {
+ wchar_t tmp_w[MAX_PATH];
+
+ GetTempPathW(MAX_PATH, tmp_w);
+ Win32NukuEnW(tmp_w, sizeof(tmp_w), tmp_w);
+
+ ms->TempDirW = CopyUniStr(tmp_w);
+ }
+ else
+ {
+ ms->TempDirW = CopyStrToUni(tmp);
+ }
+ MakeDirExW(ms->TempDirW);
+ MakeDirEx(ms->TempDir);
+
+ // Program Files
+ ms->ProgramFilesDir = MsGetSpecialDir(CSIDL_PROGRAM_FILES);
+ if (StrCmpi(ms->ProgramFilesDir, ms->ExeFileDir) == 0)
+ {
+ char tmp[MAX_PATH];
+ Format(tmp, sizeof(tmp), "%s\\Program Files", ms->WindowsDrive);
+
+ Free(ms->ProgramFilesDir);
+ ms->ProgramFilesDir = CopyStr(tmp);
+ }
+
+ ms->ProgramFilesDirW = MsGetSpecialDirW(CSIDL_PROGRAM_FILES);
+ if (UniStrCmpi(ms->ProgramFilesDirW, ms->ExeFileDirW) == 0)
+ {
+ wchar_t tmp[MAX_PATH];
+ UniFormat(tmp, sizeof(tmp), L"%s\\Program Files", ms->WindowsDriveW);
+
+ Free(ms->ProgramFilesDirW);
+ ms->ProgramFilesDirW = UniCopyStr(tmp);
+ }
+
+ // Program Files (x86)
+ ms->ProgramFilesDirX86 = MsGetSpecialDir(CSIDL_PROGRAM_FILESX86);
+ if (StrCmpi(ms->ProgramFilesDirX86, ms->ExeFileDir) == 0)
+ {
+ if (MsIs64BitWindows())
+ {
+ char tmp[MAX_PATH];
+ Format(tmp, sizeof(tmp), "%s\\Program Files (x86)", ms->WindowsDrive);
+
+ Free(ms->ProgramFilesDirX86);
+ ms->ProgramFilesDirX86 = CopyStr(tmp);
+ }
+ else
+ {
+ Free(ms->ProgramFilesDirX86);
+ ms->ProgramFilesDirX86 = CopyStr(ms->ProgramFilesDir);
+ }
+ }
+
+ ms->ProgramFilesDirX86W = MsGetSpecialDirW(CSIDL_PROGRAM_FILESX86);
+ if (UniStrCmpi(ms->ProgramFilesDirX86W, ms->ExeFileDirW) == 0)
+ {
+ if (MsIs64BitWindows())
+ {
+ wchar_t tmp[MAX_PATH];
+ UniFormat(tmp, sizeof(tmp), L"%s\\Program Files (x86)", ms->WindowsDriveW);
+
+ Free(ms->ProgramFilesDirX86W);
+ ms->ProgramFilesDirX86W = UniCopyStr(tmp);
+ }
+ else
+ {
+ Free(ms->ProgramFilesDirX86W);
+ ms->ProgramFilesDirX86W = UniCopyStr(ms->ProgramFilesDirW);
+ }
+ }
+
+ // Program Files (x64)
+ if (MsIs64BitWindows())
+ {
+ if (Is64())
+ {
+ ms->ProgramFilesDirX64 = CopyStr(ms->ProgramFilesDir);
+ ms->ProgramFilesDirX64W = CopyUniStr(ms->ProgramFilesDirW);
+ }
+ else
+ {
+ char tmpa[MAX_SIZE];
+ wchar_t tmpw[MAX_SIZE];
+
+ ReplaceStrEx(tmpa, sizeof(tmpa), ms->ProgramFilesDir, "\\Program Files (x86)", "\\Program Files", false);
+ UniReplaceStrEx(tmpw, sizeof(tmpw), ms->ProgramFilesDirW, L"\\Program Files (x86)", L"\\Program Files", false);
+
+ ms->ProgramFilesDirX64 = CopyStr(tmpa);
+ ms->ProgramFilesDirX64W = CopyUniStr(tmpw);
+ }
+ }
+ else
+ {
+ ms->ProgramFilesDirX64 = CopyStr(ms->ProgramFilesDir);
+ ms->ProgramFilesDirX64W = CopyUniStr(ms->ProgramFilesDirW);
+ }
+
+ if (MsIsNt())
+ {
+ // Common start menu
+ ms->CommonStartMenuDir = MsGetSpecialDir(CSIDL_COMMON_STARTMENU);
+ ms->CommonStartMenuDirW = MsGetSpecialDirW(CSIDL_COMMON_STARTMENU);
+
+ // Common program
+ ms->CommonProgramsDir = MsGetSpecialDir(CSIDL_COMMON_PROGRAMS);
+ ms->CommonProgramsDirW = MsGetSpecialDirW(CSIDL_COMMON_PROGRAMS);
+
+ // Common startup
+ ms->CommonStartupDir = MsGetSpecialDir(CSIDL_COMMON_STARTUP);
+ ms->CommonStartupDirW = MsGetSpecialDirW(CSIDL_COMMON_STARTUP);
+
+ // Common application data
+ ms->CommonAppDataDir = MsGetSpecialDir(CSIDL_COMMON_APPDATA);
+ ms->CommonAppDataDirW = MsGetSpecialDirW(CSIDL_COMMON_APPDATA);
+
+ // Common desktop
+ ms->CommonDesktopDir = MsGetSpecialDir(CSIDL_COMMON_DESKTOPDIRECTORY);
+ ms->CommonDesktopDirW = MsGetSpecialDirW(CSIDL_COMMON_DESKTOPDIRECTORY);
+
+ // Local Settings
+ ms->LocalAppDataDir = MsGetSpecialDir(CSIDL_LOCAL_APPDATA);
+ ms->LocalAppDataDirW = MsGetSpecialDirW(CSIDL_LOCAL_APPDATA);
+ }
+ else
+ {
+ // Start menu of the individual
+ ms->PersonalStartMenuDir = MsGetSpecialDir(CSIDL_STARTMENU);
+ ms->CommonStartMenuDir = CopyStr(ms->PersonalStartMenuDir);
+ ms->PersonalStartMenuDirW = MsGetSpecialDirW(CSIDL_STARTMENU);
+ ms->CommonStartMenuDirW = CopyUniStr(ms->PersonalStartMenuDirW);
+
+ // Program of the individual
+ ms->PersonalProgramsDir = MsGetSpecialDir(CSIDL_PROGRAMS);
+ ms->CommonProgramsDir = CopyStr(ms->PersonalProgramsDir);
+ ms->PersonalProgramsDirW = MsGetSpecialDirW(CSIDL_PROGRAMS);
+ ms->CommonProgramsDirW = CopyUniStr(ms->PersonalProgramsDirW);
+
+ // Start-up of the individual
+ ms->PersonalStartupDir = MsGetSpecialDir(CSIDL_STARTUP);
+ ms->CommonStartupDir = CopyStr(ms->PersonalStartupDir);
+ ms->PersonalStartupDirW = MsGetSpecialDirW(CSIDL_STARTUP);
+ ms->CommonStartupDirW = CopyUniStr(ms->PersonalStartupDirW);
+
+ // Application data of the individual
+ ms->PersonalAppDataDir = MsGetSpecialDir(CSIDL_APPDATA);
+ ms->CommonAppDataDir = CopyStr(ms->PersonalAppDataDir);
+ ms->PersonalAppDataDirW = MsGetSpecialDirW(CSIDL_APPDATA);
+ ms->CommonAppDataDirW = CopyUniStr(ms->PersonalAppDataDirW);
+
+ // Desktops of the individual
+ ms->PersonalDesktopDir = MsGetSpecialDir(CSIDL_DESKTOP);
+ ms->CommonDesktopDir = CopyStr(ms->PersonalDesktopDir);
+ ms->PersonalDesktopDirW = MsGetSpecialDirW(CSIDL_DESKTOP);
+ ms->CommonDesktopDirW = CopyUniStr(ms->PersonalDesktopDirW);
+
+ // Local Settings
+ ms->LocalAppDataDir = CopyStr(ms->PersonalAppDataDir);
+ ms->LocalAppDataDirW = CopyUniStr(ms->PersonalAppDataDirW);
+ }
+}
+
+// Check whether the current user is a Administrators
+bool MsCheckIsAdmin()
+{
+ UCHAR test_bit[32];
+ UCHAR tmp[32];
+ UCHAR exe_hash[SHA1_SIZE];
+ char *name_tag = "Vpn_Check_Admin_Key_%u";
+ DWORD type;
+ DWORD size;
+ char name[MAX_SIZE];
+
+ HashSha1(exe_hash, MsGetExeFileNameW(), UniStrLen(MsGetExeFileNameW()));
+
+ Format(name, sizeof(name), name_tag, *((UINT *)exe_hash));
+
+ Rand(test_bit, sizeof(test_bit));
+
+ if (RegSetValueEx(HKEY_LOCAL_MACHINE, name, 0, REG_BINARY, test_bit, sizeof(test_bit)) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ size = sizeof(tmp);
+ if (RegQueryValueEx(HKEY_LOCAL_MACHINE, name, 0, &type, tmp, &size) != ERROR_SUCCESS)
+ {
+ RegDeleteValue(HKEY_LOCAL_MACHINE, name);
+ return false;
+ }
+
+ RegDeleteValue(HKEY_LOCAL_MACHINE, name);
+
+ if (Cmp(test_bit, tmp, 32) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Library initialization
+void MsInit()
+{
+ char *str_ansi;
+ wchar_t *str_unicode;
+ OSVERSIONINFO os;
+ char tmp[MAX_SIZE];
+ UINT size;
+ if (ms != NULL)
+ {
+ // Already initialized
+ return;
+ }
+
+ ms = ZeroMalloc(sizeof(MS));
+
+ // Getting instance handle
+ ms->hInst = GetModuleHandle(NULL);
+
+ // Get the KERNEL32.DLL
+ ms->hKernel32 = LoadLibrary("kernel32.dll");
+
+ // Get a command line string from the OS
+ str_ansi = CopyStr(GetCommandLineA());
+ Trim(str_ansi);
+ str_unicode = UniCopyStr(GetCommandLineW());
+ UniTrim(str_unicode);
+
+ SetCommandLineStr(MsCutExeNameFromCommandLine(str_ansi));
+ SetCommandLineUniStr(MsCutExeNameFromUniCommandLine(str_unicode));
+
+ Free(str_unicode);
+ Free(str_ansi);
+
+ // Get the version of the OS
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+ GetVersionEx(&os);
+
+ if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ // NT series
+ ms->IsNt = true;
+
+ ms->nt = MsLoadNtApiFunctions();
+
+ if (ms->nt == NULL)
+ {
+ ms->IsNt = false;
+ ms->IsAdmin = true;
+ }
+ else
+ {
+ // Whether I am an Administrators
+ ms->IsAdmin = MsCheckIsAdmin();
+ }
+ }
+ else
+ {
+ // In 9x system: Impersonate a Administrators always
+ ms->IsAdmin = true;
+ }
+
+ // Get information about the current process
+ ms->hCurrentProcess = GetCurrentProcess();
+ ms->CurrentProcessId = GetCurrentProcessId();
+
+ // Get the EXE file name
+ GetModuleFileName(NULL, tmp, sizeof(tmp));
+ ms->ExeFileName = CopyStr(tmp);
+ Win32GetDirFromPath(tmp, sizeof(tmp), tmp);
+ ms->ExeFileDir = CopyStr(tmp);
+
+ // Get the EXE file name (Unicode)
+ if (IsNt())
+ {
+ wchar_t tmp_w[MAX_PATH];
+
+ GetModuleFileNameW(NULL, tmp_w, sizeof(tmp_w));
+ ms->ExeFileNameW = CopyUniStr(tmp_w);
+
+ Win32GetDirFromPathW(tmp_w, sizeof(tmp_w), tmp_w);
+ ms->ExeFileDirW = CopyUniStr(tmp_w);
+ }
+ else
+ {
+ ms->ExeFileNameW = CopyStrToUni(ms->ExeFileName);
+ ms->ExeFileDirW = CopyStrToUni(ms->ExeFileDir);
+ }
+
+ // Get the special directories
+ MsGetSpecialDirs();
+
+ // Initialize the temporary directory
+ MsInitTempDir();
+
+ // Get the user name
+ size = sizeof(tmp);
+ GetUserName(tmp, &size);
+ ms->UserName = CopyStr(tmp);
+
+ // Get the user name (Unicode)
+ if (IsNt())
+ {
+ wchar_t tmp_w[MAX_PATH];
+
+ size = sizeof(tmp_w);
+
+ GetUserNameW(tmp_w, &size);
+ ms->UserNameW = CopyUniStr(tmp_w);
+ }
+ else
+ {
+ ms->UserNameW = CopyStrToUni(ms->UserName);
+ }
+
+ // Get the full user name
+ if (ms->nt != NULL && ms->nt->GetUserNameExA != NULL)
+ {
+ wchar_t tmp_w[MAX_PATH];
+
+ size = sizeof(tmp);
+ if (ms->nt->GetUserNameExA(NameSamCompatible, tmp, &size))
+ {
+ ms->UserNameEx = CopyStr(tmp);
+ }
+
+ size = sizeof(tmp_w);
+ if (ms->nt->GetUserNameExW(NameSamCompatible, tmp_w, &size))
+ {
+ ms->UserNameExW = CopyUniStr(tmp_w);
+ }
+ }
+
+ if (ms->UserNameEx == NULL)
+ {
+ ms->UserNameEx = CopyStr(ms->UserName);
+ }
+ if (ms->UserNameExW == NULL)
+ {
+ ms->UserNameExW = CopyUniStr(ms->UserNameW);
+ }
+
+ // Initialization of the adapter list
+ MsInitAdapterListModule();
+
+ // Initialization of minidump base file name
+ if (true)
+ {
+ wchar_t tmp[MAX_PATH];
+ if (MsIsAdmin())
+ {
+ CombinePathW(tmp, sizeof(tmp), ms->ExeFileDirW, L"vpn_debug\\dump");
+ }
+ else
+ {
+ CombinePathW(tmp, sizeof(tmp), ms->TempDirW, L"vpn_debug\\dump");
+ }
+ ms->MinidumpBaseFileNameW = CopyUniStr(tmp);
+ }
+
+ MsSetEnableMinidump(true);
+
+ if (MsIsNt())
+ {
+ if (ms->nt->MiniDumpWriteDump != NULL)
+ {
+ SetUnhandledExceptionFilter(MsExceptionHandler);
+ }
+ }
+
+ // Open a LSA handle
+ hLsa = NULL;
+ lsa_package_id = 0;
+ if (MsIsNt())
+ {
+ MsEnablePrivilege(SE_TCB_NAME, true);
+
+ if (ms->nt->AllocateLocallyUniqueId != NULL &&
+ ms->nt->LsaConnectUntrusted != NULL &&
+ ms->nt->LsaLookupAuthenticationPackage != NULL &&
+ ms->nt->LsaLogonUser != NULL &&
+ ms->nt->LsaDeregisterLogonProcess != NULL &&
+ ms->nt->LsaFreeReturnBuffer != NULL)
+ {
+ HANDLE h = NULL;
+ NTSTATUS ret = ms->nt->LsaConnectUntrusted(&h);
+
+ if (ret == 0)
+ {
+ LSA_STRING pkg_name;
+ ULONG ul = 0;
+
+ Zero(&pkg_name, sizeof(pkg_name));
+ pkg_name.Buffer = MSV1_0_PACKAGE_NAME;
+ pkg_name.Length = pkg_name.MaximumLength = StrLen(MSV1_0_PACKAGE_NAME);
+
+ ret = ms->nt->LsaLookupAuthenticationPackage(h, &pkg_name, &ul);
+
+ if (ret == 0)
+ {
+ Zero(&lsa_token_source, sizeof(lsa_token_source));
+
+ ms->nt->AllocateLocallyUniqueId(&lsa_token_source.SourceIdentifier);
+ Copy(lsa_token_source.SourceName, "SE-VPN ", 8);
+
+ lsa_package_id = ul;
+ hLsa = h;
+ }
+ else
+ {
+ ms->nt->LsaDeregisterLogonProcess(h);
+ }
+ }
+ }
+ }
+
+ // Read the msi.dll
+ if (hMsi == NULL)
+ {
+ hMsi = LoadLibrary("msi.dll");
+
+ if (hMsi != NULL)
+ {
+ _MsiConfigureProductW =
+ (UINT (__stdcall *)(LPCWSTR,int,INSTALLSTATE)) GetProcAddress(hMsi, "MsiConfigureProductW");
+ _MsiGetProductInfoW =
+ (UINT (__stdcall *)(LPCWSTR,LPCWSTR,LPWSTR,LPDWORD)) GetProcAddress(hMsi, "MsiGetProductInfoW");
+ _MsiSetInternalUI =
+ (INSTALLUILEVEL (__stdcall *)(INSTALLUILEVEL,HWND *)) GetProcAddress(hMsi, "MsiSetInternalUI");
+ _MsiLocateComponentW =
+ (INSTALLSTATE (__stdcall *)(LPCWSTR,LPWSTR,LPDWORD)) GetProcAddress(hMsi, "MsiLocateComponentW");
+ }
+ }
+
+ // Lock created
+ vlan_lock = NewLock();
+}
+
+// Uninstall the MSI product
+bool MsMsiUninstall(char *product_code, HWND hWnd, bool *reboot_required)
+{
+ wchar_t *product_code_w;
+ bool ret = false;
+ INSTALLUILEVEL old_level;
+ HWND old_hwnd;
+ UINT r;
+ // Validate arguments
+ if (product_code == NULL)
+ {
+ return false;
+ }
+ if (_MsiSetInternalUI == NULL || _MsiConfigureProductW == NULL)
+ {
+ return false;
+ }
+
+ if (reboot_required != NULL)
+ {
+ *reboot_required = false;
+ }
+
+ product_code_w = CopyStrToUni(product_code);
+
+ old_hwnd = hWnd;
+ old_level = _MsiSetInternalUI(INSTALLUILEVEL_PROGRESSONLY, &old_hwnd);
+
+ r = _MsiConfigureProductW(product_code_w, INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT);
+
+ if (r == ERROR_SUCCESS || r == ERROR_SUCCESS_REBOOT_INITIATED || r == ERROR_SUCCESS_REBOOT_REQUIRED)
+ {
+ ret = true;
+
+ if (r == ERROR_SUCCESS_REBOOT_INITIATED || r == ERROR_SUCCESS_REBOOT_REQUIRED)
+ {
+ if (reboot_required != NULL)
+ {
+ *reboot_required = true;
+ }
+ }
+ }
+
+ if (old_level != INSTALLUILEVEL_NOCHANGE)
+ {
+ _MsiSetInternalUI(old_level, &old_hwnd);
+ }
+
+ Free(product_code_w);
+
+ return ret;
+}
+
+// Get the installation directory of the MSI component
+bool MsGetMsiInstalledDir(char *component_code, wchar_t *dir, UINT dir_size)
+{
+ wchar_t *component_code_w;
+ bool ret = false;
+ wchar_t tmp[MAX_SIZE];
+ UINT sz = sizeof(tmp) / sizeof(wchar_t);
+ // Validate arguments
+ if (component_code == NULL || dir == NULL)
+ {
+ return false;
+ }
+ if (_MsiGetProductInfoW == NULL)
+ {
+ return false;
+ }
+
+ component_code_w = CopyStrToUni(component_code);
+
+ Zero(tmp, sizeof(tmp));
+
+ if (_MsiLocateComponentW(component_code_w, tmp, &sz) == INSTALLSTATE_LOCAL)
+ {
+ if (UniIsEmptyStr(tmp) == false)
+ {
+ GetDirNameFromFilePathW(dir, dir_size, tmp);
+ ret = true;
+ }
+ }
+
+ Free(component_code_w);
+
+ return ret;
+}
+
+// Determine whether to create a minidump
+void MsSetEnableMinidump(bool enabled)
+{
+ ms->MiniDumpEnabled = enabled;
+}
+
+// Output the minidump
+void MsWriteMinidump(wchar_t *filename, void *ex)
+{
+ wchar_t tmp[MAX_PATH];
+ wchar_t dir[MAX_PATH];
+ HANDLE h;
+ MINIDUMP_EXCEPTION_INFORMATION info;
+ struct _EXCEPTION_POINTERS *exp = (struct _EXCEPTION_POINTERS *)ex;
+
+ if (filename != NULL)
+ {
+ UniStrCpy(tmp, sizeof(tmp), filename);
+ }
+ else
+ {
+ SYSTEMTIME tm;
+
+ Zero(&tm, sizeof(tm));
+ GetLocalTime(&tm);
+
+ UniFormat(tmp, sizeof(tmp), L"%s_%04u%02u%02u_%02u%02u%02u.dmp",
+ ms->MinidumpBaseFileNameW,
+ tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond);
+ }
+
+ GetDirNameFromFilePathW(dir, sizeof(dir), tmp);
+
+ CreateDirectoryW(dir, NULL);
+
+ Zero(&info, sizeof(info));
+
+ if (exp != NULL)
+ {
+ info.ThreadId = GetCurrentThreadId();
+ info.ExceptionPointers = exp;
+ info.ClientPointers = true;
+ }
+
+ h = CreateFileW(tmp, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ ms->nt->MiniDumpWriteDump(ms->hCurrentProcess, ms->CurrentProcessId,
+ h,
+ MiniDumpNormal | MiniDumpWithFullMemory | MiniDumpWithDataSegs |
+ MiniDumpWithHandleData
+ ,
+ info.ThreadId == 0 ? NULL : &info, NULL, NULL);
+
+ FlushFileBuffers(h);
+ CloseHandle(h);
+ }
+}
+
+// Exception handler
+LONG CALLBACK MsExceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo)
+{
+ if (ms->MiniDumpEnabled)
+ {
+ MsWriteMinidump(NULL, ExceptionInfo);
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+// Release of the library
+void MsFree()
+{
+ if (ms == NULL)
+ {
+ // Uninitialized
+ return;
+ }
+
+ // Release the LSA
+ if (hLsa != NULL)
+ {
+ ms->nt->LsaDeregisterLogonProcess(hLsa);
+
+ hLsa = NULL;
+ }
+
+ // Release of the adapter list
+ MsFreeAdapterListModule();
+
+ // Release of the temporary directory
+ MsFreeTempDir();
+
+ if (ms->IsNt)
+ {
+ // Release of NT series API
+ MsFreeNtApiFunctions(ms->nt);
+ }
+
+ // Memory release
+ // ANSI
+ Free(ms->WindowsDir);
+ Free(ms->System32Dir);
+ Free(ms->TempDir);
+ Free(ms->WinTempDir);
+ Free(ms->WindowsDrive);
+ Free(ms->ProgramFilesDir);
+ Free(ms->CommonStartMenuDir);
+ Free(ms->CommonProgramsDir);
+ Free(ms->CommonStartupDir);
+ Free(ms->CommonAppDataDir);
+ Free(ms->CommonDesktopDir);
+ Free(ms->PersonalStartMenuDir);
+ Free(ms->PersonalProgramsDir);
+ Free(ms->PersonalStartupDir);
+ Free(ms->PersonalAppDataDir);
+ Free(ms->PersonalDesktopDir);
+ Free(ms->MyDocumentsDir);
+ Free(ms->ExeFileDir);
+ Free(ms->ExeFileName);
+ Free(ms->UserName);
+ Free(ms->UserNameEx);
+ Free(ms->LocalAppDataDir);
+ Free(ms->ProgramFilesDirX86);
+ Free(ms->ProgramFilesDirX64);
+ // Unicode
+ Free(ms->WindowsDirW);
+ Free(ms->System32DirW);
+ Free(ms->TempDirW);
+ Free(ms->WinTempDirW);
+ Free(ms->WindowsDriveW);
+ Free(ms->ProgramFilesDirW);
+ Free(ms->CommonStartMenuDirW);
+ Free(ms->CommonProgramsDirW);
+ Free(ms->CommonStartupDirW);
+ Free(ms->CommonAppDataDirW);
+ Free(ms->CommonDesktopDirW);
+ Free(ms->PersonalStartMenuDirW);
+ Free(ms->PersonalProgramsDirW);
+ Free(ms->PersonalStartupDirW);
+ Free(ms->PersonalAppDataDirW);
+ Free(ms->PersonalDesktopDirW);
+ Free(ms->MyDocumentsDirW);
+ Free(ms->ExeFileDirW);
+ Free(ms->ExeFileNameW);
+ Free(ms->UserNameW);
+ Free(ms->UserNameExW);
+ Free(ms->LocalAppDataDirW);
+ Free(ms->MinidumpBaseFileNameW);
+ Free(ms->ProgramFilesDirX86W);
+ Free(ms->ProgramFilesDirX64W);
+
+ Free(ms);
+ ms = NULL;
+
+ // Delete the lock
+ DeleteLock(vlan_lock);
+ vlan_lock = NULL;
+}
+
+// Directory acquisition related
+char *MsGetCommonAppDataDir()
+{
+ return ms->CommonAppDataDir;
+}
+char *MsGetLocalAppDataDir()
+{
+ return ms->LocalAppDataDir;
+}
+char *MsGetWindowsDir()
+{
+ return ms->WindowsDir;
+}
+wchar_t *MsGetWindowsDirW()
+{
+ return ms->WindowsDirW;
+}
+char *MsGetSystem32Dir()
+{
+ return ms->System32Dir;
+}
+char *MsGetTempDir()
+{
+ return ms->TempDir;
+}
+char *MsGetWindowsDrive()
+{
+ return ms->WindowsDrive;
+}
+char *MsGetProgramFilesDir()
+{
+ return ms->ProgramFilesDir;
+}
+char *MsGetProgramFilesDirX86()
+{
+ return ms->ProgramFilesDirX86;
+}
+char *MsGetProgramFilesDirX64()
+{
+ return ms->ProgramFilesDirX64;
+}
+char *MsGetCommonStartMenuDir()
+{
+ return ms->CommonStartMenuDir;
+}
+char *MsGetCommonProgramsDir()
+{
+ return ms->CommonProgramsDir;
+}
+char *MsGetCommonStartupDir()
+{
+ return ms->CommonStartupDir;
+}
+char *MsGetCommonDesktopDir()
+{
+ return ms->CommonDesktopDir;
+}
+char *MsGetPersonalStartMenuDir()
+{
+ if (ms->PersonalStartMenuDir == NULL)
+ {
+ ms->PersonalStartMenuDir = MsGetSpecialDir(CSIDL_STARTMENU);
+ }
+ return ms->PersonalStartMenuDir;
+}
+char *MsGetPersonalProgramsDir()
+{
+ if (ms->PersonalProgramsDir == NULL)
+ {
+ ms->PersonalProgramsDir = MsGetSpecialDir(CSIDL_PROGRAMS);
+ }
+ return ms->PersonalProgramsDir;
+}
+char *MsGetPersonalStartupDir()
+{
+ if (ms->PersonalStartupDir == NULL)
+ {
+ ms->PersonalStartupDir = MsGetSpecialDir(CSIDL_STARTUP);
+ }
+ return ms->PersonalStartupDir;
+}
+char *MsGetPersonalAppDataDir()
+{
+ if (ms->PersonalAppDataDir == NULL)
+ {
+ ms->PersonalAppDataDir = MsGetSpecialDir(CSIDL_APPDATA);
+ }
+ return ms->PersonalAppDataDir;
+}
+char *MsGetPersonalDesktopDir()
+{
+ if (ms->PersonalDesktopDir == NULL)
+ {
+ ms->PersonalDesktopDir = MsGetSpecialDir(CSIDL_DESKTOP);
+ }
+ return ms->PersonalDesktopDir;
+}
+char *MsGetMyDocumentsDir()
+{
+ if (ms->MyDocumentsDir == NULL)
+ {
+ ms->MyDocumentsDir = MsGetSpecialDir(CSIDL_PERSONAL);
+ }
+ return ms->MyDocumentsDir;
+}
+char *MsGetMyTempDir()
+{
+ return ms->MyTempDir;
+}
+char *MsGetUserName()
+{
+ return ms->UserName;
+}
+char *MsGetUserNameEx()
+{
+ return ms->UserNameEx;
+}
+char *MsGetWinTempDir()
+{
+ return ms->WinTempDir;
+}
+
+wchar_t *MsGetExeFileNameW()
+{
+ return ms == NULL ? L"Unknown" : ms->ExeFileNameW;
+}
+wchar_t *MsGetExeFileDirW()
+{
+ return ms->ExeFileDirW;
+}
+wchar_t *MsGetWindowDirW()
+{
+ return ms->WindowsDirW;
+}
+wchar_t *MsGetSystem32DirW()
+{
+ return ms->System32DirW;
+}
+wchar_t *MsGetTempDirW()
+{
+ return ms->TempDirW;
+}
+wchar_t *MsGetWindowsDriveW()
+{
+ return ms->WindowsDriveW;
+}
+wchar_t *MsGetProgramFilesDirW()
+{
+ return ms->ProgramFilesDirW;
+}
+wchar_t *MsGetCommonStartMenuDirW()
+{
+ return ms->CommonStartMenuDirW;
+}
+wchar_t *MsGetCommonProgramsDirW()
+{
+ return ms->CommonProgramsDirW;
+}
+wchar_t *MsGetProgramFilesDirX86W()
+{
+ return ms->ProgramFilesDirX86W;
+}
+wchar_t *MsGetProgramFilesDirX64W()
+{
+ return ms->ProgramFilesDirX64W;
+}
+wchar_t *MsGetCommonStartupDirW()
+{
+ return ms->CommonStartupDirW;
+}
+wchar_t *MsGetCommonAppDataDirW()
+{
+ return ms->CommonAppDataDirW;
+}
+wchar_t *MsGetCommonDesktopDirW()
+{
+ return ms->CommonDesktopDirW;
+}
+wchar_t *MsGetPersonalStartMenuDirW()
+{
+ if (ms->PersonalStartMenuDirW == NULL)
+ {
+ ms->PersonalStartMenuDirW = MsGetSpecialDirW(CSIDL_STARTMENU);
+ }
+
+ return ms->PersonalStartMenuDirW;
+}
+wchar_t *MsGetPersonalProgramsDirW()
+{
+ if (ms->PersonalProgramsDirW == NULL)
+ {
+ ms->PersonalProgramsDirW = MsGetSpecialDirW(CSIDL_PROGRAMS);
+ }
+
+ return ms->PersonalProgramsDirW;
+}
+wchar_t *MsGetPersonalStartupDirW()
+{
+ if (ms->PersonalStartupDirW == NULL)
+ {
+ ms->PersonalStartupDirW = MsGetSpecialDirW(CSIDL_STARTUP);
+ }
+
+ return ms->PersonalStartupDirW;
+}
+wchar_t *MsGetPersonalAppDataDirW()
+{
+ if (ms->PersonalAppDataDirW == NULL)
+ {
+ ms->PersonalAppDataDirW = MsGetSpecialDirW(CSIDL_APPDATA);
+ }
+
+ return ms->PersonalAppDataDirW;
+}
+wchar_t *MsGetPersonalDesktopDirW()
+{
+ if (ms->PersonalDesktopDirW == NULL)
+ {
+ ms->PersonalDesktopDirW = MsGetSpecialDirW(CSIDL_DESKTOP);
+ }
+
+ return ms->PersonalDesktopDirW;
+}
+wchar_t *MsGetMyDocumentsDirW()
+{
+ if (ms->MyDocumentsDirW == NULL)
+ {
+ ms->MyDocumentsDirW = MsGetSpecialDirW(CSIDL_PERSONAL);
+ }
+
+ return ms->MyDocumentsDirW;
+}
+wchar_t *MsGetLocalAppDataDirW()
+{
+ return ms->LocalAppDataDirW;
+}
+wchar_t *MsGetMyTempDirW()
+{
+ return ms->MyTempDirW;
+}
+wchar_t *MsGetUserNameW()
+{
+ return ms->UserNameW;
+}
+wchar_t *MsGetUserNameExW()
+{
+ return ms->UserNameExW;
+}
+wchar_t *MsGetWinTempDirW()
+{
+ return ms->WinTempDirW;
+}
+
+
+#endif // WIN32
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Microsoft.h b/src/Mayaqua/Microsoft.h
new file mode 100644
index 00000000..b1b752ff
--- /dev/null
+++ b/src/Mayaqua/Microsoft.h
@@ -0,0 +1,1155 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Microsoft.h
+// Header of Microsoft.c
+
+#ifdef OS_WIN32
+
+// Make available the types for Windows even if windows.h is not included
+#ifndef _WINDEF_
+
+typedef void *HWND;
+
+#endif // _WINDEF_
+
+#ifndef MICROSOFT_H
+#define MICROSOFT_H
+
+
+// Constant for Event log
+#define MS_EVENTLOG_TYPE_INFORMATION 0
+#define MS_EVENTLOG_TYPE_WARNING 1
+#define MS_EVENTLOG_TYPE_ERROR 2
+
+#define MS_RC_EVENTLOG_TYPE_INFORMATION 0x40000001L
+#define MS_RC_EVENTLOG_TYPE_WARNING 0x80000002L
+#define MS_RC_EVENTLOG_TYPE_ERROR 0xC0000003L
+
+
+// TCP/IP registry value
+#define TCP_MAX_NUM_CONNECTIONS 16777214
+
+#define DEFAULT_TCP_MAX_WINDOW_SIZE_RECV 5955584
+#define DEFAULT_TCP_MAX_WINDOW_SIZE_SEND 131072
+#define DEFAULT_TCP_MAX_NUM_CONNECTIONS 16777214
+
+// Constant
+#define SVC_ARG_INSTALL "/install"
+#define SVC_ARG_UNINSTALL "/uninstall"
+#define SVC_ARG_START "/start"
+#define SVC_ARG_STOP "/stop"
+#define SVC_ARG_TEST "/test"
+#define SVC_ARG_USERMODE "/usermode"
+#define SVC_ARG_USERMODE_SHOWTRAY "/usermode_showtray"
+#define SVC_ARG_USERMODE_HIDETRAY "/usermode_hidetray"
+#define SVC_ARG_SERVICE "/service"
+#define SVC_ARG_SETUP_INSTALL "/setup_install"
+#define SVC_ARG_SETUP_UNINSTALL "/setup_uninstall"
+#define SVC_ARG_WIN9X_SERVICE "/win9x_service"
+#define SVC_ARG_WIN9X_INSTALL "/win9x_install"
+#define SVC_ARG_WIN9X_UNINSTALL "/win9x_uninstall"
+#define SVC_ARG_TCP "/tcp"
+#define SVC_ARG_TCP_UAC "/tcp_uac"
+#define SVC_ARG_TCP_UAC_W L"/tcp_uac"
+#define SVC_ARG_TCP_SETUP "/tcpsetup"
+#define SVC_ARG_TRAFFIC "/traffic"
+#define SVC_ARG_UIHELP "/uihelp"
+#define SVC_ARG_UIHELP_W L"/uihelp"
+#define SVC_ARG_SILENT "/silent"
+
+// Time to suicide, if the service freezed
+#define SVC_SELFKILL_TIMEOUT (5 * 60 * 1000)
+
+// The name of the device driver of the virtual LAN card for Win32 (first part)
+#define VLAN_ADAPTER_NAME "VPN Client Adapter"
+#define VLAN_ADAPTER_NAME_OLD "SoftEther VPN Client 2.0 Adapter"
+
+// The name of the device driver of the virtual LAN card for Win32 (full name)
+#define VLAN_ADAPTER_NAME_TAG "VPN Client Adapter - %s"
+#define VLAN_ADAPTER_NAME_TAG_OLD "SoftEther VPN Client 2.0 Adapter - %s"
+
+// Display name of Virtual LAN card in the [Network Connections] in Win32 (full name)
+#define VLAN_CONNECTION_NAME "%s - VPN Client"
+#define VLAN_CONNECTION_NAME_OLD "%s - SoftEther VPN Client 2.0"
+
+
+// Command line format in the service mode
+#define SVC_RUN_COMMANDLINE L"\"%s\" /service"
+
+// Mode value
+#define SVC_MODE_NONE 0
+#define SVC_MODE_INSTALL 1
+#define SVC_MODE_UNINSTALL 2
+#define SVC_MODE_START 3
+#define SVC_MODE_STOP 4
+#define SVC_MODE_TEST 5
+#define SVC_MODE_USERMODE 6
+#define SVC_MODE_SERVICE 7
+#define SVC_MODE_SETUP_INSTALL 8
+#define SVC_MODE_SETUP_UNINSTALL 9
+#define SVC_MODE_WIN9X_SERVICE 10
+#define SVC_MODE_WIN9X_INSTALL 11
+#define SVC_MODE_WIN9X_UNINSTALL 12
+#define SVC_MODE_TCP 13
+#define SVC_MODE_TCPSETUP 14
+#define SVC_MODE_TRAFFIC 15
+#define SVC_MODE_UIHELP 16
+#define SVC_MODE_TCP_UAC 17
+
+
+#define WIN9X_SVC_REGKEY_1 "Software\\Microsoft\\Windows\\CurrentVersion\\RunServices"
+#define WIN9X_SVC_REGKEY_2 "Software\\Microsoft\\Windows\\CurrentVersion\\Run"
+
+#define VISTA_MMCSS_KEYNAME "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile\\Tasks"
+#define VISTA_MMCSS_FILENAME "mmcss_backup.dat"
+
+#define SVC_NAME "SVC_%s_NAME"
+#define SVC_TITLE "SVC_%s_TITLE"
+#define SVC_DESCRIPT "SVC_%s_DESCRIPT"
+
+#define SVC_USERMODE_SETTING_KEY "Software\\" GC_REG_COMPANY_NAME "\\PacketiX VPN\\UserMode Settings"
+#define SVC_HIDETRAY_REG_VALUE "HideTray_%S"
+
+#define SVC_CALLING_SM_PROCESS_ID_KEY "Software\\" GC_REG_COMPANY_NAME "\\PacketiX VPN\\Service Control\\%s"
+#define SVC_CALLING_SM_PROCESS_ID_VALUE "ProcessId"
+
+#define SOFTETHER_FW_SCRIPT_HASH "Software\\" GC_REG_COMPANY_NAME "\\PacketiX VPN\\FW ScriptHash"
+
+#define MMCSS_PROFILE_KEYNAME "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Multimedia\\SystemProfile"
+
+// Other constants
+#define MS_REG_TCP_SETTING_KEY "Software\\" GC_REG_COMPANY_NAME "\\Network Settings"
+
+
+
+// Constants about driver
+#define DRIVER_INF_FILE_NAME L"|vpn_driver.inf"
+#define DRIVER_INF_FILE_NAME_X64 L"|vpn_driver_x64.inf"
+#define DRIVER_INF_FILE_NAME_IA64 L"|vpn_driver_ia64.inf"
+#define DRIVER_INF_FILE_NAME_9X L"|vpn_driver_9x.inf"
+#define DRIVER_SYS_FILE_NAME L"|vpn_driver.sys"
+#define DRIVER_SYS_FILE_NAME_X64 L"|vpn_driver_x64.sys"
+#define DRIVER_SYS_FILE_NAME_IA64 L"|vpn_driver_ia64.sys"
+#define DRIVER_SYS_FILE_NAME_9X L"|vpn_driver_9x.sys"
+#define DRIVER_SYS6_FILE_NAME L"|vpn_driver6.sys"
+#define DRIVER_SYS6_FILE_NAME_X64 L"|vpn_driver6_x64.sys"
+#define DRIVER_SYS6_FILE_NAME_IA64 L"|vpn_driver6_ia64.sys"
+#define DRIVER_INSTALL_INF_NAME_TAG "Neo_%s.inf"
+#define DRIVER_INSTALL_SYS_NAME_TAG "Neo_%s.sys"
+#define DRIVER_INSTALL_SYS_NAME_TAG_NEW "Neo_%04u.sys"
+#define DRIVER_INSTALL_SYS_NAME_TAG_MAXID 128 // Maximum number of install
+
+
+// Vista driver installer related
+#define VISTA_DRIVER_INSTALLER_SRC L"|driver_installer.exe"
+#define VISTA_DRIVER_INSTALLER_SRC_X64 L"|driver_installer_x64.exe"
+#define VISTA_DRIVER_INSTALLER_SRC_IA64 L"|driver_installer_ia64.exe"
+#define VISTA_DRIVER_INSTALLER_DST L"%s\\driver_installer.exe"
+
+#define DRIVER_DEVICE_ID_TAG "NeoAdapter_%s"
+
+
+#if (defined(MICROSOFT_C) || defined(NETWORK_C)) && (defined(OS_WIN32))
+
+typedef enum __TCP_TABLE_CLASS {
+ _TCP_TABLE_BASIC_LISTENER,
+ _TCP_TABLE_BASIC_CONNECTIONS,
+ _TCP_TABLE_BASIC_ALL,
+ _TCP_TABLE_OWNER_PID_LISTENER,
+ _TCP_TABLE_OWNER_PID_CONNECTIONS,
+ _TCP_TABLE_OWNER_PID_ALL,
+ _TCP_TABLE_OWNER_MODULE_LISTENER,
+ _TCP_TABLE_OWNER_MODULE_CONNECTIONS,
+ _TCP_TABLE_OWNER_MODULE_ALL
+} _TCP_TABLE_CLASS, *_PTCP_TABLE_CLASS;
+
+// A pointer to the network related Win32 API function
+typedef struct NETWORK_WIN32_FUNCTIONS
+{
+ HINSTANCE hIpHlpApi32;
+ HINSTANCE hIcmp;
+ DWORD (WINAPI *DeleteIpForwardEntry)(PMIB_IPFORWARDROW);
+ DWORD (WINAPI *CreateIpForwardEntry)(PMIB_IPFORWARDROW);
+ DWORD (WINAPI *GetIpForwardTable)(PMIB_IPFORWARDTABLE, PULONG, BOOL);
+ DWORD (WINAPI *GetNetworkParams)(PFIXED_INFO, PULONG);
+ ULONG (WINAPI *GetAdaptersAddresses)(ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG);
+ DWORD (WINAPI *GetIfTable)(PMIB_IFTABLE, PULONG, BOOL);
+ DWORD (WINAPI *GetIfTable2)(void **);
+ void (WINAPI *FreeMibTable)(PVOID);
+ DWORD (WINAPI *IpRenewAddress)(PIP_ADAPTER_INDEX_MAP);
+ DWORD (WINAPI *IpReleaseAddress)(PIP_ADAPTER_INDEX_MAP);
+ DWORD (WINAPI *GetInterfaceInfo)(PIP_INTERFACE_INFO, PULONG);
+ DWORD (WINAPI *GetAdaptersInfo)(PIP_ADAPTER_INFO, PULONG);
+ DWORD (WINAPI *GetExtendedTcpTable)(PVOID, PDWORD, BOOL, ULONG, _TCP_TABLE_CLASS, ULONG);
+ DWORD (WINAPI *AllocateAndGetTcpExTableFromStack)(PVOID *, BOOL, HANDLE, DWORD, DWORD);
+ DWORD (WINAPI *GetTcpTable)(PMIB_TCPTABLE, PDWORD, BOOL);
+ DWORD (WINAPI *NotifyRouteChange)(PHANDLE, LPOVERLAPPED);
+ BOOL (WINAPI *CancelIPChangeNotify)(LPOVERLAPPED);
+ DWORD (WINAPI *NhpAllocateAndGetInterfaceInfoFromStack)(IP_INTERFACE_NAME_INFO **,
+ PDWORD, BOOL, HANDLE, DWORD);
+ HANDLE (WINAPI *IcmpCreateFile)();
+ BOOL (WINAPI *IcmpCloseHandle)(HANDLE);
+ DWORD (WINAPI *IcmpSendEcho)(HANDLE, IPAddr, LPVOID, WORD, PIP_OPTION_INFORMATION,
+ LPVOID, DWORD, DWORD);
+} NETWORK_WIN32_FUNCTIONS;
+#endif
+
+
+#ifdef MICROSOFT_C
+// WCM related code on Windows 8
+typedef enum _MS_WCM_PROPERTY
+{
+ ms_wcm_global_property_domain_policy,
+ ms_wcm_global_property_minimize_policy,
+ ms_wcm_global_property_roaming_policy,
+ ms_wcm_global_property_powermanagement_policy,
+ ms_wcm_intf_property_connection_cost, //used to set/get cost level and flags for the connection
+ ms_wcm_intf_property_dataplan_status, //used by MNO to indicate plan data associated with new cost
+ ms_wcm_intf_property_hotspot_profile, //used to store hotspot profile (WISPr credentials)
+} MS_WCM_PROPERTY, *MS_PWCM_PROPERTY;
+
+typedef struct _MS_WCM_POLICY_VALUE {
+ BOOL fValue;
+ BOOL fIsGroupPolicy;
+} MS_WCM_POLICY_VALUE, *MS_PWCM_POLICY_VALUE;
+
+#define MS_WCM_MAX_PROFILE_NAME 256
+
+typedef enum _MS_WCM_MEDIA_TYPE
+{
+ ms_wcm_media_unknown,
+ ms_wcm_media_ethernet,
+ ms_wcm_media_wlan,
+ ms_wcm_media_mbn,
+ ms_wcm_media_invalid,
+ ms_wcm_media_max
+} MS_WCM_MEDIA_TYPE, *MS_PWCM_MEDIA_TYPE;
+
+typedef struct _MS_WCM_PROFILE_INFO {
+ WCHAR strProfileName[MS_WCM_MAX_PROFILE_NAME];
+ GUID AdapterGUID;
+ MS_WCM_MEDIA_TYPE Media;
+} MS_WCM_PROFILE_INFO, *MS_PWCM_PROFILE_INFO;
+
+typedef struct _MS_WCM_PROFILE_INFO_LIST {
+ DWORD dwNumberOfItems;
+
+ MS_WCM_PROFILE_INFO ProfileInfo[1];
+
+} MS_WCM_PROFILE_INFO_LIST, *MS_PWCM_PROFILE_INFO_LIST;
+
+
+// Internal structure
+typedef struct MS
+{
+ HINSTANCE hInst;
+ HINSTANCE hKernel32;
+ bool IsNt;
+ bool IsAdmin;
+ struct NT_API *nt;
+ HANDLE hCurrentProcess;
+ UINT CurrentProcessId;
+ bool MiniDumpEnabled;
+ char *ExeFileName;
+ char *ExeFileDir;
+ char *WindowsDir;
+ char *System32Dir;
+ char *TempDir;
+ char *WinTempDir;
+ char *WindowsDrive;
+ char *ProgramFilesDir;
+ char *ProgramFilesDirX86;
+ char *ProgramFilesDirX64;
+ char *CommonStartMenuDir;
+ char *CommonProgramsDir;
+ char *CommonStartupDir;
+ char *CommonAppDataDir;
+ char *CommonDesktopDir;
+ char *PersonalStartMenuDir;
+ char *PersonalProgramsDir;
+ char *PersonalStartupDir;
+ char *PersonalAppDataDir;
+ char *PersonalDesktopDir;
+ char *MyDocumentsDir;
+ char *LocalAppDataDir;
+ char *MyTempDir;
+ char *UserName;
+ char *UserNameEx;
+ wchar_t *ExeFileNameW;
+ wchar_t *ExeFileDirW;
+ wchar_t *WindowsDirW;
+ wchar_t *System32DirW;
+ wchar_t *TempDirW;
+ wchar_t *WinTempDirW;
+ wchar_t *WindowsDriveW;
+ wchar_t *ProgramFilesDirW;
+ wchar_t *ProgramFilesDirX86W;
+ wchar_t *ProgramFilesDirX64W;
+ wchar_t *CommonStartMenuDirW;
+ wchar_t *CommonProgramsDirW;
+ wchar_t *CommonStartupDirW;
+ wchar_t *CommonAppDataDirW;
+ wchar_t *CommonDesktopDirW;
+ wchar_t *PersonalStartMenuDirW;
+ wchar_t *PersonalProgramsDirW;
+ wchar_t *PersonalStartupDirW;
+ wchar_t *PersonalAppDataDirW;
+ wchar_t *PersonalDesktopDirW;
+ wchar_t *MyDocumentsDirW;
+ wchar_t *LocalAppDataDirW;
+ wchar_t *MyTempDirW;
+ wchar_t *UserNameW;
+ wchar_t *UserNameExW;
+ wchar_t *MinidumpBaseFileNameW;
+ IO *LockFile;
+} MS;
+
+// For Windows NT API
+typedef struct NT_API
+{
+ HINSTANCE hAdvapi32;
+ HINSTANCE hShell32;
+ HINSTANCE hNewDev;
+ HINSTANCE hSetupApi;
+ HINSTANCE hWtsApi32;
+ HINSTANCE hPsApi;
+ HINSTANCE hKernel32;
+ HINSTANCE hSecur32;
+ HINSTANCE hUser32;
+ HINSTANCE hDbgHelp;
+ HINSTANCE hWcmapi;
+ HINSTANCE hDwmapi;
+ BOOL (WINAPI *OpenProcessToken)(HANDLE, DWORD, PHANDLE);
+ BOOL (WINAPI *LookupPrivilegeValue)(char *, char *, PLUID);
+ BOOL (WINAPI *AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD, PTOKEN_PRIVILEGES, PDWORD);
+ BOOL (WINAPI *InitiateSystemShutdown)(LPTSTR, LPTSTR, DWORD, BOOL, BOOL);
+ BOOL (WINAPI *LogonUserW)(wchar_t *, wchar_t *, wchar_t *, DWORD, DWORD, HANDLE *);
+ BOOL (WINAPI *LogonUserA)(char *, char *, char *, DWORD, DWORD, HANDLE *);
+ BOOL (WINAPI *UpdateDriverForPlugAndPlayDevicesW)(HWND hWnd, wchar_t *hardware_id, wchar_t *inf_path, UINT flag, BOOL *need_reboot);
+ UINT (WINAPI *CM_Get_DevNode_Status_Ex)(UINT *, UINT *, DWORD, UINT, HANDLE);
+ UINT (WINAPI *CM_Get_Device_ID_ExA)(DWORD, char *, UINT, UINT, HANDLE);
+ UINT (WINAPI *WTSQuerySessionInformation)(HANDLE, DWORD, WTS_INFO_CLASS, wchar_t *, DWORD *);
+ void (WINAPI *WTSFreeMemory)(void *);
+ BOOL (WINAPI *WTSDisconnectSession)(HANDLE, DWORD, BOOL);
+ BOOL (WINAPI *WTSEnumerateSessions)(HANDLE, DWORD, DWORD, PWTS_SESSION_INFO *, DWORD *);
+ SC_HANDLE (WINAPI *OpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
+ SC_HANDLE (WINAPI *CreateServiceA)(SC_HANDLE, LPCTSTR, LPCTSTR, DWORD, DWORD, DWORD, DWORD, LPCTSTR, LPCTSTR, LPDWORD, LPCTSTR, LPCTSTR, LPCTSTR);
+ SC_HANDLE (WINAPI *CreateServiceW)(SC_HANDLE, LPCWSTR, LPCWSTR, DWORD, DWORD, DWORD, DWORD, LPCWSTR, LPCWSTR, LPDWORD, LPCWSTR, LPCWSTR, LPCWSTR);
+ BOOL (WINAPI *ChangeServiceConfig2)(SC_HANDLE, DWORD, LPVOID);
+ BOOL (WINAPI *CloseServiceHandle)(SC_HANDLE);
+ SC_HANDLE (WINAPI *OpenService)(SC_HANDLE, LPCTSTR, DWORD);
+ BOOL (WINAPI *QueryServiceStatus)(SC_HANDLE, LPSERVICE_STATUS);
+ BOOL (WINAPI *StartService)(SC_HANDLE, DWORD, LPCTSTR);
+ BOOL (WINAPI *ControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
+ BOOL (WINAPI *SetServiceStatus)(SERVICE_STATUS_HANDLE, LPSERVICE_STATUS);
+ SERVICE_STATUS_HANDLE (WINAPI *RegisterServiceCtrlHandler)(LPCTSTR, LPHANDLER_FUNCTION);
+ BOOL (WINAPI *StartServiceCtrlDispatcher)(CONST LPSERVICE_TABLE_ENTRY);
+ BOOL (WINAPI *DeleteService)(SC_HANDLE);
+ BOOL (WINAPI *EnumProcesses)(DWORD *, DWORD, DWORD *);
+ BOOL (WINAPI *EnumProcessModules)(HANDLE, HMODULE *, DWORD, DWORD *);
+ DWORD (WINAPI *GetModuleFileNameExA)(HANDLE, HMODULE, LPSTR, DWORD);
+ DWORD (WINAPI *GetModuleFileNameExW)(HANDLE, HMODULE, LPWSTR, DWORD);
+ DWORD (WINAPI *GetProcessImageFileNameA)(HANDLE, LPSTR, DWORD);
+ DWORD (WINAPI *GetProcessImageFileNameW)(HANDLE, LPWSTR, DWORD);
+ BOOL (WINAPI *QueryFullProcessImageNameA)(HANDLE, DWORD, LPSTR, PDWORD);
+ BOOL (WINAPI *QueryFullProcessImageNameW)(HANDLE, DWORD, LPWSTR, PDWORD);
+ LONG (WINAPI *RegDeleteKeyExA)(HKEY, LPCTSTR, REGSAM, DWORD);
+ BOOL (WINAPI *IsWow64Process)(HANDLE, BOOL *);
+ void (WINAPI *GetNativeSystemInfo)(SYSTEM_INFO *);
+ BOOL (WINAPI *DuplicateTokenEx)(HANDLE, DWORD, SECURITY_ATTRIBUTES *, SECURITY_IMPERSONATION_LEVEL, TOKEN_TYPE, HANDLE *);
+ BOOL (WINAPI *ConvertStringSidToSidA)(LPCSTR, PSID *);
+ BOOL (WINAPI *SetTokenInformation)(HANDLE, TOKEN_INFORMATION_CLASS, void *, DWORD);
+ BOOL (WINAPI *GetTokenInformation)(HANDLE, TOKEN_INFORMATION_CLASS, void *, DWORD, PDWORD);
+ BOOL (WINAPI *CreateProcessAsUserA)(HANDLE, LPCSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, void *, LPCSTR, LPSTARTUPINFOA, LPPROCESS_INFORMATION);
+ BOOL (WINAPI *CreateProcessAsUserW)(HANDLE, LPCWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, void *, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION);
+ BOOL (WINAPI *LookupAccountSidA)(LPCSTR,PSID,LPSTR,LPDWORD,LPSTR,LPDWORD,PSID_NAME_USE);
+ BOOL (WINAPI *LookupAccountNameA)(LPCSTR,LPCSTR,PSID,LPDWORD,LPSTR,LPDWORD,PSID_NAME_USE);
+ BOOL (WINAPI *GetUserNameExA)(EXTENDED_NAME_FORMAT, LPSTR, PULONG);
+ BOOL (WINAPI *GetUserNameExW)(EXTENDED_NAME_FORMAT, LPWSTR, PULONG);
+ BOOL (WINAPI *SwitchDesktop)(HDESK);
+ HDESK (WINAPI *OpenDesktopA)(LPTSTR, DWORD, BOOL, ACCESS_MASK);
+ BOOL (WINAPI *CloseDesktop)(HDESK);
+ BOOL (WINAPI *SetProcessShutdownParameters)(DWORD, DWORD);
+ HANDLE (WINAPI *RegisterEventSourceW)(LPCWSTR, LPCWSTR);
+ BOOL (WINAPI *ReportEventW)(HANDLE, WORD, WORD, DWORD, PSID, WORD, DWORD, LPCWSTR *, LPVOID);
+ BOOL (WINAPI *DeregisterEventSource)(HANDLE);
+ BOOL (WINAPI *Wow64DisableWow64FsRedirection)(void **);
+ BOOLEAN (WINAPI *Wow64EnableWow64FsRedirection)(BOOLEAN);
+ BOOL (WINAPI *Wow64RevertWow64FsRedirection)(void *);
+ BOOL (WINAPI *GetFileInformationByHandle)(HANDLE, LPBY_HANDLE_FILE_INFORMATION);
+ HANDLE (WINAPI *GetProcessHeap)();
+ BOOL (WINAPI *MiniDumpWriteDump)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE,
+ PMINIDUMP_EXCEPTION_INFORMATION, PMINIDUMP_USER_STREAM_INFORMATION,
+ PMINIDUMP_CALLBACK_INFORMATION);
+ BOOL (WINAPI *AllocateLocallyUniqueId)(PLUID);
+ NTSTATUS (NTAPI *LsaConnectUntrusted)(PHANDLE);
+ NTSTATUS (NTAPI *LsaLookupAuthenticationPackage)(HANDLE, PLSA_STRING, PULONG);
+ NTSTATUS (NTAPI *LsaLogonUser)(HANDLE, PLSA_STRING, SECURITY_LOGON_TYPE, ULONG,
+ PVOID, ULONG, PTOKEN_GROUPS, PTOKEN_SOURCE, PVOID, PULONG, PLUID, PHANDLE,
+ PQUOTA_LIMITS, PNTSTATUS);
+ NTSTATUS (NTAPI *LsaDeregisterLogonProcess)(HANDLE);
+ NTSTATUS (NTAPI *LsaFreeReturnBuffer)(PVOID);
+ DWORD (WINAPI *WcmQueryProperty)(const GUID *, LPCWSTR, MS_WCM_PROPERTY, PVOID, PDWORD, PBYTE *);
+ DWORD (WINAPI *WcmSetProperty)(const GUID *, LPCWSTR, MS_WCM_PROPERTY, PVOID, DWORD, const BYTE *);
+ void (WINAPI *WcmFreeMemory)(PVOID);
+ DWORD (WINAPI *WcmGetProfileList)(PVOID, MS_WCM_PROFILE_INFO_LIST **ppProfileList);
+ DWORD (WINAPI *SetNamedSecurityInfoW)(LPWSTR, UINT, SECURITY_INFORMATION, PSID, PSID, PACL, PACL);
+ BOOL (WINAPI *AddAccessAllowedAceEx)(PACL, DWORD, DWORD, DWORD, PSID);
+ HRESULT (WINAPI *DwmIsCompositionEnabled)(BOOL *);
+ BOOL (WINAPI *GetComputerNameExW)(COMPUTER_NAME_FORMAT, LPWSTR, LPDWORD);
+} NT_API;
+
+typedef struct MS_EVENTLOG
+{
+ HANDLE hEventLog;
+} MS_EVENTLOG;
+
+extern NETWORK_WIN32_FUNCTIONS *w32net;
+
+typedef struct MS_USERMODE_SVC_PULSE_THREAD_PARAM
+{
+ void *hWnd;
+ void *GlobalPulse;
+ volatile bool Halt;
+} MS_USERMODE_SVC_PULSE_THREAD_PARAM;
+
+#endif // MICROSOFT_C
+
+// Structure to suppress the warning message
+typedef struct NO_WARNING
+{
+ DWORD ThreadId;
+ THREAD *NoWarningThread;
+ EVENT *HaltEvent;
+ volatile bool Halt;
+ wchar_t *SoundFileName;
+ UINT64 StartTimer;
+ UINT64 StartTick;
+} NO_WARNING;
+
+// ID of the root key
+#define REG_CLASSES_ROOT 0 // HKEY_CLASSES_ROOT
+#define REG_LOCAL_MACHINE 1 // HKEY_LOCAL_MACHINE
+#define REG_CURRENT_USER 2 // HKEY_CURRENT_USER
+#define REG_USERS 3 // HKEY_USERS
+
+// Service Functions
+typedef void (SERVICE_FUNCTION)();
+
+// Process list item
+typedef struct MS_PROCESS
+{
+ char ExeFilename[MAX_PATH]; // EXE file name
+ wchar_t ExeFilenameW[MAX_PATH]; // EXE file name (Unicode)
+ UINT ProcessId; // Process ID
+} MS_PROCESS;
+
+#define MAX_MS_ADAPTER_IP_ADDRESS 64
+
+// Network adapter
+typedef struct MS_ADAPTER
+{
+ char Title[MAX_PATH]; // Display name
+ wchar_t TitleW[MAX_PATH]; // Display Name (Unicode)
+ UINT Index; // Index
+ UINT Type; // Type
+ UINT Status; // Status
+ UINT Mtu; // MTU
+ UINT Speed; // Speed
+ UINT AddressSize; // Address size
+ UCHAR Address[8]; // Address
+ UINT64 RecvBytes; // Number of received bytes
+ UINT64 RecvPacketsBroadcast; // Number of broadcast packets received
+ UINT64 RecvPacketsUnicast; // Number of unicast packets received
+ UINT64 SendBytes; // Number of bytes sent
+ UINT64 SendPacketsBroadcast; // Number of sent broadcast packets
+ UINT64 SendPacketsUnicast; // Number of sent unicast packets
+ bool Info; // Whether there is detailed information
+ char Guid[MAX_SIZE]; // GUID
+ UINT NumIpAddress; // The number of IP addresses
+ IP IpAddresses[MAX_MS_ADAPTER_IP_ADDRESS]; // IP address
+ IP SubnetMasks[MAX_MS_ADAPTER_IP_ADDRESS]; // Subnet mask
+ UINT NumGateway; // The number of the gateway
+ IP Gateways[MAX_MS_ADAPTER_IP_ADDRESS]; // Gateway
+ bool UseDhcp; // Using DHCP flag
+ IP DhcpServer; // DHCP Server
+ UINT64 DhcpLeaseStart; // DHCP lease start date and time
+ UINT64 DhcpLeaseExpires; // DHCP lease expiration date and time
+ bool UseWins; // WINS use flag
+ IP PrimaryWinsServer; // Primary WINS server
+ IP SecondaryWinsServer; // Secondary WINS server
+ bool IsWireless; // Whether wireless
+ bool IsNotEthernetLan; // Whether It isn't a Ethernet LAN
+} MS_ADAPTER;
+
+// Network adapter list
+typedef struct MS_ADAPTER_LIST
+{
+ UINT Num; // Count
+ MS_ADAPTER **Adapters; // Content
+} MS_ADAPTER_LIST;
+
+// TCP setting
+typedef struct MS_TCP
+{
+ UINT RecvWindowSize; // Receive window size
+ UINT SendWindowSize; // Send window size
+} MS_TCP;
+
+// Sleep prevention
+typedef struct MS_NOSLEEP
+{
+ THREAD *Thread; // Thread
+ EVENT *HaltEvent; // Halting event
+ volatile bool Halt; // Halting flag
+ bool NoScreenSaver; // Prevent Screensaver
+
+ // Following is for Windows Vista
+ wchar_t ScreenSaveActive[MAX_PATH];
+ wchar_t SCRNSAVE_EXE[MAX_PATH];
+} MS_NOSLEEP;
+
+// Child window enumeration
+typedef struct ENUM_CHILD_WINDOW_PARAM
+{
+ LIST *o;
+ bool no_recursion;
+ bool include_ipcontrol;
+} ENUM_CHILD_WINDOW_PARAM;
+
+// Driver version information
+typedef struct MS_DRIVER_VER
+{
+ UINT Year, Month, Day;
+ UINT Major, Minor, Build;
+} MS_DRIVER_VER;
+
+
+// Function prototype
+void MsInit();
+void MsFree();
+char *MsCutExeNameFromCommandLine(char *str);
+wchar_t *MsCutExeNameFromUniCommandLine(wchar_t *str);
+
+DWORD MsRegAccessMaskFor64Bit(bool force32bit);
+DWORD MsRegAccessMaskFor64BitEx(bool force32bit, bool force64bit);
+
+bool MsRegIsKey(UINT root, char *name);
+bool MsRegIsKeyEx(UINT root, char *name, bool force32bit);
+bool MsRegIsKeyEx2(UINT root, char *name, bool force32bit, bool force64bit);
+
+bool MsRegIsValue(UINT root, char *keyname, char *valuename);
+bool MsRegIsValueEx(UINT root, char *keyname, char *valuename, bool force32bit);
+bool MsRegIsValueEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit);
+
+bool MsRegGetValueTypeAndSize(UINT root, char *keyname, char *valuename, UINT *type, UINT *size);
+bool MsRegGetValueTypeAndSizeEx(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit);
+bool MsRegGetValueTypeAndSizeEx2(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit, bool force64bit);
+bool MsRegGetValueTypeAndSizeW(UINT root, char *keyname, char *valuename, UINT *type, UINT *size);
+bool MsRegGetValueTypeAndSizeExW(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit);
+bool MsRegGetValueTypeAndSizeEx2W(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit, bool force64bit);
+
+bool MsRegReadValue(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size);
+bool MsRegReadValueEx(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit);
+bool MsRegReadValueEx2(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit, bool force64bit);
+bool MsRegReadValueW(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size);
+bool MsRegReadValueExW(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit);
+bool MsRegReadValueEx2W(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit, bool force64bit);
+
+char *MsRegReadStr(UINT root, char *keyname, char *valuename);
+char *MsRegReadStrEx(UINT root, char *keyname, char *valuename, bool force32bit);
+char *MsRegReadStrEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit);
+wchar_t *MsRegReadStrW(UINT root, char *keyname, char *valuename);
+wchar_t *MsRegReadStrExW(UINT root, char *keyname, char *valuename, bool force32bit);
+wchar_t *MsRegReadStrEx2W(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit);
+
+UINT MsRegReadInt(UINT root, char *keyname, char *valuename);
+UINT MsRegReadIntEx(UINT root, char *keyname, char *valuename, bool force32bit);
+UINT MsRegReadIntEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit);
+LIST *MsRegReadStrList(UINT root, char *keyname, char *valuename);
+LIST *MsRegReadStrListEx(UINT root, char *keyname, char *valuename, bool force32bit);
+LIST *MsRegReadStrListEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit);
+
+BUF *MsRegReadBin(UINT root, char *keyname, char *valuename);
+BUF *MsRegReadBinEx(UINT root, char *keyname, char *valuename, bool force32bit);
+BUF *MsRegReadBinEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit);
+
+bool MsRegNewKey(UINT root, char *keyname);
+bool MsRegNewKeyEx(UINT root, char *keyname, bool force32bit);
+bool MsRegNewKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit);
+
+bool MsRegWriteValue(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size);
+bool MsRegWriteValueEx(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit);
+bool MsRegWriteValueEx2(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit, bool force64bit);
+bool MsRegWriteValueW(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size);
+bool MsRegWriteValueExW(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit);
+bool MsRegWriteValueEx2W(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit, bool force64bit);
+
+bool MsRegWriteStr(UINT root, char *keyname, char *valuename, char *str);
+bool MsRegWriteStrEx(UINT root, char *keyname, char *valuename, char *str, bool force32bit);
+bool MsRegWriteStrEx2(UINT root, char *keyname, char *valuename, char *str, bool force32bit, bool force64bit);
+bool MsRegWriteStrExpand(UINT root, char *keyname, char *valuename, char *str);
+bool MsRegWriteStrExpandEx(UINT root, char *keyname, char *valuename, char *str, bool force32bit);
+bool MsRegWriteStrExpandEx2(UINT root, char *keyname, char *valuename, char *str, bool force32bit, bool force64bit);
+bool MsRegWriteStrW(UINT root, char *keyname, char *valuename, wchar_t *str);
+bool MsRegWriteStrExW(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit);
+bool MsRegWriteStrEx2W(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit, bool force64bit);
+bool MsRegWriteStrExpandW(UINT root, char *keyname, char *valuename, wchar_t *str);
+bool MsRegWriteStrExpandExW(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit);
+bool MsRegWriteStrExpandEx2W(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit, bool force64bit);
+
+bool MsRegWriteInt(UINT root, char *keyname, char *valuename, UINT value);
+bool MsRegWriteIntEx(UINT root, char *keyname, char *valuename, UINT value, bool force32bit);
+bool MsRegWriteIntEx2(UINT root, char *keyname, char *valuename, UINT value, bool force32bit, bool force64bit);
+bool MsRegWriteBin(UINT root, char *keyname, char *valuename, void *data, UINT size);
+bool MsRegWriteBinEx(UINT root, char *keyname, char *valuename, void *data, UINT size, bool force32bit);
+bool MsRegWriteBinEx2(UINT root, char *keyname, char *valuename, void *data, UINT size, bool force32bit, bool force64bit);
+
+TOKEN_LIST *MsRegEnumKey(UINT root, char *keyname);
+TOKEN_LIST *MsRegEnumKeyEx(UINT root, char *keyname, bool force32bit);
+TOKEN_LIST *MsRegEnumKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit);
+TOKEN_LIST *MsRegEnumValue(UINT root, char *keyname);
+TOKEN_LIST *MsRegEnumValueEx(UINT root, char *keyname, bool force32bit);
+TOKEN_LIST *MsRegEnumValueEx2(UINT root, char *keyname, bool force32bit, bool force64bit);
+
+bool MsRegDeleteKey(UINT root, char *keyname);
+bool MsRegDeleteKeyEx(UINT root, char *keyname, bool force32bit);
+bool MsRegDeleteKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit);
+bool MsRegDeleteValue(UINT root, char *keyname, char *valuename);
+bool MsRegDeleteValueEx(UINT root, char *keyname, char *valuename, bool force32bit);
+bool MsRegDeleteValueEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit);
+
+bool MsIsNt();
+bool MsIsAdmin();
+bool MsEnablePrivilege(char *name, bool enable);
+void *MsGetCurrentProcess();
+UINT MsGetCurrentProcessId();
+char *MsGetExeFileName();
+char *MsGetExeDirName();
+wchar_t *MsGetExeDirNameW();
+
+bool MsShutdown(bool reboot, bool force);
+bool MsShutdownEx(bool reboot, bool force, UINT time_limit, char *message);
+bool MsCheckLogon(wchar_t *username, char *password);
+bool MsIsPasswordEmpty(wchar_t *username);
+TOKEN_LIST *MsEnumNetworkAdapters(char *start_with_name, char *start_with_name_2);
+TOKEN_LIST *MsEnumNetworkAdaptersNeo();
+bool MsGetNeoDeiverFilename(char *name, UINT size, char *instance_name);
+bool MsMakeNewNeoDriverFilename(char *name, UINT size);
+void MsGenerateNeoDriverFilenameFromInt(char *name, UINT size, UINT n);
+TOKEN_LIST *MsEnumNeoDriverFilenames();
+char *MsGetNetworkAdapterGuid(char *tag_name, char *instance_name);
+wchar_t *MsGetNetworkConnectionName(char *guid);
+char *MsGetNetworkConfigRegKeyNameFromGuid(char *guid);
+char *MsGetNetworkConfigRegKeyNameFromInstanceName(char *tag_name, char *instance_name);
+void MsSetNetworkConfig(char *tag_name, char *instance_name, char *friendly_name, bool show_icon);
+void MsInitNetworkConfig(char *tag_name, char *instance_name, char *connection_tag_name);
+void MsNormalizeInterfaceDefaultGatewaySettings(char *tag_name, char *instance_name);
+
+char *MsGetSpecialDir(int id);
+wchar_t *MsGetSpecialDirW(int id);
+void MsGetSpecialDirs();
+bool MsCheckIsAdmin();
+void MsInitTempDir();
+void MsFreeTempDir();
+void MsGenLockFile(wchar_t *name, UINT size, wchar_t *temp_dir);
+void MsDeleteTempDir();
+void MsDeleteAllFile(char *dir);
+void MsDeleteAllFileW(wchar_t *dir);
+char *MsCreateTempFileName(char *name);
+char *MsCreateTempFileNameByExt(char *ext);
+IO *MsCreateTempFile(char *name);
+IO *MsCreateTempFileByExt(char *ext);
+
+bool MsInstallVLan(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver);
+bool MsInstallVLanWithoutLock(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver);
+bool MsInstallVLanInternal(wchar_t *infpath, wchar_t *hwid_w, char *hwid);
+bool MsUpgradeVLan(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver);
+bool MsUpgradeVLanWithoutLock(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver);
+bool MsEnableVLan(char *instance_name);
+bool MsEnableVLanWithoutLock(char *instance_name);
+bool MsDisableVLan(char *instance_name);
+bool MsDisableVLanWithoutLock(char *instance_name);
+bool MsUninstallVLan(char *instance_name);
+bool MsUninstallVLanWithoutLock(char *instance_name);
+bool MsIsVLanEnabled(char *instance_name);
+bool MsIsVLanEnabledWithoutLock(char *instance_name);
+bool MsIsValidVLanInstanceNameForInfCatalog(char *instance_name);
+void MsGetInfCatalogDir(char *dst, UINT size);
+void MsRestartVLan(char *instance_name);
+void MsRestartVLanWithoutLock(char *instance_name);
+bool MsIsVLanExists(char *tag_name, char *instance_name);
+void MsDeleteTroubleVLAN(char *tag_name, char *instance_name);
+bool MsStartDriverInstall(char *instance_name, UCHAR *mac_address, char *neo_sys, UCHAR *ret_mac_address, MS_DRIVER_VER *ver);
+void MsFinishDriverInstall(char *instance_name, char *neo_sys);
+void MsGetDriverPath(char *instance_name, wchar_t *src_inf, wchar_t *src_sys, wchar_t *dest_inf, wchar_t *dest_sys, wchar_t *src_cat, wchar_t *dest_cat, char *neo_sys);
+void MsGetDriverPathA(char *instance_name, char *src_inf, char *src_sys, char *dest_inf, char *dest_sys, char *src_cat, char *dst_cat, char *neo_sys);
+void MsGenMacAddress(UCHAR *mac);
+char *MsGetMacAddress(char *tag_name, char *instance_name);
+char *MsGetNetCfgRegKeyName(char *tag_name, char *instance_name);
+void MsSetMacAddress(char *tag_name, char *instance_name, char *mac_address);
+char *MsGetDriverVersion(char *tag_name, char *instance_name);
+char *MsGetDriverFileName(char *tag_name, char *instance_name);
+void MsTest();
+void MsInitGlobalNetworkConfig();
+void MsDisableNetworkOffloadingEtc();
+void MsSetThreadPriorityHigh();
+void MsSetThreadPriorityLow();
+void MsSetThreadPriorityIdle();
+void MsSetThreadPriorityRealtime();
+void MsRestoreThreadPriority();
+char *MsGetLocalAppDataDir();
+char *MsGetCommonAppDataDir();
+char *MsGetWindowsDir();
+char *MsGetSystem32Dir();
+char *MsGetTempDir();
+char *MsGetWindowsDrive();
+char *MsGetProgramFilesDir();
+char *MsGetProgramFilesDirX86();
+char *MsGetProgramFilesDirX64();
+char *MsGetCommonStartMenuDir();
+char *MsGetCommonProgramsDir();
+char *MsGetCommonStartupDir();
+char *MsGetCommonAppDataDir();
+char *MsGetCommonDesktopDir();
+char *MsGetPersonalStartMenuDir();
+char *MsGetPersonalProgramsDir();
+char *MsGetPersonalStartupDir();
+char *MsGetPersonalAppDataDir();
+char *MsGetPersonalDesktopDir();
+char *MsGetMyDocumentsDir();
+char *MsGetMyTempDir();
+char *MsGetUserName();
+char *MsGetUserNameEx();
+char *MsGetWinTempDir();
+wchar_t *MsGetWindowsDirW();
+wchar_t *MsGetExeFileNameW();
+wchar_t *MsGetExeFileDirW();
+wchar_t *MsGetWindowDirW();
+wchar_t *MsGetSystem32DirW();
+wchar_t *MsGetTempDirW();
+wchar_t *MsGetWindowsDriveW();
+wchar_t *MsGetProgramFilesDirW();
+wchar_t *MsGetProgramFilesDirX86W();
+wchar_t *MsGetProgramFilesDirX64W();
+wchar_t *MsGetCommonStartMenuDirW();
+wchar_t *MsGetCommonProgramsDirW();
+wchar_t *MsGetCommonStartupDirW();
+wchar_t *MsGetCommonAppDataDirW();
+wchar_t *MsGetCommonDesktopDirW();
+wchar_t *MsGetPersonalStartMenuDirW();
+wchar_t *MsGetPersonalProgramsDirW();
+wchar_t *MsGetPersonalStartupDirW();
+wchar_t *MsGetPersonalAppDataDirW();
+wchar_t *MsGetPersonalDesktopDirW();
+wchar_t *MsGetMyDocumentsDirW();
+wchar_t *MsGetLocalAppDataDirW();
+wchar_t *MsGetMyTempDirW();
+wchar_t *MsGetUserNameW();
+wchar_t *MsGetUserNameExW();
+wchar_t *MsGetWinTempDirW();
+struct SAFE_TABLE *MsGetSafeTable();
+UINT MsGetProcessId();
+void MsTerminateProcess();
+bool MsIsServiceInstalled(char *name);
+bool MsInstallService(char *name, char *title, wchar_t *description, char *path);
+bool MsInstallServiceExW(char *name, wchar_t *title, wchar_t *description, wchar_t *path, UINT *error_code);
+bool MsInstallServiceW(char *name, wchar_t *title, wchar_t *description, wchar_t *path);
+bool MsInstallDeviceDriverW(char *name, wchar_t *title, wchar_t *path, UINT *error_code);
+bool MsUpdateServiceConfig(char *name);
+bool MsSetServiceDescription(char *name, wchar_t *description);
+bool MsUninstallService(char *name);
+bool MsStartService(char *name);
+bool MsStartServiceEx(char *name, UINT *error_code);
+bool MsStopService(char *name);
+bool MsIsServiceRunning(char *name);
+bool MsIsTerminalServiceInstalled();
+bool MsIsUserSwitchingInstalled();
+bool MsIsTerminalServiceMultiUserInstalled();
+UINT MsGetCurrentTerminalSessionId();
+bool MsIsTerminalSessionActive(UINT session_id);
+bool MsIsCurrentTerminalSessionActive();
+bool MsIsCurrentDesktopAvailableForVnc();
+wchar_t *MsGetSessionUserName(UINT session_id);
+UINT MsService(char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon, char *cmd_line);
+void MsTestModeW(wchar_t *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop);
+void MsTestMode(char *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop);
+void MsServiceMode(SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop);
+void MsUserModeW(wchar_t *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon);
+void MsUserMode(char *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon);
+bool MsIsUserMode();
+void MsTestOnly();
+void MsStopUserModeFromService();
+char *MsGetPenCoreDllFileName();
+void MsPlaySound(char *name);
+void MsSetThreadSingleCpu();
+void MsWin9xTest();
+bool MsCheckVLanDeviceIdFromRootEnum(char *name);
+bool MsInstallVLan9x(char *instance_name, MS_DRIVER_VER *ver);
+void MsUpdateCompatibleIDs(char *instance_name);
+LIST *MsGetProcessList();
+LIST *MsGetProcessList9x();
+LIST *MsGetProcessListNt();
+void MsFreeProcessList(LIST *o);
+void MsPrintProcessList(LIST *o);
+int MsCompareProcessList(void *p1, void *p2);
+MS_PROCESS *MsSearchProcessById(LIST *o, UINT id);
+void MsGetCurrentProcessExeName(char *name, UINT size);
+void MsGetCurrentProcessExeNameW(wchar_t *name, UINT size);
+bool MsKillProcess(UINT id);
+UINT MsKillProcessByExeName(wchar_t *name);
+void MsKillOtherInstance();
+void MsKillOtherInstanceEx(char *exclude_svcname);
+bool MsGetShortPathNameA(char *long_path, char *short_path, UINT short_path_size);
+bool MsGetShortPathNameW(wchar_t *long_path, wchar_t *short_path, UINT short_path_size);
+void MsWriteCallingServiceManagerProcessId(char *svcname, UINT pid);
+UINT MsReadCallingServiceManagerProcessId(char *svcname, bool current_user);
+bool MsStopIPsecService();
+char *MsGetIPsecServiceName();
+bool MsStartIPsecService();
+
+void MsGenerateUserModeSvcGlobalPulseName(char *name, UINT size, char *svc_name);
+void *MsCreateUserModeSvcGlocalPulse(char *svc_name);
+void MsStopUserModeSvc(char *svc_name);
+void MsUserModeGlobalPulseRecvThread(THREAD *thread, void *param);
+
+MS_ADAPTER_LIST *MsCreateAdapterListInner();
+MS_ADAPTER_LIST *MsCreateAdapterListInnerEx(bool no_info);
+MS_ADAPTER_LIST *MsCreateAdapterListInnerExVista(bool no_info);
+void MsFreeAdapter(MS_ADAPTER *a);
+void MsFreeAdapterList(MS_ADAPTER_LIST *o);
+wchar_t *MsGetAdapterTypeStr(UINT type);
+wchar_t *MsGetAdapterStatusStr(UINT status);
+MS_ADAPTER *MsCloneAdapter(MS_ADAPTER *a);
+MS_ADAPTER_LIST *MsCloneAdapterList(MS_ADAPTER_LIST *o);
+void MsInitAdapterListModule();
+void MsFreeAdapterListModule();
+MS_ADAPTER_LIST *MsCreateAdapterList();
+MS_ADAPTER_LIST *MsCreateAdapterListEx(bool no_info);
+void MsGetAdapterTcpIpInformation(MS_ADAPTER *a);
+MS_ADAPTER *MsGetAdapter(char *title);
+MS_ADAPTER *MsGetAdapterByGuid(char *guid);
+MS_ADAPTER *MsGetAdapterByGuidFromList(MS_ADAPTER_LIST *o, char *guid);
+UINT ConvertMidStatusVistaToXp(UINT st);
+
+void *MsLoadLibrary(char *name);
+void *MsLoadLibraryW(wchar_t *name);
+void *MsLoadLibraryAsDataFile(char *name);
+void *MsLoadLibraryAsDataFileW(wchar_t *name);
+void *MsLoadLibraryRawW(wchar_t *name);
+void MsFreeLibrary(void *h);
+void *MsGetProcAddress(void *h, char *name);
+
+void MsPrintTick();
+bool MsDisableIme();
+
+void MsGetTcpConfig(MS_TCP *tcp);
+void MsSetTcpConfig(MS_TCP *tcp);
+void MsSaveTcpConfigReg(MS_TCP *tcp);
+bool MsLoadTcpConfigReg(MS_TCP *tcp);
+bool MsIsTcpConfigSupported();
+void MsApplyTcpConfig();
+bool MsIsShouldShowTcpConfigApp();
+void MsDeleteTcpConfigReg();
+
+UINT MsGetConsoleWidth();
+UINT MsSetConsoleWidth(UINT size);
+NO_WARNING *MsInitNoWarning();
+NO_WARNING *MsInitNoWarningEx(UINT start_timer);
+void MsFreeNoWarning(NO_WARNING *nw);
+void MsNoWarningThreadProc(THREAD *thread, void *param);
+char *MsNoWarningSoundInit();
+void MsNoWarningSoundFree(char *s);
+bool MsCloseWarningWindow(NO_WARNING *nw, UINT thread_id);
+LIST *MsEnumChildWindows(LIST *o, HWND hWnd);
+void MsAddWindowToList(LIST *o, HWND hWnd);
+UINT MsGetThreadLocale();
+LIST *NewWindowList();
+int CmpWindowList(void *p1, void *p2);
+void AddWindow(LIST *o, HWND hWnd);
+void FreeWindowList(LIST *o);
+LIST *EnumAllChildWindow(HWND hWnd);
+LIST *EnumAllChildWindowEx(HWND hWnd, bool no_recursion, bool include_ipcontrol, bool no_self);
+LIST *EnumAllWindow();
+LIST *EnumAllWindowEx(bool no_recursion, bool include_ipcontrol);
+LIST *EnumAllTopWindow();
+
+bool MsExecDriverInstaller(char *arg);
+bool MsIsVista();
+bool MsIsWin2000();
+bool MsIsWin2000OrGreater();
+bool MsIsWinXPOrGreater();
+void MsRegistWindowsFirewallEx(char *title, char *exe);
+void MsRegistWindowsFirewallEx2(char *title, char *exe, char *dir);
+bool MsIs64BitWindows();
+bool MsIsX64();
+bool MsIsIA64();
+void *MsDisableWow64FileSystemRedirection();
+void MsRestoreWow64FileSystemRedirection(void *p);
+void MsSetWow64FileSystemRedirectionEnable(bool enable);
+bool MsIsWindows8();
+bool MsIsWindows7();
+bool MsIsInfCatalogRequired();
+
+bool MsCheckFileDigitalSignature(HWND hWnd, char *name, bool *danger);
+bool MsCheckFileDigitalSignatureW(HWND hWnd, wchar_t *name, bool *danger);
+
+
+bool MsGetProcessExeName(char *path, UINT size, UINT id);
+bool MsGetProcessExeNameW(wchar_t *path, UINT size, UINT id);
+bool MsGetWindowOwnerProcessExeName(char *path, UINT size, HWND hWnd);
+bool MsGetWindowOwnerProcessExeNameW(wchar_t *path, UINT size, HWND hWnd);
+
+void *MsRunAsUserEx(char *filename, char *arg, bool hide);
+void *MsRunAsUserExW(wchar_t *filename, wchar_t *arg, bool hide);
+void *MsRunAsUserExInner(char *filename, char *arg, bool hide);
+void *MsRunAsUserExInnerW(wchar_t *filename, wchar_t *arg, bool hide);
+
+UINT MsGetCursorPosHash();
+bool MsIsProcessExists(char *exename);
+bool MsIsProcessExistsW(wchar_t *exename);
+
+void MsGetComputerName(char *name, UINT size);
+void MsGetComputerNameFull(wchar_t *name, UINT size);
+void MsGetComputerNameFullEx(wchar_t *name, UINT size, bool with_cache);
+void MsNoSleepThread(THREAD *thread, void *param);
+void MsNoSleepThreadVista(THREAD *thread, void *param);
+UINT64 MsGetScreenSaverTimeout();
+void *MsNoSleepStart(bool no_screensaver);
+void MsNoSleepEnd(void *p);
+bool MsIsRemoteDesktopAvailable();
+bool MsIsRemoteDesktopCanEnableByRegistory();
+bool MsIsRemoteDesktopEnabled();
+bool MsEnableRemoteDesktop();
+
+void MsSetFileToHidden(char *name);
+void MsSetFileToHiddenW(wchar_t *name);
+bool MsGetFileVersion(char *name, UINT *v1, UINT *v2, UINT *v3, UINT *v4);
+bool MsGetFileVersionW(wchar_t *name, UINT *v1, UINT *v2, UINT *v3, UINT *v4);
+
+bool MsExtractCabinetFileFromExe(char *exe, char *cab);
+bool MsExtractCabinetFileFromExeW(wchar_t *exe, wchar_t *cab);
+BUF *MsExtractResourceFromExe(char *exe, char *type, char *name);
+BUF *MsExtractResourceFromExeW(wchar_t *exe, char *type, char *name);
+bool MsExtractCab(char *cab_name, char *dest_dir_name);
+bool MsExtractCabW(wchar_t *cab_name, wchar_t *dest_dir_name);
+bool MsGetCabarcExeFilename(char *name, UINT size);
+bool MsGetCabarcExeFilenameW(wchar_t *name, UINT size);
+bool MsExtractCabFromMsi(char *msi, char *cab);
+bool MsExtractCabFromMsiW(wchar_t *msi, wchar_t *cab);
+bool MsIsDirectory(char *name);
+bool MsIsDirectoryW(wchar_t *name);
+bool MsUniIsDirectory(wchar_t *name);
+bool MsUniFileDelete(wchar_t *name);
+bool MsUniDirectoryDelete(wchar_t *name);
+bool MsUniMakeDir(wchar_t *name);
+void MsUniMakeDirEx(wchar_t *name);
+void MsMakeDirEx(char *name);
+bool MsMakeDir(char *name);
+bool MsDirectoryDelete(char *name);
+bool MsFileDelete(char *name);
+bool MsExecute(char *exe, char *arg);
+bool MsExecute2(char *exe, char *arg, bool runas);
+bool MsExecuteW(wchar_t *exe, wchar_t *arg);
+bool MsExecute2W(wchar_t *exe, wchar_t *arg, bool runas);
+bool MsExecuteEx(char *exe, char *arg, void **process_handle);
+bool MsExecuteEx2(char *exe, char *arg, void **process_handle, bool runas);
+bool MsExecuteExW(wchar_t *exe, wchar_t *arg, void **process_handle);
+bool MsExecuteEx2W(wchar_t *exe, wchar_t *arg, void **process_handle, bool runas);
+void MsCloseHandle(void *handle);
+UINT MsWaitProcessExit(void *process_handle);
+bool MsIsFileLocked(char *name);
+bool MsIsFileLockedW(wchar_t *name);
+bool MsIsLocalDrive(char *name);
+bool MsIsLocalDriveW(wchar_t *name);
+void MsUpdateSystem();
+bool MsGetPhysicalMacAddressFromNetbios(void *address);
+bool MsGetPhysicalMacAddressFromApi(void *address);
+bool MsGetPhysicalMacAddress(void *address);
+bool MsIsUseWelcomeLogin();
+UINT64 MsGetHiResCounter();
+double MsGetHiResTimeSpan(UINT64 diff);
+UINT64 MsGetHiResTimeSpanUSec(UINT64 diff);
+BUF *MsRegSubkeysToBuf(UINT root, char *keyname, bool force32bit, bool force64bit);
+void MsBufToRegSubkeys(UINT root, char *keyname, BUF *b, bool overwrite, bool force32bit, bool force64bit);
+void MsRegDeleteSubkeys(UINT root, char *keyname, bool force32bit, bool force64bit);
+void MsRestartMMCSS();
+bool MsIsMMCSSNetworkThrottlingEnabled();
+void MsSetMMCSSNetworkThrottlingEnable(bool enable);
+void MsSetShutdownParameters(UINT level, UINT flag);
+void MsChangeIconOnTrayEx2(void *icon, wchar_t *tooltip, wchar_t *info_title, wchar_t *info, UINT info_flags);
+bool MsIsTrayInited();
+UINT MsGetClipboardOwnerProcessId();
+void MsDeleteClipboard();
+void *MsInitEventLog(wchar_t *src_name);
+void MsFreeEventLog(void *p);
+bool MsWriteEventLog(void *p, UINT type, wchar_t *str);
+bool MsIsWinXPOrWinVista();
+bool MsGetFileInformation(void *h, void *info);
+void MsSetErrorModeToSilent();
+void MsSetEnableMinidump(bool enabled);
+void MsWriteMinidump(wchar_t *filename, void *ex);
+
+
+void *MsInitGlobalLock(char *name, bool ts_local);
+void MsGlobalLock(void *p);
+void MsGlobalUnlock(void *p);
+void MsFreeGlobalLock(void *p);
+
+void *MsOpenOrCreateGlobalPulse(char *name);
+bool MsWaitForGlobalPulse(void *p, UINT timeout);
+void MsCloseGlobalPulse(void *p);
+void MsSendGlobalPulse(void *p);
+
+bool MsPerformMsChapV2AuthByLsa(char *username, UCHAR *challenge8, UCHAR *client_response_24, UCHAR *ret_pw_hash_hash);
+
+void MsDisableWcmNetworkMinimize();
+bool MsSetFileSecureAcl(wchar_t *path);
+
+bool MsGetMsiInstalledDir(char *component_code, wchar_t *dir, UINT dir_size);
+bool MsMsiUninstall(char *product_code, HWND hWnd, bool *reboot_required);
+
+UINT MsGetUserLocaleId();
+UINT MsGetSystemLocaleId();
+bool MsIsCurrentUserLocaleIdJapanese();
+
+TOKEN_LIST *MsEnumResources(void *hModule, char *type);
+void *MsGetCurrentModuleHandle();
+
+bool MsIsAeroEnabled();
+bool MsIsAeroColor();
+
+bool MsIsInVmMain();
+bool MsIsInVm();
+
+void MsTest();
+
+bool MsSaveSystemInfo(wchar_t *dst_filename);
+bool MsCollectVpnInfo(BUF *bat, char *tmpdir, char *svc_name, wchar_t *config_name, wchar_t *logdir_name);
+
+// Inner functions
+#ifdef MICROSOFT_C
+
+LONG CALLBACK MsExceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo);
+HKEY MsGetRootKeyFromInt(UINT root);
+NT_API *MsLoadNtApiFunctions();
+void MsFreeNtApiFunctions(NT_API *nt);
+void MsDestroyDevInfo(HDEVINFO info);
+HDEVINFO MsGetDevInfoFromDeviceId(SP_DEVINFO_DATA *dev_info_data, char *device_id);
+bool MsStartDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data);
+bool MsStopDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data);
+bool MsDeleteDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data);
+bool MsIsDeviceRunning(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data);
+void CALLBACK MsServiceDispatcher(DWORD argc, LPTSTR *argv);
+void CALLBACK MsServiceHandler(DWORD opcode);
+bool MsServiceStopProc();
+void MsServiceStoperMainThread(THREAD *t, void *p);
+void MsServiceStarterMainThread(THREAD *t, void *p);
+LRESULT CALLBACK MsUserModeWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+bool MsShowIconOnTray(HWND hWnd, HICON icon, wchar_t *tooltip, UINT msg);
+void MsRestoreIconOnTray();
+void MsChangeIconOnTray(HICON icon, wchar_t *tooltip);
+bool MsChangeIconOnTrayEx(HICON icon, wchar_t *tooltip, wchar_t *info_title, wchar_t *info, UINT info_flags, bool add);
+void MsHideIconOnTray();
+void MsUserModeTrayMenu(HWND hWnd);
+bool MsAppendMenu(HMENU hMenu, UINT flags, UINT_PTR id, wchar_t *str);
+bool MsInsertMenu(HMENU hMenu, UINT pos, UINT flags, UINT_PTR id_new_item, wchar_t *lp_new_item);
+bool CALLBACK MsEnumChildWindowProc(HWND hWnd, LPARAM lParam);
+BOOL CALLBACK EnumTopWindowProc(HWND hWnd, LPARAM lParam);
+bool CALLBACK MsEnumThreadWindowProc(HWND hWnd, LPARAM lParam);
+HANDLE MsCreateUserToken();
+SID *MsGetSidFromAccountName(char *name);
+void MsFreeSid(SID *sid);
+bool CALLBACK MsEnumResourcesInternalProc(HMODULE hModule, const char *type, char *name, LONG_PTR lParam);
+
+void CALLBACK MsScmDispatcher(DWORD argc, LPTSTR *argv);
+
+
+#endif // MICROSOFT_C
+
+#endif // MICROSOFT_H
+
+#endif // OS_WIN32
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c
new file mode 100644
index 00000000..3025c5e3
--- /dev/null
+++ b/src/Mayaqua/Network.c
@@ -0,0 +1,21774 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Network.c
+// Network communication module
+
+#include <GlobalConst.h>
+
+#define ENCRYPT_C
+#define NETWORK_C
+
+#define __WINCRYPT_H__
+
+#ifdef WIN32
+// Include windows.h for Socket API
+#define _WIN32_WINNT 0x0502
+#define WINVER 0x0502
+#include <Ws2tcpip.h>
+#include <Wspiapi.h>
+#include <winsock2.h>
+#include <windows.h>
+#include <Iphlpapi.h>
+#include <ws2ipdef.h>
+#include <netioapi.h>
+#include <Icmpapi.h>
+#endif // WIN32
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/engine.h>
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs7.h>
+#include <openssl/pkcs12.h>
+#include <openssl/rc4.h>
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+#include <Mayaqua/Mayaqua.h>
+
+#ifdef OS_WIN32
+NETWORK_WIN32_FUNCTIONS *w32net;
+struct ROUTE_CHANGE_DATA
+{
+ OVERLAPPED Overlapped;
+ HANDLE Handle;
+ UINT NumCalled;
+};
+#endif // OS_WIN32
+
+// Whether the blocking occurs in SSL
+#if defined(UNIX_BSD)
+#define FIX_SSL_BLOCKING
+#endif
+
+// IPV6_V6ONLY constant
+#ifdef UNIX_LINUX
+#ifndef IPV6_V6ONLY
+#define IPV6_V6ONLY 26
+#endif // IPV6_V6ONLY
+#endif // UNIX_LINUX
+
+#ifdef UNIX_SOLARIS
+#ifndef IPV6_V6ONLY
+#define IPV6_V6ONLY 0x27
+#endif // IPV6_V6ONLY
+#endif // UNIX_SOLARIS
+
+
+
+// HTTP constant
+static char http_404_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>404 Not Found</TITLE>\r\n</HEAD><BODY>\r\n<H1>Not Found</H1>\r\nThe requested URL $TARGET$ was not found on this server.<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
+static char http_403_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>403 Forbidden</TITLE>\r\n</HEAD><BODY>\r\n<H1>Forbidden</H1>\r\nYou don't have permission to access $TARGET$\r\non this server.<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
+static char http_500_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>500 Server Error</TITLE>\r\n</HEAD><BODY>\r\n<H1>Server Error</H1>\r\nServer Error<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
+static char http_501_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>501 Method Not Implemented</TITLE>\r\n</HEAD><BODY>\r\n<H1>Method Not Implemented</H1>\r\n$METHOD$ to $TARGET$ not supported.<P>\r\nInvalid method in request $METHOD$ $TARGET$ $VERSION$<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
+static char http_detect_server_startwith[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>403 Forbidden</TITLE>\r\n</HEAD><BODY>\r\n<H1>Forbidden</H1>\r\nYou don't have permission to access ";
+static char http_detect_server_tag_future[] = "9C37197CA7C2428388C2E6E59B829B30";
+
+// DNS cache list
+static LIST *DnsCache;
+
+// Lock related
+static LOCK *machine_name_lock = NULL;
+static LOCK *disconnect_function_lock = NULL;
+static LOCK *aho = NULL;
+static LOCK *socket_library_lock = NULL;
+extern LOCK *openssl_lock;
+static LOCK *ssl_accept_lock = NULL;
+static LOCK *ssl_connect_lock = NULL;
+static TOKEN_LIST *cipher_list_token = NULL;
+static COUNTER *num_tcp_connections = NULL;
+static LOCK *dns_lock = NULL;
+static LOCK *unix_dns_server_addr_lock = NULL;
+static IP unix_dns_server;
+static LIST *HostCacheList = NULL;
+static LIST *WaitThreadList = NULL;
+static bool disable_cache = false;
+static bool NetworkReleaseMode = false; // Network release mode
+static UCHAR machine_ip_process_hash[SHA1_SIZE];
+static LOCK *machine_ip_process_hash_lock = NULL;
+static LOCK *current_global_ip_lock = NULL;
+static LOCK *current_fqdn_lock = NULL;
+static bool current_global_ip_set = false;
+static IP current_glocal_ipv4 = {0};
+static IP current_glocal_ipv6 = {0};
+static char current_fqdn[MAX_SIZE];
+static bool g_no_rudp_server = false;
+static bool g_no_rudp_register = false;
+static bool g_natt_low_priority = false;
+static LOCK *host_ip_address_list_cache_lock = NULL;
+static UINT64 host_ip_address_list_cache_last = 0;
+static LIST *host_ip_address_cache = NULL;
+
+
+static char *cipher_list = "RC4-MD5 RC4-SHA AES128-SHA AES256-SHA DES-CBC-SHA DES-CBC3-SHA";
+static LIST *ip_clients = NULL;
+
+static LIST *local_mac_list = NULL;
+static LOCK *local_mac_list_lock = NULL;
+
+static UINT rand_port_numbers[256] = {0};
+
+
+static bool g_use_privateip_file = false;
+
+typedef struct PRIVATE_IP_SUBNET
+{
+ UINT Ip, Mask, Ip2;
+} PRIVATE_IP_SUBNET;
+
+static LIST *g_private_ip_list = NULL;
+
+
+static LIST *g_dyn_value_list = NULL;
+
+
+//#define RUDP_DETAIL_LOG
+
+
+
+
+// Get a value from a dynamic value list (Returns a default value if the value is not found)
+UINT64 GetDynValueOrDefault(char *name, UINT64 default_value, UINT64 min_value, UINT64 max_value)
+{
+ UINT64 ret = GetDynValue(name);
+
+ if (ret == 0)
+ {
+ return default_value;
+ }
+
+ if (ret < min_value)
+ {
+ ret = min_value;
+ }
+
+ if (ret > max_value)
+ {
+ ret = max_value;
+ }
+
+ return ret;
+}
+
+// Get a value from a dynamic value list (Returns a default value if the value is not found)
+// The value is limited to 1/5 to 50 times of the default value for safety
+UINT64 GetDynValueOrDefaultSafe(char *name, UINT64 default_value)
+{
+ return GetDynValueOrDefault(name, default_value, default_value / (UINT64)5, default_value * (UINT64)50);
+}
+
+// Get a value from a dynamic value list
+UINT64 GetDynValue(char *name)
+{
+ UINT64 ret = 0;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return 0;
+ }
+
+ if (g_dyn_value_list == NULL)
+ {
+ return 0;
+ }
+
+ LockList(g_dyn_value_list);
+ {
+ UINT i;
+
+ for (i = 0; i < LIST_NUM(g_dyn_value_list);i++)
+ {
+ DYN_VALUE *vv = LIST_DATA(g_dyn_value_list, i);
+
+ if (StrCmpi(vv->Name, name) == 0)
+ {
+ ret = vv->Value;
+ break;
+ }
+ }
+ }
+ UnlockList(g_dyn_value_list);
+
+ return ret;
+}
+
+// Set the value to the dynamic value list
+void SetDynListValue(char *name, UINT64 value)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ if (g_dyn_value_list == NULL)
+ {
+ return;
+ }
+
+ LockList(g_dyn_value_list);
+ {
+ UINT i;
+ DYN_VALUE *v = NULL;
+
+ for (i = 0; i < LIST_NUM(g_dyn_value_list);i++)
+ {
+ DYN_VALUE *vv = LIST_DATA(g_dyn_value_list, i);
+
+ if (StrCmpi(vv->Name, name) == 0)
+ {
+ v = vv;
+ break;
+ }
+ }
+
+ if (v == NULL)
+ {
+ v = ZeroMalloc(sizeof(DYN_VALUE));
+ StrCpy(v->Name, sizeof(v->Name), name);
+
+ Add(g_dyn_value_list, v);
+ }
+
+ v->Value = value;
+ }
+ UnlockList(g_dyn_value_list);
+}
+
+// Apply by extracting dynamic value list from the specified PACK
+void ExtractAndApplyDynList(PACK *p)
+{
+ BUF *b;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ b = PackGetBuf(p, "DynList");
+ if (b == NULL)
+ {
+ return;
+ }
+
+ AddDynList(b);
+
+ FreeBuf(b);
+}
+
+// Insert the data to the dynamic value list
+void AddDynList(BUF *b)
+{
+ PACK *p;
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ SeekBufToBegin(b);
+
+ p = BufToPack(b);
+ if (p == NULL)
+ {
+ return;
+ }
+
+ t = GetPackElementNames(p);
+ if (t != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *name = t->Token[i];
+ UINT64 v = PackGetInt64(p, name);
+
+ SetDynListValue(name, v);
+ }
+
+ FreeToken(t);
+ }
+
+ FreePack(p);
+}
+
+// Initialization of the dynamic value list
+void InitDynList()
+{
+ g_dyn_value_list = NewList(NULL);
+}
+
+// Solution of dynamic value list
+void FreeDynList()
+{
+ UINT i;
+ if (g_dyn_value_list == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(g_dyn_value_list);i++)
+ {
+ DYN_VALUE *d = LIST_DATA(g_dyn_value_list, i);
+
+ Free(d);
+ }
+
+ ReleaseList(g_dyn_value_list);
+
+ g_dyn_value_list = NULL;
+}
+
+// Check whether the string in the string list appears in the specified string
+bool IsInStrByStrList(char *str, char *str_list)
+{
+ TOKEN_LIST *t;
+ bool ret = false;
+ // Validate arguments
+ if (str == NULL || str_list == NULL)
+ {
+ return false;
+ }
+
+ t = ParseTokenWithoutNullStr(str_list, ", \t\r\n");
+ if (t != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *s = t->Token[i];
+
+ if (StrLen(s) >= 1)
+ {
+ if (InStrEx(str, s, true))
+ {
+ ret = true;
+ break;
+ }
+ }
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+
+// Search whether the IP address exists on the IP address list string
+bool IsIpInStrList(IP *ip, char *ip_list)
+{
+ char ip_str[128];
+ TOKEN_LIST *t;
+ bool ret = false;
+ // Validate arguments
+ if (ip == NULL || ip_list == NULL)
+ {
+ return false;
+ }
+
+ Zero(ip_str, sizeof(ip_str));
+ IPToStr(ip_str, sizeof(ip_str), ip);
+
+ t = ParseTokenWithoutNullStr(ip_list, ", \t\r\n");
+
+ if (t != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *s = t->Token[i];
+
+ if (StrCmpi(s, ip_str) == 0)
+ {
+ ret = true;
+ break;
+ }
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+
+// Disable NAT-T function globally
+void DisableRDUPServerGlobally()
+{
+ g_no_rudp_server = true;
+}
+
+// Disable NAT-T registration globally
+void DisableRUDPRegisterGlobally()
+{
+ g_no_rudp_register = true;
+}
+
+// Lower the priority of the host at NAT-T
+void SetNatTLowPriority()
+{
+ g_natt_low_priority = true;
+}
+
+// Extract only the host name part from FQDN
+void GetSimpleHostname(char *hostname, UINT hostname_size, char *fqdn)
+{
+ UINT i;
+ ClearStr(hostname, hostname_size);
+ // Validate arguments
+ if (hostname == NULL || fqdn == NULL)
+ {
+ return;
+ }
+
+ StrCpy(hostname, hostname_size, fqdn);
+ Trim(hostname);
+
+ i = SearchStrEx(hostname, ".", 0, true);
+ if (i != INFINITE)
+ {
+ hostname[i] = 0;
+ }
+}
+
+// Get the current time zone
+int GetCurrentTimezone()
+{
+ int ret = 0;
+
+#ifdef OS_WIN32
+ ret = GetCurrentTimezoneWin32();
+#else // OS_WIN32
+ {
+#if defined(UNIX_MACOS) || defined(UNIX_BSD)
+ struct timeval tv;
+ struct timezone tz;
+
+ Zero(&tv, sizeof(tv));
+ Zero(&tz, sizeof(tz));
+
+ gettimeofday(&tv, &tz);
+
+ ret = tz.tz_minuteswest;
+
+#else // defined(UNIX_MACOS) || defined(UNIX_BSD)
+ tzset();
+
+ ret = timezone / 60;
+#endif // defined(UNIX_MACOS) || defined(UNIX_BSD)
+ }
+#endif // OS_WIN32
+
+ return ret;
+}
+
+// Flag of whether to use the DNS proxy
+bool IsUseDnsProxy()
+{
+ return false;
+}
+
+// Flag of whether to use an alternate host name
+bool IsUseAlternativeHostname()
+{
+ return IsUseDnsProxy();
+}
+
+#ifdef OS_WIN32
+// Get the current time zone (Win32)
+int GetCurrentTimezoneWin32()
+{
+ TIME_ZONE_INFORMATION info;
+ Zero(&info, sizeof(info));
+
+ if (GetTimeZoneInformation(&info) == TIME_ZONE_ID_INVALID)
+ {
+ return 0;
+ }
+
+ return info.Bias;
+}
+#endif // OS_WIN32
+
+
+// Set the current FQDN of the DDNS
+void SetCurrentDDnsFqdn(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ Lock(current_fqdn_lock);
+ {
+ StrCpy(current_fqdn, sizeof(current_fqdn), name);
+ }
+ Unlock(current_fqdn_lock);
+}
+
+// Get the current DDNS FQDN hash
+UINT GetCurrentDDnsFqdnHash()
+{
+ UINT ret;
+ UCHAR hash[SHA1_SIZE];
+ char name[MAX_SIZE];
+
+ ClearStr(name, sizeof(name));
+ GetCurrentDDnsFqdn(name, sizeof(name));
+
+ Trim(name);
+ StrUpper(name);
+
+ HashSha1(hash, name, StrLen(name));
+
+ Copy(&ret, hash, sizeof(UINT));
+
+ return ret;
+}
+
+// Get the current DDNS FQDN
+void GetCurrentDDnsFqdn(char *name, UINT size)
+{
+ ClearStr(name, size);
+ // Validate arguments
+ if (name == NULL || size == 0)
+ {
+ return;
+ }
+
+ Lock(current_fqdn_lock);
+ {
+ StrCpy(name, size, current_fqdn);
+ }
+ Unlock(current_fqdn_lock);
+
+ Trim(name);
+}
+
+// Check whether the specified MAC address exists on the local host (high speed)
+bool IsMacAddressLocalFast(void *addr)
+{
+ bool ret = false;
+ // Validate arguments
+ if (addr == NULL)
+ {
+ return false;
+ }
+
+ Lock(local_mac_list_lock);
+ {
+ if (local_mac_list == NULL)
+ {
+ // First enumeration
+ RefreshLocalMacAddressList();
+ }
+
+ ret = IsMacAddressLocalInner(local_mac_list, addr);
+ }
+ Unlock(local_mac_list_lock);
+
+ return ret;
+}
+
+// Update the local MAC address list
+void RefreshLocalMacAddressList()
+{
+ Lock(local_mac_list_lock);
+ {
+ if (local_mac_list != NULL)
+ {
+ FreeNicList(local_mac_list);
+ }
+
+ local_mac_list = GetNicList();
+ }
+ Unlock(local_mac_list_lock);
+}
+
+// Check whether the specified MAC address exists on the local host
+bool IsMacAddressLocal(void *addr)
+{
+ LIST *o;
+ bool ret;
+ // Validate arguments
+ if (addr == NULL)
+ {
+ return false;
+ }
+
+ o = GetNicList();
+
+ ret = IsMacAddressLocalInner(o, addr);
+
+ FreeNicList(o);
+
+ return ret;
+}
+bool IsMacAddressLocalInner(LIST *o, void *addr)
+{
+ bool ret = false;
+ UINT i;
+ // Validate arguments
+ if (o == NULL || addr == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ NIC_ENTRY *e = LIST_DATA(o, i);
+
+ if (Cmp(e->MacAddress, addr, 6) == 0)
+ {
+ ret = true;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+// Get a list of the NICs on the computer
+LIST *GetNicList()
+{
+ LIST *o = NULL;
+
+#ifdef OS_WIN32
+ o = Win32GetNicList();
+#endif // OS_WIN32
+
+#ifdef UNIX_LINUX
+#endif // UNIX_LINUX
+
+ if (o == NULL)
+ {
+ return NewListFast(NULL);
+ }
+
+ return o;
+}
+
+#ifdef OS_WIN32
+LIST *Win32GetNicList()
+{
+ UINT i;
+ LIST *o = NewListFast(NULL);
+ MS_ADAPTER_LIST *al = MsCreateAdapterList();
+
+ if (al == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < al->Num;i++)
+ {
+ MS_ADAPTER *a = al->Adapters[i];
+
+ if (a->Type == 6 && a->AddressSize == 6)
+ {
+ NIC_ENTRY *e = ZeroMalloc(sizeof(NIC_ENTRY));
+
+ StrCpy(e->IfName, sizeof(e->IfName), a->Title);
+ Copy(e->MacAddress, a->Address, 6);
+
+ Add(o, e);
+ }
+ }
+
+ MsFreeAdapterList(al);
+
+ return o;
+}
+#endif // OS_WIN32
+
+// Release the NIC list
+void FreeNicList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ NIC_ENTRY *e = LIST_DATA(o, i);
+
+ Free(e);
+ }
+
+ ReleaseList(o);
+}
+
+// If the computer is connected to the FLET'S line currently, detect the type of the line (obsolete)
+UINT DetectFletsType()
+{
+ UINT ret = 0;
+ //LIST *o = GetHostIPAddressList();
+// UINT i;
+
+/*
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *ip = LIST_DATA(o, i);
+
+ if (IsIP6(ip))
+ {
+ char ip_str[MAX_SIZE];
+
+ IPToStr(ip_str, sizeof(ip_str), ip);
+
+ if (IsInSameNetwork6ByStr(ip_str, "2001:c90::", "/32"))
+ {
+ // NTT East B-FLETs
+ ret |= FLETS_DETECT_TYPE_EAST_BFLETS_PRIVATE;
+ }
+
+ if (IsInSameNetwork6ByStr(ip_str, "2408:200::", "/23"))
+ {
+ // Wrapping in network of NTT East NGN
+ ret |= FLETS_DETECT_TYPE_EAST_NGN_PRIVATE;
+ }
+
+ if (IsInSameNetwork6ByStr(ip_str, "2001:a200::", "/23"))
+ {
+ // Wrapping in network of NTT West NGN
+ ret |= FLETS_DETECT_TYPE_WEST_NGN_PRIVATE;
+ }
+ }
+ }
+
+ FreeHostIPAddressList(o);
+*/
+ return ret;
+}
+
+// Query for the IP address using the DNS proxy for the B FLETs
+bool GetIPViaDnsProxyForJapanFlets(IP *ip_ret, char *hostname, bool ipv6, UINT timeout, bool *cancel, char *dns_proxy_hostname)
+{
+ SOCK *s;
+ char connect_hostname[MAX_SIZE];
+ char connect_hostname2[MAX_SIZE];
+ IP dns_proxy_ip;
+ bool ret = false;
+ bool dummy_flag = false;
+ char request_str[512];
+ // Validate arguments
+ if (ip_ret == NULL || hostname == NULL)
+ {
+ return false;
+ }
+ if (timeout == 0)
+ {
+ timeout = BFLETS_DNS_PROXY_TIMEOUT_FOR_QUERY;
+ }
+ if (cancel == NULL)
+ {
+ cancel = &dummy_flag;
+ }
+
+ // Get the IP address of the DNS proxy server
+ if (IsEmptyStr(dns_proxy_hostname))
+ {
+ // B FLETs
+ if (GetDnsProxyIPAddressForJapanBFlets(&dns_proxy_ip, BFLETS_DNS_PROXY_TIMEOUT_FOR_GET_F, cancel) == false)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // FLET'S NEXT
+ if (GetIP4Ex6Ex2(&dns_proxy_ip, dns_proxy_hostname, FLETS_NGN_DNS_QUERY_TIMEOUT, true, cancel, true) == false)
+ {
+ return false;
+ }
+ }
+
+ if (*cancel)
+ {
+ return false;
+ }
+
+ IPToStr(connect_hostname, sizeof(connect_hostname), &dns_proxy_ip);
+
+ /*{
+ StrCpy(connect_hostname, sizeof(connect_hostname), "2409:250:62c0:100:6a05:caff:fe09:5158");
+ }*/
+
+ StrCpy(connect_hostname2, sizeof(connect_hostname2), connect_hostname);
+ if (IsIP6(&dns_proxy_ip))
+ {
+ Format(connect_hostname2, sizeof(connect_hostname2), "[%s]", connect_hostname);
+ }
+
+ s = ConnectEx3(connect_hostname, BFLETS_DNS_PROXY_PORT, timeout, cancel, NULL, NULL, false, false, false);
+
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ if (*cancel)
+ {
+ Disconnect(s);
+ ReleaseSock(s);
+
+ return false;
+ }
+
+ SetTimeout(s, timeout);
+
+ // Start the SSL
+ if (StartSSLEx(s, NULL, NULL, true, 0, NULL) && (*cancel == false))
+ {
+ UCHAR hash[SHA1_SIZE];
+ BUF *hash2 = StrToBin(BFLETS_DNS_PROXY_CERT_HASH);
+
+ Zero(hash, sizeof(hash));
+ GetXDigest(s->RemoteX, hash, true);
+
+ if (Cmp(hash, hash2->Buf, SHA1_SIZE) == 0)
+ {
+ // Send the HTTP Request
+ Format(request_str, sizeof(request_str),
+ "GET " BFLETS_DNS_PROXY_PATH "?q=%s&ipv6=%u\r\n"
+ "\r\n",
+ hostname, ipv6, connect_hostname2);
+
+ if (SendAll(s, request_str, StrLen(request_str), true))
+ {
+ if (*cancel == false)
+ {
+ BUF *recv_buf = NewBuf();
+ UINT port_ret;
+
+ while (true)
+ {
+ UCHAR tmp[MAX_SIZE];
+ UINT r;
+
+ r = Recv(s, tmp, sizeof(tmp), true);
+
+ if (r == 0 || (recv_buf->Size > 65536))
+ {
+ break;
+ }
+ else
+ {
+ WriteBuf(recv_buf, tmp, r);
+ }
+ }
+
+ ret = RUDPParseIPAndPortStr(recv_buf->Buf, recv_buf->Size, ip_ret, &port_ret);
+
+ FreeBuf(recv_buf);
+ }
+ }
+ }
+
+ FreeBuf(hash2);
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ if (ret)
+ {
+ NewDnsCache(hostname, ip_ret);
+ }
+
+ return ret;
+}
+
+// Get the IP address of the available DNS proxy in B-FLET'S service that is provided by NTT East of Japan
+bool GetDnsProxyIPAddressForJapanBFlets(IP *ip_ret, UINT timeout, bool *cancel)
+{
+ BUF *b;
+ LIST *o;
+ bool ret = false;
+ // Validate arguments
+ if (ip_ret == NULL)
+ {
+ return false;
+ }
+ if (timeout == 0)
+ {
+ timeout = BFLETS_DNS_PROXY_TIMEOUT_FOR_GET_F;
+ }
+
+ b = QueryFileByUdpForJapanBFlets(timeout, cancel);
+
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ o = ReadIni(b);
+
+ if (o != NULL)
+ {
+ INI_ENTRY *e = GetIniEntry(o, "DDnsServerForBFlets");
+
+ if (e != NULL)
+ {
+ char *s = e->Value;
+
+ if (IsEmptyStr(s) == false)
+ {
+ IP ip;
+
+ if (StrToIP(&ip, s))
+ {
+ if (IsZeroIp(&ip) == false)
+ {
+ Copy(ip_ret, &ip, sizeof(IP));
+ ret = true;
+ }
+ }
+ }
+ }
+ }
+
+ FreeIni(o);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Get a valid F.txt file in B-FLET'S service that is provided by NTT East of Japan
+BUF *QueryFileByUdpForJapanBFlets(UINT timeout, bool *cancel)
+{
+ bool dummy_flag = false;
+ BUF *txt_buf = NULL;
+ BUF *ret = NULL;
+ LIST *ip_list = NULL;
+ UINT i;
+ // Validate arguments
+ if (cancel == NULL)
+ {
+ cancel = &dummy_flag;
+ }
+ if (timeout == 0)
+ {
+ timeout = BFLETS_DNS_PROXY_TIMEOUT_FOR_GET_F;
+ }
+
+ txt_buf = ReadDump(UDP_FILE_QUERY_BFLETS_TXT_FILENAME);
+ if (txt_buf == NULL)
+ {
+ return NULL;
+ }
+
+ ip_list = NewListFast(NULL);
+
+ while (true)
+ {
+ char *line = CfgReadNextLine(txt_buf);
+ if (line == NULL)
+ {
+ break;
+ }
+
+ Trim(line);
+
+ if (IsEmptyStr(line) == false && StartWith(line, "#") == false)
+ {
+ IP ip;
+
+ if (StrToIP6(&ip, line))
+ {
+ if (IsZeroIp(&ip) == false)
+ {
+ if (IsIPv6LocalNetworkAddress(&ip) == false)
+ {
+ Add(ip_list, Clone(&ip, sizeof(IP)));
+ }
+ }
+ }
+ }
+
+ Free(line);
+ }
+
+ FreeBuf(txt_buf);
+
+ ret = QueryFileByIPv6Udp(ip_list, timeout, cancel);
+
+ for (i = 0;i < LIST_NUM(ip_list);i++)
+ {
+ IP *ip = LIST_DATA(ip_list, i);
+
+ Free(ip);
+ }
+
+ ReleaseList(ip_list);
+
+ return ret;
+}
+
+// Request a file by UDP (send the requests to the multiple IP addresses at the same time)
+BUF *QueryFileByIPv6Udp(LIST *ip_list, UINT timeout, bool *cancel)
+{
+ bool dummy_flag = false;
+ UINT64 start_tick, giveup_tick;
+ UINT64 next_send_tick;
+ SOCK *s;
+ INTERRUPT_MANAGER *interrupt;
+ BUF *buf = NULL;
+ SOCK_EVENT *se;
+ UCHAR *tmp_buf;
+ UINT tmp_buf_size = 65535;
+ // Validate arguments
+ if (cancel == NULL)
+ {
+ cancel = &dummy_flag;
+ }
+ if (ip_list == NULL)
+ {
+ return NULL;
+ }
+
+ s = NewUDP6(0, NULL);
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ tmp_buf = Malloc(tmp_buf_size);
+
+ start_tick = Tick64();
+ giveup_tick = start_tick + (UINT64)timeout;
+ next_send_tick = 0;
+
+ interrupt = NewInterruptManager();
+
+ AddInterrupt(interrupt, giveup_tick);
+
+ se = NewSockEvent();
+ JoinSockToSockEvent(s, se);
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+
+ if (now >= giveup_tick)
+ {
+ // Time-out
+ break;
+ }
+
+ if (*cancel)
+ {
+ // User canceled
+ break;
+ }
+
+ // Receive
+ while (true)
+ {
+ IP src_ip;
+ UINT src_port;
+ UINT r;
+
+ r = RecvFrom(s, &src_ip, &src_port, tmp_buf, tmp_buf_size);
+
+ if (r == SOCK_LATER || r == 0)
+ {
+ break;
+ }
+
+ if (src_port == UDP_FILE_QUERY_DST_PORT)
+ {
+ if (r >= 40)
+ {
+ if (Cmp(tmp_buf, UDP_FILE_QUERY_MAGIC_NUMBER, StrLen(UDP_FILE_QUERY_MAGIC_NUMBER)) == 0)
+ {
+ // Successful reception
+ buf = NewBuf();
+ WriteBuf(buf, tmp_buf, r);
+ SeekBuf(buf, 0, 0);
+ break;
+ }
+ }
+ }
+ }
+
+ if (buf != NULL)
+ {
+ // Successful reception
+ break;
+ }
+
+ if (next_send_tick == 0 || (now >= next_send_tick))
+ {
+ // Transmission
+ UINT i;
+ for (i = 0;i < LIST_NUM(ip_list);i++)
+ {
+ IP *ip = LIST_DATA(ip_list, i);
+ UCHAR c = 'F';
+
+ SendTo(s, ip, UDP_FILE_QUERY_DST_PORT, &c, 1);
+ }
+
+ next_send_tick = now + (UINT64)UDP_FILE_QUERY_RETRY_INTERVAL;
+ AddInterrupt(interrupt, next_send_tick);
+ }
+
+ WaitSockEvent(se, GetNextIntervalForInterrupt(interrupt));
+ }
+
+ FreeInterruptManager(interrupt);
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ ReleaseSockEvent(se);
+
+ Free(tmp_buf);
+
+ return buf;
+}
+
+// Parse the user name of the NT
+void ParseNtUsername(char *src_username, char *dst_username, UINT dst_username_size, char *dst_domain, UINT dst_domain_size, bool do_not_parse_atmark)
+{
+ char tmp_username[MAX_SIZE];
+ char tmp_domain[MAX_SIZE];
+ TOKEN_LIST *t;
+
+ if (src_username != dst_username)
+ {
+ ClearStr(dst_username, dst_username_size);
+ }
+
+ ClearStr(dst_domain, dst_domain_size);
+ // Validate arguments
+ if (src_username == NULL || dst_username == NULL || dst_domain == NULL)
+ {
+ return;
+ }
+
+ StrCpy(tmp_username, sizeof(tmp_username), src_username);
+ ClearStr(tmp_domain, sizeof(tmp_domain));
+
+ // Analysis of username@domain.name format
+ if (do_not_parse_atmark == false)
+ {
+ t = ParseTokenWithNullStr(tmp_username, "@");
+ if (t->NumTokens >= 1)
+ {
+ StrCpy(tmp_username, sizeof(tmp_username), t->Token[0]);
+ }
+ if (t->NumTokens >= 2)
+ {
+ StrCpy(tmp_domain, sizeof(tmp_domain), t->Token[1]);
+ }
+ FreeToken(t);
+ }
+
+ // If the username part is in "domain\username" format, split it
+ t = ParseTokenWithNullStr(tmp_username, "\\");
+ if (t->NumTokens >= 2)
+ {
+ if (IsEmptyStr(tmp_domain))
+ {
+ StrCpy(tmp_domain, sizeof(tmp_domain), t->Token[0]);
+ }
+
+ StrCpy(tmp_username, sizeof(tmp_username), t->Token[1]);
+ }
+ FreeToken(t);
+
+ StrCpy(dst_username, dst_username_size, tmp_username);
+ StrCpy(dst_domain, dst_domain_size, tmp_domain);
+}
+
+// The calculation of the optimum MSS value for use in TCP/IP packet in the payload of bulk transfer in R-UDP session
+UINT RUDPCalcBestMssForBulk(RUDP_STACK *r, RUDP_SESSION *se)
+{
+ UINT ret;
+ // Validate arguments
+ if (r == NULL || se == NULL)
+ {
+ return 0;
+ }
+
+ ret = MTU_FOR_PPPOE;
+
+ // IPv4
+ if (IsIP6(&se->YourIp) == false)
+ {
+ ret -= 20;
+ }
+ else
+ {
+ ret -= 40;
+ }
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ // ICMP
+ ret -= 8;
+
+ ret -= SHA1_SIZE;
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ // UDP
+ ret -= 8;
+
+ // DNS
+ ret -= 42;
+ }
+
+ // IV
+ ret -= SHA1_SIZE;
+
+ // Sign
+ ret -= SHA1_SIZE;
+
+ // SEQ_NO
+ ret -= sizeof(UINT64);
+
+ // Padding Max
+ ret -= 31;
+
+ // Ethernet header (target packets of communication)
+ ret -= 14;
+
+ // IPv4 Header (target packet of communication)
+ ret -= 20;
+
+ // TCP header (target packet of communication)
+ ret -= 20;
+
+ // I don't know well, but subtract 24 bytes
+ ret -= 24;
+
+ return ret;
+}
+
+// Processing of the reply packet from the NAT-T server
+void RUDPProcess_NatT_Recv(RUDP_STACK *r, UDPPACKET *udp)
+{
+ BUF *b;
+ PACK *p;
+ // Validate arguments
+ if (r == NULL || udp == NULL)
+ {
+ return;
+ }
+
+ if (udp->Size >= 8)
+ {
+ char tmp[128];
+
+ Zero(tmp, sizeof(tmp));
+ Copy(tmp, udp->Data, MIN(udp->Size, sizeof(tmp) - 1));
+
+ if (StartWith(tmp, "IP="))
+ {
+ IP my_ip;
+ UINT my_port;
+
+ // There was a response to the packet to determine the NAT state
+ if (IsEmptyStr(r->NatT_Registered_IPAndPort) == false)
+ {
+ if (StrCmpi(r->NatT_Registered_IPAndPort, tmp) != 0)
+ {
+ // Redo getting the token and registration because the NAT state is changed
+ ClearStr(r->NatT_Registered_IPAndPort, sizeof(r->NatT_Registered_IPAndPort));
+
+ r->NatT_GetTokenNextTick = 0;
+ r->NatT_GetTokenFailNum = 0;
+ r->NatT_Token_Ok = false;
+ Zero(r->NatT_Token, sizeof(r->NatT_Token));
+
+ r->NatT_RegisterNextTick = 0;
+ r->NatT_RegisterFailNum = 0;
+ r->NatT_Register_Ok = false;
+ }
+ }
+
+ if (RUDPParseIPAndPortStr(udp->Data, udp->Size, &my_ip, &my_port))
+ {
+ if (r->NatTGlobalUdpPort != NULL)
+ {
+ *r->NatTGlobalUdpPort = my_port;
+ }
+ }
+
+ return;
+ }
+ }
+
+ // Interpret the UDP packet
+ b = NewBuf();
+ WriteBuf(b, udp->Data, udp->Size);
+ SeekBuf(b, 0, 0);
+
+ p = BufToPack(b);
+
+ if (p != NULL)
+ {
+ bool is_ok = PackGetBool(p, "ok");
+ UINT64 tran_id = PackGetInt64(p, "tran_id");
+
+ ExtractAndApplyDynList(p);
+
+ if (r->ServerMode)
+ {
+ if (PackCmpStr(p, "opcode", "get_token"))
+ {
+ // Get the Token
+ if (is_ok && (tran_id == r->NatT_TranId))
+ {
+ char tmp[MAX_SIZE];
+
+ if (PackGetStr(p, "token", tmp, sizeof(tmp)) && IsEmptyStr(tmp) == false)
+ {
+ char myip[MAX_SIZE];
+ // Acquisition success
+ StrCpy(r->NatT_Token, sizeof(r->NatT_Token), tmp);
+ r->NatT_Token_Ok = true;
+ r->NatT_GetTokenNextTick = r->Now + (UINT64)GenRandInterval(UDP_NAT_T_GET_TOKEN_INTERVAL_2_MIN, UDP_NAT_T_GET_TOKEN_INTERVAL_2_MAX);
+ r->NatT_GetTokenFailNum = 0;
+
+ // Since success to obtain the self global IPv4 address,
+ // re-obtain the destination NAT-T host from this IPv4 address
+ if (PackGetStr(p, "your_ip", myip, sizeof(myip)))
+ {
+ IP ip;
+ char new_hostname[MAX_SIZE];
+
+ StrToIP(&ip, myip);
+
+ SetCurrentGlobalIP(&ip, false);
+
+ RUDPGetRegisterHostNameByIP(new_hostname,
+ sizeof(new_hostname), &ip);
+
+ Lock(r->Lock);
+ {
+ if (StrCmpi(r->CurrentRegisterHostname, new_hostname) != 0)
+ {
+ // Change the host name
+ Debug("CurrentRegisterHostname Changed: New=%s\n", new_hostname);
+ StrCpy(r->CurrentRegisterHostname, sizeof(r->CurrentRegisterHostname), new_hostname);
+
+ Zero(&r->NatT_IP, sizeof(r->NatT_IP));
+ //Zero(&r->NatT_IP_Safe, sizeof(r->NatT_IP_Safe));
+
+ Set(r->HaltEvent);
+ }
+ }
+ Unlock(r->Lock);
+ }
+
+ AddInterrupt(r->Interrupt, r->NatT_GetTokenNextTick);
+ }
+ }
+ }
+ else if (PackCmpStr(p, "opcode", "nat_t_register"))
+ {
+ // NAT-T server registration result
+ if (is_ok && (tran_id == r->NatT_TranId))
+ {
+ UINT my_global_port;
+ // Successful registration
+ r->NatT_Register_Ok = true;
+ r->NatT_RegisterNextTick = r->Now + (UINT64)GenRandInterval(UDP_NAT_T_REGISTER_INTERVAL_MIN, UDP_NAT_T_REGISTER_INTERVAL_MAX);
+ r->NatT_RegisterFailNum = 0;
+
+ Debug("NAT-T Registered.\n");
+
+ // Save the IP address and port number at the time of registration
+ PackGetStr(p, "your_ip_and_port", r->NatT_Registered_IPAndPort, sizeof(r->NatT_Registered_IPAndPort));
+
+ // Global port of itself
+ my_global_port = PackGetInt(p, "your_port");
+
+ if (my_global_port != 0)
+ {
+ if (r->NatTGlobalUdpPort != NULL)
+ {
+ *r->NatTGlobalUdpPort = my_global_port;
+ }
+ }
+
+ AddInterrupt(r->Interrupt, r->NatT_RegisterNextTick);
+ }
+ }
+ else if (PackCmpStr(p, "opcode", "nat_t_connect_relay"))
+ {
+ // Connection request from the client via the NAT-T server
+ if (is_ok)
+ {
+ char client_ip_str[MAX_SIZE];
+ UINT client_port;
+ IP client_ip;
+
+ PackGetStr(p, "client_ip", client_ip_str, sizeof(client_ip_str));
+ client_port = PackGetInt(p, "client_port");
+ StrToIP(&client_ip, client_ip_str);
+
+ if (IsZeroIp(&client_ip) == false && client_port != 0)
+ {
+ UCHAR *rand_data;
+ UINT rand_size;
+
+ rand_size = Rand32() % 19;
+ rand_data = Malloc(rand_size);
+
+ Rand(rand_data, rand_size);
+
+ RUDPSendPacket(r, &client_ip, client_port, rand_data, rand_size, 0);
+
+ Free(rand_data);
+ }
+ }
+ }
+ }
+
+ FreePack(p);
+ }
+
+ FreeBuf(b);
+}
+
+// Process such as packet transmission for NAT-T server
+void RUDPDo_NatT_Interrupt(RUDP_STACK *r)
+{
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ if (r->ServerMode)
+ {
+ if (IsZeroIp(&r->NatT_IP_Safe) == false)
+ {
+ if (g_no_rudp_register == false)
+ {
+ if (r->NatT_GetTokenNextTick == 0 || r->Now >= r->NatT_GetTokenNextTick)
+ {
+ // Try to get a token from the NAT-T server periodically
+ PACK *p = NewPack();
+ BUF *b;
+
+ PackAddStr(p, "opcode", "get_token");
+ PackAddInt64(p, "tran_id", r->NatT_TranId);
+ PackAddInt(p, "nat_traversal_version", UDP_NAT_TRAVERSAL_VERSION);
+
+ b = PackToBuf(p);
+ FreePack(p);
+
+ RUDPSendPacket(r, &r->NatT_IP_Safe, UDP_NAT_T_PORT, b->Buf, b->Size, 0);
+
+ FreeBuf(b);
+
+ // Determine the next acquisition time
+ r->NatT_GetTokenFailNum++;
+ r->NatT_GetTokenNextTick = r->Now + (UINT64)(UDP_NAT_T_GET_TOKEN_INTERVAL_1 * (UINT64)MIN(r->NatT_GetTokenFailNum, UDP_NAT_T_GET_TOKEN_INTERVAL_FAIL_MAX));
+ AddInterrupt(r->Interrupt, r->NatT_GetTokenNextTick);
+ r->NatT_Token_Ok = false;
+ }
+ }
+
+ if (r->NatT_NextNatStatusCheckTick == 0 || r->Now >= r->NatT_NextNatStatusCheckTick)
+ {
+ UCHAR a = 'A';
+ UINT ddns_hash;
+ // Check of the NAT state
+ RUDPSendPacket(r, &r->NatT_IP_Safe, UDP_NAT_T_PORT, &a, 1, 0);
+
+ // Execution time of the next
+ r->NatT_NextNatStatusCheckTick = r->Now + (UINT64)GenRandInterval(UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MIN, UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MAX);
+ AddInterrupt(r->Interrupt, r->NatT_NextNatStatusCheckTick);
+
+ // Check whether the DDNS host name changing have not occurred
+ ddns_hash = GetCurrentDDnsFqdnHash();
+
+ if (r->LastDDnsFqdnHash != ddns_hash)
+ {
+ r->LastDDnsFqdnHash = ddns_hash;
+ // Do the Register immediately if there is a change in the DDNS host name
+ r->NatT_RegisterNextTick = 0;
+ }
+ }
+
+ if (r->NatT_Token_Ok && g_no_rudp_register == false)
+ {
+ if (r->NatT_RegisterNextTick == 0 || r->Now >= r->NatT_RegisterNextTick)
+ {
+ // Try to register itself periodically for NAT-T server
+ PACK *p = NewPack();
+ BUF *b;
+ char private_ip_str[MAX_SIZE];
+ char machine_key[MAX_SIZE];
+ char machine_name[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ char ddns_fqdn[MAX_SIZE];
+
+ Debug("NAT-T Registering...\n");
+
+ GetCurrentDDnsFqdn(ddns_fqdn, sizeof(ddns_fqdn));
+
+ PackAddStr(p, "opcode", "nat_t_register");
+ PackAddInt64(p, "tran_id", r->NatT_TranId);
+ PackAddStr(p, "token", r->NatT_Token);
+ PackAddStr(p, "svc_name", r->SvcName);
+ PackAddStr(p, "product_str", CEDAR_PRODUCT_STR);
+ PackAddInt(p, "nat_traversal_version", UDP_NAT_TRAVERSAL_VERSION);
+
+
+ if (g_natt_low_priority)
+ {
+ PackAddBool(p, "low_priority", g_natt_low_priority);
+ }
+
+ Zero(private_ip_str, sizeof(private_ip_str));
+ if (IsZeroIp(&r->My_Private_IP_Safe) == false)
+ {
+ IPToStr(private_ip_str, sizeof(private_ip_str), &r->My_Private_IP_Safe);
+ PackAddStr(p, "private_ip", private_ip_str);
+ }
+
+ PackAddInt(p, "private_port", r->UdpSock->LocalPort);
+
+ Zero(hash, sizeof(hash));
+ GetCurrentMachineIpProcessHash(hash);
+ BinToStr(machine_key, sizeof(machine_key), hash, sizeof(hash));
+ PackAddStr(p, "machine_key", machine_key);
+
+ Zero(machine_name, sizeof(machine_name));
+ GetMachineName(machine_name, sizeof(machine_name));
+ PackAddStr(p, "host_name", machine_name);
+ PackAddStr(p, "ddns_fqdn", ddns_fqdn);
+
+ b = PackToBuf(p);
+ FreePack(p);
+
+ RUDPSendPacket(r, &r->NatT_IP_Safe, UDP_NAT_T_PORT, b->Buf, b->Size, 0);
+ //RUDPSendPacket(r, &r->NatT_IP_Safe, UDP_NAT_T_PORT, "a", 1);
+
+ FreeBuf(b);
+
+ // Determine the next acquisition time
+ r->NatT_RegisterFailNum++;
+ r->NatT_RegisterNextTick = r->Now + (UINT64)UDP_NAT_T_REGISTER_INTERVAL_INITIAL * (UINT64)MIN(r->NatT_RegisterFailNum, UDP_NAT_T_REGISTER_INTERVAL_FAIL_MAX);
+ AddInterrupt(r->Interrupt, r->NatT_RegisterNextTick);
+ r->NatT_Register_Ok = false;
+ }
+ }
+ }
+ }
+}
+
+// R-UDP packet reception procedure
+void RUDPRecvProc(RUDP_STACK *r, UDPPACKET *p)
+{
+ RUDP_SESSION *se = NULL;
+ // Validate arguments
+ if (r == NULL || p == NULL)
+ {
+ return;
+ }
+
+ if (r->ServerMode && r->NoNatTRegister == false)
+ {
+ if (p->SrcPort == UDP_NAT_T_PORT && CmpIpAddr(&p->SrcIP, &r->NatT_IP_Safe) == 0)
+ {
+ // There was a response from the NAT-T server
+ RUDPProcess_NatT_Recv(r, p);
+ return;
+ }
+ }
+
+ if (r->ServerMode)
+ {
+ if (r->ProcRpcRecv != NULL)
+ {
+ if (r->ProcRpcRecv(r, p))
+ {
+ return;
+ }
+ }
+ }
+
+ if (r->ServerMode)
+ {
+ // Search the session by the end-point information if in the server mode
+ se = RUDPSearchSession(r, &p->DstIP, p->DestPort, &p->SrcIP, p->SrcPort);
+ }
+ else
+ {
+ // Session should exist only one in the case of client mode
+ if (LIST_NUM(r->SessionList) >= 1)
+ {
+ se = LIST_DATA(r->SessionList, 0);
+ }
+ else
+ {
+ se = NULL;
+ }
+ }
+
+ if (p->Size < 20)
+ {
+ // The received packet is too small
+ if (r->ServerMode == false)
+ {
+ if (se != NULL && se->Status == RUDP_SESSION_STATUS_CONNECT_SENT)
+ {
+ if (CmpIpAddr(&se->YourIp, &p->SrcIP) == 0)
+ {
+ // If the connection initialization packet which is shorter than 20 bytes
+ // has been received from the server side, overwrite the source port number
+ // of the packet to the client-side session information (for some NAT)
+ se->YourPort = p->SrcPort;
+ }
+ }
+ }
+ return;
+ }
+
+ if (se == NULL && r->ServerMode && p->Size >= 40)
+ {
+ // Corresponding to a sudden change of port number on the client side.
+ // The target session is a session which matches the client side IP address
+ // and the key and the signature is verified
+ UINT i;
+ for (i = 0; i < LIST_NUM(r->SessionList);i++)
+ {
+ RUDP_SESSION *s = LIST_DATA(r->SessionList, i);
+
+ if (CmpIpAddr(&s->YourIp, &p->SrcIP) == 0)
+ {
+ if (RUDPCheckSignOfRecvPacket(r, s, p->Data, p->Size))
+ {
+ // Signature matched
+ se = s;
+ break;
+ }
+ }
+ }
+ }
+
+ if (se == NULL)
+ {
+ // There is no session
+ if (r->ServerMode)
+ {
+ if (p->Size < 40)
+ {
+ bool ok = true;
+ UCHAR ctoken_hash[SHA1_SIZE];
+
+ Zero(ctoken_hash, sizeof(ctoken_hash));
+
+ // Examine the quota of new session creation
+ if (LIST_NUM(r->SessionList) >= RUDP_QUOTA_MAX_NUM_SESSIONS)
+ {
+ // Entire number of sessions exceeds the limit
+ ok = false;
+ }
+ else
+ {
+ UINT i;
+ // Check the number of sessions per IP address
+ UINT num = 0;
+
+ for (i = 0;i < LIST_NUM(r->SessionList);i++)
+ {
+ RUDP_SESSION *se = LIST_DATA(r->SessionList, i);
+
+ if (CmpIpAddr(&se->YourIp, &p->SrcIP) == 0)
+ {
+ num++;
+ }
+ }
+
+ if (num >= RUDP_QUOTA_MAX_NUM_SESSIONS_PER_IP)
+ {
+ // Limit exceeded the number of sessions per IP address
+ ok = false;
+ }
+ }
+
+
+ if (ok)
+ {
+ char ip_str[64];
+
+ // Create a session since a new session creation request packet was received
+ se = RUDPNewSession(true, &p->DstIP, p->DestPort, &p->SrcIP, p->SrcPort, p->Data);
+ se->Status = RUDP_SESSION_STATUS_ESTABLISHED;
+ Insert(r->SessionList, se);
+
+ IPToStr(ip_str, sizeof(ip_str), &p->SrcIP);
+ Debug("RUDPNewSession %X %s:%u\n", se, ip_str, p->SrcPort);
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ // In case of ICMP, save the ICMP TYPE number to use
+ se->Icmp_Type = (p->Type == ICMP_TYPE_INFORMATION_REQUEST ? ICMP_TYPE_INFORMATION_REPLY : p->Type);
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ // Save the Tran ID to be used if it's a DNS
+ se->Dns_TranId = (USHORT)p->Type;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (p->Size < 40)
+ {
+ if (r->ServerMode)
+ {
+ if (Cmp(se->Key_Init, p->Data, SHA1_SIZE) == 0)
+ {
+ // New session creation request packet have received more than once. reply an ACK immediately for second and subsequent
+ se->LastSentTick = 0;
+
+ // Update the endpoint information
+ Copy(&se->YourIp, &p->SrcIP, sizeof(IP));
+ se->YourPort = p->SrcPort;
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ // In case of ICMP, save the ICMP TYPE number to use
+ se->Icmp_Type = (p->Type == ICMP_TYPE_INFORMATION_REQUEST ? ICMP_TYPE_INFORMATION_REPLY : p->Type);
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ // Save the Tran ID to be used if it's a DNS
+ se->Dns_TranId = (USHORT)p->Type;
+ }
+ }
+ else
+ {
+ // Since the different session creation request packet have been received from the same end point, ignore it
+ }
+ }
+ }
+ else
+ {
+ // Process the received packet
+ if (RUDPProcessRecvPacket(r, se, p->Data, p->Size) || RUDPProcessBulkRecvPacket(r, se, p->Data, p->Size))
+ {
+ // Update endpoint information (only the port number)
+ //Copy(&se->YourIp, &p->SrcIP, sizeof(IP));
+ se->YourPort = p->SrcPort;
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ // In case of ICMP, save the ICMP TYPE number to use
+ if (r->ServerMode)
+ {
+ se->Icmp_Type = (p->Type == ICMP_TYPE_INFORMATION_REQUEST ? ICMP_TYPE_INFORMATION_REPLY : p->Type);
+ }
+ else
+ {
+ se->Icmp_Type = (p->Type == ICMP_TYPE_INFORMATION_REPLY ? ICMP_TYPE_INFORMATION_REQUEST : p->Type);
+ }
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ if (r->ServerMode)
+ {
+ // Save the Tran ID to be used if it's a DNS
+ se->Dns_TranId = (USHORT)p->Type;
+ }
+ }
+ }
+ }
+ }
+}
+
+// R-UDP interrupt processing procedure
+void RUDPInterruptProc(RUDP_STACK *r)
+{
+ UINT i;
+ LIST *o;
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ // Packet transmission and other process for NAT-T server
+ if (r->NoNatTRegister == false)
+ {
+ RUDPDo_NatT_Interrupt(r);
+ }
+
+ if (r->ServerMode == false)
+ {
+ if (r->ClientInitiated == false)
+ {
+ bool client_target_inited = false;
+ Lock(r->Lock);
+ {
+ client_target_inited = r->TargetIpAndPortInited;
+ }
+ Unlock(r->Lock);
+
+ if (client_target_inited)
+ {
+ // Start a connection when there is the end point information of the destination server to connect as a client
+ RUDP_SESSION *se;
+ UCHAR init_key[SHA1_SIZE];
+ char ip_str[128];
+ UINT64 ui;
+
+ Rand(init_key, SHA1_SIZE);
+
+ se = RUDPNewSession(false, &r->UdpSock->LocalIP, r->UdpSock->LocalPort,
+ &r->TargetIp, r->TargetPort, init_key);
+
+ IPToStr(ip_str, sizeof(ip_str), &r->TargetIp);
+ Debug("RUDPNewSession %X %s:%u\n", se, ip_str, r->TargetPort);
+
+ Insert(r->SessionList, se);
+
+ ui = Endian64(se->Magic_Disconnect);
+ WriteFifo(se->SendFifo, &ui, sizeof(UINT64));
+
+ r->ClientInitiated = true;
+ }
+ }
+ }
+
+ // Process for all the sessions
+ for (i = 0;i < LIST_NUM(r->SessionList);i++)
+ {
+ RUDP_SESSION *se = LIST_DATA(r->SessionList, i);
+
+ if (r->Halt)
+ {
+ // Disconnect all the sessions if the R-UDP stack stopped
+ RUDPDisconnectSession(r, se, false);
+ }
+
+ if (se->FlushBulkSendTube)
+ {
+ if (se->TcpSock != NULL && se->TcpSock->BulkSendTube != NULL)
+ {
+ TubeFlush(se->TcpSock->BulkSendTube);
+ }
+
+ se->FlushBulkSendTube = false;
+ }
+
+ if (se->Status == RUDP_SESSION_STATUS_ESTABLISHED)
+ {
+ // Process for all of the sessions which is established a connection
+ UINT j;
+
+ if (r->Now >= (se->LatestRecvMyTick + (UINT64)RUDP_TIMEOUT))
+ {
+ // Disconnect the session because the fully communication failure is detected for a while
+ Debug("R-UDP Session %X Timed Out.\n", se);
+
+ RUDPDisconnectSession(r, se, false);
+ }
+
+ // If there are received segments, read to the part that has arrived in succession
+ if (FifoSize(se->RecvFifo) <= RUDP_MAX_FIFO_SIZE)
+ {
+ LIST *o;
+ UINT64 current_seq_no;
+
+ o = NULL;
+ current_seq_no = se->LastRecvCompleteSeqNo;
+ for (j = 0;j < LIST_NUM(se->RecvSegmentList);j++)
+ {
+ RUDP_SEGMENT *s;
+
+ current_seq_no++;
+
+ s = LIST_DATA(se->RecvSegmentList, j);
+
+ if (s->SeqNo == current_seq_no)
+ {
+#ifdef RUDP_DETAIL_LOG
+ Debug("%X s->SeqNo = %I64u, current_seq_no = %I64u\n", se, s->SeqNo, current_seq_no);
+#endif // RUDP_DETAIL_LOG
+
+ if (s->Size == sizeof(se->Magic_KeepAliveRequest) && Cmp(s->Data, se->Magic_KeepAliveRequest, sizeof(se->Magic_KeepAliveRequest)) == 0)
+ {
+ // Receive the KeepAlive Request
+#ifdef RUDP_DETAIL_LOG
+ Debug("Recv KeepAlive Request\n");
+#endif // RUDP_DETAIL_LOG
+
+ // Send a KeepAlive Response if the transmisson queue is empty
+ if (LIST_NUM(se->SendSegmentList) == 0)
+ {
+#ifdef RUDP_DETAIL_LOG
+ Debug("Send KeepAlive Response\n");
+#endif // RUDP_DETAIL_LOG
+
+ RUDPSendSegment(r, se, se->Magic_KeepAliveResponse, sizeof(se->Magic_KeepAliveResponse));
+ }
+ }
+ else if (s->Size == sizeof(se->Magic_KeepAliveResponse) && Cmp(s->Data, se->Magic_KeepAliveResponse, sizeof(se->Magic_KeepAliveResponse)) == 0)
+ {
+ // Receive the KeepAlive Response
+#ifdef RUDP_DETAIL_LOG
+ Debug("Recv KeepAlive Response\n");
+#endif // RUDP_DETAIL_LOG
+ }
+ else
+ {
+ // Write to the receive FIFO
+ WriteFifo(se->RecvFifo, s->Data, s->Size);
+ }
+ r->TotalLogicalReceived += s->Size;
+
+ // Advance the SEQ NO which has been received completely
+ se->LastRecvCompleteSeqNo = s->SeqNo;
+
+ // Add to the Delete list
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+ Add(o, s);
+ }
+ else
+ {
+ // Continuous reading is interrupted
+#ifdef RUDP_DETAIL_LOG
+ Debug("%X s->SeqNo = %I64u, current_seq_no = %I64u\n", se, s->SeqNo, current_seq_no);
+ WHERE;
+#endif // RUDP_DETAIL_LOG
+ break;
+ }
+ }
+
+ // Delete the segment which has been received completely
+ if (o != NULL)
+ {
+ for (j = 0;j < LIST_NUM(o);j++)
+ {
+ RUDP_SEGMENT *s = LIST_DATA(o, j);
+
+ Delete(se->RecvSegmentList, s);
+ Free(s);
+ }
+ ReleaseList(o);
+ }
+ }
+
+ if (r->ServerMode && se->Magic_Disconnect == 0)
+ {
+ if (FifoSize(se->RecvFifo) >= sizeof(UINT64))
+ {
+ UINT64 ui;
+
+ if (ReadFifo(se->RecvFifo, &ui, sizeof(UINT64)) == sizeof(UINT64))
+ {
+ ui = Endian64(ui);
+
+ if ((ui & 0xffffffff00000000ULL) != 0ULL)
+ {
+ se->Magic_Disconnect = ui;
+ }
+ }
+ }
+ }
+
+ // If the data remains in FIFO, write it to the TCP socket as possible
+ if (r->ServerMode == false || se->Magic_Disconnect != 0)
+ {
+ while (FifoSize(se->RecvFifo) >= 1)
+ {
+ UINT ret;
+
+ RUDPInitSock(r, se);
+
+ ret = Send(se->TcpSock, FifoPtr(se->RecvFifo), FifoSize(se->RecvFifo), false);
+
+ if (ret == SOCK_LATER)
+ {
+ // Can not write any more
+ break;
+ }
+ else if (ret == 0)
+ {
+ // Disconnected
+ Disconnect(se->TcpSock);
+ RUDPDisconnectSession(r, se, false);
+ break;
+ }
+ else
+ {
+ // Writing success
+ ReadFifo(se->RecvFifo, NULL, ret);
+ }
+ }
+ }
+
+ // Read the data as much as possible from the TCP socket and store it to FIFO
+ if (se->TcpSock != NULL)
+ {
+ SetNoNeedToRead(se->TcpSock);
+
+ while (FifoSize(se->SendFifo) <= RUDP_MAX_FIFO_SIZE)
+ {
+ UINT ret = Recv(se->TcpSock, r->TmpBuf, sizeof(r->TmpBuf), false);
+
+ if (ret == SOCK_LATER)
+ {
+ // Can not read any more
+ break;
+ }
+ else if (ret == 0)
+ {
+ // Disconnected
+ Disconnect(se->TcpSock);
+ RUDPDisconnectSession(r, se, false);
+ break;
+ }
+ else
+ {
+ // Reading success
+ WriteFifo(se->SendFifo, r->TmpBuf, ret);
+ }
+ }
+ }
+
+ // Attempt to send a divided segment
+ while (true)
+ {
+ UINT64 seq_no_min, seq_no_max;
+
+ seq_no_min = RUDPGetCurrentSendingMinSeqNo(se);
+ seq_no_max = RUDPGetCurrentSendingMaxSeqNo(se);
+
+#ifdef RUDP_DETAIL_LOG
+ Debug("min=%I64u max=%I64u\n", seq_no_min, seq_no_max);
+#endif // RUDP_DETAIL_LOG
+
+ if (seq_no_min == 0 || ((seq_no_min + RUDP_MAX_NUM_ACK - 1) >= se->NextSendSeqNo))
+ {
+ // Because there is a room to send a new segment, send a segment
+ UINT size = MIN(FifoSize(se->SendFifo), RUDP_MAX_SEGMENT_SIZE);
+
+ if (size == 0)
+ {
+ // There is no more data to send in FIFO
+ break;
+ }
+
+ // Transmission
+ RUDPSendSegment(r, se, FifoPtr(se->SendFifo), size);
+
+ r->TotalLogicalSent += size;
+
+ // Advance the FIFO
+ ReadFifo(se->SendFifo, NULL, size);
+ }
+ else
+ {
+ // There is no room to send a new segment further
+ break;
+ }
+ }
+
+ if (se->DisconnectFlag == false)
+ {
+ UINT64 seq_no_min;
+
+ if (se->LastSentTick == 0 || (r->Now >= (se->LastSentTick + (UINT64)se->NextKeepAliveInterval)))
+ {
+ if (LIST_NUM(se->SendSegmentList) == 0)
+ {
+ // Send a Keep-Alive if no data was sent for a while and the transmission queue is empty
+ RUDPSendSegment(r, se, se->Magic_KeepAliveRequest, sizeof(se->Magic_KeepAliveRequest));
+
+#ifdef RUDP_DETAIL_LOG
+ Debug("Sent KeepAlive Request\n");
+#endif // RUDP_DETAIL_LOG
+ }
+
+ se->NextKeepAliveInterval = RUDP_KEEPALIVE_INTERVAL_MIN + (Rand32() % (RUDP_KEEPALIVE_INTERVAL_MAX - RUDP_KEEPALIVE_INTERVAL_MIN));
+
+ AddInterrupt(r->Interrupt, r->Now + se->NextKeepAliveInterval);
+ }
+
+ seq_no_min = RUDPGetCurrentSendingMinSeqNo(se);
+ for (j = 0;j < LIST_NUM(se->SendSegmentList);j++)
+ {
+ RUDP_SEGMENT *s = LIST_DATA(se->SendSegmentList, j);
+
+ if (s->SeqNo <= (seq_no_min + RUDP_MAX_NUM_ACK - 1))
+ {
+ if (s->NextSendTick == 0 || r->Now >= s->NextSendTick)
+ {
+ UINT next_interval;
+ // Transmits a segment which has not been sent even once yet, or whose retransmission time has arrived
+ RUDPSendSegmentNow(r, se, s->SeqNo, s->Data, s->Size);
+
+ if (se->CurrentRtt != 0)
+ {
+ next_interval = (se->CurrentRtt * 120 / 100) * Power(2, MIN(s->NumSent, 10));
+ }
+ else
+ {
+ next_interval = RUDP_RESEND_TIMER * Power(2, MIN(s->NumSent, 10));
+ }
+
+ next_interval = MIN(next_interval, RUDP_RESEND_TIMER_MAX);
+
+ s->NumSent++;
+
+ s->NextSendTick = r->Now + next_interval;
+
+ AddInterrupt(r->Interrupt, s->NextSendTick);
+ }
+ }
+ }
+
+ while (LIST_NUM(se->ReplyAckList) >= 1)
+ {
+ // If there are ACKs which is not responded yet in the list, send all of them
+ RUDPSendSegmentNow(r, se, se->NextSendSeqNo, NULL, 0);
+ }
+
+ // Send all if there are bulk transfer data
+ if (se->TcpSock != NULL)
+ {
+ SOCK *s = se->TcpSock;
+
+ if (s->BulkRecvTube != NULL)
+ {
+ TUBE *t = s->BulkRecvTube;
+
+ while (true)
+ {
+ TUBEDATA *d = TubeRecvAsync(t);
+
+ if (d == NULL)
+ {
+ break;
+ }
+
+ if (d->Header != NULL && d->HeaderSize == sizeof(TCP_PAIR_HEADER))
+ {
+ TCP_PAIR_HEADER *h = d->Header;
+
+ if (h->EnableHMac)
+ {
+ se->UseHMac = true;
+ }
+ }
+
+ RUDPBulkSend(r, se, d->Data, d->DataSize);
+
+ FreeTubeData(d);
+ }
+ }
+ }
+ }
+ }
+
+ if (r->ServerMode == false)
+ {
+ if (se->Status == RUDP_SESSION_STATUS_CONNECT_SENT)
+ {
+ // Send a connection request periodically from the client side
+ if (se->LastSentTick == 0 || ((se->LastSentTick + (UINT64)RUDP_RESEND_TIMER) <= r->Now))
+ {
+ UCHAR tmp[40];
+ UINT size_of_padding = 19;
+ UINT size = size_of_padding + SHA1_SIZE;
+
+ se->LastSentTick = r->Now;
+
+ Copy(tmp, se->Key_Init, SHA1_SIZE);
+ Rand(tmp + SHA1_SIZE, size_of_padding);
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ // ICMP packet
+ UCHAR *rand_data;
+ UINT rand_size;
+
+ rand_size = Rand32() % 64 + 64;
+ rand_data = Malloc(rand_size);
+ Rand(rand_data, rand_size);
+
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, rand_data, rand_size, ICMP_TYPE_ECHO_REQUEST);
+ Free(rand_data);
+
+ se->Client_Icmp_NextSendEchoRequest = r->Now + GenRandInterval(RUDP_CLIENT_ECHO_REQUEST_SEND_INTERVAL_MIN, RUDP_CLIENT_ECHO_REQUEST_SEND_INTERVAL_MAX);
+ AddInterrupt(r->Interrupt, se->Client_Icmp_NextSendEchoRequest);
+
+ // Try in both INFORMATION_REQUEST and ECHO_RESPONSE from the client side first
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, tmp, size, ICMP_TYPE_ECHO_RESPONSE);
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, tmp, size, ICMP_TYPE_INFORMATION_REQUEST);
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ // DNS
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, tmp, size, se->Dns_TranId);
+ }
+ else
+ {
+ // Normal UDP
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, tmp, size, 0);
+ }
+
+ AddInterrupt(r->Interrupt, r->Now + (UINT64)RUDP_RESEND_TIMER);
+ }
+ }
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ if (se->Client_Icmp_NextSendEchoRequest == 0 || (r->Now >= se->Client_Icmp_NextSendEchoRequest))
+ {
+ // Periodic ICMP Echo transmission from the client side when R-UDP used in ICMP mode
+ // (To maintain the mapping table of the NAT)
+ UCHAR *rand_data;
+ UINT rand_size;
+
+ rand_size = Rand32() % 64 + 64;
+ rand_data = Malloc(rand_size);
+ Rand(rand_data, rand_size);
+
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, rand_data, rand_size, ICMP_TYPE_ECHO_REQUEST);
+ Free(rand_data);
+
+ se->Client_Icmp_NextSendEchoRequest = r->Now + GenRandInterval(RUDP_CLIENT_ECHO_REQUEST_SEND_INTERVAL_MIN, RUDP_CLIENT_ECHO_REQUEST_SEND_INTERVAL_MAX);
+ AddInterrupt(r->Interrupt, se->Client_Icmp_NextSendEchoRequest);
+ }
+ }
+ }
+ }
+
+ // Release the disconnected sessions
+ o = NULL;
+ for (i = 0;i < LIST_NUM(r->SessionList);i++)
+ {
+ RUDP_SESSION *se = LIST_DATA(r->SessionList, i);
+
+ if (se->DisconnectFlag)
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, se);
+ }
+ }
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ RUDP_SESSION *se = LIST_DATA(o, i);
+
+ Delete(r->SessionList, se);
+
+ RUDPFreeSession(se);
+ }
+
+ ReleaseList(o);
+ }
+}
+
+// Do the bulk send
+void RUDPBulkSend(RUDP_STACK *r, RUDP_SESSION *se, void *data, UINT data_size)
+{
+ UCHAR *buf;
+ UINT buf_size;
+ UINT padding_size;
+ UINT i;
+ CRYPT *c;
+ UCHAR crypt_key_src[SHA1_SIZE * 2];
+ UCHAR crypt_key[SHA1_SIZE];
+ UINT icmp_type;
+ UCHAR sign[SHA1_SIZE];
+ UCHAR iv[SHA1_SIZE + 1];
+ // Validate arguments
+ if (r == NULL || se == NULL || (data == NULL && data_size != 0))
+ {
+ return;
+ }
+
+ padding_size = Rand32() % 31 + 1;
+
+ buf_size = SHA1_SIZE + SHA1_SIZE + sizeof(UINT64) + data_size + padding_size;
+ buf = Malloc(buf_size);
+
+ // SEQ NO
+ WRITE_UINT64(buf + SHA1_SIZE + SHA1_SIZE, se->BulkNextSeqNo);
+ se->BulkNextSeqNo++;
+
+ // Data
+ Copy(buf + SHA1_SIZE + SHA1_SIZE + sizeof(UINT64), data, data_size);
+
+ // Padding
+ for (i = 0;i < padding_size;i++)
+ {
+ buf[SHA1_SIZE + SHA1_SIZE + sizeof(UINT64) + data_size + i] = (UCHAR)padding_size;
+ }
+
+ // Encryption
+ Copy(iv, se->BulkNextIv, SHA1_SIZE);
+ Copy(crypt_key_src + 0, se->BulkSendKey->Data, SHA1_SIZE);
+ Copy(crypt_key_src + SHA1_SIZE, iv, SHA1_SIZE);
+ HashSha1(crypt_key, crypt_key_src, SHA1_SIZE * 2);
+ c = NewCrypt(crypt_key, sizeof(crypt_key));
+ Encrypt(c, buf + SHA1_SIZE + SHA1_SIZE, buf + SHA1_SIZE + SHA1_SIZE, sizeof(UINT64) + data_size + padding_size);
+ FreeCrypt(c);
+
+ // IV
+ Copy(buf + SHA1_SIZE, iv, SHA1_SIZE);
+
+ // Sign
+ if (se->UseHMac == false)
+ {
+ Copy(buf + 0, se->BulkSendKey->Data, SHA1_SIZE);
+ HashSha1(sign, buf, SHA1_SIZE + SHA1_SIZE + sizeof(UINT64) + data_size + padding_size);
+ Copy(buf + 0, sign, SHA1_SIZE);
+ }
+ else
+ {
+ HMacSha1(buf + 0, se->BulkSendKey->Data, SHA1_SIZE, buf + SHA1_SIZE, SHA1_SIZE + sizeof(UINT64) + data_size + padding_size);
+ }
+
+ // Next IV
+ Copy(se->BulkNextIv, buf + buf_size - SHA1_SIZE, SHA1_SIZE);
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ icmp_type = se->Icmp_Type;
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ icmp_type = se->Dns_TranId;
+ }
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, buf, buf_size, icmp_type);
+
+ Free(buf);
+}
+
+// Start a socket for R-UDP Listening
+SOCK *ListenRUDP(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode)
+{
+ return ListenRUDPEx(svc_name, proc_interrupts, proc_rpc_recv, param, port, no_natt_register, over_dns_mode, NULL, 0);
+}
+SOCK *ListenRUDPEx(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode,
+ volatile UINT *natt_global_udp_port, UCHAR rand_port_id)
+{
+ SOCK *s;
+ RUDP_STACK *r;
+
+ // Creating a R-UDP stack
+ r = NewRUDPServer(svc_name, proc_interrupts, proc_rpc_recv, param, port, no_natt_register, over_dns_mode, natt_global_udp_port, rand_port_id);
+ if (r == NULL)
+ {
+ return NULL;
+ }
+
+ s = NewSock();
+
+ s->Type = SOCK_RUDP_LISTEN;
+ s->ListenMode = true;
+ s->Connected = true;
+
+ s->LocalPort = r->UdpSock->LocalPort;
+
+ s->R_UDP_Stack = r;
+
+ return s;
+}
+
+// Accept on the R-UDP socket
+SOCK *AcceptRUDP(SOCK *s)
+{
+ // Validate arguments
+ if (s == NULL || s->Type != SOCK_RUDP_LISTEN || s->ListenMode == false)
+ {
+ return NULL;
+ }
+
+ while (true)
+ {
+ RUDP_STACK *r = s->R_UDP_Stack;
+ SOCK *ret;
+
+ if (s->Disconnecting || s->CancelAccept)
+ {
+ return NULL;
+ }
+
+ ret = GetNextWithLock(r->NewSockQueue);
+
+ if (ret != NULL)
+ {
+ switch (r->Protocol)
+ {
+ case RUDP_PROTOCOL_UDP:
+ StrCpy(ret->UnderlayProtocol, sizeof(ret->UnderlayProtocol), SOCK_UNDERLAY_NAT_T);
+ break;
+
+ case RUDP_PROTOCOL_DNS:
+ StrCpy(ret->UnderlayProtocol, sizeof(ret->UnderlayProtocol), SOCK_UNDERLAY_DNS);
+ break;
+
+ case RUDP_PROTOCOL_ICMP:
+ StrCpy(ret->UnderlayProtocol, sizeof(ret->UnderlayProtocol), SOCK_UNDERLAY_ICMP);
+ break;
+ }
+
+ return ret;
+ }
+
+ Wait(r->NewSockConnectEvent, INFINITE);
+ }
+}
+
+// Verify the signature of the received packet
+bool RUDPCheckSignOfRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data, UINT recv_size)
+{
+ UCHAR sign[SHA1_SIZE];
+ UCHAR sign2[SHA1_SIZE];
+ UCHAR *p;
+ UINT size;
+ // Validate arguments
+ if (r == NULL || se == NULL || recv_data == NULL || recv_size == 0)
+ {
+ return false;
+ }
+
+ p = (UCHAR *)recv_data;
+ size = recv_size;
+ if (size < SHA1_SIZE)
+ {
+ return false;
+ }
+
+ // Verification the signature (segment packet)
+ Copy(sign, p, SHA1_SIZE);
+ Copy(p, se->Key_Recv, SHA1_SIZE);
+ HashSha1(sign2, p, recv_size);
+
+ if (r->Protocol == RUDP_PROTOCOL_DNS || r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ XorData(sign2, sign2, r->SvcNameHash, SHA1_SIZE);
+ }
+
+ Copy(p, sign, SHA1_SIZE);
+ if (Cmp(sign, sign2, SHA1_SIZE) == 0)
+ {
+ return true;
+ }
+
+ if (se->BulkRecvKey == NULL)
+ {
+ return false;
+ }
+
+ // Verification signature (bulk packet)
+ if (se->UseHMac == false)
+ {
+ Copy(sign, p, SHA1_SIZE);
+ Copy(p, se->BulkRecvKey->Data, SHA1_SIZE);
+ HashSha1(sign2, p, recv_size);
+ Copy(p, sign, SHA1_SIZE);
+
+ if (Cmp(sign, sign2, SHA1_SIZE) == 0)
+ {
+ return true;
+ }
+ }
+
+ HMacSha1(sign2, se->BulkRecvKey->Data, SHA1_SIZE, p + SHA1_SIZE, size - SHA1_SIZE);
+ if (Cmp(p, sign2, SHA1_SIZE) == 0)
+ {
+ se->UseHMac = true;
+ return true;
+ }
+
+ return false;
+}
+
+// Process the received packet (bulk)
+bool RUDPProcessBulkRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data, UINT recv_size)
+{
+ UCHAR sign[SHA1_SIZE];
+ UCHAR sign2[SHA1_SIZE];
+ UCHAR *p;
+ UCHAR *iv;
+ UINT size;
+ UCHAR keygen[SHA1_SIZE * 2];
+ UCHAR key[SHA1_SIZE];
+ CRYPT *c;
+ UCHAR padlen;
+ UINT64 seq_no;
+ UCHAR *payload;
+ UINT payload_size;
+ // Validate arguments
+ if (r == NULL || se == NULL || recv_data == NULL || recv_size == 0 || se->BulkRecvKey == NULL)
+ {
+ return false;
+ }
+
+ p = (UCHAR *)recv_data;
+ size = recv_size;
+ if (size < SHA1_SIZE)
+ {
+ return false;
+ }
+
+ // Validate the signature
+ if (se->UseHMac == false)
+ {
+ Copy(sign, p, SHA1_SIZE);
+ Copy(p, se->BulkRecvKey->Data, SHA1_SIZE);
+ HashSha1(sign2, p, recv_size);
+ Copy(p, sign, SHA1_SIZE);
+
+ if (Cmp(sign, sign2, SHA1_SIZE) != 0)
+ {
+ HMacSha1(sign2, se->BulkRecvKey->Data, SHA1_SIZE, p + SHA1_SIZE, recv_size - SHA1_SIZE);
+
+ if (Cmp(p, sign2, SHA1_SIZE) != 0)
+ {
+ return false;
+ }
+ else
+ {
+ se->UseHMac = true;
+ }
+ }
+ else
+ {
+ }
+ }
+ else
+ {
+ HMacSha1(sign2, se->BulkRecvKey->Data, SHA1_SIZE, p + SHA1_SIZE, recv_size - SHA1_SIZE);
+
+ if (Cmp(p, sign2, SHA1_SIZE) != 0)
+ {
+ return false;
+ }
+ }
+
+ p += SHA1_SIZE;
+ size -= SHA1_SIZE;
+
+ // IV
+ if (size < SHA1_SIZE)
+ {
+ return false;
+ }
+ iv = p;
+ p += SHA1_SIZE;
+ size -= SHA1_SIZE;
+
+ // Decrypt
+ if (size < 1)
+ {
+ return false;
+ }
+ Copy(keygen + 0, se->BulkRecvKey->Data, SHA1_SIZE);
+ Copy(keygen + SHA1_SIZE, iv, SHA1_SIZE);
+ HashSha1(key, keygen, sizeof(keygen));
+
+ c = NewCrypt(key, sizeof(key));
+ Encrypt(c, p, p, size);
+ FreeCrypt(c);
+
+ // padlen
+ padlen = p[size - 1];
+ if (padlen == 0)
+ {
+ return false;
+ }
+ if (size < padlen)
+ {
+ return false;
+ }
+ size -= padlen;
+
+ // SEQ NO
+ seq_no = READ_UINT64(p);
+ p += sizeof(UINT64);
+ size -= sizeof(UINT64);
+
+ if (seq_no == 0 || seq_no >= (0xF000000000000000ULL))
+ {
+ // Sequence number is invalid
+ return false;
+ }
+
+ if ((seq_no + RUDP_BULK_SEQ_NO_RANGE) < se->BulkRecvSeqNoMax)
+ {
+ // Sequence number is too small
+ return false;
+ }
+
+ se->LastRecvTick = r->Now;
+
+ payload = p;
+ payload_size = size;
+
+ se->BulkRecvSeqNoMax = MAX(seq_no, se->BulkRecvSeqNoMax);
+
+ // Send the received bulk packet to the Tube of the socket
+ RUDPInitSock(r, se);
+
+ if (se->TcpSock != NULL)
+ {
+ SOCK *s = se->TcpSock;
+ TUBE *t = s->BulkSendTube;
+
+ if (t != NULL)
+ {
+ TubeSendEx2(t, payload, payload_size, NULL, true, RUDP_BULK_MAX_RECV_PKTS_IN_QUEUE);
+
+ se->FlushBulkSendTube = true;
+ }
+ }
+
+ return true;
+}
+
+// Process the received packet (segment)
+bool RUDPProcessRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data, UINT recv_size)
+{
+ UCHAR sign[SHA1_SIZE];
+ UCHAR sign2[SHA1_SIZE];
+ UCHAR *p;
+ UCHAR *iv;
+ UINT size;
+ UCHAR keygen[SHA1_SIZE * 2];
+ UCHAR key[SHA1_SIZE];
+ CRYPT *c;
+ UCHAR padlen;
+ UINT num_ack;
+ UINT i;
+ UINT64 seq_no;
+ UCHAR *payload;
+ UINT payload_size;
+ UINT64 max_ack;
+ UINT64 my_tick, your_tick;
+ // Validate arguments
+ if (r == NULL || se == NULL || recv_data == NULL || recv_size == 0)
+ {
+ return false;
+ }
+
+ p = (UCHAR *)recv_data;
+ size = recv_size;
+ if (size < SHA1_SIZE)
+ {
+ return false;
+ }
+
+ // Validate the signature
+ Copy(sign, p, SHA1_SIZE);
+ Copy(p, se->Key_Recv, SHA1_SIZE);
+ HashSha1(sign2, p, recv_size);
+ Copy(p, sign, SHA1_SIZE);
+
+ if (r->Protocol == RUDP_PROTOCOL_DNS || r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ XorData(sign2, sign2, r->SvcNameHash, SHA1_SIZE);
+ }
+
+ if (Cmp(sign, sign2, SHA1_SIZE) != 0)
+ {
+ //WHERE;
+ return false;
+ }
+ p += SHA1_SIZE;
+ size -= SHA1_SIZE;
+
+ // IV
+ if (size < SHA1_SIZE)
+ {
+ return false;
+ }
+ iv = p;
+ p += SHA1_SIZE;
+ size -= SHA1_SIZE;
+
+ // Decrypt
+ if (size < 1)
+ {
+ return false;
+ }
+ Copy(keygen + 0, iv, SHA1_SIZE);
+ Copy(keygen + SHA1_SIZE, se->Key_Recv, SHA1_SIZE);
+ HashSha1(key, keygen, sizeof(keygen));
+
+ c = NewCrypt(key, sizeof(key));
+ Encrypt(c, p, p, size);
+ FreeCrypt(c);
+
+ // padlen
+ padlen = p[size - 1];
+ if (padlen == 0)
+ {
+ return false;
+ }
+ if (size < padlen)
+ {
+ return false;
+ }
+ size -= padlen;
+
+ // MyTick
+ if (size < sizeof(UINT64))
+ {
+ return false;
+ }
+ my_tick = READ_UINT64(p);
+ p += sizeof(UINT64);
+ size -= sizeof(UINT64);
+
+ // YourTick
+ if (size < sizeof(UINT64))
+ {
+ return false;
+ }
+ your_tick = READ_UINT64(p);
+ p += sizeof(UINT64);
+ size -= sizeof(UINT64);
+
+ if (your_tick > r->Now)
+ {
+ return false;
+ }
+
+ // MAX_ACK
+ if (size < sizeof(UINT64))
+ {
+ return false;
+ }
+ max_ack = READ_UINT64(p);
+ p += sizeof(UINT64);
+ size -= sizeof(UINT64);
+
+ // num_ack
+ if (size < sizeof(UINT))
+ {
+ return false;
+ }
+
+ num_ack = READ_UINT(p);
+ if (num_ack > RUDP_MAX_NUM_ACK)
+ {
+ return false;
+ }
+ p += sizeof(UINT);
+ size -= sizeof(UINT);
+
+ // ACKs
+ if (size < (sizeof(UINT64) * num_ack + sizeof(UINT64)))
+ {
+ return false;
+ }
+
+ if (max_ack >= 1)
+ {
+ RUDPProcessAck2(r, se, max_ack);
+ }
+
+ for (i = 0;i < num_ack;i++)
+ {
+ UINT64 seq = READ_UINT64(p);
+
+ RUDPProcessAck(r, se, seq);
+
+ p += sizeof(UINT64);
+ size -= sizeof(UINT64);
+ }
+
+ // Processing of the Tick (Calculation of RTT)
+ if (my_tick >= 2)
+ {
+ my_tick--;
+ }
+ se->YourTick = MAX(se->YourTick, my_tick);
+
+ se->LatestRecvMyTick = MAX(se->LatestRecvMyTick, your_tick);
+
+ if (se->LatestRecvMyTick2 != se->LatestRecvMyTick)
+ {
+ se->LatestRecvMyTick2 = se->LatestRecvMyTick;
+ se->CurrentRtt = (UINT)(r->Now - se->LatestRecvMyTick);
+
+#ifdef RUDP_DETAIL_LOG
+ Debug("CurrentRTT = %u\n", se->CurrentRtt);
+#endif // RUDP_DETAIL_LOG
+ }
+
+ // SEQ NO
+ seq_no = READ_UINT64(p);
+ p += sizeof(UINT64);
+ size -= sizeof(UINT64);
+
+ if (seq_no == 0)
+ {
+ // Sequence number of 0 is a invalid packet
+ return true;
+ }
+
+ if (seq_no == se->Magic_Disconnect)
+ {
+ // Disconnected from opponent
+ RUDPDisconnectSession(r, se, true);
+ return true;
+ }
+
+ // Update the last reception date and time
+ se->LastRecvTick = r->Now;
+
+ payload = p;
+ payload_size = size;
+
+#ifdef RUDP_DETAIL_LOG
+ Debug("RUDP %X Segment Recv: %I64u (num_ack=%u, size=%u)\n", se, seq_no, num_ack, size);
+#endif // RUDP_DETAIL_LOG
+
+ if (payload_size >= 1 && payload_size <= RUDP_MAX_SEGMENT_SIZE)
+ {
+ // Received one or more bytes of data
+
+#ifdef RUDP_DETAIL_LOG
+ Debug("Recv Size: %X %I64u %u %u\n", se, seq_no, payload_size, recv_size);
+#endif // RUDP_DETAIL_LOG
+
+ RUDPProcessRecvPayload(r, se, seq_no, payload, payload_size);
+ }
+
+ if (r->ServerMode == false)
+ {
+ if (se->Status == RUDP_SESSION_STATUS_CONNECT_SENT)
+ {
+ // Shift to the established state if the connection is not yet in established state
+ se->Status = RUDP_SESSION_STATUS_ESTABLISHED;
+
+ RUDPInitSock(r, se);
+ }
+ }
+
+ return true;
+}
+
+// Disconnect the session
+void RUDPDisconnectSession(RUDP_STACK *r, RUDP_SESSION *se, bool disconnected_by_you)
+{
+ // Validate arguments
+ if (r == NULL || se == NULL)
+ {
+ return;
+ }
+
+ if (se->DisconnectFlag == false)
+ {
+ UINT i;
+
+ se->DisconnectFlag = true;
+ se->DisconnectedByYou = disconnected_by_you;
+
+ Debug("R-UDP Session %X Disconnected. by you flag: %u\n", se, disconnected_by_you);
+
+ if (se->TcpSock != NULL)
+ {
+ // Disconnect a TCP socket
+ Disconnect(se->TcpSock);
+ ReleaseSock(se->TcpSock);
+
+ se->TcpSock = NULL;
+ }
+
+ // Send 5 disconnect signals serially if to disconnect from here
+ if (disconnected_by_you == false)
+ {
+ for (i = 0;i < 5;i++)
+ {
+ RUDPSendSegmentNow(r, se, se->Magic_Disconnect, NULL, 0);
+ }
+ }
+ }
+}
+
+// Initialize the TCP socket for the session
+void RUDPInitSock(RUDP_STACK *r, RUDP_SESSION *se)
+{
+ SOCK *s1, *s2;
+ UINT mss;
+ // Validate arguments
+ if (r == NULL || se == NULL || se->DisconnectFlag)
+ {
+ return;
+ }
+
+ if (se->TcpSock != NULL)
+ {
+ // It has already been created
+ return;
+ }
+
+ // Creating a TCP socket pair
+ if (NewTcpPair(&s1, &s2) == false)
+ {
+ // Failed to create. Disconnect the session
+ RUDPDisconnectSession(r, se, false);
+ return;
+ }
+
+ // Calculate the optimal MSS
+ mss = RUDPCalcBestMssForBulk(r, se);
+
+ if (r->ServerMode)
+ {
+ // Server mode
+ se->TcpSock = s2;
+
+ JoinSockToSockEvent(s2, r->SockEvent);
+
+ // Update the end point information of the socket s1
+ ZeroIP4(&s1->LocalIP);
+ s1->LocalPort = se->MyPort;
+ Copy(&s1->RemoteIP, &se->YourIp, sizeof(IP));
+ s1->RemotePort = se->YourPort;
+ if (IsLocalHostIP(&s1->RemoteIP) == false)
+ {
+ AddIpClient(&s1->RemoteIP);
+ s1->IpClientAdded = true;
+ }
+ s1->IsRUDPSocket = true;
+
+ s1->BulkSendKey = se->BulkSendKey;
+ s1->BulkRecvKey = se->BulkRecvKey;
+
+ AddRef(s1->BulkSendKey->Ref);
+ AddRef(s1->BulkRecvKey->Ref);
+
+ s1->RUDP_OptimizedMss = mss;
+
+ // Enqueue the newly created socket, and set the event
+ InsertQueueWithLock(r->NewSockQueue, s1);
+ Set(r->NewSockConnectEvent);
+ }
+ else
+ {
+ // Client mode
+ Lock(r->Lock);
+ {
+ if (r->TargetConnectedSock == NULL && r->DoNotSetTargetConnectedSock == false)
+ {
+ // Update the end point information of the socket s2
+ Copy(&s2->LocalIP, &r->UdpSock->LocalIP, sizeof(IP));
+ s2->LocalPort = se->MyPort;
+ Copy(&s2->RemoteIP, &se->YourIp, sizeof(IP));
+ s2->RemotePort = se->YourPort;
+ if (IsLocalHostIP(&s2->RemoteIP) == false)
+ {
+ AddIpClient(&s2->RemoteIP);
+ s2->IpClientAdded = true;
+ }
+ s2->IsRUDPSocket = true;
+
+ s2->BulkSendKey = se->BulkSendKey;
+ s2->BulkRecvKey = se->BulkRecvKey;
+
+ AddRef(s2->BulkSendKey->Ref);
+ AddRef(s2->BulkRecvKey->Ref);
+
+ s2->RUDP_OptimizedMss = mss;
+
+ // Register the socket to the RUDP stack
+ r->TargetConnectedSock = s2;
+ s2->R_UDP_Stack = r;
+ se->TcpSock = s1;
+
+ JoinSockToSockEvent(s1, r->SockEvent);
+
+ // Set the event to be set when the connection is successful
+ Set(r->TargetConnectedEvent);
+ }
+ else
+ {
+ Disconnect(s1);
+ Disconnect(s2);
+ ReleaseSock(s1);
+ ReleaseSock(s2);
+ }
+ }
+ Unlock(r->Lock);
+ }
+}
+
+// Process the received payload
+void RUDPProcessRecvPayload(RUDP_STACK *r, RUDP_SESSION *se, UINT64 seq, void *payload_data, UINT payload_size)
+{
+ RUDP_SEGMENT t;
+ RUDP_SEGMENT *s;
+ // Validate arguments
+ if (r == NULL || se == NULL || seq == 0 || payload_data == NULL || payload_size == 0 || payload_size > RUDP_MAX_SEGMENT_SIZE)
+ {
+ return;
+ }
+
+ if (seq > (se->LastRecvCompleteSeqNo + RUDP_MAX_NUM_ACK))
+ {
+ // Ignore the segment which have sequence number beyond the window size, and also not to reply an ACK
+ return;
+ }
+
+ if (seq <= se->LastRecvCompleteSeqNo)
+ {
+ // Do not receive the segment which have the sequence number that has been already received. However, reply an ACK for it
+ AddInt64Distinct(se->ReplyAckList, seq);
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ t.SeqNo = seq;
+
+ s = Search(se->RecvSegmentList, &t);
+ if (s != NULL)
+ {
+ // Do not receive the segment which have the sequence number that has been already received. However, reply an ACK for it
+ AddInt64Distinct(se->ReplyAckList, seq);
+ return;
+ }
+
+ // Received a segment of the new sequence number
+ s = ZeroMalloc(sizeof(RUDP_SEGMENT));
+ s->SeqNo = seq;
+ Copy(s->Data, payload_data, payload_size);
+ s->Size = payload_size;
+ Insert(se->RecvSegmentList, s);
+
+ // Reply an ACK
+ AddInt64Distinct(se->ReplyAckList, seq);
+
+ // Create a socket for session if it have not been created yet
+ //RUDPInitSock(r, se);
+}
+
+// Process the incoming ACK
+void RUDPProcessAck(RUDP_STACK *r, RUDP_SESSION *se, UINT64 seq)
+{
+ RUDP_SEGMENT t;
+ RUDP_SEGMENT *s;
+ // Validate arguments
+ if (r == NULL || se == NULL || seq == 0)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ t.SeqNo = seq;
+
+ s = Search(se->SendSegmentList, &t);
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Delete(se->SendSegmentList, s);
+ Free(s);
+}
+
+// Remove all segments which are preceding max_seq as already delivered
+void RUDPProcessAck2(RUDP_STACK *r, RUDP_SESSION *se, UINT64 max_seq)
+{
+ LIST *o;
+ UINT i;
+ // Validate arguments
+ if (r == NULL || se == NULL || max_seq == 0)
+ {
+ return;
+ }
+
+ o = NULL;
+
+ for (i = 0;i < LIST_NUM(se->SendSegmentList);i++)
+ {
+ RUDP_SEGMENT *s = LIST_DATA(se->SendSegmentList, i);
+
+ if (s->SeqNo <= max_seq)
+ {
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, s);
+ }
+ }
+
+ if (o != NULL)
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ RUDP_SEGMENT *s = LIST_DATA(o, i);
+
+ Delete(se->SendSegmentList, s);
+
+ Free(s);
+ }
+
+ ReleaseList(o);
+ }
+}
+
+// Get the minimum sequence number which is trying to send
+UINT64 RUDPGetCurrentSendingMinSeqNo(RUDP_SESSION *se)
+{
+ RUDP_SEGMENT *s;
+ // Validate arguments
+ if (se == NULL)
+ {
+ return 0;
+ }
+
+ if (LIST_NUM(se->SendSegmentList) == 0)
+ {
+ return 0;
+ }
+
+ s = LIST_DATA(se->SendSegmentList, 0);
+
+ return s->SeqNo;
+}
+
+// Get the maximum sequence number which is trying to send
+UINT64 RUDPGetCurrentSendingMaxSeqNo(RUDP_SESSION *se)
+{
+ RUDP_SEGMENT *s;
+ // Validate arguments
+ if (se == NULL)
+ {
+ return 0;
+ }
+
+ if (LIST_NUM(se->SendSegmentList) == 0)
+ {
+ return 0;
+ }
+
+ s = LIST_DATA(se->SendSegmentList, (LIST_NUM(se->SendSegmentList) - 1));
+
+ return s->SeqNo;
+}
+
+// R-UDP segment transmission
+void RUDPSendSegmentNow(RUDP_STACK *r, RUDP_SESSION *se, UINT64 seq_no, void *data, UINT size)
+{
+ UCHAR dst[RUDP_MAX_PACKET_SIZE];
+ UCHAR *p;
+ UCHAR *iv;
+ LIST *o = NULL;
+ UINT i;
+ UCHAR padlen;
+ UINT current_size;
+ UCHAR sign[SHA1_SIZE];
+ UCHAR key[SHA1_SIZE];
+ UCHAR keygen[SHA1_SIZE * 2];
+ CRYPT *c;
+ UINT next_iv_pos;
+ UINT num_ack;
+ UINT icmp_type = 0;
+ // Validate arguments
+ if (r == NULL || se == NULL || (size != 0 && data == NULL) || (size > RUDP_MAX_SEGMENT_SIZE))
+ {
+ return;
+ }
+
+ Zero(dst, sizeof(dst));
+ p = dst;
+
+ // SIGN
+ Copy(p, se->Key_Send, SHA1_SIZE);
+ p += SHA1_SIZE;
+
+ // IV
+ iv = p;
+ Copy(iv, se->NextIv, SHA1_SIZE);
+ p += SHA1_SIZE;
+
+ for (i = 0;i < MIN(LIST_NUM(se->ReplyAckList), RUDP_MAX_NUM_ACK);i++)
+ {
+ UINT64 *seq = LIST_DATA(se->ReplyAckList, i);
+
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, seq);
+ }
+
+ // MyTick
+ WRITE_UINT64(p, r->Now);
+ p += sizeof(UINT64);
+
+ // YourTick
+ WRITE_UINT64(p, se->YourTick);
+ p += sizeof(UINT64);
+
+ // MAX_ACK
+ WRITE_UINT64(p, se->LastRecvCompleteSeqNo);
+ p += sizeof(UINT64);
+
+ // NUM_ACK
+ num_ack = LIST_NUM(o);
+ WRITE_UINT(p, num_ack);
+ p += sizeof(UINT);
+
+ if (o != NULL)
+ {
+ // ACK body
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ UINT64 *seq = LIST_DATA(o, i);
+
+ WRITE_UINT64(p, *seq);
+ p += sizeof(UINT64);
+
+ Delete(se->ReplyAckList, seq);
+
+ Free(seq);
+ }
+ ReleaseList(o);
+ }
+
+ // SEQ
+ WRITE_UINT64(p, seq_no);
+ p += sizeof(UINT64);
+
+ // data
+ Copy(p, data, size);
+ p += size;
+
+ // padding
+ padlen = Rand8();
+ padlen = MAX(padlen, 1);
+
+ for (i = 0;i < padlen;i++)
+ {
+ *p = padlen;
+ p++;
+ }
+
+ current_size = (UINT)(p - dst);
+
+ // Encrypt
+ Copy(keygen + 0, iv, SHA1_SIZE);
+ Copy(keygen + SHA1_SIZE, se->Key_Send, SHA1_SIZE);
+ HashSha1(key, keygen, sizeof(keygen));
+ c = NewCrypt(key, sizeof(key));
+ Encrypt(c, dst + SHA1_SIZE * 2, dst + SHA1_SIZE * 2, current_size - (SHA1_SIZE * 2));
+ FreeCrypt(c);
+
+ // Sign
+ HashSha1(sign, dst, current_size);
+ if (r->Protocol == RUDP_PROTOCOL_DNS || r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ XorData(sign, sign, r->SvcNameHash, SHA1_SIZE);
+ }
+ Copy(dst, sign, SHA1_SIZE);
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ icmp_type = se->Icmp_Type;
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ icmp_type = se->Dns_TranId;
+ }
+ RUDPSendPacket(r, &se->YourIp, se->YourPort, dst, current_size, icmp_type);
+
+ if (size >= 1)
+ {
+ se->LastSentTick = r->Now;
+ }
+
+ // Next IV
+ next_iv_pos = Rand32() % (current_size - SHA1_SIZE);
+ Copy(se->NextIv, dst + next_iv_pos, SHA1_SIZE);
+
+#ifdef RUDP_DETAIL_LOG
+ Debug("RUDP %X Segment Sent: %I64u (num_ack=%u, size=%u)\n", se, seq_no, num_ack, size);
+#endif // RUDP_DETAIL_LOG
+
+ if (size >= 1)
+ {
+#ifdef RUDP_DETAIL_LOG
+ Debug("Send Size: %X %I64u %u %u\n", se, seq_no, size, current_size);
+#endif // RUDP_DETAIL_LOG
+ }
+}
+
+// R-UDP segment transmission (only put into the queue)
+void RUDPSendSegment(RUDP_STACK *r, RUDP_SESSION *se, void *data, UINT size)
+{
+ RUDP_SEGMENT *s;
+ // Validate arguments
+ if (r == NULL || se == NULL || (size != 0 && data == NULL) || (size > RUDP_MAX_SEGMENT_SIZE))
+ {
+ return;
+ }
+
+ s = ZeroMalloc(sizeof(RUDP_SEGMENT));
+
+ Copy(s->Data, data, size);
+ s->Size = size;
+
+ s->SeqNo = se->NextSendSeqNo++;
+
+ Insert(se->SendSegmentList, s);
+}
+
+// Search for a session
+RUDP_SESSION *RUDPSearchSession(RUDP_STACK *r, IP *my_ip, UINT my_port, IP *your_ip, UINT your_port)
+{
+ RUDP_SESSION t;
+ RUDP_SESSION *se;
+ // Validate arguments
+ if (r == NULL || my_ip == NULL || your_ip == NULL)
+ {
+ return NULL;
+ }
+
+ Copy(&t.MyIp, my_ip, sizeof(IP));
+ t.MyPort = my_port;
+ Copy(&t.YourIp, your_ip, sizeof(IP));
+ t.YourPort = your_port;
+
+ se = Search(r->SessionList, &t);
+
+ return se;
+}
+
+// Release of the session
+void RUDPFreeSession(RUDP_SESSION *se)
+{
+ UINT i;
+ // Validate arguments
+ if (se == NULL)
+ {
+ return;
+ }
+
+ Debug("RUDPFreeSession %X\n", se);
+
+ for (i = 0;i < LIST_NUM(se->SendSegmentList);i++)
+ {
+ RUDP_SEGMENT *s = LIST_DATA(se->SendSegmentList, i);
+
+ Free(s);
+ }
+
+ ReleaseList(se->SendSegmentList);
+
+ for (i = 0;i < LIST_NUM(se->RecvSegmentList);i++)
+ {
+ RUDP_SEGMENT *s = LIST_DATA(se->RecvSegmentList, i);
+
+ Free(s);
+ }
+
+ ReleaseList(se->RecvSegmentList);
+
+ if (se->TcpSock != NULL)
+ {
+ Disconnect(se->TcpSock);
+ ReleaseSock(se->TcpSock);
+ }
+
+ ReleaseInt64List(se->ReplyAckList);
+
+ ReleaseFifo(se->RecvFifo);
+ ReleaseFifo(se->SendFifo);
+
+ ReleaseSharedBuffer(se->BulkSendKey);
+ ReleaseSharedBuffer(se->BulkRecvKey);
+
+ Free(se);
+}
+
+// Create a new session
+RUDP_SESSION *RUDPNewSession(bool server_mode, IP *my_ip, UINT my_port, IP *your_ip, UINT your_port, UCHAR *init_key)
+{
+ RUDP_SESSION *se;
+ UCHAR key1[SHA1_SIZE];
+ UCHAR key2[SHA1_SIZE];
+ UCHAR bulk_send_key[SHA1_SIZE];
+ UCHAR bulk_recv_key[SHA1_SIZE];
+ BUF *b;
+
+ se = ZeroMalloc(sizeof(RUDP_SESSION));
+
+ Copy(&se->MyIp, my_ip, sizeof(IP));
+ se->MyPort = my_port;
+
+ Copy(&se->YourIp, your_ip, sizeof(IP));
+ se->YourPort = your_port;
+
+ Copy(se->Key_Init, init_key, SHA1_SIZE);
+ se->LastSentTick = 0;
+ se->LastRecvTick = Tick64();
+ se->LatestRecvMyTick = Tick64();
+
+ se->NextSendSeqNo = 1;
+
+ se->ServerMode = server_mode;
+
+ se->SendSegmentList = NewList(RUDPCompareSegmentList);
+ se->RecvSegmentList = NewList(RUDPCompareSegmentList);
+
+ // Generate the two keys
+ b = NewBuf();
+ WriteBuf(b, init_key, SHA1_SIZE);
+ WriteBufStr(b, "zurukko");
+ HashSha1(key1, b->Buf, b->Size);
+ FreeBuf(b);
+
+ b = NewBuf();
+ WriteBuf(b, init_key, SHA1_SIZE);
+ WriteBuf(b, key1, SHA1_SIZE);
+ WriteBufStr(b, "yasushineko");
+ HashSha1(key2, b->Buf, b->Size);
+ FreeBuf(b);
+
+ // Generate the magic number for the KeepAlive
+ b = NewBuf();
+ WriteBuf(b, init_key, SHA1_SIZE);
+ WriteBufStr(b, "Magic_KeepAliveRequest");
+ HashSha1(se->Magic_KeepAliveRequest, b->Buf, b->Size);
+ FreeBuf(b);
+ b = NewBuf();
+ WriteBuf(b, init_key, SHA1_SIZE);
+ WriteBufStr(b, "Magic_KeepAliveResponse");
+ HashSha1(se->Magic_KeepAliveResponse, b->Buf, b->Size);
+ FreeBuf(b);
+
+ if (server_mode == false)
+ {
+ se->Magic_Disconnect = 0xffffffff00000000ULL | (UINT64)(Rand32());
+ }
+
+ Copy(se->Key_Init, init_key, SHA1_SIZE);
+
+ if (se->ServerMode)
+ {
+ Copy(se->Key_Send, key1, SHA1_SIZE);
+ Copy(se->Key_Recv, key2, SHA1_SIZE);
+ }
+ else
+ {
+ Copy(se->Key_Send, key2, SHA1_SIZE);
+ Copy(se->Key_Recv, key1, SHA1_SIZE);
+ }
+
+ Rand(se->NextIv, sizeof(se->NextIv));
+
+ se->ReplyAckList = NewInt64List(true);
+
+ se->NextKeepAliveInterval = RUDP_KEEPALIVE_INTERVAL_MIN + (Rand32() % (RUDP_KEEPALIVE_INTERVAL_MAX - RUDP_KEEPALIVE_INTERVAL_MIN));
+
+ se->RecvFifo = NewFifo();
+ se->SendFifo = NewFifo();
+
+ se->Dns_TranId = Rand16() % 65535 + 1;
+
+ // Generate the bulk transfer key
+ Rand(bulk_send_key, sizeof(bulk_send_key));
+ Rand(bulk_recv_key, sizeof(bulk_recv_key));
+
+ se->BulkSendKey = NewSharedBuffer(bulk_send_key, sizeof(bulk_send_key));
+ se->BulkRecvKey = NewSharedBuffer(bulk_recv_key, sizeof(bulk_recv_key));
+
+ Rand(se->BulkNextIv, sizeof(se->BulkNextIv));
+ se->BulkNextSeqNo = 1;
+
+ return se;
+}
+
+// Comparison function of the segment list items
+int RUDPCompareSegmentList(void *p1, void *p2)
+{
+ RUDP_SEGMENT *s1, *s2;
+ UINT r;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *((RUDP_SEGMENT **)p1);
+ s2 = *((RUDP_SEGMENT **)p2);
+ if (s1 == NULL || s2 == NULL)
+ {
+ return 0;
+ }
+
+ r = COMPARE_RET(s1->SeqNo, s2->SeqNo);
+
+ return r;
+}
+
+// Send a UDP packet
+void RUDPSendPacket(RUDP_STACK *r, IP *dest_ip, UINT dest_port, void *data, UINT size, UINT icmp_type)
+{
+ UDPPACKET *p;
+ // Validate arguments
+ if (r == NULL || dest_ip == NULL || dest_port == 0 || data == NULL || size == 0)
+ {
+ return;
+ }
+
+ p = NewUdpPacket(&r->UdpSock->LocalIP, r->UdpSock->LocalPort,
+ dest_ip, dest_port,
+ Clone(data, size), size);
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP || r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ // ICMP Type / DNS Tran ID
+ p->Type = icmp_type;
+ }
+
+ Add(r->SendPacketList, p);
+}
+
+// R-UDP main thread
+void RUDPMainThread(THREAD *thread, void *param)
+{
+ RUDP_STACK *r;
+ bool halt_flag = false;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ r = (RUDP_STACK *)param;
+
+ AddWaitThread(thread);
+ NoticeThreadInit(thread);
+
+ while (true)
+ {
+ UINT wait_interval;
+ UINT i;
+ UINT min_wait_interval;
+ UINT num_ignore_errors = 0;
+
+ r->Now = Tick64();
+
+ Lock(r->Lock);
+ {
+ Copy(&r->NatT_IP_Safe, &r->NatT_IP, sizeof(IP));
+ Copy(&r->My_Private_IP_Safe, &r->My_Private_IP, sizeof(IP));
+ }
+ Unlock(r->Lock);
+
+ // Receive the data from the UDP socket
+ while (true)
+ {
+ UINT ret;
+ IP ip_src;
+ UINT port_src;
+
+ ret = RecvFrom(r->UdpSock, &ip_src, &port_src, r->TmpBuf, sizeof(r->TmpBuf));
+
+ if (ret == SOCK_LATER)
+ {
+ // There is no packet more
+ break;
+ }
+ else if (ret != 0)
+ {
+ // Receive a Packet
+ bool ok = false;
+ UDPPACKET *p = NewUdpPacket(&ip_src, port_src,
+ &r->UdpSock->LocalIP, r->UdpSock->LocalPort,
+ Clone(r->TmpBuf, ret), ret);
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ // Analyse the incoming ICMP packet
+ UINT ip_header_size = GetIpHeaderSize(p->Data, p->Size);
+
+ if (ip_header_size >= sizeof(IPV4_HEADER))
+ {
+ if (p->Size >= (ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + SHA1_SIZE))
+ {
+ IPV4_HEADER *ip_header = (IPV4_HEADER *)(((UCHAR *)p->Data) + 0);
+ ICMP_HEADER *icmp_header = (ICMP_HEADER *)(((UCHAR *)p->Data) + ip_header_size);
+ ICMP_ECHO *echo_header = (ICMP_ECHO *)(((UCHAR *)p->Data) + ip_header_size + sizeof(ICMP_HEADER));
+
+ if (icmp_header->Type == ICMP_TYPE_ECHO_RESPONSE ||
+ icmp_header->Type == (r->ServerMode ? ICMP_TYPE_INFORMATION_REQUEST : ICMP_TYPE_INFORMATION_REPLY))
+ {
+ UCHAR hash[SHA1_SIZE];
+
+ HashSha1(hash, ((UCHAR *)p->Data) + ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + SHA1_SIZE,
+ p->Size - (ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + SHA1_SIZE));
+
+ if (Cmp(hash, ((UCHAR *)p->Data) + ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO), SHA1_SIZE) == 0)
+ {
+ UCHAR *new_data;
+ UINT new_data_size;
+ if (r->ServerMode)
+ {
+ // On the server side, the ICMP ID and the SEQ NO of received messages are treated as a source port number
+ Copy(&p->SrcPort, echo_header, sizeof(UINT));
+ }
+
+ // Record the Type
+ p->Type = icmp_header->Type;
+
+ // Erase the header part
+ new_data_size = p->Size - (ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + SHA1_SIZE);
+ new_data = Clone(((UCHAR *)p->Data) + ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + SHA1_SIZE, new_data_size);
+ Free(p->Data);
+ p->Data = new_data;
+ p->Size = new_data_size;
+
+ ok = true;
+ }
+ }
+ }
+ }
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ // Analyse the incoming DNS packet
+ UINT offset;
+
+ if (r->ServerMode == false)
+ {
+ offset = 42;
+ }
+ else
+ {
+ offset = 37;
+ }
+
+ if (p->Size > offset)
+ {
+ UCHAR *new_data;
+ UINT new_size = p->Size - offset;
+
+ p->Type = *((USHORT *)p->Data);
+
+ new_data = Clone(((UCHAR *)p->Data) + offset, new_size);
+
+ Free(p->Data);
+ p->Data = new_data;
+ p->Size = new_size;
+
+ ok = true;
+ }
+ }
+ else
+ {
+ // Don't do anything for ordinary UDP packet
+ ok = true;
+ }
+
+ if (ok)
+ {
+ // Process the received packet
+ RUDPRecvProc(r, p);
+
+ r->TotalPhysicalReceived += ret;
+ }
+
+ FreeUdpPacket(p);
+ }
+ else
+ {
+ if (r->UdpSock->IgnoreRecvErr)
+ {
+ // An ignorable reception error occurs
+ if ((num_ignore_errors++) >= MAX_NUM_IGNORE_ERRORS)
+ {
+ break;
+ }
+ }
+ else
+ {
+ // A non-ignorable reception error occurs
+ break;
+ }
+ }
+ }
+
+ // Call the interrupt notification callback function
+ if (r->ProcInterrupts != NULL)
+ {
+ r->ProcInterrupts(r);
+ }
+
+ RUDPInterruptProc(r);
+
+ // Send all packets in the transmission packet list
+ for (i = 0;i < LIST_NUM(r->SendPacketList);i++)
+ {
+ UDPPACKET *p = LIST_DATA(r->SendPacketList, i);
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP)
+ {
+ // In case of the ICMP protocol, assemble an ICMP header
+ UINT dst_size = sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + SHA1_SIZE + p->Size;
+ UCHAR *dst_data = ZeroMalloc(dst_size);
+
+ ICMP_HEADER *icmp_header = (ICMP_HEADER *)dst_data;
+ ICMP_ECHO *icmp_echo = (ICMP_ECHO *)(dst_data + sizeof(ICMP_HEADER));
+ UCHAR *hash = dst_data + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO);
+ UCHAR *icmp_data = dst_data + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + SHA1_SIZE;
+
+ // Header
+ icmp_header->Type = (UCHAR)p->Type;
+ icmp_header->Code = 0;
+ icmp_header->Checksum = 0;
+
+ if (r->ServerMode)
+ {
+ // On the server side, use the port number in the opponent internal data as ICMP ID and SEQ NO
+ Copy(icmp_echo, &p->DestPort, 4);
+ }
+ else
+ {
+ // Use the fixed ICMP ID and SEQ NO on the client side
+ icmp_echo->Identifier = Endian16(r->Client_IcmpId);
+ icmp_echo->SeqNo = Endian16(r->Client_IcmpSeqNo);
+ }
+
+ // Data body
+ Copy(icmp_data, p->Data, p->Size);
+
+ // Hash
+ HashSha1(hash, icmp_data, p->Size);
+
+ // Checksum calculation
+ icmp_header->Checksum = IpChecksum(dst_data, dst_size);
+
+ // Replacement
+ Free(p->Data);
+ p->Data = dst_data;
+ p->Size = dst_size;
+ }
+ else if (r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ BUF *b = NewBuf();
+ // In case of over DNS protocol, assemble a header that conforms to the DNS protocol
+ if (r->ServerMode == false)
+ {
+ // DNS query header
+ USHORT us = Rand16() % 65535 + 1;
+ static UCHAR dns_query_header_1[] =
+ {
+ 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
+ };
+ static UCHAR dns_query_header_2[] =
+ {
+ 0x00, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x29, 0x10,
+ 0x00, 0x00, 0x00, 0x80, 0x00,
+ };
+ UCHAR rand_data[4];
+ char rand_str[MAX_SIZE];
+
+ Rand(rand_data, sizeof(rand_data));
+ BinToStr(rand_str, sizeof(rand_str), rand_data, sizeof(rand_data));
+ StrLower(rand_str);
+
+ WriteBuf(b, &us, sizeof(USHORT));
+ WriteBuf(b, dns_query_header_1, sizeof(dns_query_header_1));
+ WriteBuf(b, rand_str, 8);
+ WriteBuf(b, dns_query_header_2, sizeof(dns_query_header_2));
+ us = Endian16((USHORT)p->Size);
+ WriteBuf(b, &us, sizeof(USHORT));
+ WriteBuf(b, p->Data, p->Size);
+ }
+ else
+ {
+ // DNS response header
+ USHORT us = p->Type;
+ UINT ui;
+ static UCHAR dns_response_header_1[] =
+ {
+ 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x08,
+ };
+ static UCHAR dns_response_header_2[] =
+ {
+ 0x00, 0x00, 0x30, 0x00, 0x01,
+ 0xc0, 0x0c, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0xa4, 0x5b,
+ };
+ static UCHAR dns_response_header_3[] =
+ {
+ 0x01, 0x00, 0x03, 0x08,
+ };
+ UCHAR rand_data[4];
+ char rand_str[MAX_SIZE];
+
+ Rand(rand_data, sizeof(rand_data));
+ BinToStr(rand_str, sizeof(rand_str), rand_data, sizeof(rand_data));
+ StrLower(rand_str);
+
+ WriteBuf(b, &us, sizeof(USHORT));
+ WriteBuf(b, dns_response_header_1, sizeof(dns_response_header_1));
+ WriteBuf(b, rand_str, 8);
+ WriteBuf(b, dns_response_header_2, sizeof(dns_response_header_2));
+ us = Endian16((USHORT)(p->Size + 4));
+ WriteBuf(b, &us, sizeof(USHORT));
+ WriteBuf(b, dns_response_header_3, sizeof(dns_response_header_3));
+ WriteBuf(b, p->Data, p->Size);
+
+ ui = Rand16() % (60 * 60 * 12) + (60 * 60 * 12);
+ WRITE_UINT(((UCHAR *)b->Buf) + 0x20, ui);
+ }
+ Free(p->Data);
+ p->Data = b->Buf;
+ p->Size = b->Size;
+ Free(b);
+ }
+
+ SendTo(r->UdpSock, &p->DstIP, p->DestPort, p->Data, p->Size);
+
+ r->TotalPhysicalSent += p->Size;
+
+ FreeUdpPacket(p);
+ }
+ DeleteAll(r->SendPacketList);
+
+ if (r->Halt)
+ {
+ // If it is necessary to stop, stop it after cycling through a loop
+ if (halt_flag == false)
+ {
+ halt_flag = true;
+ continue;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ // Rest the CPU until the next event
+ wait_interval = GetNextIntervalForInterrupt(r->Interrupt);
+ if (r->ServerMode)
+ {
+ min_wait_interval = RUDP_LOOP_WAIT_INTERVAL_S;
+ }
+ else
+ {
+ min_wait_interval = RUDP_LOOP_WAIT_INTERVAL_C;
+ }
+
+ if (wait_interval == INFINITE)
+ {
+ wait_interval = min_wait_interval;
+ }
+ else
+ {
+ wait_interval = MIN(min_wait_interval, wait_interval);
+ }
+
+#ifdef RUDP_DETAIL_LOG
+ Debug("wait_interval = %u\n", wait_interval);
+#endif // RUDP_DETAIL_LOG
+
+ if (wait_interval >= 1)
+ {
+ WaitSockEvent(r->SockEvent, wait_interval);
+ }
+
+#ifdef RUDP_DETAIL_LOG
+ if (r->ServerMode)
+ {
+ char str1[MAX_SIZE];
+ char str2[MAX_SIZE];
+ double rate = 0.0;
+
+ ToStr64(str1, r->TotalPhysicalReceived);
+ ToStr64(str2, r->TotalLogicalReceived);
+
+ if (r->TotalPhysicalReceived >= 1)
+ {
+ rate = (double)r->TotalLogicalReceived / (double)r->TotalPhysicalReceived;
+ }
+
+ Debug("%s / %s %.4f\n", str1, str2, rate);
+ }
+#endif // RUDP_DETAIL_LOG
+ }
+
+ Disconnect(r->UdpSock);
+
+ DelWaitThread(thread);
+}
+
+// Generate a appropriate register host name from the IP address
+void RUDPGetRegisterHostNameByIP(char *dst, UINT size, IP *ip)
+{
+ char tmp[16];
+ // Validate arguments
+ if (dst == NULL)
+ {
+ return;
+ }
+
+ if (ip != NULL && IsIP4(ip))
+ {
+ UCHAR hash[SHA1_SIZE];
+
+ HashSha1(hash, ip->addr, 4);
+ BinToStr(tmp, sizeof(tmp), hash, 2);
+ }
+ else
+ {
+ UCHAR rand[2];
+ Rand(rand, 2);
+ BinToStr(tmp, sizeof(tmp), rand, 2);
+ }
+
+ StrLower(tmp);
+ Format(dst, size,
+ (IsUseAlternativeHostname() ? UDP_NAT_T_SERVER_TAG_ALT : UDP_NAT_T_SERVER_TAG),
+ tmp[0], tmp[1], tmp[2], tmp[3]);
+
+
+ if (false)
+ {
+ Debug("Hash Src IP: %r\n"
+ "Hash Dst HN: %s\n",
+ ip,
+ dst);
+ }
+}
+
+// Analyze the IP address and port number from the string
+bool RUDPParseIPAndPortStr(void *data, UINT data_size, IP *ip, UINT *port)
+{
+ char tmp[MAX_SIZE];
+ UINT i;
+ char ipstr[MAX_SIZE];
+ char *portstr;
+ // Validate arguments
+ if (data == NULL || ip == NULL || port == NULL)
+ {
+ return false;
+ }
+
+ Zero(tmp, sizeof(tmp));
+
+ Copy(tmp, data, MIN(data_size, sizeof(tmp) - 1));
+
+ if (StartWith(tmp, "IP=") == false)
+ {
+ return false;
+ }
+
+ i = SearchStrEx(tmp, "#", 0, true);
+ if (i != INFINITE)
+ {
+ tmp[i] = 0;
+ }
+
+ StrCpy(ipstr, sizeof(ipstr), tmp + 3);
+
+ i = SearchStrEx(ipstr, ",PORT=", 0, true);
+ if (i == INFINITE)
+ {
+ return false;
+ }
+
+ ipstr[i] = 0;
+ portstr = ipstr + i + 6;
+
+ StrToIP(ip, ipstr);
+ *port = ToInt(portstr);
+
+ return true;
+}
+
+// R-UDP NAT-T IP address acquisition thread
+void RUDPIpQueryThread(THREAD *thread, void *param)
+{
+ RUDP_STACK *r;
+ UINT64 next_getip_tick = 0;
+ UINT64 next_getprivate_ip_tick = 0;
+ UINT last_ip_hash = 0;
+ void *route_change_poller = NULL;
+ char current_hostname[MAX_SIZE];
+ bool last_time_ip_changed = false;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ r = (RUDP_STACK *)param;
+
+ last_ip_hash = GetHostIPAddressHash32();
+
+ route_change_poller = NewRouteChange();
+ IsRouteChanged(route_change_poller);
+
+ Zero(current_hostname, sizeof(current_hostname));
+
+ while (r->Halt == false)
+ {
+ UINT ip_hash = GetHostIPAddressHash32();
+ UINT64 now = Tick64();
+ bool ip_changed = false;
+
+ if (ip_hash != last_ip_hash)
+ {
+ last_time_ip_changed = false;
+ }
+
+ if ((ip_hash != last_ip_hash) || (IsRouteChanged(route_change_poller)))
+ {
+ if (last_time_ip_changed == false)
+ {
+ // Call all getting functions from the beginning
+ // if the routing table or the IP address of this host has changed
+ next_getip_tick = 0;
+ next_getprivate_ip_tick = 0;
+ ip_changed = true;
+
+ last_ip_hash = ip_hash;
+
+ last_time_ip_changed = true;
+ }
+ }
+ else
+ {
+ last_time_ip_changed = false;
+ }
+
+ Lock(r->Lock);
+ {
+ if (StrCmpi(current_hostname, r->CurrentRegisterHostname) != 0)
+ {
+ // The target host name has changed
+ next_getip_tick = 0;
+ StrCpy(current_hostname, sizeof(current_hostname), r->CurrentRegisterHostname);
+ }
+ }
+ Unlock(r->Lock);
+
+ // Get the IP address of the NAT-T server with DNS
+ if (next_getip_tick == 0 || now >= next_getip_tick)
+ {
+ IP ip;
+
+ if (GetIP4(&ip, current_hostname) && IsZeroIp(&ip) == false)
+ {
+ Lock(r->Lock);
+ {
+// Debug("%r %r\n",&r->NatT_IP, &ip);
+ if (CmpIpAddr(&r->NatT_IP, &ip) != 0)
+ {
+// WHERE;
+ ip_changed = true;
+ Copy(&r->NatT_IP, &ip, sizeof(IP));
+ }
+ }
+ Unlock(r->Lock);
+ }
+
+ if (IsZeroIp(&r->NatT_IP))
+ {
+ next_getip_tick = now + (UINT64)UDP_NAT_T_GET_IP_INTERVAL;
+ }
+ else
+ {
+ next_getip_tick = now + (UINT64)UDP_NAT_T_GET_IP_INTERVAL_AFTER;
+ }
+
+ if (ip_changed)
+ {
+ Debug("NAT-T: NAT-T Server IP (%s): %r\n", current_hostname, &r->NatT_IP);
+
+ r->NatT_GetTokenNextTick = 0;
+ r->NatT_RegisterNextTick = 0;
+ r->NatT_GetTokenFailNum = 0;
+ r->NatT_RegisterFailNum = 0;
+
+ r->NatT_TranId = Rand64();
+
+ SetSockEvent(r->SockEvent);
+ }
+ }
+
+ // Get a private IP address of this host using TCP
+ if (next_getprivate_ip_tick == 0 || now >= next_getprivate_ip_tick)
+ {
+ IP ip;
+
+ if (GetMyPrivateIP(&ip))
+ {
+ Lock(r->Lock);
+ {
+ Copy(&r->My_Private_IP, &ip, sizeof(IP));
+ }
+ Unlock(r->Lock);
+ }
+
+ if (IsZeroIp(&r->My_Private_IP))
+ {
+ next_getprivate_ip_tick = now + (UINT64)UDP_NAT_T_GET_PRIVATE_IP_INTERVAL;
+ }
+ else
+ {
+ next_getprivate_ip_tick = now + (UINT64)GenRandInterval(UDP_NAT_T_GET_PRIVATE_IP_INTERVAL_AFTER_MIN, UDP_NAT_T_GET_PRIVATE_IP_INTERVAL_AFTER_MAX);
+ }
+
+ Debug("NAT-T: My Private IP: %r\n", &r->My_Private_IP);
+ }
+
+ if (r->Halt)
+ {
+ break;
+ }
+
+ Wait(r->HaltEvent, RUDP_LOOP_WAIT_INTERVAL_S);
+ }
+
+ FreeRouteChange(route_change_poller);
+}
+
+// Generate a random intervals
+UINT GenRandInterval(UINT min, UINT max)
+{
+ UINT a, b;
+
+ a = MIN(min, max);
+ b = MAX(min, max);
+
+ if (a == b)
+ {
+ return a;
+ }
+
+ return (Rand32() % (b - a)) + a;
+}
+
+// Identify the private IP of the interface which is used to connect to the Internet currently
+bool GetMyPrivateIP(IP *ip)
+{
+ SOCK *s;
+ IP t;
+ char *hostname = UDP_NAT_T_GET_PRIVATE_IP_TCP_SERVER;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ if (IsUseAlternativeHostname())
+ {
+ hostname = UDP_NAT_T_GET_PRIVATE_IP_TCP_SERVER_ALT;
+ }
+
+ s = ConnectEx(hostname, UDP_NAT_T_PORT_FOR_TCP_1, UDP_NAT_T_GET_PRIVATE_IP_CONNECT_TIMEOUT);
+
+ if (s == NULL)
+ {
+ s = ConnectEx(hostname, UDP_NAT_T_PORT_FOR_TCP_2, UDP_NAT_T_GET_PRIVATE_IP_CONNECT_TIMEOUT);
+
+ if (s == NULL)
+ {
+ s = ConnectEx(hostname, UDP_NAT_T_PORT_FOR_TCP_3, UDP_NAT_T_GET_PRIVATE_IP_CONNECT_TIMEOUT);
+
+ if (s == NULL)
+ {
+ return false;
+ }
+ }
+ }
+
+ Copy(&t, &s->LocalIP, sizeof(IP));
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ if (IsZeroIp(&t))
+ {
+ return false;
+ }
+
+ Copy(ip, &t, sizeof(IP));
+
+ return true;
+}
+
+// Function to wait until changing any IP address of the host or expiring the specified time or waking the event
+void WaitUntilHostIPAddressChanged(void *p, EVENT *event, UINT timeout, UINT ip_check_interval)
+{
+ UINT64 start, end;
+ UINT last_hash;
+ // Validate arguments
+ if (timeout == 0x7FFFFFFF)
+ {
+ timeout = 0xFFFFFFFF;
+ }
+ if (ip_check_interval == 0)
+ {
+ ip_check_interval = 0xFFFFFFFF;
+ }
+ if (event == NULL || timeout == 0)
+ {
+ return;
+ }
+
+ start = Tick64();
+ end = start + (UINT64)timeout;
+ last_hash = GetHostIPAddressHash32();
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+ UINT next_interval;
+
+ if (now >= end)
+ {
+ break;
+ }
+
+ if (p != NULL)
+ {
+ if (IsRouteChanged(p))
+ {
+ break;
+ }
+ }
+
+ if (last_hash != GetHostIPAddressHash32())
+ {
+ break;
+ }
+
+ next_interval = (UINT)(end - now);
+ next_interval = MIN(next_interval, ip_check_interval);
+
+ if (Wait(event, next_interval))
+ {
+ break;
+ }
+ }
+}
+void *InitWaitUntilHostIPAddressChanged()
+{
+ void *p = NewRouteChange();
+
+ if (p != NULL)
+ {
+ IsRouteChanged(p);
+ }
+
+ return p;
+}
+void FreeWaitUntilHostIPAddressChanged(void *p)
+{
+ FreeRouteChange(p);
+}
+
+// Get whether the specified IPv6 address is on the local network
+bool IsIPv6LocalNetworkAddress(IP *ip)
+{
+ UINT type;
+ LIST *o;
+ UINT i;
+ bool ret = false;
+ IP mask64;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+ if (IsIP6(ip) == false)
+ {
+ return false;
+ }
+ if (IsZeroIp(ip))
+ {
+ return false;
+ }
+
+ type = GetIPAddrType6(ip);
+
+ if (type & IPV6_ADDR_LOCAL_UNICAST)
+ {
+ return true;
+ }
+
+ if ((type & IPV6_ADDR_GLOBAL_UNICAST) == 0)
+ {
+ return false;
+ }
+
+ IntToSubnetMask6(&mask64, 64);
+
+ o = GetHostIPAddressList();
+
+ ret = false;
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *p = LIST_DATA(o, i);
+
+ if (IsIP6(p))
+ {
+ if (IsZeroIp(p) == false)
+ {
+ if (IsLocalHostIP6(p) == false)
+ {
+ if (IsInSameNetwork6(p, ip, &mask64))
+ {
+ ret = true;
+ }
+ }
+ }
+ }
+ }
+
+ FreeHostIPAddressList(o);
+
+ return ret;
+}
+
+// Check whether the specified IP address is localhost or the IP address of the local interface of itself
+bool IsIPLocalHostOrMySelf(IP *ip)
+{
+ LIST *o;
+ bool ret = false;
+ UINT i;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ o = GetHostIPAddressList();
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *p = LIST_DATA(o, i);
+
+ if (CmpIpAddr(p, ip) == 0)
+ {
+ ret = true;
+
+ break;
+ }
+ }
+
+ FreeHostIPAddressList(o);
+
+ if (IsLocalHostIP4(ip) || IsLocalHostIP6(ip))
+ {
+ ret = true;
+ }
+
+ return ret;
+}
+
+// Get the results of the port number that is determined at random
+UINT RUDPGetRandPortNumber(UCHAR rand_port_id)
+{
+ UINT ret;
+ // Validate arguments
+ if (rand_port_id == 0)
+ {
+ return 0;
+ }
+
+ ret = rand_port_numbers[rand_port_id];
+
+ Debug("rand_port_id[%u] = %u\n", rand_port_id, ret);
+ return ret;
+}
+
+// Obtain the hash value of combining all of the IP address assigned to the host
+UINT GetHostIPAddressHash32()
+{
+ BUF *b;
+ UINT i;
+ UCHAR hash[SHA1_SIZE];
+ UINT ret;
+ LIST *o = GetHostIPAddressList();
+
+ if (o == NULL)
+ {
+ return 0;
+ }
+
+ b = NewBuf();
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *ip = LIST_DATA(o, i);
+
+ WriteBuf(b, ip, sizeof(IP));
+
+ WriteBufStr(b, ":-) yas (-:");
+ }
+ FreeHostIPAddressList(o);
+
+ WriteBuf(b, rand_port_numbers, sizeof(rand_port_numbers));
+
+ HashSha1(hash, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ Copy(&ret, hash, sizeof(UINT));
+
+ return ret;
+}
+
+// Create an IPv4 UDP socket destined for a particular target
+SOCK *NewUDP4ForSpecificIp(IP *target_ip, UINT port)
+{
+ SOCK *s;
+ IP local_ip;
+ // Validate arguments
+ if (target_ip == NULL || IsZeroIP(target_ip) || IsIP4(target_ip) == false)
+ {
+ target_ip = NULL;
+ }
+
+ Zero(&local_ip, sizeof(local_ip));
+ GetBestLocalIpForTarget(&local_ip, target_ip);
+
+ s = NewUDP4(port, &local_ip);
+
+ if (s == NULL)
+ {
+ s = NewUDP4(port, NULL);
+ }
+
+ return s;
+}
+
+// Get the best self IPv4 address to connect to the target IPv4 address
+bool GetBestLocalIpForTarget(IP *local_ip, IP *target_ip)
+{
+ bool ret = false;
+ ROUTE_ENTRY *e;
+ IP ip2;
+ UINT n = 0;
+ IP zero_ip;
+ // Validate arguments
+ Zero(local_ip, sizeof(IP));
+ ZeroIP4(&zero_ip);
+ if (target_ip == NULL)
+ {
+ target_ip = &zero_ip;
+ }
+ if (local_ip == NULL || IsIP4(target_ip) == false)
+ {
+ return false;
+ }
+
+ Copy(&ip2, target_ip, sizeof(IP));
+
+ while (true)
+ {
+ n++;
+ if (n >= 64)
+ {
+ break;
+ }
+
+ e = GetBestRouteEntry(&ip2);
+ if (e != NULL)
+ {
+ if (IsZeroIp(&e->GatewayIP))
+ {
+ Free(e);
+ break;
+ }
+
+ if (e->LocalRouting)
+ {
+ ret = true;
+ Copy(local_ip, &e->GatewayIP, sizeof(IP));
+ Free(e);
+ break;
+ }
+ else
+ {
+ Copy(&ip2, &e->GatewayIP, sizeof(IP));
+ }
+
+ Free(e);
+ }
+ }
+
+ if (ret == false)
+ {
+ if (IsLocalHostIP4(target_ip))
+ {
+ GetLocalHostIP4(local_ip);
+ ret = true;
+ }
+ }
+
+ return ret;
+}
+
+// Create a R-UDP client (Connection via NAT-T gateway)
+SOCK *NewRUDPClientNatT(char *svc_name, IP *ip, UINT *error_code, UINT timeout, bool *cancel, char *hint_str, char *target_hostname)
+{
+ IP nat_t_ip;
+ UINT dummy_int = 0;
+ UINT64 giveup_tick;
+ bool dummy_bool = false;
+ SOCK_EVENT *sock_event;
+ SOCK *sock;
+ bool same_lan = false;
+ char hostname[MAX_SIZE];
+ if (timeout == 0)
+ {
+ timeout = RUDP_TIMEOUT;
+ }
+ if (error_code == NULL)
+ {
+ error_code = &dummy_int;
+ }
+ if (cancel == NULL)
+ {
+ cancel = &dummy_bool;
+ }
+ *error_code = RUDP_ERROR_UNKNOWN;
+ if (svc_name == NULL || ip == NULL)
+ {
+ return NULL;
+ }
+
+ ListenTcpForPopupFirewallDialog();
+
+ giveup_tick = Tick64() + (UINT64)timeout;
+
+ // Get the IP address of the NAT-T server
+ RUDPGetRegisterHostNameByIP(hostname, sizeof(hostname), ip);
+ if (GetIP4Ex(&nat_t_ip, hostname, 0, cancel) == false)
+ {
+ *error_code = RUDP_ERROR_NAT_T_NO_RESPONSE;
+ return NULL;
+ }
+
+ if (Tick64() >= giveup_tick)
+ {
+ *error_code = RUDP_ERROR_TIMEOUT;
+ return NULL;
+ }
+ if (*cancel)
+ {
+ *error_code = RUDP_ERROR_USER_CANCELED;
+ return NULL;
+ }
+
+ sock = NewUDP4ForSpecificIp(&nat_t_ip, 0);
+ if (sock == NULL)
+ {
+ *error_code = RUDP_ERROR_UNKNOWN;
+ return NULL;
+ }
+ else
+ {
+ UINT64 next_send_request_tick = 0;
+ INTERRUPT_MANAGER *interrupt = NewInterruptManager();
+ UINT64 tran_id = Rand64();
+ UINT tmp_size = 65536;
+ UCHAR *tmp = Malloc(tmp_size);
+ char result_ip_str[MAX_SIZE];
+ IP result_ip;
+ UINT result_port;
+ SOCK *ret = NULL;
+ UINT num_tries = 0;
+
+ AddInterrupt(interrupt, giveup_tick);
+
+ sock_event = NewSockEvent();
+ JoinSockToSockEvent(sock, sock_event);
+
+ // Communication with the NAT-T server
+ while (true)
+ {
+ UINT64 now = Tick64();
+ UINT interval;
+ UINT r;
+ IP src_ip;
+ UINT src_port;
+ UINT err;
+ UINT num_ignore_errors = 0;
+
+ if (now >= giveup_tick)
+ {
+ // Time-out
+LABEL_TIMEOUT:
+ *error_code = RUDP_ERROR_NAT_T_NO_RESPONSE;
+ break;
+ }
+
+ if (*cancel)
+ {
+ // User canceled
+ *error_code = RUDP_ERROR_USER_CANCELED;
+ break;
+ }
+
+ err = INFINITE;
+
+ // Receive a response packet from the NAT-T server
+ while (err == INFINITE)
+ {
+ r = RecvFrom(sock, &src_ip, &src_port, tmp, tmp_size);
+ if (r == SOCK_LATER)
+ {
+ // No packet
+ break;
+ }
+ else if (r == 0)
+ {
+ if (sock->IgnoreRecvErr == false)
+ {
+ // Communication error
+ goto LABEL_TIMEOUT;
+ }
+ else
+ {
+ if ((num_ignore_errors++) >= MAX_NUM_IGNORE_ERRORS)
+ {
+ goto LABEL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ // Check the source IP address and the port number
+ if (CmpIpAddr(&src_ip, &nat_t_ip) == 0 && src_port == UDP_NAT_T_PORT)
+ {
+ BUF *b = NewBuf();
+ PACK *p;
+
+ WriteBuf(b, tmp, r);
+ SeekBuf(b, 0, 0);
+
+ p = BufToPack(b);
+
+ if (p != NULL)
+ {
+ // Compare tran_id
+ if (PackGetInt64(p, "tran_id") == tran_id)
+ {
+ // Compare opcode
+ if (PackCmpStr(p, "opcode", "nat_t_connect_request"))
+ {
+ bool ok = PackGetBool(p, "ok");
+ bool multi_candidate = PackGetBool(p, "multi_candidates");
+
+ if (ok)
+ {
+ // Success
+ PackGetStr(p, "result_ip", result_ip_str, sizeof(result_ip_str));
+ StrToIP(&result_ip, result_ip_str);
+
+ result_port = PackGetInt(p, "result_port");
+
+ same_lan = PackGetBool(p, "same_lan");
+
+ if (result_port != 0)
+ {
+ if (IsZeroIp(&result_ip) == false)
+ {
+ if ((sock->IPv6 == false && IsIP4(&result_ip)) ||
+ (sock->IPv6 && IsIP6(&result_ip)))
+ {
+ err = RUDP_ERROR_OK;
+ }
+ }
+ }
+ }
+ else if (multi_candidate)
+ {
+ // There are two or more computers behind the specified IP address
+ err = RUDP_ERROR_NAT_T_TWO_OR_MORE;
+ }
+ else
+ {
+ // Failure
+ err = RUDP_ERROR_NAT_T_NOT_FOUND;
+ }
+ }
+ }
+
+ FreePack(p);
+ }
+
+ FreeBuf(b);
+ }
+ }
+ }
+
+ if (err != INFINITE)
+ {
+ *error_code = err;
+ break;
+ }
+
+ if (next_send_request_tick == 0 || now >= next_send_request_tick)
+ {
+ // Send a connection request to the NAT-T server
+ BUF *b;
+ char ip_str[MAX_SIZE];
+ PACK *p = NewPack();
+
+ PackAddStr(p, "opcode", "nat_t_connect_request");
+ PackAddInt64(p, "tran_id", tran_id);
+ IPToStr(ip_str, sizeof(ip_str), ip);
+ PackAddStr(p, "dest_ip", ip_str);
+ if (IsEmptyStr(hint_str) == false)
+ {
+ PackAddStr(p, "hint", hint_str);
+ }
+ if (IsEmptyStr(target_hostname) == false)
+ {
+ PackAddStr(p, "target_hostname", target_hostname);
+ }
+ PackAddStr(p, "svc_name", svc_name);
+
+ PackAddInt(p, "nat_traversal_version", UDP_NAT_TRAVERSAL_VERSION);
+
+ b = PackToBuf(p);
+ FreePack(p);
+ SendTo(sock, &nat_t_ip, UDP_NAT_T_PORT, b->Buf, b->Size);
+ FreeBuf(b);
+
+ // Determine the next transmission time
+ next_send_request_tick = now + (UINT64)UDP_NAT_T_CONNECT_INTERVAL * (UINT64)(Power(2, MAX(num_tries, 6)));
+ num_tries++;
+ AddInterrupt(interrupt, next_send_request_tick);
+ }
+
+ interval = GetNextIntervalForInterrupt(interrupt);
+ interval = MIN(interval, 50);
+
+ WaitSockEvent(sock_event, interval);
+ }
+
+ Free(tmp);
+ FreeInterruptManager(interrupt);
+
+ if (*error_code == RUDP_ERROR_OK)
+ {
+ UINT remain_timeout;
+ UINT64 now = Tick64();
+ // Success to get the IP address and the port number of the target
+
+ // Get the rest timeout tolerance
+ if (now <= giveup_tick)
+ {
+ remain_timeout = (UINT)(giveup_tick - now);
+ }
+ else
+ {
+ remain_timeout = 0;
+ }
+
+ remain_timeout = MAX(remain_timeout, 2000);
+
+ if (same_lan)
+ {
+ // Discard current UDP socket and create a new UDP socket in NewRUDPClientDirect().
+ // Because using a UDP socket which used for communication with the NAT-T server
+ // can cause trouble when the client and the server exists in the same LAN.
+ ReleaseSockEvent(sock_event);
+ ReleaseSock(sock);
+
+ sock = NULL;
+ sock_event = NULL;
+ }
+
+ ret = NewRUDPClientDirect(svc_name, &result_ip, result_port, error_code, remain_timeout, cancel,
+ sock, sock_event, 0, false);
+ }
+
+ if (sock_event != NULL)
+ {
+ ReleaseSockEvent(sock_event);
+ }
+
+ if (sock != NULL)
+ {
+ ReleaseSock(sock);
+ }
+
+ return ret;
+ }
+}
+
+// Listen to the TCP for a moment to show the firewall dialog
+void ListenTcpForPopupFirewallDialog()
+{
+#ifdef OS_WIN32
+ static bool tried = false;
+
+ if (tried == false)
+ {
+ SOCK *s;
+ tried = true;
+ s = ListenAnyPortEx2(false, true);
+
+ if (s != NULL)
+ {
+ Disconnect(s);
+ ReleaseSock(s);
+ }
+ }
+#endif // OS_WIN32
+}
+
+// Create a R-UDP client (direct connection)
+SOCK *NewRUDPClientDirect(char *svc_name, IP *ip, UINT port, UINT *error_code, UINT timeout, bool *cancel, SOCK *sock, SOCK_EVENT *sock_event, UINT local_port, bool over_dns_mode)
+{
+ RUDP_STACK *r;
+ UINT dummy_int = 0;
+ SOCK *ret = NULL;
+ // Validate arguments
+ if (error_code == NULL)
+ {
+ error_code = &dummy_int;
+ }
+ if (timeout == 0)
+ {
+ timeout = RUDP_TIMEOUT;
+ }
+ *error_code = RUDP_ERROR_UNKNOWN;
+ if (svc_name == NULL || ip == NULL || port == 0)
+ {
+ return NULL;
+ }
+
+ r = NewRUDP(false, svc_name, NULL, NULL, NULL, local_port, sock, sock_event, false, over_dns_mode, ip, NULL, 0);
+ if (r == NULL)
+ {
+ *error_code = RUDP_ERROR_UNKNOWN;
+ return NULL;
+ }
+
+ // Set the port number and the target IP address
+ Lock(r->Lock);
+ {
+ Copy(&r->TargetIp, ip, sizeof(IP));
+ r->TargetPort = port;
+ r->TargetIpAndPortInited = true;
+ }
+ Unlock(r->Lock);
+ SetSockEvent(r->SockEvent);
+
+ // Wait for a connection success/failure to the target IP address
+ WaitEx(r->TargetConnectedEvent, timeout, cancel);
+ Lock(r->Lock);
+ {
+ if (r->TargetConnectedSock != NULL)
+ {
+ // The connection succeeded
+ ret = r->TargetConnectedSock;
+ r->TargetConnectedSock = NULL;
+ }
+ else
+ {
+ r->DoNotSetTargetConnectedSock = true;
+ }
+ }
+ Unlock(r->Lock);
+
+ if (ret == NULL)
+ {
+ // Stop the R-UDP stack if the connection has failed
+ *error_code = RUDP_ERROR_TIMEOUT;
+ FreeRUDP(r);
+ }
+ else if (cancel != NULL && (*cancel))
+ {
+ // User canceled
+ *error_code = RUDP_ERROR_USER_CANCELED;
+
+ Disconnect(ret);
+ ReleaseSock(ret);
+
+ ret = NULL;
+ }
+ else
+ {
+ *error_code = RUDP_ERROR_OK;
+ }
+
+ return ret;
+}
+
+// Creating a R-UDP server
+RUDP_STACK *NewRUDPServer(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode, volatile UINT *natt_global_udp_port, UCHAR rand_port_id)
+{
+ RUDP_STACK *r;
+ // Validate arguments
+ if (IsEmptyStr(svc_name))
+ {
+ return NULL;
+ }
+
+ if (g_no_rudp_server)
+ {
+ return NULL;
+ }
+
+ ListenTcpForPopupFirewallDialog();
+
+ r = NewRUDP(true, svc_name, proc_interrupts, proc_rpc_recv, param, port, NULL, NULL, no_natt_register, over_dns_mode, NULL, natt_global_udp_port, rand_port_id);
+
+ if (r == NULL)
+ {
+ return NULL;
+ }
+
+ return r;
+}
+
+// Creating a R-UDP
+RUDP_STACK *NewRUDP(bool server_mode, char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, SOCK *sock, SOCK_EVENT *sock_event, bool server_no_natt_register, bool over_dns_mode, IP *client_target_ip, volatile UINT *natt_global_udp_port, UCHAR rand_port_id)
+{
+ RUDP_STACK *r;
+ char tmp[MAX_SIZE];
+ UCHAR pid_hash[SHA1_SIZE];
+ UINT pid;
+ USHORT pid_us;
+
+ // Validate arguments
+ if (IsEmptyStr(svc_name))
+ {
+ return NULL;
+ }
+
+ ListenTcpForPopupFirewallDialog();
+
+ if (sock == NULL)
+ {
+ if (server_mode == false && client_target_ip != NULL)
+ {
+ sock = NewUDP4ForSpecificIp(client_target_ip, port);
+ }
+ else
+ {
+ if (rand_port_id == 0)
+ {
+ sock = NewUDP(port);
+ }
+ else
+ {
+ sock = NewUDPEx2RandMachineAndExePath(false, NULL, 0, rand_port_id);
+ }
+ }
+
+ if (sock == NULL)
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ AddRef(sock->ref);
+ }
+
+ if (port == 0)
+ {
+ port = sock->LocalPort;
+ }
+
+ if (rand_port_id != 0)
+ {
+ rand_port_numbers[rand_port_id] = port;
+ }
+
+ if (sock_event == NULL)
+ {
+ sock_event = NewSockEvent();
+ }
+ else
+ {
+ AddRef(sock_event->ref);
+ }
+
+ r = ZeroMalloc(sizeof(RUDP_STACK));
+
+ StrCpy(r->SvcName, sizeof(r->SvcName), svc_name);
+ r->RandPortId = rand_port_id;
+ r->NatTGlobalUdpPort = natt_global_udp_port;
+ r->ServerMode = server_mode;
+ r->Interrupt = NewInterruptManager();
+ r->SessionList = NewList(RUDPCompareSessionList);
+ r->UdpSock = sock;
+ r->Port = port;
+ r->SockEvent = sock_event;
+ r->HaltEvent = NewEvent();
+ r->Now = Tick64();
+ r->Lock = NewLock();
+ r->Param = param;
+ r->TargetConnectedEvent = NewEvent();
+ r->SendPacketList = NewList(NULL);
+ r->NewSockConnectEvent = NewEvent();
+ r->NewSockQueue = NewQueue();
+ r->NatT_TranId = Rand64();
+
+ StrCpy(tmp, sizeof(tmp), r->SvcName);
+ Trim(tmp);
+ StrLower(tmp);
+
+ HashSha1(r->SvcNameHash, tmp, StrLen(tmp));
+
+ r->Client_IcmpId = (USHORT)(Rand32() % 65534 + 1);
+ r->Client_IcmpSeqNo = (USHORT)(Rand32() % 65534 + 1);
+
+ // Determination of the type of the protocol
+ r->Protocol = RUDP_PROTOCOL_UDP;
+ if (r->Port == MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4))
+ {
+ r->Protocol = RUDP_PROTOCOL_ICMP;
+
+ // Generate the ICMP ID based on the process ID
+#ifdef OS_WIN32
+ pid = (UINT)MsGetProcessId();
+#else // OS_WIN32
+ pid = (UINT)getpid();
+#endif // OS_WIN32
+
+ pid = Endian32(pid);
+ HashSha1(pid_hash, &pid, sizeof(UINT));
+
+ pid_us = READ_USHORT(pid_hash);
+ if (pid_us == 0 || pid_us == 0xFFFF)
+ {
+ pid_us = 1;
+ }
+
+ r->Client_IcmpId = pid_us;
+ }
+ else if (over_dns_mode)
+ {
+ r->Protocol = RUDP_PROTOCOL_DNS;
+ }
+
+ if (r->ServerMode)
+ {
+ r->NoNatTRegister = server_no_natt_register;
+
+ if (r->Protocol == RUDP_PROTOCOL_ICMP || r->Protocol == RUDP_PROTOCOL_DNS)
+ {
+ // Never register to the NAT-T server in case of using the DNS or the ICMP
+ r->NoNatTRegister = true;
+ }
+ }
+
+ RUDPGetRegisterHostNameByIP(r->CurrentRegisterHostname, sizeof(r->CurrentRegisterHostname), NULL);
+
+ if (r->ServerMode)
+ {
+ r->ProcInterrupts = proc_interrupts;
+ r->ProcRpcRecv = proc_rpc_recv;
+ }
+
+ if (r->ServerMode && r->NoNatTRegister == false)
+ {
+ r->IpQueryThread = NewThread(RUDPIpQueryThread, r);
+ }
+
+ JoinSockToSockEvent(r->UdpSock, r->SockEvent);
+
+ r->Thread = NewThread(RUDPMainThread, r);
+ WaitThreadInit(r->Thread);
+
+ return r;
+}
+
+// R-UDP session comparison function
+int RUDPCompareSessionList(void *p1, void *p2)
+{
+ RUDP_SESSION *s1, *s2;
+ UINT r;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ s1 = *((RUDP_SESSION **)p1);
+ s2 = *((RUDP_SESSION **)p2);
+ if (s1 == NULL || s2 == NULL)
+ {
+ return 0;
+ }
+
+ r = CmpIpAddr(&s1->YourIp, &s2->YourIp);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = COMPARE_RET(s1->YourPort, s2->YourPort);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = CmpIpAddr(&s1->MyIp, &s2->MyIp);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ r = COMPARE_RET(s1->MyPort, s2->MyPort);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ return 0;
+}
+
+// Release of the R-UDP
+void FreeRUDP(RUDP_STACK *r)
+{
+ UINT i;
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ r->Halt = true;
+ Set(r->HaltEvent);
+ SetSockEvent(r->SockEvent);
+
+ if (r->ServerMode && r->NoNatTRegister == false)
+ {
+ WaitThread(r->IpQueryThread, INFINITE);
+ ReleaseThread(r->IpQueryThread);
+ }
+
+ WaitThread(r->Thread, INFINITE);
+ ReleaseThread(r->Thread);
+
+ for (i = 0;i < LIST_NUM(r->SessionList);i++)
+ {
+ RUDP_SESSION *se = LIST_DATA(r->SessionList, i);
+
+ RUDPFreeSession(se);
+ }
+
+ ReleaseList(r->SessionList);
+
+ for (i = 0;i < LIST_NUM(r->SendPacketList);i++)
+ {
+ UDPPACKET *p = LIST_DATA(r->SendPacketList, i);
+
+ FreeUdpPacket(p);
+ }
+
+ while (true)
+ {
+ SOCK *s = GetNext(r->NewSockQueue);
+ if (s == NULL)
+ {
+ break;
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+ }
+
+ ReleaseQueue(r->NewSockQueue);
+
+ ReleaseList(r->SendPacketList);
+
+ FreeInterruptManager(r->Interrupt);
+
+ Disconnect(r->UdpSock);
+ ReleaseSock(r->UdpSock);
+ ReleaseSockEvent(r->SockEvent);
+ ReleaseEvent(r->HaltEvent);
+ ReleaseEvent(r->TargetConnectedEvent);
+
+ ReleaseEvent(r->NewSockConnectEvent);
+
+ Disconnect(r->TargetConnectedSock);
+ ReleaseSock(r->TargetConnectedSock);
+
+ DeleteLock(r->Lock);
+
+ if (r->RandPortId != 0)
+ {
+ rand_port_numbers[r->RandPortId] = 0;
+ }
+
+ Free(r);
+}
+
+// Generate a hash from the current computer name and the process name
+void GetCurrentMachineIpProcessHash(void *hash)
+{
+ // Validate arguments
+ if (hash == NULL)
+ {
+ return;
+ }
+
+ Lock(machine_ip_process_hash_lock);
+ {
+ if (IsZero(machine_ip_process_hash, SHA1_SIZE))
+ {
+ GetCurrentMachineIpProcessHashInternal(machine_ip_process_hash);
+ }
+
+ Copy(hash, machine_ip_process_hash, SHA1_SIZE);
+ }
+ Unlock(machine_ip_process_hash_lock);
+}
+void GetCurrentMachineIpProcessHashInternal(void *hash)
+{
+ BUF *b;
+ LIST *ip_list;
+ char machine_name[MAX_SIZE];
+ wchar_t exe_path[MAX_PATH];
+ char *product_id = NULL;
+ // Validate arguments
+ if (hash == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductId");
+ if (product_id == NULL)
+ {
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductId");
+ }
+#endif // OS_WIN32
+
+ b = NewBuf();
+
+ GetMachineHostName(machine_name, sizeof(machine_name));
+ Trim(machine_name);
+ StrUpper(machine_name);
+
+ GetExeNameW(exe_path, sizeof(exe_path));
+ UniTrim(exe_path);
+ UniStrUpper(exe_path);
+
+ WriteBuf(b, machine_name, StrSize(machine_name));
+ WriteBuf(b, exe_path, UniStrSize(exe_path));
+ WriteBuf(b, product_id, StrSize(product_id));
+
+ ip_list = GetHostIPAddressList();
+ if (ip_list != NULL)
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(ip_list);i++)
+ {
+ IP *ip = LIST_DATA(ip_list, i);
+
+ WriteBuf(b, ip, sizeof(IP));
+ }
+ }
+ FreeHostIPAddressList(ip_list);
+
+ HashSha1(hash, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ Free(product_id);
+}
+
+// Create a pair of pre-bound TCP sockets
+bool NewTcpPair(SOCK **s1, SOCK **s2)
+{
+ SOCK *a;
+ SOCK *s, *c;
+ TUBE *t1, *t2;
+ SOCK_EVENT *e1, *e2;
+ // Validate arguments
+ if (s1 == NULL || s2 == NULL)
+ {
+ return false;
+ }
+
+ a = ListenAnyPortEx2(true, true);
+ if (a == NULL)
+ {
+ return false;
+ }
+
+ c = Connect("127.0.0.1", a->LocalPort);
+ if (c == NULL)
+ {
+ ReleaseSock(a);
+ return false;
+ }
+
+ s = Accept(a);
+ if (s == NULL)
+ {
+ ReleaseSock(c);
+ ReleaseSock(a);
+ return false;
+ }
+
+ ReleaseSock(a);
+
+ if ((s->LocalPort != c->RemotePort) || (s->RemotePort != c->LocalPort))
+ {
+ ReleaseSock(s);
+ ReleaseSock(c);
+ return false;
+ }
+
+ NewTubePair(&t1, &t2, sizeof(TCP_PAIR_HEADER));
+
+ // Creating a socket event
+ e1 = NewSockEvent();
+ e2 = NewSockEvent();
+
+ SetTubeSockEvent(t1, e1);
+ SetTubeSockEvent(t2, e2);
+
+ AddRef(t1->Ref);
+ AddRef(t2->Ref);
+ s->BulkRecvTube = c->BulkSendTube = t1;
+ s->BulkSendTube = c->BulkRecvTube = t2;
+
+ ReleaseSockEvent(e1);
+ ReleaseSockEvent(e2);
+
+ *s1 = s;
+ *s2 = c;
+
+ return true;
+}
+
+// Listen in any available port
+SOCK *ListenAnyPortEx(bool local_only)
+{
+ return ListenAnyPortEx2(local_only, false);
+}
+SOCK *ListenAnyPortEx2(bool local_only, bool disable_ca)
+{
+ UINT i;
+ SOCK *s;
+ for (i = 40000;i < 65536;i++)
+ {
+ s = ListenEx(i, local_only);
+ if (s != NULL)
+ {
+ return s;
+ }
+ }
+
+ return NULL;
+}
+
+int cb_test(int a, X509_STORE_CTX *ctx)
+{
+ WHERE;
+ return 1;
+}
+
+// Create a new SSL pipe
+SSL_PIPE *NewSslPipe(bool server_mode, X *x, K *k, DH_CTX *dh)
+{
+ SSL_PIPE *s;
+ SSL *ssl;
+ SSL_CTX *ssl_ctx = NewSSLCtx();
+
+ Lock(openssl_lock);
+ {
+ if (server_mode)
+ {
+ SSL_CTX_set_ssl_version(ssl_ctx, TLSv1_server_method());
+
+ AddChainSslCertOnDirectory(ssl_ctx);
+
+ if (dh != NULL)
+ {
+ SSL_CTX_set_tmp_dh(ssl_ctx, dh->dh);
+ }
+ }
+ else
+ {
+ SSL_CTX_set_ssl_version(ssl_ctx, TLSv1_client_method());
+ }
+
+ //SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, cb_test);
+
+ if (dh != NULL)
+ {
+ SSL_CTX_set_options(ssl_ctx, SSL_OP_SINGLE_DH_USE);
+ }
+
+ ssl = SSL_new(ssl_ctx);
+ }
+ Unlock(openssl_lock);
+
+ s = ZeroMalloc(sizeof(SSL_PIPE));
+
+ s->ssl = ssl;
+ s->ssl_ctx = ssl_ctx;
+ s->ServerMode = server_mode;
+
+ s->SslInOut = NewSslBioSsl();
+ s->RawIn = NewSslBioMem();
+ s->RawOut = NewSslBioMem();
+
+ if (x != NULL && k != NULL)
+ {
+ Lock(openssl_lock);
+ {
+ SSL_use_certificate(s->ssl, x->x509);
+ SSL_use_PrivateKey(s->ssl, k->pkey);
+ }
+ Unlock(openssl_lock);
+ }
+
+ if (s->ServerMode == false)
+ {
+ SSL_set_connect_state(s->ssl);
+ }
+ else
+ {
+ SSL_set_accept_state(s->ssl);
+ }
+
+ SSL_set_bio(s->ssl, s->RawIn->bio, s->RawOut->bio);
+ BIO_set_ssl(s->SslInOut->bio, s->ssl, BIO_NOCLOSE);
+
+ //s->RawIn->NoFree = true;
+ s->RawOut->NoFree = true;
+
+ return s;
+}
+
+// Synchronization of the SSL pipe
+bool SyncSslPipe(SSL_PIPE *s)
+{
+ UINT i;
+ // Validate arguments
+ if (s == NULL || s->IsDisconnected)
+ {
+ return false;
+ }
+
+ for (i = 0;i < 2;i++)
+ {
+ if (SslBioSync(s->RawIn, true, false) == false)
+ {
+ s->IsDisconnected = true;
+ Debug("SyncSslPipe: s->RawIn error.\n");
+ return false;
+ }
+
+ if (SslBioSync(s->RawOut, false, true) == false)
+ {
+ s->IsDisconnected = true;
+ Debug("SyncSslPipe: s->RawOut error.\n");
+ return false;
+ }
+
+ if (SslBioSync(s->SslInOut, true, true) == false)
+ {
+ s->IsDisconnected = true;
+ Debug("SyncSslPipe: s->SslInOut error.\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Release of the SSL pipe
+void FreeSslPipe(SSL_PIPE *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ FreeSslBio(s->SslInOut);
+ FreeSslBio(s->RawIn);
+ FreeSslBio(s->RawOut);
+
+ SSL_free(s->ssl);
+ SSL_CTX_free(s->ssl_ctx);
+
+ Free(s);
+}
+
+// Release of the SSL BIO
+void FreeSslBio(SSL_BIO *b)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return;
+ }
+
+ if (b->NoFree == false)
+ {
+ BIO_free(b->bio);
+ }
+
+ ReleaseFifo(b->RecvFifo);
+ ReleaseFifo(b->SendFifo);
+
+ Free(b);
+}
+
+// Create a new SSL BIO (SSL)
+SSL_BIO *NewSslBioSsl()
+{
+ SSL_BIO *b = ZeroMalloc(sizeof(SSL_BIO));
+
+ b->bio = BIO_new(BIO_f_ssl());
+
+ b->RecvFifo = NewFifo();
+ b->SendFifo = NewFifo();
+
+ return b;
+}
+
+// Create a new SSL BIO (memory)
+SSL_BIO *NewSslBioMem()
+{
+ SSL_BIO *b = ZeroMalloc(sizeof(SSL_BIO));
+
+ b->bio = BIO_new(BIO_s_mem());
+
+ b->RecvFifo = NewFifo();
+ b->SendFifo = NewFifo();
+
+ return b;
+}
+
+// Synchronize memory contents of the SSL BIO with the FIFO
+bool SslBioSync(SSL_BIO *b, bool sync_send, bool sync_recv)
+{
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (b->IsDisconnected)
+ {
+ return false;
+ }
+
+ // Write the contents of the SendFifo to the BIO
+ if (sync_send)
+ {
+ while (b->SendFifo->size >= 1)
+ {
+ int r = BIO_write(b->bio, GetFifoPointer(b->SendFifo), FifoSize(b->SendFifo));
+
+ if (r == 0)
+ {
+ b->IsDisconnected = true;
+ WHERE;
+ return false;
+ }
+ else
+ {
+ if (r < 0)
+ {
+ if (BIO_should_retry(b->bio))
+ {
+ break;
+ }
+ else
+ {
+ b->IsDisconnected = true;
+ WHERE;
+ return false;
+ }
+ }
+ else
+ {
+ ReadFifo(b->SendFifo, NULL, (UINT)r);
+ }
+ }
+ }
+ }
+
+ // Save to the RecvFifo by reading from the BIO
+ if (sync_recv)
+ {
+ while (true)
+ {
+ UCHAR tmp[4096];
+ int r;
+
+ r = BIO_read(b->bio, tmp, sizeof(tmp));
+
+ if (r == 0)
+ {
+ b->IsDisconnected = true;
+ WHERE;
+ return false;
+ }
+ else
+ {
+ if (r < 0)
+ {
+ if (BIO_should_retry(b->bio))
+ {
+ break;
+ }
+ else
+ {
+ b->IsDisconnected = true;
+ WHERE;
+ Debug("OpenSSL Error: %s\n", ERR_error_string(ERR_peek_last_error(), NULL));
+ return false;
+ }
+ }
+ else
+ {
+ WriteFifo(b->RecvFifo, tmp, (UINT)r);
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+// Release the memory for the return value of the ICMP API
+void IcmpApiFreeResult(ICMP_RESULT *ret)
+{
+ // Validate arguments
+ if (ret == NULL)
+ {
+ return;
+ }
+
+ if (ret->Data != NULL)
+ {
+ Free(ret->Data);
+ }
+
+ Free(ret);
+}
+
+// Send an ICMP Echo using ICMP API
+ICMP_RESULT *IcmpApiEchoSend(IP *dest_ip, UCHAR ttl, UCHAR *data, UINT size, UINT timeout)
+{
+#ifdef OS_WIN32
+ // Validate arguments
+ if (dest_ip == NULL || IsIP4(dest_ip) == false || (size != 0 && data == NULL))
+ {
+ return NULL;
+ }
+ if (ttl == 0)
+ {
+ ttl = 127;
+ }
+
+ if (IsIcmpApiSupported())
+ {
+ HANDLE h;
+ DWORD dw;
+ IPAddr dest_addr;
+ UINT reply_size;
+ ICMP_ECHO_REPLY *reply;
+ ICMP_RESULT *ret = NULL;
+ IP_OPTION_INFORMATION opt;
+
+ h = w32net->IcmpCreateFile();
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return NULL;
+ }
+
+ Zero(&opt, sizeof(opt));
+ opt.Ttl = ttl;
+
+ IPToInAddr((struct in_addr *)&dest_addr, dest_ip);
+
+ reply_size = sizeof(*reply) + size + 64;
+ reply = ZeroMalloc(reply_size);
+
+ dw = w32net->IcmpSendEcho(h, dest_addr, data, size, &opt, reply, reply_size, timeout);
+
+ ret = ZeroMalloc(sizeof(ICMP_RESULT));
+
+ if (dw >= 1 && reply->Status == IP_SUCCESS)
+ {
+ ret->Ok = true;
+ }
+ else
+ {
+ switch (reply->Status)
+ {
+ case IP_DEST_NET_UNREACHABLE:
+ ret->Type = ICMP_TYPE_DESTINATION_UNREACHABLE;
+ ret->Code = ICMP_CODE_NET_UNREACHABLE;
+ break;
+
+ case IP_DEST_HOST_UNREACHABLE:
+ ret->Type = ICMP_TYPE_DESTINATION_UNREACHABLE;
+ ret->Code = ICMP_CODE_HOST_UNREACHABLE;
+ break;
+
+ case IP_DEST_PROT_UNREACHABLE:
+ ret->Type = ICMP_TYPE_DESTINATION_UNREACHABLE;
+ ret->Code = ICMP_CODE_PROTOCOL_UNREACHABLE;
+ break;
+
+ case IP_DEST_PORT_UNREACHABLE:
+ ret->Type = ICMP_TYPE_DESTINATION_UNREACHABLE;
+ ret->Code = ICMP_CODE_PORT_UNREACHABLE;
+ break;
+
+ case IP_TTL_EXPIRED_TRANSIT:
+ ret->Type = ICMP_TYPE_TIME_EXCEEDED;
+ ret->Code = ICMP_CODE_TTL_EXCEEDED_IN_TRANSIT;
+ break;
+
+ case IP_TTL_EXPIRED_REASSEM:
+ ret->Type = ICMP_TYPE_TIME_EXCEEDED;
+ ret->Code = ICMP_CODE_FRAGMENT_REASSEMBLY_TIME_EXCEEDED;
+ break;
+
+ default:
+ ret->Timeout = true;
+ break;
+ }
+ }
+
+ if (ret->Timeout == false)
+ {
+ ret->Ttl = reply->Options.Ttl;
+ ret->Rtt = reply->RoundTripTime;
+ InAddrToIP(&ret->IpAddress, (struct in_addr *)&reply->Address);
+
+ if (reply->DataSize >= 1 && reply->Data != NULL)
+ {
+ ret->DataSize = reply->DataSize;
+ ret->Data = Clone(reply->Data, reply->DataSize);
+ }
+ }
+
+ Free(reply);
+
+ w32net->IcmpCloseHandle(h);
+
+ return ret;
+ }
+ else
+ {
+ return NULL;
+ }
+
+#else // OS_WIN32
+ return NULL;
+#endif // OS_WIN32
+}
+
+// Detect whether the ICMP API is supported
+bool IsIcmpApiSupported()
+{
+#ifdef OS_WIN32
+ if (w32net->IcmpCloseHandle != NULL &&
+ w32net->IcmpCreateFile != NULL &&
+ w32net->IcmpSendEcho != NULL)
+ {
+ return true;
+ }
+#endif // OS_WIN32
+
+ return false;
+}
+
+// Initialize the routing table change detector
+ROUTE_CHANGE *NewRouteChange()
+{
+#ifdef OS_WIN32
+ return Win32NewRouteChange();
+#else // OS_WIN32
+ return NULL;
+#endif // OS_WIN32
+}
+
+// Release the routing table change detector
+void FreeRouteChange(ROUTE_CHANGE *r)
+{
+#ifdef OS_WIN32
+ Win32FreeRouteChange(r);
+#endif // OS_WIN32
+}
+
+// Get whether the routing table has been changed
+bool IsRouteChanged(ROUTE_CHANGE *r)
+{
+#ifdef OS_WIN32
+ return Win32IsRouteChanged(r);
+#else // OS_WIN32
+ return false;
+#endif // OS_WIN32
+}
+
+// Routing table change detector function (Win32)
+#ifdef OS_WIN32
+ROUTE_CHANGE *Win32NewRouteChange()
+{
+ ROUTE_CHANGE *r;
+ bool ret;
+
+ if (MsIsNt() == false)
+ {
+ return NULL;
+ }
+
+ if (w32net->CancelIPChangeNotify == NULL ||
+ w32net->NotifyRouteChange == NULL)
+ {
+ return NULL;
+ }
+
+ r = ZeroMalloc(sizeof(ROUTE_CHANGE));
+
+ r->Data = ZeroMalloc(sizeof(ROUTE_CHANGE_DATA));
+
+ r->Data->Overlapped.hEvent = CreateEventA(NULL, false, true, NULL);
+
+ ret = w32net->NotifyRouteChange(&r->Data->Handle, &r->Data->Overlapped);
+ if (!(ret == NO_ERROR || ret == WSA_IO_PENDING || WSAGetLastError() == WSA_IO_PENDING))
+ {
+ Free(r->Data);
+ Free(r);
+
+ return NULL;
+ }
+
+ return r;
+}
+
+void Win32FreeRouteChange(ROUTE_CHANGE *r)
+{
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ w32net->CancelIPChangeNotify(&r->Data->Overlapped);
+ CloseHandle(r->Data->Overlapped.hEvent);
+
+ Free(r->Data);
+ Free(r);
+}
+
+bool Win32IsRouteChanged(ROUTE_CHANGE *r)
+{
+ // Validate arguments
+ if (r == NULL)
+ {
+ return false;
+ }
+
+ if ((r->Data->NumCalled++) == 0)
+ {
+ return true;
+ }
+
+ if (WaitForSingleObject(r->Data->Overlapped.hEvent, 0) == WAIT_OBJECT_0)
+ {
+ w32net->NotifyRouteChange(&r->Data->Handle, &r->Data->Overlapped);
+ return true;
+ }
+
+ return false;
+}
+
+typedef struct WIN32_ACCEPT_CHECK_DATA
+{
+ bool IsIPv6;
+ bool Rejected;
+} WIN32_ACCEPT_CHECK_DATA;
+
+// Function for determining whether accept or not in Win32
+int CALLBACK Win32AcceptCheckCallback_Delay(LPWSABUF lpCallerId, LPWSABUF lpCallerData, LPQOS pQos,
+ LPQOS lpGQOS, LPWSABUF lpCalleeId, LPWSABUF lpCalleeData,
+ GROUP FAR * g, DWORD_PTR dwCallbackData)
+{
+ return CF_DEFER;
+}
+
+int CALLBACK Win32AcceptCheckCallback(LPWSABUF lpCallerId, LPWSABUF lpCallerData, LPQOS pQos,
+ LPQOS lpGQOS, LPWSABUF lpCalleeId, LPWSABUF lpCalleeData,
+ GROUP FAR * g, DWORD_PTR dwCallbackData)
+{
+ return CF_ACCEPT;
+}
+
+// Accept function for Win32
+SOCKET Win32Accept_XP(SOCK *sock, SOCKET s, struct sockaddr *addr, int *addrlen, bool ipv6)
+{
+ SOCKET ret;
+ WIN32_ACCEPT_CHECK_DATA d;
+ UINT err;
+ int initial_addrlen = *addrlen;
+ UINT num_error = 0;
+ // Validate arguments
+ if (s == INVALID_SOCKET)
+ {
+ return INVALID_SOCKET;
+ }
+
+L_LOOP:
+
+ Zero(&d, sizeof(d));
+
+ d.IsIPv6 = ipv6;
+
+ *addrlen = initial_addrlen;
+ Zero(addr, initial_addrlen);
+ ret = WSAAccept(s, addr, addrlen, Win32AcceptCheckCallback, (DWORD_PTR)&d);
+
+ if (ret == INVALID_SOCKET)
+ {
+ err = WSAGetLastError();
+
+ num_error++;
+
+ Debug("!!! WSAAccept Error: %u rej=%u num=%u tick=%I64u\n", WSAGetLastError(), d.Rejected, num_error, Tick64());
+
+ if (d.Rejected && err == WSAECONNREFUSED)
+ {
+ goto L_LOOP;
+ }
+
+ if (err == WSAETIMEDOUT)
+ {
+ goto L_LOOP;
+ }
+ }
+
+ return ret;
+}
+
+// Accept function for Win32
+SOCKET Win32Accept(SOCK *sock, SOCKET s, struct sockaddr *addr, int *addrlen, bool ipv6)
+{
+ SOCKET ret;
+ WIN32_ACCEPT_CHECK_DATA d;
+ UINT err;
+ int initial_addrlen = *addrlen;
+ UINT num_error = 0;
+ UINT zero = 0;
+ UINT tmp = 0;
+ UINT ret_size = 0;
+ // Validate arguments
+ if (sock == NULL || s == INVALID_SOCKET)
+ {
+ return INVALID_SOCKET;
+ }
+
+ if (sock->hAcceptEvent == NULL)
+ {
+ sock->hAcceptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ WSAEventSelect(s, sock->hAcceptEvent, FD_ACCEPT | FD_CLOSE);
+ }
+
+L_LOOP:
+
+ if (sock->CancelAccept)
+ {
+ return INVALID_SOCKET;
+ }
+
+ Zero(&d, sizeof(d));
+
+ d.IsIPv6 = ipv6;
+
+ *addrlen = initial_addrlen;
+ Zero(addr, initial_addrlen);
+ ret = WSAAccept(s, addr, addrlen, Win32AcceptCheckCallback, (DWORD_PTR)&d);
+
+ if (ret == INVALID_SOCKET)
+ {
+ err = WSAGetLastError();
+
+ if (err == WSAEWOULDBLOCK)
+ {
+ //Debug("!!! WSAAccept: WSAEWOULDBLOCK\n");
+ UINT wait_ret = WaitForSingleObject(sock->hAcceptEvent, 1234);
+
+ if (wait_ret == WAIT_OBJECT_0 || wait_ret == WAIT_TIMEOUT)
+ {
+ goto L_LOOP;
+ }
+
+ Debug("!!! WaitForSingleObject Error. ret=%u GetLastError=%u\n", wait_ret, GetLastError());
+ }
+
+ num_error++;
+
+ Debug("!!! WSAAccept Error: %u rej=%u num=%u tick=%I64u\n", err, d.Rejected, num_error, Tick64());
+
+ if (d.Rejected && err == WSAECONNREFUSED)
+ {
+ goto L_LOOP;
+ }
+
+ if (err == WSAETIMEDOUT)
+ {
+ goto L_LOOP;
+ }
+ }
+ else
+ {
+ // Remove a new socket from the event
+ WSAEventSelect(ret, sock->hAcceptEvent, 0);
+
+ // Restore the new socket to synchronized
+ WSAIoctl(ret, FIONBIO, &zero, sizeof(zero), &tmp, sizeof(tmp), &ret_size, NULL, NULL);
+ }
+
+ return ret;
+}
+
+#endif // OS_WIN32
+
+
+// Get whether the aquirement of the Process ID of the TCP connection succeed
+bool CanGetTcpProcessId()
+{
+ UINT i;
+ bool ret = false;
+ LIST *o = GetTcpTableList();
+
+ if (o == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ TCPTABLE *t = LIST_DATA(o, i);
+
+ if (t->ProcessId != 0)
+ {
+ ret = true;
+ break;
+ }
+ }
+
+ FreeTcpTableList(o);
+
+ return ret;
+}
+
+
+
+
+#define USE_OLD_GETIP
+
+// Set the arp_filter in Linux
+void SetLinuxArpFilter()
+{
+ char *filename = "/proc/sys/net/ipv4/conf/all/arp_filter";
+ char *data = "1\n";
+ IO *o;
+
+ o = FileCreate(filename);
+ if (o == NULL)
+ {
+ return;
+ }
+
+ FileWrite(o, data, StrLen(data));
+ FileFlush(o);
+
+ FileClose(o);
+}
+
+// Determine whether the string is a IPv6 mask
+bool IsIpMask6(char *str)
+{
+ IP mask;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ return StrToMask6(&mask, str);
+}
+
+// Determine whether the string is a IPv6 address
+bool IsStrIPv6Address(char *str)
+{
+ IP ip;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ if (StrToIP6(&ip, str) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Convert the subnet mask to an integer
+UINT SubnetMaskToInt6(IP *a)
+{
+ UINT i;
+ // Validate arguments
+ if (IsIP6(a) == false)
+ {
+ return 0;
+ }
+
+ for (i = 0;i <= 128;i++)
+ {
+ IP tmp;
+
+ IntToSubnetMask6(&tmp, i);
+
+ if (CmpIpAddr(a, &tmp) == 0)
+ {
+ return i;
+ }
+ }
+
+ return 0;
+}
+UINT SubnetMaskToInt4(IP *a)
+{
+ UINT i;
+ // Validate arguments
+ if (IsIP4(a) == false)
+ {
+ return 0;
+ }
+
+ for (i = 0;i <= 32;i++)
+ {
+ IP tmp;
+
+ IntToSubnetMask4(&tmp, i);
+
+ if (CmpIpAddr(a, &tmp) == 0)
+ {
+ return i;
+ }
+ }
+
+ return 0;
+}
+UINT SubnetMaskToInt(IP *a)
+{
+ if (IsIP6(a))
+ {
+ return SubnetMaskToInt6(a);
+ }
+ else
+ {
+ return SubnetMaskToInt4(a);
+ }
+}
+
+// Determine whether the specified IP address is a subnet mask
+bool IsSubnetMask6(IP *a)
+{
+ UINT i;
+ // Validate arguments
+ if (IsIP6(a) == false)
+ {
+ return false;
+ }
+
+ for (i = 0;i <= 128;i++)
+ {
+ IP tmp;
+
+ IntToSubnetMask6(&tmp, i);
+
+ if (CmpIpAddr(a, &tmp) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Generate a global address from the MAC address
+void GenerateEui64GlobalAddress(IP *ip, IP *prefix, IP *subnet, UCHAR *mac)
+{
+ UCHAR tmp[8];
+ IP a;
+ IP subnet_not;
+ IP or1, or2;
+ // Validate arguments
+ if (ip == NULL || prefix == NULL || subnet == NULL || mac == NULL)
+ {
+ return;
+ }
+
+ GenerateEui64Address6(tmp, mac);
+
+ ZeroIP6(&a);
+
+ Copy(&a.ipv6_addr[8], tmp, 8);
+
+ IPNot6(&subnet_not, subnet);
+ IPAnd6(&or1, &a, &subnet_not);
+ IPAnd6(&or2, prefix, subnet);
+
+ IPOr6(ip, &or1, &or2);
+}
+
+// Generate a local address from the MAC address
+void GenerateEui64LocalAddress(IP *a, UCHAR *mac)
+{
+ UCHAR tmp[8];
+ // Validate arguments
+ if (a == NULL || mac == NULL)
+ {
+ return;
+ }
+
+ GenerateEui64Address6(tmp, mac);
+
+ ZeroIP6(a);
+ a->ipv6_addr[0] = 0xfe;
+ a->ipv6_addr[1] = 0x80;
+
+ Copy(&a->ipv6_addr[8], tmp, 8);
+}
+
+// Generate the EUI-64 address from the MAC address
+void GenerateEui64Address6(UCHAR *dst, UCHAR *mac)
+{
+ // Validate arguments
+ if (dst == NULL || mac == NULL)
+ {
+ return;
+ }
+
+ Copy(dst, mac, 3);
+ Copy(dst + 5, mac, 3);
+
+ dst[3] = 0xff;
+ dst[4] = 0xfe;
+ dst[0] = ((~(dst[0] & 0x02)) & 0x02) | (dst[0] & 0xfd);
+}
+
+// Examine whether two IP addresses are in the same network
+bool IsInSameNetwork6ByStr(char *ip1, char *ip2, char *subnet)
+{
+ IP p1, p2, s;
+
+ if (StrToIP6(&p1, ip1) == false)
+ {
+ return false;
+ }
+
+ if (StrToIP6(&p2, ip2) == false)
+ {
+ return false;
+ }
+
+ if (StrToMask6(&s, subnet) == false)
+ {
+ return false;
+ }
+
+ return IsInSameNetwork6(&p1, &p2, &s);
+}
+bool IsInSameNetwork6(IP *a1, IP *a2, IP *subnet)
+{
+ IP prefix1, prefix2;
+ // Validate arguments
+ if (IsIP6(a1) == false || IsIP6(a2) == false || IsIP6(subnet) == false)
+ {
+ return false;
+ }
+
+ if (a1->ipv6_scope_id != a2->ipv6_scope_id)
+ {
+ return false;
+ }
+
+ GetPrefixAddress6(&prefix1, a1, subnet);
+ GetPrefixAddress6(&prefix2, a2, subnet);
+
+ if (CmpIpAddr(&prefix1, &prefix2) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool IsInSameNetwork4(IP *a1, IP *a2, IP *subnet)
+{
+ IP net1, net2;
+ // Validate arguments
+ if (IsIP4(a1) == false || IsIP4(a2) == false || IsIP4(subnet) == false)
+ {
+ return false;
+ }
+
+ IPAnd4(&net1, a1, subnet);
+ IPAnd4(&net2, a2, subnet);
+
+ if (CmpIpAddr(&net1, &net2) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Check whether it is a network address prefix
+bool IsNetworkAddress6(IP *ip, IP *subnet)
+{
+ return IsNetworkPrefixAddress6(ip, subnet);
+}
+bool IsNetworkPrefixAddress6(IP *ip, IP *subnet)
+{
+ IP host;
+ // Validate arguments
+ if (ip == NULL || subnet == NULL)
+ {
+ return false;
+ }
+
+ if (IsIP6(ip) == false || IsIP6(subnet) == false)
+ {
+ return false;
+ }
+
+ GetHostAddress6(&host, ip, subnet);
+
+ if (IsZeroIp(&host))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Check whether the unicast address is available
+bool CheckUnicastAddress(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ if ((GetIPAddrType6(ip) & IPV6_ADDR_UNICAST) == 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the host address
+void GetHostAddress6(IP *dst, IP *ip, IP *subnet)
+{
+ IP not;
+ // Validate arguments
+ if (dst == NULL || ip == NULL || subnet == NULL)
+ {
+ return;
+ }
+
+ IPNot6(&not, subnet);
+
+ IPAnd6(dst, ip, &not);
+
+ dst->ipv6_scope_id = ip->ipv6_scope_id;
+}
+
+// Get the prefix address
+void GetPrefixAddress6(IP *dst, IP *ip, IP *subnet)
+{
+ // Validate arguments
+ if (dst == NULL || ip == NULL || subnet == NULL)
+ {
+ return;
+ }
+
+ IPAnd6(dst, ip, subnet);
+
+ dst->ipv6_scope_id = ip->ipv6_scope_id;
+}
+
+// Get the solicited-node multicast address
+void GetSoliciationMulticastAddr6(IP *dst, IP *src)
+{
+ IP prefix;
+ IP mask104;
+ IP or1, or2;
+
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ ZeroIP6(&prefix);
+ prefix.ipv6_addr[0] = 0xff;
+ prefix.ipv6_addr[1] = 0x02;
+ prefix.ipv6_addr[11] = 0x01;
+ prefix.ipv6_addr[12] = 0xff;
+
+ IntToSubnetMask6(&mask104, 104);
+
+ IPAnd6(&or1, &prefix, &mask104);
+ IPAnd6(&or2, src, &mask104);
+
+ IPOr6(dst, &or1, &or2);
+
+ dst->ipv6_scope_id = src->ipv6_scope_id;
+}
+
+// Generate a MAC address corresponding to the multicast address
+void GenerateMulticastMacAddress6(UCHAR *mac, IP *ip)
+{
+ // Validate arguments
+ if (mac == NULL)
+ {
+ return;
+ }
+
+ mac[0] = 0x33;
+ mac[1] = 0x33;
+ mac[2] = ip->ipv6_addr[12];
+ mac[3] = ip->ipv6_addr[13];
+ mac[4] = ip->ipv6_addr[14];
+ mac[5] = ip->ipv6_addr[15];
+}
+
+// Get the type of the IPv6 address
+UINT GetIPv6AddrType(IPV6_ADDR *addr)
+{
+ IP ip;
+ // Validate arguments
+ if (addr == NULL)
+ {
+ return 0;
+ }
+
+ IPv6AddrToIP(&ip, addr);
+
+ return GetIPAddrType6(&ip);
+}
+UINT GetIPAddrType6(IP *ip)
+{
+ UINT ret = 0;
+ // Validate arguments
+ if (IsIP6(ip) == false)
+ {
+ return 0;
+ }
+
+ if (ip->ipv6_addr[0] == 0xff)
+ {
+ IP all_node, all_router;
+
+ GetAllNodeMulticaseAddress6(&all_node);
+
+ GetAllRouterMulticastAddress6(&all_router);
+
+ ret |= IPV6_ADDR_MULTICAST;
+
+ if (Cmp(ip->ipv6_addr, all_node.ipv6_addr, 16) == 0)
+ {
+ ret |= IPV6_ADDR_ALL_NODE_MULTICAST;
+ }
+ else if (Cmp(ip->ipv6_addr, all_router.ipv6_addr, 16) == 0)
+ {
+ ret |= IPV6_ADDR_ALL_ROUTER_MULTICAST;
+ }
+ else
+ {
+ if (ip->ipv6_addr[1] == 0x02 && ip->ipv6_addr[2] == 0 && ip->ipv6_addr[3] == 0 &&
+ ip->ipv6_addr[4] == 0 && ip->ipv6_addr[5] == 0 && ip->ipv6_addr[6] == 0 &&
+ ip->ipv6_addr[7] == 0 && ip->ipv6_addr[8] == 0 && ip->ipv6_addr[9] == 0 &&
+ ip->ipv6_addr[10] == 0 && ip->ipv6_addr[11] == 0x01 && ip->ipv6_addr[12] == 0xff)
+ {
+ ret |= IPV6_ADDR_SOLICIATION_MULTICAST;
+ }
+ }
+ }
+ else
+ {
+ ret |= IPV6_ADDR_UNICAST;
+
+ if (ip->ipv6_addr[0] == 0xfe && (ip->ipv6_addr[1] & 0xc0) == 0x80)
+ {
+ ret |= IPV6_ADDR_LOCAL_UNICAST;
+ }
+ else
+ {
+ ret |= IPV6_ADDR_GLOBAL_UNICAST;
+
+ if (IsZero(&ip->ipv6_addr, 16))
+ {
+ ret |= IPV6_ADDR_ZERO;
+ }
+ else
+ {
+ IP loopback;
+
+ GetLoopbackAddress6(&loopback);
+
+ if (Cmp(ip->ipv6_addr, loopback.ipv6_addr, 16) == 0)
+ {
+ ret |= IPV6_ADDR_LOOPBACK;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Address that all of the bits are set
+void GetAllFilledAddress6(IP *ip)
+{
+ UINT i;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ ZeroIP6(ip);
+
+ for (i = 0;i < 15;i++)
+ {
+ ip->ipv6_addr[i] = 0xff;
+ }
+}
+
+// Loopback address
+void GetLoopbackAddress6(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ ZeroIP6(ip);
+
+ ip->ipv6_addr[15] = 0x01;
+}
+
+// All-nodes multicast address
+void GetAllNodeMulticaseAddress6(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ ZeroIP6(ip);
+
+ ip->ipv6_addr[0] = 0xff;
+ ip->ipv6_addr[1] = 0x02;
+ ip->ipv6_addr[15] = 0x01;
+}
+
+// All-routers multicast address
+void GetAllRouterMulticastAddress6(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ ZeroIP6(ip);
+
+ ip->ipv6_addr[0] = 0xff;
+ ip->ipv6_addr[1] = 0x02;
+ ip->ipv6_addr[15] = 0x02;
+}
+
+// Logical operation of the IPv4 address
+void IPNot4(IP *dst, IP *a)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || a == NULL || IsIP4(a) == false)
+ {
+ Zero(dst, sizeof(IP));
+ return;
+ }
+
+ i = IPToUINT(a);
+ i = ~i;
+
+ UINTToIP(dst, i);
+}
+void IPOr4(IP *dst, IP *a, IP *b)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || a == NULL || b == NULL || IsIP4(a) == false || IsIP4(b) == false)
+ {
+ Zero(dst, sizeof(IP));
+ return;
+ }
+
+ i = IPToUINT(a) | IPToUINT(b);
+
+ UINTToIP(dst, i);
+}
+void IPAnd4(IP *dst, IP *a, IP *b)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || a == NULL || b == NULL || IsIP4(a) == false || IsIP4(b) == false)
+ {
+ Zero(dst, sizeof(IP));
+ return;
+ }
+
+ i = IPToUINT(a) & IPToUINT(b);
+
+ UINTToIP(dst, i);
+}
+
+// Logical operation of the IPv6 address
+void IPAnd6(IP *dst, IP *a, IP *b)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || IsIP6(a) == false || IsIP6(b) == false)
+ {
+ ZeroIP6(dst);
+ return;
+ }
+
+ ZeroIP6(dst);
+ for (i = 0;i < 16;i++)
+ {
+ dst->ipv6_addr[i] = a->ipv6_addr[i] & b->ipv6_addr[i];
+ }
+}
+void IPOr6(IP *dst, IP *a, IP *b)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || IsIP6(a) == false || IsIP6(b) == false)
+ {
+ ZeroIP6(dst);
+ return;
+ }
+
+ ZeroIP6(dst);
+ for (i = 0;i < 16;i++)
+ {
+ dst->ipv6_addr[i] = a->ipv6_addr[i] | b->ipv6_addr[i];
+ }
+}
+void IPNot6(IP *dst, IP *a)
+{
+ UINT i;
+ // Validate arguments
+ if (dst == NULL || IsIP6(a) == false)
+ {
+ ZeroIP6(dst);
+ return;
+ }
+
+ ZeroIP6(dst);
+ for (i = 0;i < 16;i++)
+ {
+ dst->ipv6_addr[i] = ~(a->ipv6_addr[i]);
+ }
+}
+
+// Creating a subnet mask
+void IntToSubnetMask6(IP *ip, UINT i)
+{
+ UINT j = i / 8;
+ UINT k = i % 8;
+ UINT z;
+ IP a;
+
+ ZeroIP6(&a);
+
+ for (z = 0;z < 16;z++)
+ {
+ if (z < j)
+ {
+ a.ipv6_addr[z] = 0xff;
+ }
+ else if (z == j)
+ {
+ a.ipv6_addr[z] = ~(0xff >> k);
+ }
+ }
+
+ Copy(ip, &a, sizeof(IP));
+}
+
+// Convert the IP address to a string
+void IP6AddrToStr(char *str, UINT size, IPV6_ADDR *addr)
+{
+ // Validate arguments
+ if (str == NULL || addr == NULL)
+ {
+ return;
+ }
+
+ IPToStr6Array(str, size, addr->Value);
+}
+void IPToStr6Array(char *str, UINT size, UCHAR *bytes)
+{
+ IP ip;
+ // Validate arguments
+ if (str == NULL || bytes == NULL)
+ {
+ return;
+ }
+
+ SetIP6(&ip, bytes);
+
+ IPToStr6(str, size, &ip);
+}
+void IPToStr6(char *str, UINT size, IP *ip)
+{
+ char tmp[MAX_SIZE];
+
+ IPToStr6Inner(tmp, ip);
+
+ StrCpy(str, size, tmp);
+}
+void IPToStr6Inner(char *str, IP *ip)
+{
+ UINT i;
+ USHORT values[8];
+ UINT zero_started_index;
+ UINT max_zero_len;
+ UINT max_zero_start;
+ IP a;
+ // Validate arguments
+ if (str == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ Copy(&a, ip, sizeof(IP));
+
+ for (i = 0;i < 8;i++)
+ {
+ Copy(&values[i], &a.ipv6_addr[i * 2], sizeof(USHORT));
+ values[i] = Endian16(values[i]);
+ }
+
+ // Search for omitable part
+ zero_started_index = INFINITE;
+ max_zero_len = 0;
+ max_zero_start = INFINITE;
+ for (i = 0;i < 9;i++)
+ {
+ USHORT v = (i != 8 ? values[i] : 1);
+
+ if (v == 0)
+ {
+ if (zero_started_index == INFINITE)
+ {
+ zero_started_index = i;
+ }
+ }
+ else
+ {
+ UINT zero_len;
+
+ if (zero_started_index != INFINITE)
+ {
+ zero_len = i - zero_started_index;
+ if (zero_len >= 2)
+ {
+ if (max_zero_len < zero_len)
+ {
+ max_zero_start = zero_started_index;
+ max_zero_len = zero_len;
+ }
+ }
+
+ zero_started_index = INFINITE;
+ }
+ }
+ }
+
+ // Format a string
+ StrCpy(str, 0, "");
+ for (i = 0;i < 8;i++)
+ {
+ char tmp[16];
+
+ ToHex(tmp, values[i]);
+ StrLower(tmp);
+
+ if (i == max_zero_start)
+ {
+ if (i == 0)
+ {
+ StrCat(str, 0, "::");
+ }
+ else
+ {
+ StrCat(str, 0, ":");
+ }
+ i += max_zero_len - 1;
+ }
+ else
+ {
+ StrCat(str, 0, tmp);
+ if (i != 7)
+ {
+ StrCat(str, 0, ":");
+ }
+ }
+ }
+
+ // Scope ID
+ if (ip->ipv6_scope_id != 0)
+ {
+ char tmp[64];
+
+ StrCat(str, 0, "%");
+ ToStr(tmp, ip->ipv6_scope_id);
+
+ StrCat(str, 0, tmp);
+ }
+}
+
+// Convert the string to an IP address
+bool StrToIP6(IP *ip, char *str)
+{
+ TOKEN_LIST *t;
+ char tmp[MAX_PATH];
+ IP a;
+ UINT i;
+ UINT scope_id = 0;
+ // Validate arguments
+ if (str == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ ZeroIP6(&a);
+
+ StrCpy(tmp, sizeof(tmp), str);
+ Trim(tmp);
+
+ if (StartWith(tmp, "[") && EndWith(tmp, "]"))
+ {
+ // If the string is enclosed in square brackets, remove brackets
+ StrCpy(tmp, sizeof(tmp), &tmp[1]);
+
+ if (StrLen(tmp) >= 1)
+ {
+ tmp[StrLen(tmp) - 1] = 0;
+ }
+ }
+
+ // Remove the scope ID by analyzing if there is it
+ i = SearchStrEx(tmp, "%", 0, false);
+ if (i != INFINITE)
+ {
+ char ss[MAX_PATH];
+
+ StrCpy(ss, sizeof(ss), &tmp[i + 1]);
+
+ tmp[i] = 0;
+
+ Trim(tmp);
+
+ Trim(ss);
+
+ scope_id = ToInt(ss);
+ }
+
+ // Tokenize
+ t = ParseTokenWithNullStr(tmp, ":");
+ if (t->NumTokens >= 3 && t->NumTokens <= 8)
+ {
+ UINT i, n;
+ bool b = true;
+ UINT k = 0;
+
+ n = 0;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *str = t->Token[i];
+
+ if (i != 0 && i != (t->NumTokens - 1) && StrLen(str) == 0)
+ {
+ n++;
+ if (n == 1)
+ {
+ k += 2 * (8 - t->NumTokens + 1);
+ }
+ else
+ {
+ b = false;
+ break;
+ }
+ }
+ else
+ {
+ UCHAR chars[2];
+
+ if (CheckIPItemStr6(str) == false)
+ {
+ b = false;
+ break;
+ }
+
+ IPItemStrToChars6(chars, str);
+
+ a.ipv6_addr[k++] = chars[0];
+ a.ipv6_addr[k++] = chars[1];
+ }
+ }
+
+ if (n != 0 && n != 1)
+ {
+ b = false;
+ }
+ else if (n == 0 && t->NumTokens != 8)
+ {
+ b = false;
+ }
+
+ if (b == false)
+ {
+ FreeToken(t);
+ return false;
+ }
+ }
+ else
+ {
+ FreeToken(t);
+ return false;
+ }
+
+ FreeToken(t);
+
+ Copy(ip, &a, sizeof(IP));
+
+ ip->ipv6_scope_id = scope_id;
+
+ return true;
+}
+bool StrToIP6Addr(IPV6_ADDR *ip, char *str)
+{
+ IP ip2;
+ // Validate arguments
+ if (ip == NULL || str == NULL)
+ {
+ Zero(ip, sizeof(IPV6_ADDR));
+ return false;
+ }
+
+ if (StrToIP6(&ip2, str) == false)
+ {
+ return false;
+ }
+
+ if (IPToIPv6Addr(ip, &ip2) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Convert an IP address character to the UCHAR type
+void IPItemStrToChars6(UCHAR *chars, char *str)
+{
+ char tmp[5];
+ BUF *b;
+ UINT len;
+ // Validate arguments
+ if (chars == NULL)
+ {
+ return;
+ }
+
+ Zero(tmp, sizeof(tmp));
+
+ len = StrLen(str);
+ switch (len)
+ {
+ case 0:
+ tmp[0] = tmp[1] = tmp[2] = tmp[3] = '0';
+ break;
+
+ case 1:
+ tmp[0] = tmp[1] = tmp[2] = '0';
+ tmp[3] = str[0];
+ break;
+
+ case 2:
+ tmp[0] = tmp[1] = '0';
+ tmp[2] = str[0];
+ tmp[3] = str[1];
+ break;
+
+ case 3:
+ tmp[0] = '0';
+ tmp[1] = str[0];
+ tmp[2] = str[1];
+ tmp[3] = str[2];
+ break;
+
+ case 4:
+ tmp[0] = str[0];
+ tmp[1] = str[1];
+ tmp[2] = str[2];
+ tmp[3] = str[3];
+ break;
+ }
+
+ b = StrToBin(tmp);
+
+ chars[0] = ((UCHAR *)b->Buf)[0];
+ chars[1] = ((UCHAR *)b->Buf)[1];
+
+ FreeBuf(b);
+}
+
+// Check whether invalid characters are included in the element string of the IP address
+bool CheckIPItemStr6(char *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ len = StrLen(str);
+ if (len >= 5)
+ {
+ // Invalid length
+ return false;
+ }
+
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ if ((c >= 'a' && c <= 'f') ||
+ (c >= 'A' && c <= 'F') ||
+ (c >= '0' && c <= '9'))
+ {
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Create an IPv4 address of all zero
+void ZeroIP4(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ Zero(ip, sizeof(IP));
+}
+
+// Create an IPv6 address of all zero
+void ZeroIP6(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ SetIP6(ip, NULL);
+}
+
+// Get the IP address of the localhost
+void GetLocalHostIP6(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+ ZeroIP6(ip);
+
+ ip->ipv6_addr[15] = 1;
+}
+void GetLocalHostIP4(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ SetIP(ip, 127, 0, 0, 1);
+}
+
+// Check whether the specified address is a localhost
+bool IsLocalHostIP6(IP *ip)
+{
+ IP local;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+ if (IsIP6(ip) == false)
+ {
+ return false;
+ }
+
+ GetLocalHostIP6(&local);
+
+ if (CmpIpAddr(&local, ip) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool IsLocalHostIP4(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+ if (IsIP4(ip) == false)
+ {
+ return false;
+ }
+
+ if (ip->addr[0] == 127)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool IsLocalHostIP(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ if (IsIP4(ip))
+ {
+ return IsLocalHostIP4(ip);
+ }
+ else
+ {
+ return IsLocalHostIP6(ip);
+ }
+}
+
+// Convert the IPV6_ADDR to an IP
+void IPv6AddrToIP(IP *ip, IPV6_ADDR *addr)
+{
+ // Validate arguments
+ if (ip == NULL || addr == NULL)
+ {
+ return;
+ }
+
+ SetIP6(ip, addr->Value);
+}
+
+// Convert the IP to an IPV6_ADDR
+bool IPToIPv6Addr(IPV6_ADDR *addr, IP *ip)
+{
+ UINT i;
+ // Validate arguments
+ if (addr == NULL || ip == NULL)
+ {
+ Zero(addr, sizeof(IPV6_ADDR));
+ return false;
+ }
+
+ if (IsIP6(ip) == false)
+ {
+ Zero(addr, sizeof(IPV6_ADDR));
+ return false;
+ }
+
+ for (i = 0;i < 16;i++)
+ {
+ addr->Value[i] = ip->ipv6_addr[i];
+ }
+
+ return true;
+}
+
+// Set an IPv6 address
+void SetIP6(IP *ip, UCHAR *value)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ Zero(ip, sizeof(IP));
+
+ ip->addr[0] = 223;
+ ip->addr[1] = 255;
+ ip->addr[2] = 255;
+ ip->addr[3] = 254;
+
+ if (value != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < 16;i++)
+ {
+ ip->ipv6_addr[i] = value[i];
+ }
+ }
+}
+
+// Check whether the specified address is a IPv6 address
+bool IsIP6(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ if (ip->addr[0] == 223 && ip->addr[1] == 255 && ip->addr[2] == 255 && ip->addr[3] == 254)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool IsIP4(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ return (IsIP6(ip) ? false : true);
+}
+
+// Examine whether the version of the two IP addresses are same
+bool IsSameIPVer(IP *ip1, IP *ip2)
+{
+ // Validate arguments
+ if (ip1 == NULL || ip2 == NULL)
+ {
+ return false;
+ }
+
+ if (IsIP4(ip1) && IsIP4(ip2))
+ {
+ return true;
+ }
+
+ if (IsIP6(ip1) && IsIP6(ip2))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Copy the IP address
+void CopyIP(IP *dst, IP *src)
+{
+ Copy(dst, src, sizeof(IP));
+}
+
+// Check the length of the IPv6 subnet
+bool CheckSubnetLength6(UINT i)
+{
+ if (i >= 1 && i <= 127)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Get the process ID of the corresponding TCP connection by the socket
+UINT GetTcpProcessIdFromSocket(SOCK *s)
+{
+ LIST *o;
+ TCPTABLE *t;
+ UINT pid = 0;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ o = GetTcpTableList();
+ if (o == NULL)
+ {
+ return 0;
+ }
+
+ t = GetTcpTableFromEndPoint(o, &s->LocalIP, s->LocalPort,
+ &s->RemoteIP, s->RemotePort);
+
+ if (t != NULL)
+ {
+ pid = t->ProcessId;
+ }
+
+ FreeTcpTableList(o);
+
+ return pid;
+}
+UINT GetTcpProcessIdFromSocketReverse(SOCK *s)
+{
+ LIST *o;
+ TCPTABLE *t;
+ UINT pid = 0;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return 0;
+ }
+
+ o = GetTcpTableList();
+ if (o == NULL)
+ {
+ return 0;
+ }
+
+ t = GetTcpTableFromEndPoint(o, &s->RemoteIP, s->RemotePort,
+ &s->LocalIP, s->LocalPort);
+
+ if (t != NULL)
+ {
+ pid = t->ProcessId;
+ }
+
+ FreeTcpTableList(o);
+
+ return pid;
+}
+
+// Search in the TCP table by the end point
+TCPTABLE *GetTcpTableFromEndPoint(LIST *o, IP *local_ip, UINT local_port, IP *remote_ip, UINT remote_port)
+{
+ IP local;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ SetIP(&local, 127, 0, 0, 1);
+
+ if (local_ip == NULL)
+ {
+ local_ip = &local;
+ }
+
+ if (remote_ip == NULL)
+ {
+ remote_ip = &local;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ TCPTABLE *t = LIST_DATA(o, i);
+
+ if (t->Status == TCP_STATE_SYN_SENT || t->Status == TCP_STATE_SYN_RCVD ||
+ t->Status == TCP_STATE_ESTAB)
+ {
+ if (CmpIpAddr(&t->LocalIP, local_ip) == 0)
+ {
+ if (CmpIpAddr(&t->RemoteIP, remote_ip) == 0)
+ {
+ if (t->LocalPort == local_port)
+ {
+ if (t->RemotePort == remote_port)
+ {
+ return t;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// Get the TCP table list (Win32)
+#ifdef OS_WIN32
+LIST *Win32GetTcpTableList()
+{
+ LIST *o;
+
+ // Windows XP SP2 or later
+ o = Win32GetTcpTableListByGetExtendedTcpTable();
+ if (o != NULL)
+ {
+ return o;
+ }
+
+ // Windows XP or later
+ o = Win32GetTcpTableListByAllocateAndGetTcpExTableFromStack();
+ if (o != NULL)
+ {
+ return o;
+ }
+
+ // For legacy Windows
+ return Win32GetTcpTableListByGetTcpTable();
+}
+
+// Get the TCP table list (for Windows XP SP2 or later)
+LIST *Win32GetTcpTableListByGetExtendedTcpTable()
+{
+ UINT need_size;
+ UINT i;
+ MIB_TCPTABLE_OWNER_PID *table;
+ bool ok = false;
+ LIST *o;
+ if (w32net->GetExtendedTcpTable == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < 128;i++)
+ {
+ UINT ret;
+ table = MallocFast(sizeof(MIB_TCPTABLE_OWNER_PID));
+ need_size = sizeof(MIB_TCPTABLE_OWNER_PID);
+ ret = w32net->GetExtendedTcpTable(table, &need_size, true, AF_INET, _TCP_TABLE_OWNER_PID_ALL, 0);
+ if (ret == NO_ERROR)
+ {
+ ok = true;
+ break;
+ }
+ else
+ {
+ Free(table);
+ if (ret != ERROR_INSUFFICIENT_BUFFER)
+ {
+ return NULL;
+ }
+ }
+
+ table = MallocFast(need_size);
+
+ ret = w32net->GetExtendedTcpTable(table, &need_size, true, AF_INET, _TCP_TABLE_OWNER_PID_ALL, 0);
+ if (ret == NO_ERROR)
+ {
+ ok = true;
+ break;
+ }
+ else
+ {
+ Free(table);
+
+ if (ret != ERROR_INSUFFICIENT_BUFFER)
+ {
+ return NULL;
+ }
+ }
+ }
+
+ if (ok == false)
+ {
+ return NULL;
+ }
+
+ o = NewListEx(NULL, true);
+
+ for (i = 0;i < table->dwNumEntries;i++)
+ {
+ MIB_TCPROW_OWNER_PID *r = &table->table[i];
+ TCPTABLE *t = ZeroMallocFast(sizeof(TCPTABLE));
+
+ UINTToIP(&t->LocalIP, r->dwLocalAddr);
+ t->LocalPort = Endian16((USHORT)r->dwLocalPort);
+
+ if (r->dwState != TCP_STATE_LISTEN)
+ {
+ UINTToIP(&t->RemoteIP, r->dwRemoteAddr);
+ t->RemotePort = Endian16((USHORT)r->dwRemotePort);
+ }
+
+ t->Status = r->dwState;
+ t->ProcessId = r->dwOwningPid;
+
+ Add(o, t);
+ }
+
+ Free(table);
+
+ return o;
+}
+
+// Get the TCP table list (Windows XP or later)
+LIST *Win32GetTcpTableListByAllocateAndGetTcpExTableFromStack()
+{
+ HANDLE heap;
+ UINT i;
+ MIB_TCPTABLE_OWNER_PID *table;
+ bool ok = false;
+ LIST *o;
+ if (w32net->AllocateAndGetTcpExTableFromStack == NULL)
+ {
+ return NULL;
+ }
+
+ heap = GetProcessHeap();
+
+ if (w32net->AllocateAndGetTcpExTableFromStack(&table, true, heap, HEAP_GROWABLE, AF_INET) != ERROR_SUCCESS)
+ {
+ return NULL;
+ }
+
+ o = NewListEx(NULL, true);
+
+ for (i = 0;i < table->dwNumEntries;i++)
+ {
+ MIB_TCPROW_OWNER_PID *r = &table->table[i];
+ TCPTABLE *t = ZeroMallocFast(sizeof(TCPTABLE));
+
+ UINTToIP(&t->LocalIP, r->dwLocalAddr);
+ t->LocalPort = Endian16((USHORT)r->dwLocalPort);
+
+ if (r->dwState != TCP_STATE_LISTEN)
+ {
+ UINTToIP(&t->RemoteIP, r->dwRemoteAddr);
+ t->RemotePort = Endian16((USHORT)r->dwRemotePort);
+ }
+
+ t->ProcessId = r->dwOwningPid;
+ t->Status = r->dwState;
+
+ Add(o, t);
+ }
+
+ HeapFree(heap, 0, table);
+
+ return o;
+}
+
+// Get the TCP table list (For legacy Windows)
+LIST *Win32GetTcpTableListByGetTcpTable()
+{
+ UINT need_size;
+ UINT i;
+ MIB_TCPTABLE *table;
+ bool ok = false;
+ LIST *o;
+ if (w32net->GetTcpTable == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < 128;i++)
+ {
+ UINT ret;
+ table = MallocFast(sizeof(MIB_TCPTABLE));
+ need_size = sizeof(MIB_TCPTABLE);
+ ret = w32net->GetTcpTable(table, &need_size, true);
+ if (ret == NO_ERROR)
+ {
+ ok = true;
+ break;
+ }
+ else
+ {
+ Free(table);
+ if (ret != ERROR_INSUFFICIENT_BUFFER)
+ {
+ return NULL;
+ }
+ }
+
+ table = MallocFast(need_size);
+
+ ret = w32net->GetTcpTable(table, &need_size, true);
+ if (ret == NO_ERROR)
+ {
+ ok = true;
+ break;
+ }
+ else
+ {
+ Free(table);
+
+ if (ret != ERROR_INSUFFICIENT_BUFFER)
+ {
+ return NULL;
+ }
+ }
+ }
+
+ if (ok == false)
+ {
+ return NULL;
+ }
+
+ o = NewListEx(NULL, true);
+
+ for (i = 0;i < table->dwNumEntries;i++)
+ {
+ MIB_TCPROW *r = &table->table[i];
+ TCPTABLE *t = ZeroMallocFast(sizeof(TCPTABLE));
+
+ UINTToIP(&t->LocalIP, r->dwLocalAddr);
+ t->LocalPort = Endian16((USHORT)r->dwLocalPort);
+
+ if (r->dwState != TCP_STATE_LISTEN)
+ {
+ UINTToIP(&t->RemoteIP, r->dwRemoteAddr);
+ t->RemotePort = Endian16((USHORT)r->dwRemotePort);
+ }
+
+ t->Status = r->dwState;
+
+ Add(o, t);
+ }
+
+ Free(table);
+
+ return o;
+}
+
+#endif // OS_WIN32
+
+// Display the TCP table
+void PrintTcpTableList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ Print("o == NULL\n\n");
+ return;
+ }
+
+ Print("--- TCPTABLE: %u Entries ---\n", LIST_NUM(o));
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char tmp1[MAX_PATH], tmp2[MAX_PATH];
+ TCPTABLE *t = LIST_DATA(o, i);
+
+ IPToStr(tmp1, sizeof(tmp1), &t->LocalIP);
+ IPToStr(tmp2, sizeof(tmp2), &t->RemoteIP);
+
+ Print("%s:%u <--> %s:%u state=%u pid=%u\n",
+ tmp1, t->LocalPort,
+ tmp2, t->RemotePort,
+ t->Status,
+ t->ProcessId);
+ }
+ Print("------\n\n");
+}
+
+// Comparison of TCP table items
+int CompareTcpTable(void *p1, void *p2)
+{
+ TCPTABLE *t1, *t2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ t1 = *(TCPTABLE **)p1;
+ t2 = *(TCPTABLE **)p2;
+ if (t1 == NULL || t2 == NULL)
+ {
+ return 0;
+ }
+
+ return Cmp(t1, t2, sizeof(TCPTABLE));
+}
+
+// Get the TCP table list
+LIST *GetTcpTableList()
+{
+#ifdef OS_WIN32
+ return Win32GetTcpTableList();
+#else // OS_WIN32
+ return NULL;
+#endif // OS_WIN32
+}
+
+// Release the TCP table list
+void FreeTcpTableList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ TCPTABLE *t = LIST_DATA(o, i);
+
+ Free(t);
+ }
+
+ ReleaseList(o);
+}
+
+// Get the number of clients connected from the specified IP address
+UINT GetNumIpClient(IP *ip)
+{
+ IP_CLIENT *c;
+ UINT ret = 0;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return 0;
+ }
+
+ LockList(ip_clients);
+ {
+ c = SearchIpClient(ip);
+
+ if (c != NULL)
+ {
+ ret = c->NumConnections;
+ }
+ }
+ UnlockList(ip_clients);
+
+ return ret;
+}
+
+// Add to the IP client entry
+void AddIpClient(IP *ip)
+{
+ IP_CLIENT *c;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ LockList(ip_clients);
+ {
+ c = SearchIpClient(ip);
+
+ if (c == NULL)
+ {
+ c = ZeroMallocFast(sizeof(IP_CLIENT));
+ Copy(&c->IpAddress, ip, sizeof(IP));
+ c->NumConnections = 0;
+
+ Add(ip_clients, c);
+ }
+
+ c->NumConnections++;
+ }
+ UnlockList(ip_clients);
+
+ //Debug("AddIpClient: %r\n", ip);
+}
+
+// Remove from the IP client list
+void DelIpClient(IP *ip)
+{
+ IP_CLIENT *c;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ LockList(ip_clients);
+ {
+ c = SearchIpClient(ip);
+
+ if (c != NULL)
+ {
+ c->NumConnections--;
+
+ if (c->NumConnections == 0)
+ {
+ Delete(ip_clients, c);
+ Free(c);
+ }
+ }
+ }
+ UnlockList(ip_clients);
+
+ //Debug("DelIpClient: %r\n", ip);
+}
+
+// Search for the IP client entry
+IP_CLIENT *SearchIpClient(IP *ip)
+{
+ IP_CLIENT t;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&t, sizeof(t));
+ Copy(&t.IpAddress, ip, sizeof(IP));
+
+ return Search(ip_clients, &t);
+}
+
+// Initialization of the client list
+void InitIpClientList()
+{
+ ip_clients = NewList(CompareIpClientList);
+}
+
+// Release of the client list
+void FreeIpClientList()
+{
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(ip_clients);i++)
+ {
+ IP_CLIENT *c = LIST_DATA(ip_clients, i);
+
+ Free(c);
+ }
+
+ ReleaseList(ip_clients);
+ ip_clients = NULL;
+}
+
+// Comparison of the client list entries
+int CompareIpClientList(void *p1, void *p2)
+{
+ IP_CLIENT *c1, *c2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ c1 = *(IP_CLIENT **)p1;
+ c2 = *(IP_CLIENT **)p2;
+ if (c1 == NULL || c2 == NULL)
+ {
+ return 0;
+ }
+
+ return CmpIpAddr(&c1->IpAddress, &c2->IpAddress);
+}
+
+// Normalization of the MAC address
+bool NormalizeMacAddress(char *dst, UINT size, char *src)
+{
+ BUF *b;
+ bool ret = false;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return false;
+ }
+
+ b = StrToBin(src);
+
+ if (b != NULL && b->Size == 6)
+ {
+ ret = true;
+
+ BinToStr(dst, size, b->Buf, b->Size);
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Identify whether the IP address is empty
+bool IsZeroIP(IP *ip)
+{
+ return IsZeroIp(ip);
+}
+bool IsZeroIp(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return true;
+ }
+
+ if (IsIP6(ip) == false)
+ {
+ return IsZero(ip->addr, sizeof(ip->addr));
+ }
+ else
+ {
+ return IsZero(ip->ipv6_addr, sizeof(ip->ipv6_addr));
+ }
+}
+bool IsZeroIP6Addr(IPV6_ADDR *addr)
+{
+ // Validate arguments
+ if (addr == NULL)
+ {
+ return true;
+ }
+
+ return IsZero(addr, sizeof(IPV6_ADDR));
+}
+
+// Examine whether the specified IP address is meaningful as a host
+bool IsHostIPAddress4(IP *ip)
+{
+ UINT a;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ a = IPToUINT(ip);
+
+ if (a == 0 || a == 0xffffffff)
+ {
+ return false;
+ }
+
+ return true;
+}
+bool IsHostIPAddress32(UINT ip)
+{
+ IP p;
+
+ UINTToIP(&p, ip);
+
+ return IsHostIPAddress4(&p);
+}
+
+// Check whether the specified IP address and subnet mask indicates a network correctly
+bool IsNetworkAddress(IP *ip, IP *mask)
+{
+ if (IsIP4(ip))
+ {
+ return IsNetworkAddress4(ip, mask);
+ }
+ else
+ {
+ return IsNetworkAddress6(ip, mask);
+ }
+}
+bool IsNetworkAddress4(IP *ip, IP *mask)
+{
+ UINT a, b;
+ // Validate arguments
+ if (ip == NULL || mask == NULL)
+ {
+ return false;
+ }
+
+ if (IsIP4(ip) == false || IsIP4(mask) == false)
+ {
+ return false;
+ }
+
+ if (IsSubnetMask4(mask) == false)
+ {
+ return false;
+ }
+
+ a = IPToUINT(ip);
+ b = IPToUINT(mask);
+
+ if ((a & b) == a)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool IsNetworkAddress32(UINT ip, UINT mask)
+{
+ IP a, b;
+
+ UINTToIP(&a, ip);
+ UINTToIP(&b, mask);
+
+ return IsNetworkAddress4(&a, &b);
+}
+
+// Convert the integer to a subnet mask
+UINT IntToSubnetMask32(UINT i)
+{
+ UINT ret = 0xFFFFFFFF;
+
+ switch (i)
+ {
+ case 0: ret = 0x00000000; break;
+ case 1: ret = 0x80000000; break;
+ case 2: ret = 0xC0000000; break;
+ case 3: ret = 0xE0000000; break;
+ case 4: ret = 0xF0000000; break;
+ case 5: ret = 0xF8000000; break;
+ case 6: ret = 0xFC000000; break;
+ case 7: ret = 0xFE000000; break;
+ case 8: ret = 0xFF000000; break;
+ case 9: ret = 0xFF800000; break;
+ case 10: ret = 0xFFC00000; break;
+ case 11: ret = 0xFFE00000; break;
+ case 12: ret = 0xFFF00000; break;
+ case 13: ret = 0xFFF80000; break;
+ case 14: ret = 0xFFFC0000; break;
+ case 15: ret = 0xFFFE0000; break;
+ case 16: ret = 0xFFFF0000; break;
+ case 17: ret = 0xFFFF8000; break;
+ case 18: ret = 0xFFFFC000; break;
+ case 19: ret = 0xFFFFE000; break;
+ case 20: ret = 0xFFFFF000; break;
+ case 21: ret = 0xFFFFF800; break;
+ case 22: ret = 0xFFFFFC00; break;
+ case 23: ret = 0xFFFFFE00; break;
+ case 24: ret = 0xFFFFFF00; break;
+ case 25: ret = 0xFFFFFF80; break;
+ case 26: ret = 0xFFFFFFC0; break;
+ case 27: ret = 0xFFFFFFE0; break;
+ case 28: ret = 0xFFFFFFF0; break;
+ case 29: ret = 0xFFFFFFF8; break;
+ case 30: ret = 0xFFFFFFFC; break;
+ case 31: ret = 0xFFFFFFFE; break;
+ case 32: ret = 0xFFFFFFFF; break;
+ }
+
+ if (IsLittleEndian())
+ {
+ ret = Swap32(ret);
+ }
+
+ return ret;
+}
+void IntToSubnetMask4(IP *ip, UINT i)
+{
+ UINT m;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ m = IntToSubnetMask32(i);
+
+ UINTToIP(ip, m);
+}
+
+// Examine whether the specified IP address is a subnet mask
+bool IsSubnetMask(IP *ip)
+{
+ if (IsIP6(ip))
+ {
+ return IsSubnetMask6(ip);
+ }
+ else
+ {
+ return IsSubnetMask4(ip);
+ }
+}
+bool IsSubnetMask4(IP *ip)
+{
+ UINT i;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ if (IsIP6(ip))
+ {
+ return false;
+ }
+
+ i = IPToUINT(ip);
+
+ if (IsLittleEndian())
+ {
+ i = Swap32(i);
+ }
+
+ switch (i)
+ {
+ case 0x00000000:
+ case 0x80000000:
+ case 0xC0000000:
+ case 0xE0000000:
+ case 0xF0000000:
+ case 0xF8000000:
+ case 0xFC000000:
+ case 0xFE000000:
+ case 0xFF000000:
+ case 0xFF800000:
+ case 0xFFC00000:
+ case 0xFFE00000:
+ case 0xFFF00000:
+ case 0xFFF80000:
+ case 0xFFFC0000:
+ case 0xFFFE0000:
+ case 0xFFFF0000:
+ case 0xFFFF8000:
+ case 0xFFFFC000:
+ case 0xFFFFE000:
+ case 0xFFFFF000:
+ case 0xFFFFF800:
+ case 0xFFFFFC00:
+ case 0xFFFFFE00:
+ case 0xFFFFFF00:
+ case 0xFFFFFF80:
+ case 0xFFFFFFC0:
+ case 0xFFFFFFE0:
+ case 0xFFFFFFF0:
+ case 0xFFFFFFF8:
+ case 0xFFFFFFFC:
+ case 0xFFFFFFFE:
+ case 0xFFFFFFFF:
+ return true;
+ }
+
+ return false;
+}
+bool IsSubnetMask32(UINT ip)
+{
+ IP p;
+
+ UINTToIP(&p, ip);
+
+ return IsSubnetMask4(&p);
+}
+
+// Network release mode
+void SetNetworkReleaseMode()
+{
+ NetworkReleaseMode = true;
+}
+
+#ifdef OS_UNIX // Code for UNIX
+
+// Turn on and off the non-blocking mode of the socket
+void UnixSetSocketNonBlockingMode(int fd, bool nonblock)
+{
+ UINT flag = 0;
+ // Validate arguments
+ if (fd == INVALID_SOCKET)
+ {
+ return;
+ }
+
+ if (nonblock)
+ {
+ flag = 1;
+ }
+
+#ifdef FIONBIO
+ ioctl(fd, FIONBIO, &flag);
+#else // FIONBIO
+ {
+ int flag = fcntl(fd, F_GETFL, 0);
+ if (flag != -1)
+ {
+ if (nonblock)
+ {
+ flag |= O_NONBLOCK;
+ }
+ else
+ {
+ flag = flag & ~O_NONBLOCK;
+
+ fcntl(fd, F_SETFL, flag);
+ }
+ }
+ }
+#endif // FIONBIO
+}
+
+// Do Nothing
+void UnixIpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row)
+{
+}
+
+// Do Nothing
+void UnixRouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry)
+{
+}
+
+// Do Nothing
+int UnixCompareRouteEntryByMetric(void *p1, void *p2)
+{
+ return 1;
+}
+
+// Do Nothing
+ROUTE_TABLE *UnixGetRouteTable()
+{
+ ROUTE_TABLE *ret = ZeroMalloc(sizeof(ROUTE_TABLE));
+ ret->NumEntry = 0;
+ ret->Entry = ZeroMalloc(0);
+
+ return ret;
+}
+
+// Do Nothing
+bool UnixAddRouteEntry(ROUTE_ENTRY *e, bool *already_exists)
+{
+ return true;
+}
+
+// Do Nothing
+void UnixDeleteRouteEntry(ROUTE_ENTRY *e)
+{
+ return;
+}
+
+// Do Nothing
+UINT UnixGetVLanInterfaceID(char *instance_name)
+{
+ return 1;
+}
+
+// Do Nothing
+char **UnixEnumVLan(char *tag_name)
+{
+ char **list;
+
+ list = ZeroMalloc(sizeof(char *));
+
+ return list;
+}
+
+// Do Nothing
+void UnixRenewDhcp()
+{
+}
+
+// Get the IP address of the default DNS server
+bool UnixGetDefaultDns(IP *ip)
+{
+ BUF *b;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ Lock(unix_dns_server_addr_lock);
+ {
+ if (IsZero(&unix_dns_server, sizeof(IP)) == false)
+ {
+ Copy(ip, &unix_dns_server, sizeof(IP));
+ Unlock(unix_dns_server_addr_lock);
+ return true;
+ }
+
+ ip->addr[0] = 127;
+ ip->addr[1] = 0;
+ ip->addr[2] = 0;
+ ip->addr[3] = 1;
+
+ b = ReadDump("/etc/resolv.conf");
+ if (b != NULL)
+ {
+ char *s;
+ bool f = false;
+ while ((s = CfgReadNextLine(b)) != NULL)
+ {
+ TOKEN_LIST *t = ParseToken(s, "\" \t,");
+ if (t->NumTokens == 2)
+ {
+ if (StrCmpi(t->Token[0], "nameserver") == 0)
+ {
+ StrToIP(ip, t->Token[1]);
+ f = true;
+ }
+ }
+ FreeToken(t);
+
+ Free(s);
+
+ if (f)
+ {
+ break;
+ }
+ }
+ FreeBuf(b);
+ }
+ Copy(&unix_dns_server, ip, sizeof(IP));
+ }
+ Unlock(unix_dns_server_addr_lock);
+
+ return true;
+}
+
+
+// Select procedure
+void UnixSelect(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2)
+{
+ UINT reads[MAXIMUM_WAIT_OBJECTS];
+ UINT writes[MAXIMUM_WAIT_OBJECTS];
+ UINT num_read, num_write, i;
+ UINT p1, p2;
+ SOCK_EVENT *sock_events[MAXIMUM_WAIT_OBJECTS];
+ UINT num_sock_events;
+ SOCK *s;
+ UCHAR tmp[MAX_SIZE];
+ int ret;
+ bool any_of_tubes_are_readable = false;
+ // Initialization of array
+ Zero(reads, sizeof(reads));
+ Zero(writes, sizeof(writes));
+ Zero(sock_events, sizeof(sock_events));
+ num_read = num_write = num_sock_events = 0;
+
+ // Setting the event array
+ if (set != NULL)
+ {
+ for (i = 0;i < set->NumSocket;i++)
+ {
+ s = set->Sock[i];
+ if (s != NULL)
+ {
+ UnixInitAsyncSocket(s);
+ if (s->Type == SOCK_INPROC)
+ {
+ TUBE *t = s->RecvTube;
+ if (t != NULL)
+ {
+ reads[num_read++] = t->SockEvent->pipe_read;
+
+ sock_events[num_sock_events++] = t->SockEvent;
+
+ if (t->SockEvent->current_pipe_data != 0)
+ {
+ any_of_tubes_are_readable = true;
+ }
+ }
+ }
+ else
+ {
+ if (s->NoNeedToRead == false)
+ {
+ reads[num_read++] = s->socket;
+ }
+ }
+
+ if (s->BulkRecvTube != NULL)
+ {
+ TUBE *t = s->BulkRecvTube;
+ if (t != NULL)
+ {
+ reads[num_read++] = t->SockEvent->pipe_read;
+
+ sock_events[num_sock_events++] = t->SockEvent;
+
+ if (t->SockEvent->current_pipe_data != 0)
+ {
+ any_of_tubes_are_readable = true;
+ }
+ }
+ }
+
+ if (s->WriteBlocked)
+ {
+ writes[num_write++] = s->socket;
+ }
+ }
+ }
+ }
+
+ if (timeout == 0)
+ {
+ return;
+ }
+
+ p1 = p2 = -1;
+
+ if (c1 != NULL)
+ {
+ reads[num_read++] = p1 = c1->pipe_read;
+ }
+ if (c2 != NULL)
+ {
+ reads[num_read++] = p2 = c2->pipe_read;
+ }
+
+ // Call the select
+ if (any_of_tubes_are_readable == false)
+ {
+ UnixSelectInner(num_read, reads, num_write, writes, timeout);
+ }
+
+ // Read from the pipe
+ if (c1 != NULL && c1->SpecialFlag == false && p1 != -1)
+ {
+ do
+ {
+ ret = read(p1, tmp, sizeof(tmp));
+ }
+ while (ret >= 1);
+ }
+ if (c2 != NULL && c2->SpecialFlag == false && p2 != -1)
+ {
+ do
+ {
+ ret = read(p2, tmp, sizeof(tmp));
+ }
+ while (ret >= 1);
+ }
+
+ // Read from the pipe of sockevent
+ for (i = 0;i < num_sock_events;i++)
+ {
+ SOCK_EVENT *e = sock_events[i];
+
+ e->current_pipe_data = 0;
+
+ do
+ {
+ ret = read(e->pipe_read, tmp, sizeof(tmp));
+ }
+ while (ret >= 1);
+ }
+}
+
+// Cancel
+void UnixCancel(CANCEL *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ UnixWritePipe(c->pipe_write);
+}
+
+// Release of the cancel object
+void UnixCleanupCancel(CANCEL *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (c->SpecialFlag == false)
+ {
+ UnixDeletePipe(c->pipe_read, c->pipe_write);
+ }
+
+ Free(c);
+}
+
+// Creating a new cancel object
+CANCEL *UnixNewCancel()
+{
+ CANCEL *c = ZeroMallocFast(sizeof(CANCEL));
+
+ c->ref = NewRef();
+ c->SpecialFlag = false;
+
+ UnixNewPipe(&c->pipe_read, &c->pipe_write);
+
+ return c;
+}
+
+// Add the socket to the socket event
+void UnixJoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event)
+{
+ // Validate arguments
+ if (sock == NULL || event == NULL || sock->AsyncMode)
+ {
+ return;
+ }
+ if (sock->ListenMode != false || (sock->Type == SOCK_TCP && sock->Connected == false))
+ {
+ return;
+ }
+
+ sock->AsyncMode = true;
+
+ LockList(event->SockList);
+ {
+ Add(event->SockList, sock);
+ AddRef(sock->ref);
+ }
+ UnlockList(event->SockList);
+
+ // Make the socket asynchronous mode
+ if (sock->Type != SOCK_INPROC)
+ {
+ UnixSetSocketNonBlockingMode(sock->socket, true);
+ }
+
+ // Increase the reference count of the SOCK_EVENT
+ AddRef(event->ref);
+ sock->SockEvent = event;
+
+ // Set the socket event
+ SetSockEvent(event);
+}
+
+// Wait for a socket event
+bool UnixWaitSockEvent(SOCK_EVENT *event, UINT timeout)
+{
+ UINT num_read, num_write;
+ UINT *reads, *writes;
+ UINT n;
+ char tmp[MAX_SIZE];
+ int readret = 0;
+ bool event_pipe_is_readable = false;
+ // Validate arguments
+ if (event == NULL)
+ {
+ return false;
+ }
+
+ LockList(event->SockList);
+ {
+ UINT i;
+ reads = ZeroMallocFast(sizeof(SOCK *) * (LIST_NUM(event->SockList) + 1));
+
+ num_write = 0;
+ num_read = 0;
+
+ for (i = 0;i < LIST_NUM(event->SockList);i++)
+ {
+ SOCK *s = LIST_DATA(event->SockList, i);
+
+ if (s->NoNeedToRead == false)
+ {
+ reads[num_read++] = s->socket;
+ }
+
+ if (s->WriteBlocked)
+ {
+ num_write++;
+ }
+ }
+
+ reads[num_read++] = event->pipe_read;
+
+ if (event->current_pipe_data != 0)
+ {
+ event_pipe_is_readable = true;
+ }
+
+ writes = ZeroMallocFast(sizeof(SOCK *) * num_write);
+
+ n = 0;
+
+ for (i = 0;i < (num_read - 1);i++)
+ {
+ SOCK *s = LIST_DATA(event->SockList, i);
+ if (s->WriteBlocked)
+ {
+ writes[n++] = s->socket;
+ }
+ }
+ }
+ UnlockList(event->SockList);
+
+ if (event_pipe_is_readable == false)
+ {
+ UnixSelectInner(num_read, reads, num_write, writes, timeout);
+ }
+
+ event->current_pipe_data = 0;
+ do
+ {
+ readret = read(event->pipe_read, tmp, sizeof(tmp));
+ }
+ while (readret >= 1);
+
+ Free(reads);
+ Free(writes);
+
+ return true;
+}
+
+// Set the socket event
+void UnixSetSockEvent(SOCK_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ if (event->current_pipe_data <= 100)
+ {
+ UnixWritePipe(event->pipe_write);
+ event->current_pipe_data++;
+ }
+}
+
+// Execute 'select' for the socket
+void UnixSelectInner(UINT num_read, UINT *reads, UINT num_write, UINT *writes, UINT timeout)
+{
+ struct pollfd *p;
+ UINT num;
+ UINT i;
+ UINT n;
+ UINT num_read_total, num_write_total;
+
+ if (num_read != 0 && reads == NULL)
+ {
+ num_read = 0;
+ }
+ if (num_write != 0 && writes == NULL)
+ {
+ num_write = 0;
+ }
+
+ if (timeout == 0)
+ {
+ return;
+ }
+
+ num_read_total = num_write_total = 0;
+ for (i = 0;i < num_read;i++)
+ {
+ if (reads[i] != INVALID_SOCKET)
+ {
+ num_read_total++;
+ }
+ }
+ for (i = 0;i < num_write;i++)
+ {
+ if (writes[i] != INVALID_SOCKET)
+ {
+ num_write_total++;
+ }
+ }
+
+ num = num_read_total + num_write_total;
+ p = ZeroMallocFast(sizeof(struct pollfd) * num);
+
+ n = 0;
+
+ for (i = 0;i < num_read;i++)
+ {
+ if (reads[i] != INVALID_SOCKET)
+ {
+ struct pollfd *pfd = &p[n++];
+ pfd->fd = reads[i];
+ pfd->events = POLLIN | POLLPRI | POLLERR | POLLHUP;
+ }
+ }
+
+ for (i = 0;i < num_write;i++)
+ {
+ if (writes[i] != INVALID_SOCKET)
+ {
+ struct pollfd *pfd = &p[n++];
+ pfd->fd = writes[i];
+ pfd->events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLOUT;
+ }
+ }
+
+ if (num != 0)
+ {
+ poll(p, num, timeout == INFINITE ? -1 : (int)timeout);
+ }
+ else
+ {
+ SleepThread(timeout);
+ }
+
+ Free(p);
+}
+
+// Clean-up of the socket event
+void UnixCleanupSockEvent(SOCK_EVENT *event)
+{
+ UINT i;
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(event->SockList);i++)
+ {
+ SOCK *s = LIST_DATA(event->SockList, i);
+
+ ReleaseSock(s);
+ }
+
+ ReleaseList(event->SockList);
+
+ UnixDeletePipe(event->pipe_read, event->pipe_write);
+
+ Free(event);
+}
+
+// Create a socket event
+SOCK_EVENT *UnixNewSockEvent()
+{
+ SOCK_EVENT *e = ZeroMallocFast(sizeof(SOCK_EVENT));
+
+ e->SockList = NewList(NULL);
+ e->ref = NewRef();
+
+ UnixNewPipe(&e->pipe_read, &e->pipe_write);
+
+ return e;
+}
+
+// Close the pipe
+void UnixDeletePipe(int p1, int p2)
+{
+ if (p1 != -1)
+ {
+ close(p1);
+ }
+
+ if (p2 != -1)
+ {
+ close(p2);
+ }
+}
+
+// Write to the pipe
+void UnixWritePipe(int pipe_write)
+{
+ char c = 1;
+ write(pipe_write, &c, 1);
+}
+
+// Create a new pipe
+void UnixNewPipe(int *pipe_read, int *pipe_write)
+{
+ int fd[2];
+ // Validate arguments
+ if (pipe_read == NULL || pipe_write == NULL)
+ {
+ return;
+ }
+
+ fd[0] = fd[1] = 0;
+
+ pipe(fd);
+
+ *pipe_read = fd[0];
+ *pipe_write = fd[1];
+
+ UnixSetSocketNonBlockingMode(*pipe_write, true);
+ UnixSetSocketNonBlockingMode(*pipe_read, true);
+}
+
+// Release the asynchronous socket
+void UnixFreeAsyncSocket(SOCK *sock)
+{
+ UINT p;
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+
+ Lock(sock->lock);
+ {
+ if (sock->AsyncMode == false)
+ {
+ Unlock(sock->lock);
+ return;
+ }
+
+ sock->AsyncMode = false;
+
+ // Examine whether this socket are associated to SockEvent
+ if (sock->SockEvent != NULL)
+ {
+ SOCK_EVENT *e = sock->SockEvent;
+
+ AddRef(e->ref);
+
+ p = e->pipe_write;
+ LockList(e->SockList);
+ {
+ if (Delete(e->SockList, sock))
+ {
+ ReleaseSock(sock);
+ }
+ }
+ UnlockList(e->SockList);
+
+ // Release the socket event
+ ReleaseSockEvent(sock->SockEvent);
+ sock->SockEvent = NULL;
+
+ SetSockEvent(e);
+
+ ReleaseSockEvent(e);
+ }
+ }
+ Unlock(sock->lock);
+}
+
+// Set the socket to asynchronous mode
+void UnixInitAsyncSocket(SOCK *sock)
+{
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+ if (sock->AsyncMode)
+ {
+ // The socket has been set in asynchronous mode already
+ return;
+ }
+ if (sock->ListenMode != false || ((sock->Type == SOCK_TCP || sock->Type == SOCK_INPROC) && sock->Connected == false))
+ {
+ return;
+ }
+
+ sock->AsyncMode = true;
+
+ if (sock->Type != SOCK_INPROC)
+ {
+ UnixSetSocketNonBlockingMode(sock->socket, true);
+ }
+}
+
+// Initializing the socket library
+void UnixInitSocketLibrary()
+{
+ // Do not do anything special
+}
+
+// Release of the socket library
+void UnixFreeSocketLibrary()
+{
+ // Do not do anything special
+}
+
+#endif // OS_UNIX
+
+#ifdef OS_WIN32 // Code for Windows
+
+NETWORK_WIN32_FUNCTIONS *w32net;
+
+// Comparison of IP_ADAPTER_INDEX_MAP
+int CompareIpAdapterIndexMap(void *p1, void *p2)
+{
+ IP_ADAPTER_INDEX_MAP *a1, *a2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ a1 = *(IP_ADAPTER_INDEX_MAP **)p1;
+ a2 = *(IP_ADAPTER_INDEX_MAP **)p2;
+ if (a1 == NULL || a2 == NULL)
+ {
+ return 0;
+ }
+
+ if (a1->Index > a2->Index)
+ {
+ return 1;
+ }
+ else if (a1->Index < a2->Index)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// Update the IP address of the adapter
+bool Win32RenewAddressByGuid(char *guid)
+{
+ IP_ADAPTER_INDEX_MAP a;
+ // Validate arguments
+ if (guid == NULL)
+ {
+ return false;
+ }
+
+ Zero(&a, sizeof(a));
+ if (Win32GetAdapterFromGuid(&a, guid) == false)
+ {
+ return false;
+ }
+
+ return Win32RenewAddress(&a);
+}
+bool Win32RenewAddress(void *a)
+{
+ DWORD ret;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return false;
+ }
+ if (w32net->IpRenewAddress == NULL)
+ {
+ return false;
+ }
+
+ ret = w32net->IpRenewAddress(a);
+
+ if (ret == NO_ERROR)
+ {
+ return true;
+ }
+ else
+ {
+ Debug("IpRenewAddress: Error: %u\n", ret);
+ return false;
+ }
+}
+
+// Release the IP address of the adapter
+bool Win32ReleaseAddress(void *a)
+{
+ DWORD ret;
+ // Validate arguments
+ if (a == NULL)
+ {
+ return false;
+ }
+ if (w32net->IpReleaseAddress == NULL)
+ {
+ return false;
+ }
+
+ ret = w32net->IpReleaseAddress(a);
+
+ if (ret == NO_ERROR)
+ {
+ return true;
+ }
+ else
+ {
+ Debug("IpReleaseAddress: Error: %u\n", ret);
+ return false;
+ }
+}
+bool Win32ReleaseAddressByGuid(char *guid)
+{
+ IP_ADAPTER_INDEX_MAP a;
+ // Validate arguments
+ if (guid == NULL)
+ {
+ return false;
+ }
+
+ Zero(&a, sizeof(a));
+ if (Win32GetAdapterFromGuid(&a, guid) == false)
+ {
+ return false;
+ }
+
+ return Win32ReleaseAddress(&a);
+}
+void Win32ReleaseAddressByGuidExThread(THREAD *t, void *param)
+{
+ WIN32_RELEASEADDRESS_THREAD_PARAM *p;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ p = (WIN32_RELEASEADDRESS_THREAD_PARAM *)param;
+
+ AddRef(p->Ref);
+
+ NoticeThreadInit(t);
+
+ AddWaitThread(t);
+
+ if (p->Renew == false)
+ {
+ p->Ok = Win32ReleaseAddressByGuid(p->Guid);
+ }
+ else
+ {
+ p->Ok = Win32RenewAddressByGuid(p->Guid);
+ }
+
+ ReleaseWin32ReleaseAddressByGuidThreadParam(p);
+
+ DelWaitThread(t);
+}
+bool Win32RenewAddressByGuidEx(char *guid, UINT timeout)
+{
+ return Win32ReleaseOrRenewAddressByGuidEx(guid, timeout, true);
+}
+bool Win32ReleaseAddressByGuidEx(char *guid, UINT timeout)
+{
+ return Win32ReleaseOrRenewAddressByGuidEx(guid, timeout, false);
+}
+bool Win32ReleaseOrRenewAddressByGuidEx(char *guid, UINT timeout, bool renew)
+{
+ THREAD *t;
+ WIN32_RELEASEADDRESS_THREAD_PARAM *p;
+ bool ret = false;
+ UINT64 start_tick = 0;
+ UINT64 end_tick = 0;
+ // Validate arguments
+ if (guid == NULL)
+ {
+ return false;
+ }
+ if (timeout == 0)
+ {
+ timeout = INFINITE;
+ }
+
+ p = ZeroMalloc(sizeof(WIN32_RELEASEADDRESS_THREAD_PARAM));
+ p->Ref = NewRef();
+ StrCpy(p->Guid, sizeof(p->Guid), guid);
+ p->Timeout = timeout;
+ p->Renew = renew;
+
+ t = NewThread(Win32ReleaseAddressByGuidExThread, p);
+ WaitThreadInit(t);
+ start_tick = Tick64();
+ end_tick = start_tick + (UINT64)timeout;
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+ UINT64 remain;
+ UINT remain32;
+
+ if (now >= end_tick)
+ {
+ break;
+ }
+
+ remain = end_tick - now;
+ remain32 = MIN((UINT)remain, 100);
+
+ if (WaitThread(t, remain32))
+ {
+ break;
+ }
+ }
+
+ ReleaseThread(t);
+
+ if (p->Ok)
+ {
+ ret = true;
+ }
+
+ ReleaseWin32ReleaseAddressByGuidThreadParam(p);
+
+ return ret;
+}
+void ReleaseWin32ReleaseAddressByGuidThreadParam(WIN32_RELEASEADDRESS_THREAD_PARAM *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (Release(p->Ref) == 0)
+ {
+ Free(p);
+ }
+}
+
+// Get the adapter by the GUID
+bool Win32GetAdapterFromGuid(void *a, char *guid)
+{
+ bool ret = false;
+ IP_INTERFACE_INFO *info;
+ UINT size;
+ int i;
+ LIST *o;
+ wchar_t tmp[MAX_SIZE];
+
+ // Validate arguments
+ if (a == NULL || guid == NULL)
+ {
+ return false;
+ }
+ if (w32net->GetInterfaceInfo == NULL)
+ {
+ return false;
+ }
+
+ UniFormat(tmp, sizeof(tmp), L"\\DEVICE\\TCPIP_%S", guid);
+
+ size = sizeof(IP_INTERFACE_INFO);
+ info = ZeroMallocFast(size);
+
+ if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)
+ {
+ Free(info);
+ info = ZeroMallocFast(size);
+ }
+
+ if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)
+ {
+ Free(info);
+ return false;
+ }
+
+ o = NewListFast(CompareIpAdapterIndexMap);
+
+ for (i = 0;i < info->NumAdapters;i++)
+ {
+ IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];
+
+ Add(o, a);
+ }
+
+ Sort(o);
+
+ for (i = 0;i < (int)(LIST_NUM(o));i++)
+ {
+ IP_ADAPTER_INDEX_MAP *e = LIST_DATA(o, i);
+
+ if (UniStrCmpi(e->Name, tmp) == 0)
+ {
+ Copy(a, e, sizeof(IP_ADAPTER_INDEX_MAP));
+ ret = true;
+ break;
+ }
+ }
+
+ ReleaseList(o);
+
+ Free(info);
+
+ return ret;
+}
+
+// Test
+void Win32NetworkTest()
+{
+ IP_INTERFACE_INFO *info;
+ UINT size;
+ int i;
+ LIST *o;
+
+ size = sizeof(IP_INTERFACE_INFO);
+ info = ZeroMallocFast(size);
+
+ if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)
+ {
+ Free(info);
+ info = ZeroMallocFast(size);
+ }
+
+ if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)
+ {
+ Free(info);
+ return;
+ }
+
+ o = NewListFast(CompareIpAdapterIndexMap);
+
+ for (i = 0;i < info->NumAdapters;i++)
+ {
+ IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];
+
+ Add(o, a);
+ }
+
+ Sort(o);
+
+ for (i = 0;i < (int)(LIST_NUM(o));i++)
+ {
+ IP_ADAPTER_INDEX_MAP *a = LIST_DATA(o, i);
+
+ DoNothing();
+ }
+
+ ReleaseList(o);
+
+ Free(info);
+}
+
+// Clear the DNS cache on Win32
+void Win32FlushDnsCache()
+{
+ Run("ipconfig.exe", "/flushdns", true, false);
+}
+
+// Update the DHCP address of the specified LAN card
+void Win32RenewDhcp9x(UINT if_id)
+{
+ IP_INTERFACE_INFO *info;
+ UINT size;
+ int i;
+ LIST *o;
+ // Validate arguments
+ if (if_id == 0)
+ {
+ return;
+ }
+
+ size = sizeof(IP_INTERFACE_INFO);
+ info = ZeroMallocFast(size);
+
+ if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)
+ {
+ Free(info);
+ info = ZeroMallocFast(size);
+ }
+
+ if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)
+ {
+ Free(info);
+ return;
+ }
+
+ o = NewListFast(CompareIpAdapterIndexMap);
+
+ for (i = 0;i < info->NumAdapters;i++)
+ {
+ IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];
+
+ Add(o, a);
+ }
+
+ Sort(o);
+
+ for (i = 0;i < (int)(LIST_NUM(o));i++)
+ {
+ IP_ADAPTER_INDEX_MAP *a = LIST_DATA(o, i);
+
+ if (a->Index == if_id)
+ {
+ char arg[MAX_PATH];
+ Format(arg, sizeof(arg), "/renew %u", i);
+ Run("ipconfig.exe", arg, true, false);
+ }
+ }
+
+ ReleaseList(o);
+
+ Free(info);
+}
+
+// Release the DHCP address of the specified LAN card
+void Win32ReleaseDhcp9x(UINT if_id, bool wait)
+{
+ IP_INTERFACE_INFO *info;
+ UINT size;
+ int i;
+ LIST *o;
+ // Validate arguments
+ if (if_id == 0)
+ {
+ return;
+ }
+
+ size = sizeof(IP_INTERFACE_INFO);
+ info = ZeroMallocFast(size);
+
+ if (w32net->GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER)
+ {
+ Free(info);
+ info = ZeroMallocFast(size);
+ }
+
+ if (w32net->GetInterfaceInfo(info, &size) != NO_ERROR)
+ {
+ Free(info);
+ return;
+ }
+
+ o = NewListFast(CompareIpAdapterIndexMap);
+
+ for (i = 0;i < info->NumAdapters;i++)
+ {
+ IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i];
+
+ Add(o, a);
+ }
+
+ Sort(o);
+
+ for (i = 0;i < (int)(LIST_NUM(o));i++)
+ {
+ IP_ADAPTER_INDEX_MAP *a = LIST_DATA(o, i);
+
+ if (a->Index == if_id)
+ {
+ char arg[MAX_PATH];
+ Format(arg, sizeof(arg), "/release %u", i);
+ Run("ipconfig.exe", arg, true, wait);
+ }
+ }
+
+ ReleaseList(o);
+
+ Free(info);
+}
+
+// Re-obtain an IP address from a DHCP server
+void Win32RenewDhcp()
+{
+ if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
+ {
+ Run("ipconfig.exe", "/renew", true, false);
+ if (MsIsVista())
+ {
+ Run("ipconfig.exe", "/renew6", true, false);
+ }
+ else
+ {
+ Run("netsh.exe", "int ipv6 renew", true, false);
+ }
+ }
+ else
+ {
+ Run("ipconfig.exe", "/renew_all", true, false);
+ }
+}
+
+// Enumerate a list of virtual LAN cards that contains the specified string
+char **Win32EnumVLan(char *tag_name)
+{
+ MIB_IFTABLE *p;
+ UINT ret;
+ UINT size_needed;
+ UINT num_retry = 0;
+ UINT i;
+ LIST *o;
+ char **ss;
+ // Validate arguments
+ if (tag_name == 0)
+ {
+ return NULL;
+ }
+
+RETRY:
+ p = ZeroMallocFast(sizeof(MIB_IFTABLE));
+ size_needed = 0;
+
+ // Examine the needed size
+ ret = w32net->GetIfTable(p, &size_needed, 0);
+ if (ret == ERROR_INSUFFICIENT_BUFFER)
+ {
+ // Re-allocate the memory block of the needed size
+ Free(p);
+ p = ZeroMallocFast(size_needed);
+ }
+ else if (ret != NO_ERROR)
+ {
+ // Acquisition failure
+FAILED:
+ Free(p);
+ return NULL;
+ }
+
+ // Actually get
+ ret = w32net->GetIfTable(p, &size_needed, FALSE);
+ if (ret != NO_ERROR)
+ {
+ // Acquisition failure
+ if ((++num_retry) >= 5)
+ {
+ goto FAILED;
+ }
+ Free(p);
+ goto RETRY;
+ }
+
+ // Search
+ ret = 0;
+ o = NewListFast(CompareStr);
+ for (i = 0;i < p->dwNumEntries;i++)
+ {
+ MIB_IFROW *r = &p->table[i];
+ if (SearchStrEx(r->bDescr, tag_name, 0, false) != INFINITE)
+ {
+ char *s = CopyStr(r->bDescr);
+ Add(o, s);
+ }
+ }
+
+ Free(p);
+
+ // Sort
+ Sort(o);
+
+ // Convert to string
+ ss = ZeroMallocFast(sizeof(char *) * (LIST_NUM(o) + 1));
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ ss[i] = LIST_DATA(o, i);
+ }
+ ss[LIST_NUM(o)] = NULL;
+
+ ReleaseList(o);
+
+ return ss;
+}
+
+// Get the ID of the virtual LAN card from the instance name of the virtual LAN card
+UINT Win32GetVLanInterfaceID(char *instance_name)
+{
+ MIB_IFTABLE *p;
+ UINT ret;
+ UINT size_needed;
+ UINT num_retry = 0;
+ UINT i;
+ char ps_miniport_str[MAX_SIZE];
+ char ps_miniport_str2[MAX_SIZE];
+ UINT min_len = 0x7FFFFFFF;
+ // Validate arguments
+ if (instance_name == 0)
+ {
+ return 0;
+ }
+
+RETRY:
+ p = ZeroMallocFast(sizeof(MIB_IFTABLE));
+ size_needed = 0;
+
+ // Examine the needed size
+ ret = w32net->GetIfTable(p, &size_needed, 0);
+ if (ret == ERROR_INSUFFICIENT_BUFFER)
+ {
+ // Re-allocate the memory block of the needed size
+ Free(p);
+ p = ZeroMallocFast(size_needed);
+ }
+ else if (ret != NO_ERROR)
+ {
+ // Acquisition failure
+FAILED:
+ Free(p);
+ Debug("******** GetIfTable Failed 1. Err = %u\n", ret);
+ return 0;
+ }
+
+ // Actually get
+ ret = w32net->GetIfTable(p, &size_needed, FALSE);
+ if (ret != NO_ERROR)
+ {
+ // Acquisition failure
+ if ((++num_retry) >= 5)
+ {
+ goto FAILED;
+ }
+ Free(p);
+ Debug("******** GetIfTable Failed 2. Err = %u\n", ret);
+ goto RETRY;
+ }
+
+ // "%s - Packet scheduler miniport"
+ Format(ps_miniport_str, sizeof(ps_miniport_str), "%s - ", instance_name);
+ Format(ps_miniport_str2, sizeof(ps_miniport_str2), "%s (Microsoft", instance_name);
+
+ // Search
+ ret = 0;
+ for (i = 0;i < p->dwNumEntries;i++)
+ {
+ MIB_IFROW *r = &p->table[i];
+ if (instance_name[0] != '@')
+ {
+ if (StrCmpi(r->bDescr, instance_name) == 0 || StartWith(r->bDescr, ps_miniport_str) || StartWith(r->bDescr, ps_miniport_str2))
+ {
+ UINT len = StrLen(r->bDescr);
+
+ if (len < min_len)
+ {
+ ret = r->dwIndex;
+
+ min_len = len;
+ }
+ }
+ }
+ else
+ {
+ if (SearchStrEx(r->bDescr, &instance_name[1], 0, false) != INFINITE)
+ {
+ ret = r->dwIndex;
+ }
+ }
+
+ //Debug("if[%u] (dwIndex=%u): %u, %s\n", i, r->dwIndex, r->dwType, r->bDescr);
+ }
+
+ Free(p);
+
+ return ret;
+}
+
+// Get the DNS suffix in another way
+bool Win32GetDnsSuffix(char *domain, UINT size)
+{
+ IP_ADAPTER_ADDRESSES_XP *info;
+ IP_ADAPTER_ADDRESSES_XP *cur;
+ UINT info_size;
+ bool ret = false;
+ // Validate arguments
+ ClearStr(domain, size);
+ if (domain == NULL)
+ {
+ return false;
+ }
+ if (w32net->GetAdaptersAddresses == NULL)
+ {
+ return false;
+ }
+
+ info_size = 0;
+ info = ZeroMalloc(sizeof(IP_ADAPTER_ADDRESSES_XP));
+ if (w32net->GetAdaptersAddresses(AF_INET, 0, NULL, info, &info_size) == ERROR_BUFFER_OVERFLOW)
+ {
+ Free(info);
+ info = ZeroMalloc(info_size);
+ }
+ if (w32net->GetAdaptersAddresses(AF_INET, 0, NULL, info, &info_size) != NO_ERROR)
+ {
+ Free(info);
+ return false;
+ }
+
+ cur = info;
+
+ while (cur != NULL)
+ {
+ if (UniIsEmptyStr(cur->DnsSuffix) == false)
+ {
+ UniToStr(domain, size, cur->DnsSuffix);
+ ret = true;
+ break;
+ }
+
+ cur = cur->Next;
+ }
+
+ Free(info);
+
+ return ret;
+}
+
+// Get the DNS server address of the default
+bool Win32GetDefaultDns(IP *ip, char *domain, UINT size)
+{
+ FIXED_INFO *info;
+ UINT info_size;
+ char *dns_name;
+ // Validate arguments
+ ClearStr(domain, size);
+ if (ip == NULL)
+ {
+ return false;
+ }
+ Zero(ip, sizeof(IP));
+ if (w32net->GetNetworkParams == NULL)
+ {
+ return false;
+ }
+ info_size = 0;
+ info = ZeroMallocFast(sizeof(FIXED_INFO));
+ if (w32net->GetNetworkParams(info, &info_size) == ERROR_BUFFER_OVERFLOW)
+ {
+ Free(info);
+ info = ZeroMallocFast(info_size);
+ }
+ if (w32net->GetNetworkParams(info, &info_size) != NO_ERROR)
+ {
+ Free(info);
+ return false;
+ }
+
+ if (info->DnsServerList.IpAddress.String == NULL)
+ {
+ Free(info);
+ return false;
+ }
+
+ dns_name = info->DnsServerList.IpAddress.String;
+ StrToIP(ip, dns_name);
+
+ if (domain != NULL)
+ {
+ StrCpy(domain, size, info->DomainName);
+ Trim(domain);
+ }
+
+ Free(info);
+
+ return true;
+}
+
+// IP conversion function for Win32
+void Win32UINTToIP(IP *ip, UINT i)
+{
+ UINTToIP(ip, i);
+}
+
+// IP conversion function for Win32
+UINT Win32IPToUINT(IP *ip)
+{
+ return IPToUINT(ip);
+}
+
+// Remove a routing entry from the routing table
+void Win32DeleteRouteEntry(ROUTE_ENTRY *e)
+{
+ MIB_IPFORWARDROW *p;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ p = ZeroMallocFast(sizeof(MIB_IPFORWARDROW));
+ Win32RouteEntryToIpForwardRow(p, e);
+
+ // Delete
+ w32net->DeleteIpForwardEntry(p);
+
+ Free(p);
+}
+
+// Add a routing entry to the routing table
+bool Win32AddRouteEntry(ROUTE_ENTRY *e, bool *already_exists)
+{
+ bool ret = false;
+ bool dummy = false;
+ MIB_IPFORWARDROW *p;
+ UINT err = 0;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return false;
+ }
+ if (already_exists == NULL)
+ {
+ already_exists = &dummy;
+ }
+
+ *already_exists = false;
+
+ p = ZeroMallocFast(sizeof(MIB_IPFORWARDROW));
+ Win32RouteEntryToIpForwardRow(p, e);
+
+ // Adding
+ err = w32net->CreateIpForwardEntry(p);
+ if (err != 0)
+ {
+ if (err == ERROR_OBJECT_ALREADY_EXISTS)
+ {
+ Debug("CreateIpForwardEntry: Already Exists\n");
+ *already_exists = true;
+ ret = true;
+ }
+ else
+ {
+ Debug("CreateIpForwardEntry Error: %u\n", err);
+ ret = false;
+ }
+ }
+ else
+ {
+ ret = true;
+ }
+
+ Free(p);
+
+ return ret;
+}
+
+// Get the routing table
+ROUTE_TABLE *Win32GetRouteTable()
+{
+ ROUTE_TABLE *t = ZeroMallocFast(sizeof(ROUTE_TABLE));
+ MIB_IPFORWARDTABLE *p;
+ UINT ret;
+ UINT size_needed;
+ UINT num_retry = 0;
+ LIST *o;
+ UINT i;
+ ROUTE_ENTRY *e;
+
+RETRY:
+ p = ZeroMallocFast(sizeof(MIB_IFTABLE));
+ size_needed = 0;
+
+ // Examine the needed size
+ ret = w32net->GetIpForwardTable(p, &size_needed, 0);
+ if (ret == ERROR_INSUFFICIENT_BUFFER)
+ {
+ // Re-allocate the memory block of the needed size
+ Free(p);
+ p = ZeroMallocFast(size_needed);
+ }
+ else if (ret != NO_ERROR)
+ {
+ // Acquisition failure
+FAILED:
+ Free(p);
+ t->Entry = MallocFast(0);
+ return t;
+ }
+
+ // Actually get
+ ret = w32net->GetIpForwardTable(p, &size_needed, FALSE);
+ if (ret != NO_ERROR)
+ {
+ // Acquisition failure
+ if ((++num_retry) >= 5)
+ {
+ goto FAILED;
+ }
+ Free(p);
+ goto RETRY;
+ }
+
+ // Add to the list along
+ o = NewListFast(Win32CompareRouteEntryByMetric);
+ for (i = 0;i < p->dwNumEntries;i++)
+ {
+ e = ZeroMallocFast(sizeof(ROUTE_ENTRY));
+ Win32IpForwardRowToRouteEntry(e, &p->table[i]);
+ Add(o, e);
+ }
+ Free(p);
+
+ // Sort by metric
+ Sort(o);
+
+ // Combine the results
+ t->NumEntry = LIST_NUM(o);
+ t->Entry = ToArrayEx(o, true);
+ ReleaseList(o);
+
+ return t;
+}
+
+// Sort the routing entries by metric
+int Win32CompareRouteEntryByMetric(void *p1, void *p2)
+{
+ ROUTE_ENTRY *e1, *e2;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+
+ e1 = *(ROUTE_ENTRY **)p1;
+ e2 = *(ROUTE_ENTRY **)p2;
+ if (e1 == NULL || e2 == NULL)
+ {
+ return 0;
+ }
+
+ if (e1->Metric > e2->Metric)
+ {
+ return 1;
+ }
+ else if (e1->Metric == e2->Metric)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+// Convert the ROUTE_ENTRY to a MIB_IPFORWARDROW
+void Win32RouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry)
+{
+ MIB_IPFORWARDROW *r;
+ // Validate arguments
+ if (entry == NULL || ip_forward_row == NULL)
+ {
+ return;
+ }
+
+ r = (MIB_IPFORWARDROW *)ip_forward_row;
+ Zero(r, sizeof(MIB_IPFORWARDROW));
+
+ // IP address
+ r->dwForwardDest = Win32IPToUINT(&entry->DestIP);
+ // Subnet mask
+ r->dwForwardMask = Win32IPToUINT(&entry->DestMask);
+ // Gateway IP address
+ r->dwForwardNextHop = Win32IPToUINT(&entry->GatewayIP);
+ // Local routing flag
+ if (entry->LocalRouting)
+ {
+ // Local
+ r->dwForwardType = 3;
+ }
+ else
+ {
+ // Remote router
+ r->dwForwardType = 4;
+ }
+ // Protocol
+ r->dwForwardProto = r->dwForwardType - 1; // Subtract by 1 in most cases
+ if (entry->PPPConnection)
+ {
+ // Isn't this a PPP? Danger!
+ r->dwForwardProto++;
+ }
+ // Metric
+ r->dwForwardMetric1 = entry->Metric;
+
+ if (MsIsVista() == false)
+ {
+ r->dwForwardMetric2 = r->dwForwardMetric3 = r->dwForwardMetric4 = r->dwForwardMetric5 = INFINITE;
+ }
+ else
+ {
+ r->dwForwardMetric2 = r->dwForwardMetric3 = r->dwForwardMetric4 = r->dwForwardMetric5 = 0;
+ r->dwForwardAge = 163240;
+ }
+
+ // Interface ID
+ r->dwForwardIfIndex = entry->InterfaceID;
+
+ Debug("Win32RouteEntryToIpForwardRow()\n");
+ Debug(" r->dwForwardDest=%X\n", r->dwForwardDest);
+ Debug(" r->dwForwardMask=%X\n", r->dwForwardMask);
+ Debug(" r->dwForwardNextHop=%X\n", r->dwForwardNextHop);
+ Debug(" r->dwForwardType=%u\n", r->dwForwardType);
+ Debug(" r->dwForwardProto=%u\n", r->dwForwardProto);
+ Debug(" r->dwForwardMetric1=%u\n", r->dwForwardMetric1);
+ Debug(" r->dwForwardMetric2=%u\n", r->dwForwardMetric2);
+ Debug(" r->dwForwardIfIndex=%u\n", r->dwForwardIfIndex);
+}
+
+// Convert the MIB_IPFORWARDROW to a ROUTE_ENTRY
+void Win32IpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row)
+{
+ MIB_IPFORWARDROW *r;
+ // Validate arguments
+ if (entry == NULL || ip_forward_row == NULL)
+ {
+ return;
+ }
+
+ r = (MIB_IPFORWARDROW *)ip_forward_row;
+
+ Zero(entry, sizeof(ROUTE_ENTRY));
+ // IP address
+ Win32UINTToIP(&entry->DestIP, r->dwForwardDest);
+ // Subnet mask
+ Win32UINTToIP(&entry->DestMask, r->dwForwardMask);
+ // Gateway IP address
+ Win32UINTToIP(&entry->GatewayIP, r->dwForwardNextHop);
+ // Local routing flag
+ if (r->dwForwardType == 3)
+ {
+ entry->LocalRouting = true;
+ }
+ else
+ {
+ entry->LocalRouting = false;
+ }
+ if (entry->LocalRouting && r->dwForwardProto == 3)
+ {
+ // PPP. Danger!
+ entry->PPPConnection = true;
+ }
+ // Metric
+ entry->Metric = r->dwForwardMetric1;
+ // Interface ID
+ entry->InterfaceID = r->dwForwardIfIndex;
+}
+
+// Initializing the socket library
+void Win32InitSocketLibrary()
+{
+ WSADATA data;
+ Zero(&data, sizeof(data));
+ WSAStartup(MAKEWORD(2, 2), &data);
+
+ // Load the DLL functions
+ w32net = ZeroMalloc(sizeof(NETWORK_WIN32_FUNCTIONS));
+ w32net->hIpHlpApi32 = LoadLibrary("iphlpapi.dll");
+ w32net->hIcmp = LoadLibrary("icmp.dll");
+
+ if (w32net->hIpHlpApi32 != NULL)
+ {
+ w32net->CreateIpForwardEntry =
+ (DWORD (__stdcall *)(PMIB_IPFORWARDROW))
+ GetProcAddress(w32net->hIpHlpApi32, "CreateIpForwardEntry");
+
+ w32net->DeleteIpForwardEntry =
+ (DWORD (__stdcall *)(PMIB_IPFORWARDROW))
+ GetProcAddress(w32net->hIpHlpApi32, "DeleteIpForwardEntry");
+
+ w32net->GetIfTable =
+ (DWORD (__stdcall *)(PMIB_IFTABLE, PULONG, BOOL))
+ GetProcAddress(w32net->hIpHlpApi32, "GetIfTable");
+
+ w32net->GetIfTable2 =
+ (DWORD (__stdcall *)(void **))
+ GetProcAddress(w32net->hIpHlpApi32, "GetIfTable2");
+
+ w32net->FreeMibTable =
+ (void (__stdcall *)(PVOID))
+ GetProcAddress(w32net->hIpHlpApi32, "FreeMibTable");
+
+ w32net->GetIpForwardTable =
+ (DWORD (__stdcall *)(PMIB_IPFORWARDTABLE, PULONG, BOOL))
+ GetProcAddress(w32net->hIpHlpApi32, "GetIpForwardTable");
+
+ w32net->GetNetworkParams =
+ (DWORD (__stdcall *)(PFIXED_INFO,PULONG))
+ GetProcAddress(w32net->hIpHlpApi32, "GetNetworkParams");
+
+ w32net->GetAdaptersAddresses =
+ (ULONG (__stdcall *)(ULONG,ULONG,PVOID,PIP_ADAPTER_ADDRESSES,PULONG))
+ GetProcAddress(w32net->hIpHlpApi32, "GetAdaptersAddresses");
+
+ w32net->IpRenewAddress =
+ (DWORD (__stdcall *)(PIP_ADAPTER_INDEX_MAP))
+ GetProcAddress(w32net->hIpHlpApi32, "IpRenewAddress");
+
+ w32net->IpReleaseAddress =
+ (DWORD (__stdcall *)(PIP_ADAPTER_INDEX_MAP))
+ GetProcAddress(w32net->hIpHlpApi32, "IpReleaseAddress");
+
+ w32net->GetInterfaceInfo =
+ (DWORD (__stdcall *)(PIP_INTERFACE_INFO, PULONG))
+ GetProcAddress(w32net->hIpHlpApi32, "GetInterfaceInfo");
+
+ w32net->GetAdaptersInfo =
+ (DWORD (__stdcall *)(PIP_ADAPTER_INFO, PULONG))
+ GetProcAddress(w32net->hIpHlpApi32, "GetAdaptersInfo");
+
+ w32net->GetExtendedTcpTable =
+ (DWORD (__stdcall *)(PVOID,PDWORD,BOOL,ULONG,_TCP_TABLE_CLASS,ULONG))
+ GetProcAddress(w32net->hIpHlpApi32, "GetExtendedTcpTable");
+
+ w32net->AllocateAndGetTcpExTableFromStack =
+ (DWORD (__stdcall *)(PVOID *,BOOL,HANDLE,DWORD,DWORD))
+ GetProcAddress(w32net->hIpHlpApi32, "AllocateAndGetTcpExTableFromStack");
+
+ w32net->GetTcpTable =
+ (DWORD (__stdcall *)(PMIB_TCPTABLE,PDWORD,BOOL))
+ GetProcAddress(w32net->hIpHlpApi32, "GetTcpTable");
+
+ w32net->NotifyRouteChange =
+ (DWORD (__stdcall *)(PHANDLE,LPOVERLAPPED))
+ GetProcAddress(w32net->hIpHlpApi32, "NotifyRouteChange");
+
+ w32net->CancelIPChangeNotify =
+ (BOOL (__stdcall *)(LPOVERLAPPED))
+ GetProcAddress(w32net->hIpHlpApi32, "CancelIPChangeNotify");
+
+ w32net->NhpAllocateAndGetInterfaceInfoFromStack =
+ (DWORD (__stdcall *)(IP_INTERFACE_NAME_INFO **,PDWORD,BOOL,HANDLE,DWORD))
+ GetProcAddress(w32net->hIpHlpApi32, "NhpAllocateAndGetInterfaceInfoFromStack");
+
+ w32net->IcmpCreateFile =
+ (HANDLE (__stdcall *)())
+ GetProcAddress(w32net->hIpHlpApi32, "IcmpCreateFile");
+
+ w32net->IcmpCloseHandle =
+ (BOOL (__stdcall *)(HANDLE))
+ GetProcAddress(w32net->hIpHlpApi32, "IcmpCloseHandle");
+
+ w32net->IcmpSendEcho =
+ (DWORD (__stdcall *)(HANDLE,IPAddr,LPVOID,WORD,PIP_OPTION_INFORMATION,LPVOID,DWORD,DWORD))
+ GetProcAddress(w32net->hIpHlpApi32, "IcmpSendEcho");
+ }
+
+ if (w32net->hIcmp != NULL)
+ {
+ if (w32net->IcmpCreateFile == NULL || w32net->IcmpCloseHandle == NULL || w32net->IcmpSendEcho == NULL)
+ {
+ w32net->IcmpCreateFile =
+ (HANDLE (__stdcall *)())
+ GetProcAddress(w32net->hIcmp, "IcmpCreateFile");
+
+ w32net->IcmpCloseHandle =
+ (BOOL (__stdcall *)(HANDLE))
+ GetProcAddress(w32net->hIcmp, "IcmpCloseHandle");
+
+ w32net->IcmpSendEcho =
+ (DWORD (__stdcall *)(HANDLE,IPAddr,LPVOID,WORD,PIP_OPTION_INFORMATION,LPVOID,DWORD,DWORD))
+ GetProcAddress(w32net->hIcmp, "IcmpSendEcho");
+ }
+ }
+
+ if (w32net->IcmpCreateFile == NULL || w32net->IcmpCloseHandle == NULL || w32net->IcmpSendEcho == NULL)
+ {
+ w32net->IcmpCreateFile = NULL;
+ w32net->IcmpCloseHandle = NULL;
+ w32net->IcmpSendEcho = NULL;
+ }
+}
+
+// Release of the socket library
+void Win32FreeSocketLibrary()
+{
+ if (w32net != NULL)
+ {
+ if (w32net->hIpHlpApi32 != NULL)
+ {
+ FreeLibrary(w32net->hIpHlpApi32);
+ }
+
+ if (w32net->hIcmp != NULL)
+ {
+ FreeLibrary(w32net->hIcmp);
+ }
+
+ Free(w32net);
+ w32net = NULL;
+ }
+
+ WSACleanup();
+}
+
+// Cancel
+void Win32Cancel(CANCEL *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ SetEvent((HANDLE)c->hEvent);
+}
+
+// Cleanup of the cancel object
+void Win32CleanupCancel(CANCEL *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (c->SpecialFlag == false)
+ {
+ CloseHandle(c->hEvent);
+ }
+
+ Free(c);
+}
+
+// New cancel object
+CANCEL *Win32NewCancel()
+{
+ CANCEL *c = ZeroMallocFast(sizeof(CANCEL));
+ c->ref = NewRef();
+ c->SpecialFlag = false;
+ c->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ return c;
+}
+
+// Waiting for a socket event
+bool Win32WaitSockEvent(SOCK_EVENT *event, UINT timeout)
+{
+ // Validate arguments
+ if (event == NULL || timeout == 0)
+ {
+ return false;
+ }
+
+ if (WaitForSingleObject((HANDLE)event->hEvent, timeout) == WAIT_OBJECT_0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Clean-up of the socket event
+void Win32CleanupSockEvent(SOCK_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ CloseHandle((HANDLE)event->hEvent);
+
+ Free(event);
+}
+
+// Set of the socket event
+void Win32SetSockEvent(SOCK_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ SetEvent((HANDLE)event->hEvent);
+}
+
+// Creating a socket event
+SOCK_EVENT *Win32NewSockEvent()
+{
+ SOCK_EVENT *e = ZeroMallocFast(sizeof(SOCK_EVENT));
+
+ e->ref = NewRef();
+ e->hEvent = (void *)CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ return e;
+}
+
+// Associate the socket with socket event and set it to asynchronous mode
+void Win32JoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event)
+{
+ HANDLE hEvent;
+ // Validate arguments
+ if (sock == NULL || event == NULL || sock->AsyncMode)
+ {
+ return;
+ }
+ if (sock->ListenMode != false || (sock->Type != SOCK_UDP && sock->Connected == false))
+ {
+ return;
+ }
+
+ sock->AsyncMode = true;
+
+ hEvent = event->hEvent;
+
+ // Association
+ WSAEventSelect(sock->socket, hEvent, FD_READ | FD_WRITE | FD_CLOSE);
+
+ // Increase the reference count of the SOCK_EVENT
+ AddRef(event->ref);
+ sock->SockEvent = event;
+}
+
+// Set the socket to asynchronous mode
+void Win32InitAsyncSocket(SOCK *sock)
+{
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+ if (sock->AsyncMode)
+ {
+ // This socket is already in asynchronous mode
+ return;
+ }
+ if (sock->ListenMode || ((sock->Type == SOCK_TCP || sock->Type == SOCK_INPROC) && sock->Connected == false))
+ {
+ return;
+ }
+
+ sock->AsyncMode = true;
+
+ if (sock->Type == SOCK_INPROC)
+ {
+ // Fetch the event of the TUBE
+ TUBE *t = sock->RecvTube;
+
+ if (t != NULL)
+ {
+ if (t->SockEvent != NULL)
+ {
+ sock->hEvent = t->SockEvent->hEvent;
+ }
+ }
+ }
+ else
+ {
+ // Creating an Event
+ sock->hEvent = (void *)CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ // Association
+ WSAEventSelect(sock->socket, sock->hEvent, FD_READ | FD_WRITE | FD_CLOSE);
+ }
+}
+
+// Release the asynchronous socket
+void Win32FreeAsyncSocket(SOCK *sock)
+{
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+
+ // Asynchronous socket
+ if (sock->hEvent != NULL)
+ {
+ if (sock->Type != SOCK_INPROC)
+ {
+ CloseHandle((HANDLE)sock->hEvent);
+ }
+ }
+ sock->hEvent = NULL;
+ sock->AsyncMode = false;
+
+ // Socket event
+ if (sock->SockEvent != NULL)
+ {
+ ReleaseSockEvent(sock->SockEvent);
+ sock->SockEvent = NULL;
+ }
+}
+
+// Select function for Win32
+void Win32Select(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2)
+{
+ HANDLE array[MAXIMUM_WAIT_OBJECTS];
+ UINT n, i;
+ SOCK *s;
+ // Initialization of array
+ Zero(array, sizeof(array));
+ n = 0;
+
+ // Setting the event array
+ if (set != NULL)
+ {
+ for (i = 0;i < set->NumSocket;i++)
+ {
+ s = set->Sock[i];
+ if (s != NULL)
+ {
+ Win32InitAsyncSocket(s);
+ if (s->hEvent != NULL)
+ {
+ array[n++] = (HANDLE)s->hEvent;
+ }
+
+ if (s->BulkRecvTube != NULL)
+ {
+ array[n++] = (HANDLE)s->BulkRecvTube->SockEvent->hEvent;
+ }
+ }
+ }
+ }
+ if (c1 != NULL && c1->hEvent != NULL)
+ {
+ array[n++] = c1->hEvent;
+ }
+ if (c2 != NULL && c2->hEvent != NULL)
+ {
+ array[n++] = c2->hEvent;
+ }
+
+ if (timeout == 0)
+ {
+ return;
+ }
+
+ if (n == 0)
+ {
+ // Call normal waiting function if no events to wait are registered
+ SleepThread(timeout);
+ }
+ else
+ {
+ // Wait for the event if events are registered at least one
+ if (n == 1)
+ {
+ // Calling a lightweight version If the event is only one
+ WaitForSingleObject(array[0], timeout);
+ }
+ else
+ {
+ // In case of multiple events
+ WaitForMultipleObjects(n, array, false, timeout);
+ }
+ }
+}
+
+#endif // OS_WIN32
+
+// Check whether the IPv6 is supported
+bool IsIPv6Supported()
+{
+#ifdef NO_IPV6
+ return false;
+#else // NO_IPV6
+ SOCKET s;
+
+ s = socket(AF_INET6, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET)
+ {
+ return false;
+ }
+
+ closesocket(s);
+
+ return true;
+#endif // NO_IPV6
+}
+
+// Get the host name from the host cache
+bool GetHostCache(char *hostname, UINT size, IP *ip)
+{
+ bool ret;
+ // Validate arguments
+ if (hostname == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ ret = false;
+
+ LockList(HostCacheList);
+ {
+ HOSTCACHE t, *c;
+ Zero(&t, sizeof(t));
+ Copy(&t.IpAddress, ip, sizeof(IP));
+
+ c = Search(HostCacheList, &t);
+ if (c != NULL)
+ {
+ if (IsEmptyStr(c->HostName) == false)
+ {
+ ret = true;
+ StrCpy(hostname, size, c->HostName);
+ }
+ else
+ {
+ ret = true;
+ StrCpy(hostname, size, "");
+ }
+ }
+ }
+ UnlockList(HostCacheList);
+
+ return ret;
+}
+
+// Add to the host name cache
+void AddHostCache(IP *ip, char *hostname)
+{
+ // Validate arguments
+ if (ip == NULL || hostname == NULL)
+ {
+ return;
+ }
+ if (IsNetworkNameCacheEnabled() == false)
+ {
+ return;
+ }
+
+ LockList(HostCacheList);
+ {
+ HOSTCACHE t, *c;
+ UINT i;
+ LIST *o;
+
+ Zero(&t, sizeof(t));
+ Copy(&t.IpAddress, ip, sizeof(IP));
+
+ c = Search(HostCacheList, &t);
+ if (c == NULL)
+ {
+ c = ZeroMalloc(sizeof(HOSTCACHE));
+ Copy(&c->IpAddress, ip, sizeof(IP));
+ Add(HostCacheList, c);
+ }
+
+ StrCpy(c->HostName, sizeof(c->HostName), hostname);
+ c->Expires = Tick64() + (UINT64)EXPIRES_HOSTNAME;
+
+ o = NewListFast(NULL);
+
+ for (i = 0;i < LIST_NUM(HostCacheList);i++)
+ {
+ HOSTCACHE *c = LIST_DATA(HostCacheList, i);
+
+ if (c->Expires <= Tick64())
+ {
+ Add(o, c);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ HOSTCACHE *c = LIST_DATA(o, i);
+
+ if (Delete(HostCacheList, c))
+ {
+ Free(c);
+ }
+ }
+
+ ReleaseList(o);
+ }
+ UnlockList(HostCacheList);
+}
+
+// Comparison of host name cache entries
+int CompareHostCache(void *p1, void *p2)
+{
+ HOSTCACHE *c1, *c2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ c1 = *(HOSTCACHE **)p1;
+ c2 = *(HOSTCACHE **)p2;
+ if (c1 == NULL || c2 == NULL)
+ {
+ return 0;
+ }
+
+ return CmpIpAddr(&c1->IpAddress, &c2->IpAddress);
+}
+
+// Release of the host name cache
+void FreeHostCache()
+{
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(HostCacheList);i++)
+ {
+ HOSTCACHE *c = LIST_DATA(HostCacheList, i);
+
+ Free(c);
+ }
+
+ ReleaseList(HostCacheList);
+ HostCacheList = NULL;
+}
+
+// Initialization of the host name cache
+void InitHostCache()
+{
+ HostCacheList = NewList(CompareHostCache);
+}
+
+// Add the thread to the thread waiting list
+void AddWaitThread(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ AddRef(t->ref);
+
+ LockList(WaitThreadList);
+ {
+ Add(WaitThreadList, t);
+ }
+ UnlockList(WaitThreadList);
+}
+
+// Remove the thread from the waiting list
+void DelWaitThread(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ LockList(WaitThreadList);
+ {
+ if (Delete(WaitThreadList, t))
+ {
+ ReleaseThread(t);
+ }
+ }
+ UnlockList(WaitThreadList);
+}
+
+// Creating a thread waiting list
+void InitWaitThread()
+{
+ WaitThreadList = NewList(NULL);
+}
+
+// Release of the thread waiting list
+void FreeWaitThread()
+{
+ UINT i, num;
+ THREAD **threads;
+
+ LockList(WaitThreadList);
+ {
+ num = LIST_NUM(WaitThreadList);
+ threads = ToArray(WaitThreadList);
+ DeleteAll(WaitThreadList);
+ }
+ UnlockList(WaitThreadList);
+
+ for (i = 0;i < num;i++)
+ {
+ THREAD *t = threads[i];
+ WaitThread(t, INFINITE);
+ ReleaseThread(t);
+ }
+
+ Free(threads);
+
+ ReleaseList(WaitThreadList);
+ WaitThreadList = NULL;
+}
+
+// Check the cipher list name
+bool CheckCipherListName(char *name)
+{
+ UINT i;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < cipher_list_token->NumTokens;i++)
+ {
+ if (StrCmpi(cipher_list_token->Token[i], name) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Renewing the IP address of the DHCP server
+void RenewDhcp()
+{
+#ifdef OS_WIN32
+ Win32RenewDhcp();
+#else
+ UnixRenewDhcp();
+#endif
+}
+
+// Get a domain name for UNIX
+bool UnixGetDomainName(char *name, UINT size)
+{
+ bool ret = false;
+ BUF *b = ReadDump("/etc/resolv.conf");
+
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ while (true)
+ {
+ char *s = CfgReadNextLine(b);
+ TOKEN_LIST *t;
+
+ if (s == NULL)
+ {
+ break;
+ }
+
+ Trim(s);
+
+ t = ParseToken(s, " \t");
+ if (t != NULL)
+ {
+ if (t->NumTokens == 2)
+ {
+ if (StrCmpi(t->Token[0], "domain") == 0)
+ {
+ StrCpy(name, size, t->Token[1]);
+ ret = true;
+ }
+ }
+ FreeToken(t);
+ }
+
+ Free(s);
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Get the domain name
+bool GetDomainName(char *name, UINT size)
+{
+ bool ret = false;
+ IP ip;
+ // Validate arguments
+ ClearStr(name, size);
+ if (name == NULL)
+ {
+ return false;
+ }
+
+#ifdef OS_WIN32
+ ClearStr(name, size);
+ ret = Win32GetDefaultDns(&ip, name, size);
+
+ if (ret == false || IsEmptyStr(name))
+ {
+ ret = Win32GetDnsSuffix(name, size);
+ }
+#else // OS_WIN32
+ ret = UnixGetDomainName(name, size);
+#endif // OS_WIN32
+
+ if (ret == false)
+ {
+ return false;
+ }
+
+ return (IsEmptyStr(name) ? false : true);
+}
+
+// Get the default DNS server
+bool GetDefaultDns(IP *ip)
+{
+ bool ret = false;
+#ifdef OS_WIN32
+ ret = Win32GetDefaultDns(ip, NULL, 0);
+#else
+ ret = UnixGetDefaultDns(ip);
+#endif // OS_WIN32
+ return ret;
+}
+
+// Creating a socket event
+SOCK_EVENT *NewSockEvent()
+{
+ SOCK_EVENT *e = NULL;
+#ifdef OS_WIN32
+ e = Win32NewSockEvent();
+#else
+ e = UnixNewSockEvent();
+#endif // OS_WIN32
+ return e;
+}
+
+// Set of the socket event
+void SetSockEvent(SOCK_EVENT *event)
+{
+#ifdef OS_WIN32
+ Win32SetSockEvent(event);
+#else
+ UnixSetSockEvent(event);
+#endif // OS_WIN32
+}
+
+// Clean-up of the socket event
+void CleanupSockEvent(SOCK_EVENT *event)
+{
+#ifdef OS_WIN32
+ Win32CleanupSockEvent(event);
+#else
+ UnixCleanupSockEvent(event);
+#endif // OS_WIN32
+}
+
+// Waiting for the socket event
+bool WaitSockEvent(SOCK_EVENT *event, UINT timeout)
+{
+ bool ret = false;
+#ifdef OS_WIN32
+ ret = Win32WaitSockEvent(event, timeout);
+#else
+ ret = UnixWaitSockEvent(event, timeout);
+#endif // OS_WIN32
+ return ret;
+}
+
+// Release of the socket event
+void ReleaseSockEvent(SOCK_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ if (Release(event->ref) == 0)
+ {
+ CleanupSockEvent(event);
+ }
+}
+
+// Let belonging the socket to the socket event
+void JoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event)
+{
+ // Validate arguments
+ if (sock == NULL || event == NULL)
+ {
+ return;
+ }
+
+ if (sock->Type == SOCK_INPROC)
+ {
+ // Set the SockEvent on the receiver TUBE for in-process type socket
+ SetTubeSockEvent(sock->RecvTube, event);
+ return;
+ }
+
+ if (sock->BulkRecvTube != NULL)
+ {
+ // Set the SockEvent on the receiver TUBE in case of R-UDP socket
+ SetTubeSockEvent(sock->BulkRecvTube, event);
+ }
+
+#ifdef OS_WIN32
+ Win32JoinSockToSockEvent(sock, event);
+#else
+ UnixJoinSockToSockEvent(sock, event);
+#endif // OS_WIN32
+}
+
+// New special cancel object
+CANCEL *NewCancelSpecial(void *hEvent)
+{
+ CANCEL *c;
+ // Validate arguments
+ if (hEvent == NULL)
+ {
+ return NULL;
+ }
+
+ c = ZeroMalloc(sizeof(CANCEL));
+ c->ref = NewRef();
+ c->SpecialFlag = true;
+
+#ifdef OS_WIN32
+ c->hEvent = (HANDLE)hEvent;
+#else // OS_WIN32
+ c->pipe_read = (int)hEvent;
+ c->pipe_write = -1;
+#endif // OS_WIN32
+
+ return c;
+}
+
+// Creating a cancel object
+CANCEL *NewCancel()
+{
+ CANCEL *c = NULL;
+#ifdef OS_WIN32
+ c = Win32NewCancel();
+#else
+ c = UnixNewCancel();
+#endif // OS_WIN32
+ return c;
+}
+
+// Release of the cancel object
+void ReleaseCancel(CANCEL *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ if (Release(c->ref) == 0)
+ {
+ CleanupCancel(c);
+ }
+}
+
+// Clean up of the cancel object
+void CleanupCancel(CANCEL *c)
+{
+#ifdef OS_WIN32
+ Win32CleanupCancel(c);
+#else
+ UnixCleanupCancel(c);
+#endif
+}
+
+// Cancellation triggered
+void Cancel(CANCEL *c)
+{
+#ifdef OS_WIN32
+ Win32Cancel(c);
+#else
+ UnixCancel(c);
+#endif
+}
+
+// Calculate the optimal route from the specified routing table
+ROUTE_ENTRY *GetBestRouteEntryFromRouteTable(ROUTE_TABLE *table, IP *ip)
+{
+ return GetBestRouteEntryFromRouteTableEx(table, ip, 0);
+}
+ROUTE_ENTRY *GetBestRouteEntryFromRouteTableEx(ROUTE_TABLE *table, IP *ip, UINT exclude_if_id)
+{
+ UINT i;
+ ROUTE_ENTRY *ret = NULL;
+ ROUTE_ENTRY *tmp = NULL;
+ UINT64 min_score = 0;
+ // Validate arguments
+ if (ip == NULL || table == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsIP6(ip))
+ {
+ // IPv6 is not supported
+ return NULL;
+ }
+
+ // Select routing table entry by following rule
+ // 1. Largest subnet mask
+ // 2. Smallest metric value
+ for (i = 0;i < table->NumEntry;i++)
+ {
+ ROUTE_ENTRY *e = table->Entry[i];
+ UINT dest, net, mask;
+
+ dest = IPToUINT(ip);
+ net = IPToUINT(&e->DestIP);
+ mask = IPToUINT(&e->DestMask);
+
+ if (exclude_if_id != 0)
+ {
+ if (e->InterfaceID == exclude_if_id)
+ {
+ continue;
+ }
+ }
+
+ // Mask test
+ if ((dest & mask) == (net & mask))
+ {
+ // Calculate the score
+ UINT score_high32 = mask;
+ UINT score_low32 = 0xFFFFFFFF - e->Metric;
+ UINT64 score64 = (UINT64)score_high32 * (UINT64)0x80000000 * (UINT64)2 + (UINT64)score_low32;
+ if (score64 == 0)
+ {
+ score64 = 1;
+ }
+
+ e->InnerScore = score64;
+ }
+ }
+
+ tmp = NULL;
+
+ // Search for the item with maximum score
+ for (i = 0;i < table->NumEntry;i++)
+ {
+ ROUTE_ENTRY *e = table->Entry[i];
+
+ if (e->InnerScore != 0)
+ {
+ if (e->InnerScore >= min_score)
+ {
+ tmp = e;
+ min_score = e->InnerScore;
+ }
+ }
+ }
+
+ if (tmp != NULL)
+ {
+ UINT dest, gateway, mask;
+
+ // Generate an entry
+ ret = ZeroMallocFast(sizeof(ROUTE_ENTRY));
+
+ Copy(&ret->DestIP, ip, sizeof(IP));
+ ret->DestMask.addr[0] = 255;
+ ret->DestMask.addr[1] = 255;
+ ret->DestMask.addr[2] = 255;
+ ret->DestMask.addr[3] = 255;
+ Copy(&ret->GatewayIP, &tmp->GatewayIP, sizeof(IP));
+ ret->InterfaceID = tmp->InterfaceID;
+ ret->LocalRouting = tmp->LocalRouting;
+ ret->OldIfMetric = tmp->Metric;
+ ret->Metric = 1;
+ ret->PPPConnection = tmp->PPPConnection;
+
+ // Calculation related to routing control
+ dest = IPToUINT(&tmp->DestIP);
+ gateway = IPToUINT(&tmp->GatewayIP);
+ mask = IPToUINT(&tmp->DestMask);
+ if ((dest & mask) == (gateway & mask))
+ {
+#ifdef OS_WIN32
+ if (MsIsVista() == false)
+ {
+ // Adjust for Windows
+ ret->PPPConnection = true;
+ }
+#endif // OS_WIN32
+ }
+ }
+
+ return ret;
+}
+
+// Release the routing entry
+void FreeRouteEntry(ROUTE_ENTRY *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ Free(e);
+}
+
+// Get the best route entry by analyzing the current routing table
+ROUTE_ENTRY *GetBestRouteEntry(IP *ip)
+{
+ return GetBestRouteEntryEx(ip, 0);
+}
+ROUTE_ENTRY *GetBestRouteEntryEx(IP *ip, UINT exclude_if_id)
+{
+ ROUTE_TABLE *table;
+ ROUTE_ENTRY *e = NULL;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return NULL;
+ }
+
+ table = GetRouteTable();
+ if (table == NULL)
+ {
+ return NULL;
+ }
+
+ e = GetBestRouteEntryFromRouteTableEx(table, ip, exclude_if_id);
+ FreeRouteTable(table);
+
+ return e;
+}
+
+// Get the interface ID of the virtual LAN card
+UINT GetVLanInterfaceID(char *tag_name)
+{
+ UINT ret = 0;
+#ifdef OS_WIN32
+ ret = Win32GetVLanInterfaceID(tag_name);
+#else // OS_WIN32
+ ret = UnixGetVLanInterfaceID(tag_name);
+#endif // OS_WIN32
+ return ret;
+}
+
+// Release of enumeration variable of virtual LAN card
+void FreeEnumVLan(char **s)
+{
+ char *a;
+ UINT i;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ i = 0;
+ while (true)
+ {
+ a = s[i++];
+ if (a == NULL)
+ {
+ break;
+ }
+ Free(a);
+ }
+
+ Free(s);
+}
+
+// Enumeration of virtual LAN cards
+char **EnumVLan(char *tag_name)
+{
+ char **ret = NULL;
+#ifdef OS_WIN32
+ ret = Win32EnumVLan(tag_name);
+#else // OS_WIN32
+ ret = UnixEnumVLan(tag_name);
+#endif // OS_WIN32
+ return ret;
+}
+
+// Display the routing table
+void DebugPrintRouteTable(ROUTE_TABLE *r)
+{
+ UINT i;
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ if (IsDebug() == false)
+ {
+ return;
+ }
+
+ Debug("---- Routing Table (%u Entries) ----\n", r->NumEntry);
+
+ for (i = 0;i < r->NumEntry;i++)
+ {
+ Debug(" ");
+
+ DebugPrintRoute(r->Entry[i]);
+ }
+
+ Debug("------------------------------------\n");
+}
+
+// Display the routing table entry
+void DebugPrintRoute(ROUTE_ENTRY *e)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ if (IsDebug() == false)
+ {
+ return;
+ }
+
+ RouteToStr(tmp, sizeof(tmp), e);
+
+ Debug("%s\n", tmp);
+}
+
+// Convert the routing table entry to string
+void RouteToStr(char *str, UINT str_size, ROUTE_ENTRY *e)
+{
+ char dest_ip[MAX_PATH];
+ char dest_mask[MAX_PATH];
+ char gateway_ip[MAX_PATH];
+ // Validate arguments
+ if (str == NULL || e == NULL)
+ {
+ return;
+ }
+
+ IPToStr(dest_ip, sizeof(dest_ip), &e->DestIP);
+ IPToStr(dest_mask, sizeof(dest_mask), &e->DestMask);
+ IPToStr(gateway_ip, sizeof(gateway_ip), &e->GatewayIP);
+
+ Format(str, str_size, "%s/%s %s m=%u oif=%u if=%u lo=%u p=%u",
+ dest_ip, dest_mask, gateway_ip,
+ e->Metric, e->OldIfMetric, e->InterfaceID,
+ e->LocalRouting, e->PPPConnection);
+}
+
+// Delete the routing table
+void DeleteRouteEntry(ROUTE_ENTRY *e)
+{
+ Debug("DeleteRouteEntry();\n");
+#ifdef OS_WIN32
+ Win32DeleteRouteEntry(e);
+#else // OS_WIN32
+ UnixDeleteRouteEntry(e);
+#endif
+}
+
+// Add to the routing table
+bool AddRouteEntry(ROUTE_ENTRY *e)
+{
+ bool dummy = false;
+ return AddRouteEntryEx(e, &dummy);
+}
+bool AddRouteEntryEx(ROUTE_ENTRY *e, bool *already_exists)
+{
+ bool ret = false;
+ Debug("AddRouteEntryEx();\n");
+#ifdef OS_WIN32
+ ret = Win32AddRouteEntry(e, already_exists);
+#else // OS_WIN32
+ ret = UnixAddRouteEntry(e, already_exists);
+#endif
+ return ret;
+}
+
+// Get the routing table
+ROUTE_TABLE *GetRouteTable()
+{
+ ROUTE_TABLE *t = NULL;
+ UINT i;
+ BUF *buf = NewBuf();
+ UCHAR hash[MD5_SIZE];
+
+#ifdef OS_WIN32
+ t = Win32GetRouteTable();
+#else //OS_WIN32
+ t = UnixGetRouteTable();
+#endif // OS_WIN32
+
+ WriteBuf(buf, &t->NumEntry, sizeof(t->NumEntry));
+
+ for (i = 0;i < t->NumEntry;i++)
+ {
+ ROUTE_ENTRY *e = t->Entry[i];
+
+ WriteBuf(buf, e, sizeof(ROUTE_ENTRY));
+ }
+
+ Hash(hash, buf->Buf, buf->Size, false);
+
+ FreeBuf(buf);
+
+ Copy(&t->HashedValue, hash, sizeof(t->HashedValue));
+
+ return t;
+}
+
+// Release of the routing table
+void FreeRouteTable(ROUTE_TABLE *t)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < t->NumEntry;i++)
+ {
+ Free(t->Entry[i]);
+ }
+ Free(t->Entry);
+ Free(t);
+}
+
+// UDP receiving
+UINT RecvFrom(SOCK *sock, IP *src_addr, UINT *src_port, void *data, UINT size)
+{
+ SOCKET s;
+ int ret, sz;
+ struct sockaddr_in addr;
+ // Validate arguments
+ if (sock != NULL)
+ {
+ sock->IgnoreRecvErr = false;
+ }
+ if (sock == NULL || src_addr == NULL || src_port == NULL || data == NULL)
+ {
+ return false;
+ }
+ if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)
+ {
+ return false;
+ }
+ if (size == 0)
+ {
+ return false;
+ }
+
+ if (sock->IPv6)
+ {
+ return RecvFrom6(sock, src_addr, src_port, data, size);
+ }
+
+ s = sock->socket;
+
+ sz = sizeof(addr);
+ ret = recvfrom(s, data, size, 0, (struct sockaddr *)&addr, (int *)&sz);
+ if (ret > 0)
+ {
+ InAddrToIP(src_addr, &addr.sin_addr);
+ *src_port = (UINT)ntohs(addr.sin_port);
+ if (sock->IsRawSocket)
+ {
+ *src_port = sock->LocalPort;
+/*
+ {
+ char tmp[MAX_SIZE];
+
+ IPToStr(tmp, sizeof(tmp), &sock->LocalIP);
+ Debug("Raw: %u from %s\n", sock->LocalPort, tmp);
+ }*/
+ }
+
+ Lock(sock->lock);
+ {
+ sock->RecvNum++;
+ sock->RecvSize += (UINT64)ret;
+ }
+ Unlock(sock->lock);
+
+ // Debug("UDP RecvFrom: %u\n", ret);
+
+ return (UINT)ret;
+ }
+ else
+ {
+ sock->IgnoreRecvErr = false;
+
+#ifdef OS_WIN32
+ if (WSAGetLastError() == WSAECONNRESET || WSAGetLastError() == WSAEMSGSIZE || WSAGetLastError() == WSAENETUNREACH ||
+ WSAGetLastError() == WSAENOBUFS || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAEUSERS)
+ {
+ sock->IgnoreRecvErr = true;
+ }
+ else if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINPROGRESS)
+ {
+ return SOCK_LATER;
+ }
+ else
+ {
+ UINT e = WSAGetLastError();
+// Debug("RecvFrom Error: %u\n", e);
+ }
+#else // OS_WIN32
+ if (errno == ECONNREFUSED || errno == ECONNRESET || errno == EMSGSIZE || errno == ENOBUFS || errno == ENOMEM || errno == EINTR)
+ {
+ sock->IgnoreRecvErr = true;
+ }
+ else if (errno == EAGAIN)
+ {
+ return SOCK_LATER;
+ }
+#endif // OS_WIN32
+ return 0;
+ }
+}
+UINT RecvFrom6(SOCK *sock, IP *src_addr, UINT *src_port, void *data, UINT size)
+{
+ SOCKET s;
+ int ret, sz;
+ struct sockaddr_in6 addr;
+ // Validate arguments
+ if (sock != NULL)
+ {
+ sock->IgnoreRecvErr = false;
+ }
+ if (sock == NULL || src_addr == NULL || src_port == NULL || data == NULL)
+ {
+ return false;
+ }
+ if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)
+ {
+ return false;
+ }
+ if (size == 0)
+ {
+ return false;
+ }
+
+ s = sock->socket;
+
+ sz = sizeof(addr);
+ ret = recvfrom(s, data, size, 0, (struct sockaddr *)&addr, (int *)&sz);
+ if (ret > 0)
+ {
+ InAddrToIP6(src_addr, &addr.sin6_addr);
+ src_addr->ipv6_scope_id = addr.sin6_scope_id;
+ *src_port = (UINT)ntohs(addr.sin6_port);
+ if (sock->IsRawSocket)
+ {
+ *src_port = sock->LocalPort;
+ }
+
+ Lock(sock->lock);
+ {
+ sock->RecvNum++;
+ sock->RecvSize += (UINT64)ret;
+ }
+ Unlock(sock->lock);
+
+ // Debug("UDP RecvFrom: %u\n", ret);
+
+ return (UINT)ret;
+ }
+ else
+ {
+ sock->IgnoreRecvErr = false;
+
+#ifdef OS_WIN32
+ if (WSAGetLastError() == WSAECONNRESET || WSAGetLastError() == WSAEMSGSIZE || WSAGetLastError() == WSAENETUNREACH ||
+ WSAGetLastError() == WSAENOBUFS || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAEUSERS)
+ {
+ sock->IgnoreRecvErr = true;
+ }
+ else if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINPROGRESS)
+ {
+ return SOCK_LATER;
+ }
+ else
+ {
+ UINT e = WSAGetLastError();
+ // Debug("RecvFrom Error: %u\n", e);
+ }
+#else // OS_WIN32
+ if (errno == ECONNREFUSED || errno == ECONNRESET || errno == EMSGSIZE || errno == ENOBUFS || errno == ENOMEM || errno == EINTR)
+ {
+ sock->IgnoreRecvErr = true;
+ }
+ else if (errno == EAGAIN)
+ {
+ return SOCK_LATER;
+ }
+#endif // OS_WIN32
+ return 0;
+ }
+}
+
+// Lock the OpenSSL
+void LockOpenSSL()
+{
+ Lock(openssl_lock);
+}
+
+// Unlock the OpenSSL
+void UnlockOpenSSL()
+{
+ Unlock(openssl_lock);
+}
+
+// UDP transmission
+UINT SendTo(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size)
+{
+ return SendToEx(sock, dest_addr, dest_port, data, size, false);
+}
+UINT SendToEx(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size, bool broadcast)
+{
+ SOCKET s;
+ int ret;
+ struct sockaddr_in addr;
+ // Validate arguments
+ if (sock != NULL)
+ {
+ sock->IgnoreSendErr = false;
+ }
+ if (sock == NULL || dest_addr == NULL || (sock->IsRawSocket == false && dest_port == 0) || data == NULL)
+ {
+ return 0;
+ }
+ if (dest_port >= 65536 && sock->IsRawSocket == false)
+ {
+ return 0;
+ }
+ if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)
+ {
+ return 0;
+ }
+ if (size == 0)
+ {
+ return 0;
+ }
+
+ if (sock->IPv6)
+ {
+ return SendTo6Ex(sock, dest_addr, dest_port, data, size, broadcast);
+ }
+
+ if (IsIP4(dest_addr) == false)
+ {
+ return 0;
+ }
+
+ s = sock->socket;
+ Zero(&addr, sizeof(addr));
+ addr.sin_family = AF_INET;
+ if (sock->IsRawSocket == false)
+ {
+ addr.sin_port = htons((USHORT)dest_port);
+ }
+ IPToInAddr(&addr.sin_addr, dest_addr);
+
+ if ((dest_addr->addr[0] == 255 && dest_addr->addr[1] == 255 &&
+ dest_addr->addr[2] == 255 && dest_addr->addr[3] == 255) ||
+ (dest_addr->addr[0] >= 224 && dest_addr->addr[0] <= 239)
+ || broadcast)
+ {
+ if (sock->UdpBroadcast == false)
+ {
+ bool yes = true;
+
+ sock->UdpBroadcast = true;
+
+ setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&yes, sizeof(yes));
+ }
+ }
+
+ ret = sendto(s, data, size, 0, (struct sockaddr *)&addr, sizeof(addr));
+ if (ret != (int)size)
+ {
+ sock->IgnoreSendErr = false;
+
+#ifdef OS_WIN32
+ if (WSAGetLastError() == WSAECONNRESET || WSAGetLastError() == WSAEMSGSIZE || WSAGetLastError() == WSAENETUNREACH ||
+ WSAGetLastError() == WSAENOBUFS || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAEUSERS || WSAGetLastError() == WSAEINVAL)
+ {
+ sock->IgnoreSendErr = true;
+ }
+ else if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINPROGRESS)
+ {
+ return SOCK_LATER;
+ }
+ else
+ {
+ UINT e = WSAGetLastError();
+ Debug("SendTo Error; %u\n", e);
+ }
+#else // OS_WIN32
+ if (errno == ECONNREFUSED || errno == ECONNRESET || errno == EMSGSIZE || errno == ENOBUFS || errno == ENOMEM || errno == EINTR)
+ {
+ sock->IgnoreSendErr = true;
+ }
+ else if (errno == EAGAIN)
+ {
+ return SOCK_LATER;
+ }
+#endif // OS_WIN32
+ return 0;
+ }
+
+ Lock(sock->lock);
+ {
+ sock->SendSize += (UINT64)size;
+ sock->SendNum++;
+ }
+ Unlock(sock->lock);
+
+ return ret;
+}
+UINT SendTo6(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size)
+{
+ return SendTo6Ex(sock, dest_addr, dest_port, data, size, false);
+}
+UINT SendTo6Ex(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size, bool broadcast)
+{
+ SOCKET s;
+ int ret;
+ struct sockaddr_in6 addr;
+ UINT type;
+ // Validate arguments
+ if (sock != NULL)
+ {
+ sock->IgnoreSendErr = false;
+ }
+ if (sock == NULL || dest_addr == NULL || (sock->IsRawSocket == false && dest_port == 0) || data == NULL)
+ {
+ return 0;
+ }
+ if (dest_port >= 65536 && sock->IsRawSocket == false)
+ {
+ return 0;
+ }
+ if (sock->Type != SOCK_UDP || sock->socket == INVALID_SOCKET)
+ {
+ return 0;
+ }
+ if (size == 0)
+ {
+ return 0;
+ }
+
+ if (IsIP6(dest_addr) == false)
+ {
+ return 0;
+ }
+
+ s = sock->socket;
+ Zero(&addr, sizeof(addr));
+ addr.sin6_family = AF_INET6;
+ if (sock->IsRawSocket == false)
+ {
+ addr.sin6_port = htons((USHORT)dest_port);
+ }
+ IPToInAddr6(&addr.sin6_addr, dest_addr);
+ addr.sin6_scope_id = dest_addr->ipv6_scope_id;
+
+ type = GetIPAddrType6(dest_addr);
+
+ if ((type & IPV6_ADDR_MULTICAST) || broadcast)
+ {
+ if (sock->UdpBroadcast == false)
+ {
+ bool yes = true;
+
+ sock->UdpBroadcast = true;
+
+ setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&yes, sizeof(yes));
+ }
+ }
+
+ ret = sendto(s, data, size, 0, (struct sockaddr *)&addr, sizeof(addr));
+ if (ret != (int)size)
+ {
+ sock->IgnoreSendErr = false;
+
+#ifdef OS_WIN32
+ if (WSAGetLastError() == WSAECONNRESET || WSAGetLastError() == WSAEMSGSIZE || WSAGetLastError() == WSAENETUNREACH ||
+ WSAGetLastError() == WSAENOBUFS || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAEUSERS || WSAGetLastError() == WSAEINVAL)
+ {
+ sock->IgnoreSendErr = true;
+ }
+ else if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINPROGRESS)
+ {
+ return SOCK_LATER;
+ }
+ else
+ {
+ UINT e = WSAGetLastError();
+ }
+#else // OS_WIN32
+ if (errno == ECONNREFUSED || errno == ECONNRESET || errno == EMSGSIZE || errno == ENOBUFS || errno == ENOMEM || errno == EINTR)
+ {
+ sock->IgnoreSendErr = true;
+ }
+ else if (errno == EAGAIN)
+ {
+ return SOCK_LATER;
+ }
+#endif // OS_WIN32
+ return 0;
+ }
+
+ Lock(sock->lock);
+ {
+ sock->SendSize += (UINT64)size;
+ sock->SendNum++;
+ }
+ Unlock(sock->lock);
+
+ return ret;
+}
+
+// Disable the UDP checksum
+void DisableUDPChecksum(SOCK *s)
+{
+ bool true_flag = true;
+ // Validate arguments
+ if (s == NULL || s->Type != SOCK_UDP)
+ {
+ return;
+ }
+
+ if (s->socket != INVALID_SOCKET)
+ {
+ if (s->IPv6 == false)
+ {
+#ifdef UDP_NOCHECKSUM
+ setsockopt(s->socket, IPPROTO_UDP, UDP_NOCHECKSUM, (char *)&true_flag, sizeof(bool));
+#endif // UDP_NOCHECKSUM
+ }
+ }
+}
+
+// Set the socket to asynchronous mode
+void InitAsyncSocket(SOCK *sock)
+{
+#ifdef OS_WIN32
+ Win32InitAsyncSocket(sock);
+#else // OS_WIN32
+ UnixInitAsyncSocket(sock);
+#endif // OS_WIN32
+}
+
+// Open a UDP port (port number is random, but determine the randomness in the seed)
+SOCK *NewUDPEx2Rand(bool ipv6, IP *ip, void *rand_seed, UINT rand_seed_size, UINT num_retry)
+{
+ UINT i;
+ // Validate arguments
+ if (rand_seed == NULL || rand_seed_size == 0)
+ {
+ return NULL;
+ }
+ if (num_retry == 0)
+ {
+ num_retry = RAND_UDP_PORT_DEFAULT_NUM_RETRY;
+ }
+
+ for (i = 0; i < (num_retry + 1);i++)
+ {
+ BUF *buf = NewBuf();
+ UCHAR hash[SHA1_SIZE];
+ UINT port = 0;
+ SOCK *s;
+
+ WriteBuf(buf, rand_seed, rand_seed_size);
+ WriteBufInt(buf, i);
+
+ HashSha1(hash, buf->Buf, buf->Size);
+
+ FreeBuf(buf);
+
+ port = READ_UINT(hash);
+
+ port = RAND_UDP_PORT_START + (port % (RAND_UDP_PORT_END - RAND_UDP_PORT_START));
+
+ s = NewUDPEx2(port, ipv6, ip);
+
+ if (s != NULL)
+ {
+ return s;
+ }
+ }
+
+ return NewUDPEx2(0, ipv6, ip);
+}
+
+// Generate a random port number (based on the EXE path and machine key)
+UINT NewRandPortByMachineAndExePath(UINT start_port, UINT end_port, UINT additional_int)
+{
+ BUF *b;
+ char machine_name[MAX_SIZE];
+ wchar_t exe_path[MAX_PATH];
+ char *product_id = NULL;
+ UCHAR hash[SHA1_SIZE];
+
+#ifdef OS_WIN32
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductId");
+ if (product_id == NULL)
+ {
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductId");
+ }
+#endif // OS_WIN32
+
+ b = NewBuf();
+
+ GetMachineHostName(machine_name, sizeof(machine_name));
+ Trim(machine_name);
+ StrUpper(machine_name);
+
+ GetExeNameW(exe_path, sizeof(exe_path));
+ UniTrim(exe_path);
+ UniStrUpper(exe_path);
+
+ WriteBuf(b, machine_name, StrSize(machine_name));
+ WriteBuf(b, exe_path, UniStrSize(exe_path));
+ WriteBuf(b, product_id, StrSize(product_id));
+ WriteBufInt(b, additional_int);
+
+ HashSha1(hash, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ Free(product_id);
+
+ return (READ_UINT(hash) % (end_port - start_port)) + start_port;
+}
+
+// Open the UDP port (based on the EXE path and machine key)
+SOCK *NewUDPEx2RandMachineAndExePath(bool ipv6, IP *ip, UINT num_retry, UCHAR rand_port_id)
+{
+ BUF *b;
+ char machine_name[MAX_SIZE];
+ wchar_t exe_path[MAX_PATH];
+ char *product_id = NULL;
+ UCHAR hash[SHA1_SIZE];
+
+#ifdef OS_WIN32
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductId");
+ if (product_id == NULL)
+ {
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductId");
+ }
+#endif // OS_WIN32
+
+ b = NewBuf();
+
+ GetMachineHostName(machine_name, sizeof(machine_name));
+ Trim(machine_name);
+ StrUpper(machine_name);
+
+ GetExeNameW(exe_path, sizeof(exe_path));
+ UniTrim(exe_path);
+ UniStrUpper(exe_path);
+
+ WriteBuf(b, machine_name, StrSize(machine_name));
+ WriteBuf(b, exe_path, UniStrSize(exe_path));
+ WriteBuf(b, product_id, StrSize(product_id));
+ WriteBufChar(b, rand_port_id);
+ //WriteBufInt(b, GetHostIPAddressHash32());
+
+ HashSha1(hash, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ Free(product_id);
+
+ return NewUDPEx2Rand(ipv6, ip, hash, sizeof(hash), num_retry);
+}
+
+// Create and initialize the UDP socket
+// If port is specified as 0, system assigns a certain port.
+SOCK *NewUDP(UINT port)
+{
+ return NewUDPEx(port, false);
+}
+SOCK *NewUDPEx(UINT port, bool ipv6)
+{
+ return NewUDPEx2(port, ipv6, NULL);
+}
+SOCK *NewUDPEx2(UINT port, bool ipv6, IP *ip)
+{
+ if (ipv6 == false)
+ {
+ return NewUDP4(port, ip);
+ }
+ else
+ {
+ return NewUDP6(port, ip);
+ }
+}
+SOCK *NewUDPEx3(UINT port, IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return NewUDPEx2(port, false, NULL);
+ }
+
+ if (IsIP4(ip))
+ {
+ return NewUDPEx2(port, false, ip);
+ }
+ else
+ {
+ return NewUDPEx2(port, true, ip);
+ }
+}
+SOCK *NewUDP4(UINT port, IP *ip)
+{
+ SOCK *sock;
+ SOCKET s;
+ struct sockaddr_in addr;
+ // Validate arguments
+ if (ip != NULL && IsIP4(ip) == false)
+ {
+ return NULL;
+ }
+
+ if (IS_SPECIAL_PORT(port) == false)
+ {
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ }
+ else
+ {
+ s = socket(AF_INET, SOCK_RAW, GET_SPECIAL_PORT(port));
+ }
+ if (s == INVALID_SOCKET)
+ {
+ return NULL;
+ }
+
+ Zero(&addr, sizeof(addr));
+ addr.sin_family = AF_INET;
+
+ if (ip == NULL || IsZeroIP(ip))
+ {
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ }
+ else
+ {
+ IPToInAddr(&addr.sin_addr, ip);
+ }
+
+ if (port == 0 || IS_SPECIAL_PORT(port))
+ {
+ addr.sin_port = 0;
+ }
+ else
+ {
+ addr.sin_port = htons((USHORT)port);
+ }
+
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)
+ {
+ // Failure
+ if (port != 0)
+ {
+ bool true_flag = true;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)
+ {
+ bool false_flag = false;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&false_flag, sizeof(bool));
+#ifdef SO_EXCLUSIVEADDRUSE
+ setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *)&true_flag, sizeof(bool));
+#endif // SO_EXCLUSIVEADDRUSE
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)
+ {
+ closesocket(s);
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ closesocket(s);
+ return NULL;
+ }
+ }
+
+ sock = NewSock();
+
+ sock->Type = SOCK_UDP;
+ sock->Connected = false;
+ sock->AsyncMode = false;
+ sock->ServerMode = false;
+ if (port != 0)
+ {
+ sock->ServerMode = true;
+ }
+
+ sock->socket = s;
+
+ InitUdpSocketBufferSize((int)s);
+
+ if (IS_SPECIAL_PORT(port))
+ {
+ bool no = false;
+ setsockopt(sock->socket, IPPROTO_IP, IP_HDRINCL, (char *)&no, sizeof(no));
+
+ sock->IsRawSocket = true;
+ sock->RawSocketIPProtocol = GET_SPECIAL_PORT(port);
+ }
+
+ QuerySocketInformation(sock);
+
+ return sock;
+}
+SOCK *NewUDP6(UINT port, IP *ip)
+{
+ SOCK *sock;
+ SOCKET s;
+ struct sockaddr_in6 addr;
+ // Validate arguments
+ if (ip != NULL && IsIP6(ip) == false)
+ {
+ return NULL;
+ }
+
+ if (IS_SPECIAL_PORT(port) == false)
+ {
+ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ }
+ else
+ {
+ s = socket(AF_INET6, SOCK_RAW, GET_SPECIAL_PORT(port));
+ }
+ if (s == INVALID_SOCKET)
+ {
+ return NULL;
+ }
+
+ Zero(&addr, sizeof(addr));
+ addr.sin6_family = AF_INET6;
+ if (port == 0)
+ {
+ addr.sin6_port = 0;
+ }
+ else
+ {
+ addr.sin6_port = htons((USHORT)port);
+ }
+
+ if (ip != NULL && IsZeroIP(ip) == false)
+ {
+ IPToInAddr6(&addr.sin6_addr, ip);
+ addr.sin6_scope_id = ip->ipv6_scope_id;
+ }
+
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)
+ {
+ // Failure
+ if (port != 0)
+ {
+ bool true_flag = true;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)
+ {
+ bool false_flag = false;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&false_flag, sizeof(bool));
+#ifdef SO_EXCLUSIVEADDRUSE
+ setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *)&true_flag, sizeof(bool));
+#endif // SO_EXCLUSIVEADDRUSE
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0)
+ {
+ closesocket(s);
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ closesocket(s);
+ return NULL;
+ }
+ }
+
+ sock = NewSock();
+
+ sock->Type = SOCK_UDP;
+ sock->Connected = false;
+ sock->AsyncMode = false;
+ sock->ServerMode = false;
+ sock->IPv6 = true;
+ if (port != 0)
+ {
+ sock->ServerMode = true;
+ }
+
+ sock->socket = s;
+
+ InitUdpSocketBufferSize(s);
+
+ if (IS_SPECIAL_PORT(port))
+ {
+ bool no = false;
+#ifdef IPV6_HDRINCL
+ setsockopt(sock->socket, IPPROTO_IP, IPV6_HDRINCL, (char *)&no, sizeof(no));
+#endif // IPV6_HDRINCL
+ setsockopt(sock->socket, IPPROTO_IP, IP_HDRINCL, (char *)&no, sizeof(no));
+
+ sock->IsRawSocket = true;
+ sock->RawSocketIPProtocol = GET_SPECIAL_PORT(port);
+ }
+
+ QuerySocketInformation(sock);
+
+ return sock;
+}
+
+// Select function
+void Select(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2)
+{
+#ifdef OS_WIN32
+ Win32Select(set, timeout, c1, c2);
+#else
+ UnixSelect(set, timeout, c1, c2);
+#endif // OS_WIN32
+}
+
+// Add a socket to the socket set
+void AddSockSet(SOCKSET *set, SOCK *sock)
+{
+ // Validate arguments
+ if (set == NULL || sock == NULL)
+ {
+ return;
+ }
+ if (sock->Type == SOCK_TCP && sock->Connected == false)
+ {
+ return;
+ }
+
+ if (set->NumSocket >= MAX_SOCKSET_NUM)
+ {
+ // Upper limit
+ return;
+ }
+ set->Sock[set->NumSocket++] = sock;
+}
+
+// Initializing the socket set
+void InitSockSet(SOCKSET *set)
+{
+ // Validate arguments
+ if (set == NULL)
+ {
+ return;
+ }
+
+ Zero(set, sizeof(SOCKSET));
+}
+
+// Receive all by TCP
+bool RecvAll(SOCK *sock, void *data, UINT size, bool secure)
+{
+ UINT recv_size, sz, ret;
+ // Validate arguments
+ if (sock == NULL || data == NULL)
+ {
+ return false;
+ }
+ if (size == 0)
+ {
+ return true;
+ }
+ if (sock->AsyncMode)
+ {
+ return false;
+ }
+
+ recv_size = 0;
+
+ while (true)
+ {
+ sz = size - recv_size;
+ ret = Recv(sock, (UCHAR *)data + recv_size, sz, secure);
+ if (ret == 0)
+ {
+ return false;
+ }
+ recv_size += ret;
+ if (recv_size >= size)
+ {
+ return true;
+ }
+ }
+}
+
+// Send the TCP send buffer
+bool SendNow(SOCK *sock, int secure)
+{
+ bool ret;
+ // Validate arguments
+ if (sock == NULL || sock->AsyncMode != false)
+ {
+ return false;
+ }
+ if (sock->SendBuf->Size == 0)
+ {
+ return true;
+ }
+
+ ret = SendAll(sock, sock->SendBuf->Buf, sock->SendBuf->Size, secure);
+ ClearBuf(sock->SendBuf);
+
+ return ret;
+}
+
+// Append to the TCP send buffer
+void SendAdd(SOCK *sock, void *data, UINT size)
+{
+ // Validate arguments
+ if (sock == NULL || data == NULL || size == 0 || sock->AsyncMode != false)
+ {
+ return;
+ }
+
+ WriteBuf(sock->SendBuf, data, size);
+}
+
+// Send all by TCP
+bool SendAll(SOCK *sock, void *data, UINT size, bool secure)
+{
+ UCHAR *buf;
+ UINT sent_size;
+ UINT ret;
+ // Validate arguments
+ if (sock == NULL || data == NULL)
+ {
+ return false;
+ }
+ if (sock->AsyncMode)
+ {
+ return false;
+ }
+ if (size == 0)
+ {
+ return true;
+ }
+
+ buf = (UCHAR *)data;
+ sent_size = 0;
+
+ while (true)
+ {
+ ret = Send(sock, buf, size - sent_size, secure);
+ if (ret == 0)
+ {
+ return false;
+ }
+ sent_size += ret;
+ buf += ret;
+ if (sent_size >= size)
+ {
+ return true;
+ }
+ }
+}
+
+// Set the cipher algorithm name to want to use
+void SetWantToUseCipher(SOCK *sock, char *name)
+{
+ // Validate arguments
+ if (sock == NULL || name == NULL)
+ {
+ return;
+ }
+
+ if (sock->WaitToUseCipher)
+ {
+ Free(sock->WaitToUseCipher);
+ }
+ sock->WaitToUseCipher = CopyStr(name);
+}
+
+// Add all the chain certificates in the chain_certs directory
+void AddChainSslCertOnDirectory(struct ssl_ctx_st *ctx)
+{
+ wchar_t dirname[MAX_SIZE];
+ wchar_t exedir[MAX_SIZE];
+ DIRLIST *dir;
+
+ // Validate arguments
+ if (ctx == NULL)
+ {
+ return;
+ }
+
+ GetExeDirW(exedir, sizeof(exedir));
+
+ CombinePathW(dirname, sizeof(dirname), exedir, L"chain_certs");
+
+ MakeDirExW(dirname);
+
+ dir = EnumDirW(dirname);
+
+ if (dir != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < dir->NumFiles;i++)
+ {
+ DIRENT *e = dir->File[i];
+
+ if (e->Folder == false)
+ {
+ wchar_t tmp[MAX_SIZE];
+ X *x;
+
+ CombinePathW(tmp, sizeof(tmp), dirname, e->FileNameW);
+
+ x = FileToXW(tmp);
+
+ if (x != NULL)
+ {
+ AddChainSslCert(ctx, x);
+
+ FreeX(x);
+ }
+ }
+ }
+
+ FreeDir(dir);
+ }
+}
+
+// Add the chain certificate
+bool AddChainSslCert(struct ssl_ctx_st *ctx, X *x)
+{
+ bool ret = false;
+ X *x_copy;
+ // Validate arguments
+ if (ctx == NULL || x == NULL)
+ {
+ return ret;
+ }
+
+ x_copy = CloneX(x);
+
+ if (x_copy != NULL)
+ {
+ SSL_CTX_add_extra_chain_cert(ctx, x_copy->x509);
+ x_copy->do_not_free = true;
+
+ ret = true;
+
+ FreeX(x_copy);
+ }
+
+ return ret;
+}
+
+// Start a TCP-SSL communication
+bool StartSSL(SOCK *sock, X *x, K *priv)
+{
+ return StartSSLEx(sock, x, priv, false, 0, NULL);
+}
+bool StartSSLEx(SOCK *sock, X *x, K *priv, bool client_tls, UINT ssl_timeout, char *sni_hostname)
+{
+ X509 *x509;
+ EVP_PKEY *key;
+ UINT prev_timeout = 1024;
+ SSL_CTX *ssl_ctx;
+
+#ifdef UNIX_SOLARIS
+ SOCKET_TIMEOUT_PARAM *ttparam;
+#endif //UNIX_SOLARIS
+
+ // Validate arguments
+ if (sock == NULL)
+ {
+ Debug("StartSSL Error: #0\n");
+ return false;
+ }
+ if (sock->Connected && sock->Type == SOCK_INPROC && sock->ListenMode == false)
+ {
+ sock->SecureMode = true;
+ return true;
+ }
+ if (sock->Connected == false || sock->socket == INVALID_SOCKET ||
+ sock->ListenMode != false)
+ {
+ Debug("StartSSL Error: #1\n");
+ return false;
+ }
+ if (x != NULL && priv == NULL)
+ {
+ Debug("StartSSL Error: #2\n");
+ return false;
+ }
+ if (ssl_timeout == 0)
+ {
+ ssl_timeout = TIMEOUT_SSL_CONNECT;
+ }
+
+ if (sock->SecureMode)
+ {
+ //Debug("StartSSL Error: #3\n");
+ // SSL communication has already started
+ return true;
+ }
+
+ Lock(sock->ssl_lock);
+ if (sock->SecureMode)
+ {
+ //Debug("StartSSL Error: #4\n");
+ // SSL communication has already started
+ Unlock(sock->ssl_lock);
+ return true;
+ }
+
+ ssl_ctx = NewSSLCtx();
+
+ Lock(openssl_lock);
+ {
+ if (sock->ServerMode)
+ {
+ SSL_CTX_set_ssl_version(ssl_ctx, SSLv23_method());
+
+ Unlock(openssl_lock);
+ AddChainSslCertOnDirectory(ssl_ctx);
+ Lock(openssl_lock);
+ }
+ else
+ {
+ if (client_tls == false)
+ {
+ SSL_CTX_set_ssl_version(ssl_ctx, SSLv3_method());
+ }
+ else
+ {
+ SSL_CTX_set_ssl_version(ssl_ctx, TLSv1_client_method());
+ }
+ }
+ sock->ssl = SSL_new(ssl_ctx);
+ SSL_set_fd(sock->ssl, (int)sock->socket);
+
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ if (sock->ServerMode == false && client_tls)
+ {
+ if (IsEmptyStr(sni_hostname) == false)
+ {
+ // Set the SNI host name
+ SSL_set_tlsext_host_name(sock->ssl, sni_hostname);
+ }
+ }
+#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
+ }
+ Unlock(openssl_lock);
+
+ if (x != NULL)
+ {
+ // Check the certificate and the private key
+ if (CheckXandK(x, priv))
+ {
+ // Use the certificate
+ x509 = x->x509;
+ key = priv->pkey;
+
+ Lock(openssl_lock);
+ {
+ SSL_use_certificate(sock->ssl, x509);
+ SSL_use_PrivateKey(sock->ssl, key);
+ }
+ Unlock(openssl_lock);
+ }
+ }
+
+ if (sock->WaitToUseCipher != NULL)
+ {
+ // Set the cipher algorithm name to want to use
+ Lock(openssl_lock);
+ {
+ SSL_set_cipher_list(sock->ssl, sock->WaitToUseCipher);
+ }
+ Unlock(openssl_lock);
+ }
+
+ if (sock->ServerMode)
+ {
+// Lock(ssl_connect_lock);
+
+// Run the time-out thread for SOLARIS
+#ifdef UNIX_SOLARIS
+ ttparam = NewSocketTimeout(sock);
+#endif // UNIX_SOLARIS
+
+ // Server mode
+ if (SSL_accept(sock->ssl) <= 0)
+ {
+
+// Stop the timeout thread
+#ifdef UNIX_SOLARIS
+ FreeSocketTimeout(ttparam);
+#endif // UNIX_SOLARIS
+
+ // Unlock(ssl_connect_lock);
+ // SSL-Accept failure
+ Lock(openssl_lock);
+ {
+ SSL_free(sock->ssl);
+ sock->ssl = NULL;
+ }
+ Unlock(openssl_lock);
+
+ Unlock(sock->ssl_lock);
+ Debug("StartSSL Error: #5\n");
+ FreeSSLCtx(ssl_ctx);
+ return false;
+ }
+
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+#ifdef TLSEXT_NAMETYPE_host_name
+ if (true)
+ {
+ // Get the SNI host name
+ const char *sni_recv_hostname = SSL_get_servername(sock->ssl, TLSEXT_NAMETYPE_host_name);
+
+ if (IsEmptyStr((char *)sni_recv_hostname) == false)
+ {
+ StrCpy(sock->SniHostname, sizeof(sock->SniHostname), (char *)sni_recv_hostname);
+ }
+ }
+#endif // TLSEXT_NAMETYPE_host_name
+#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
+
+// Stop the timeout thread
+#ifdef UNIX_SOLARIS
+ FreeSocketTimeout(ttparam);
+#endif // UNIX_SOLARIS
+
+ // Unlock(ssl_connect_lock);
+ }
+ else
+ {
+ prev_timeout = GetTimeout(sock);
+ SetTimeout(sock, ssl_timeout);
+ Lock(ssl_connect_lock);
+ // Client mode
+ if (SSL_connect(sock->ssl) <= 0)
+ {
+ Unlock(ssl_connect_lock);
+ // SSL-connect failure
+ Lock(openssl_lock);
+ {
+ SSL_free(sock->ssl);
+ sock->ssl = NULL;
+ }
+ Unlock(openssl_lock);
+
+ Unlock(sock->ssl_lock);
+ Debug("StartSSL Error: #5\n");
+ SetTimeout(sock, prev_timeout);
+ FreeSSLCtx(ssl_ctx);
+ return false;
+ }
+ Unlock(ssl_connect_lock);
+ SetTimeout(sock, prev_timeout);
+ }
+
+ // SSL communication is initiated
+ sock->SecureMode = true;
+
+ // Get the certificate of the remote host
+ Lock(openssl_lock);
+ {
+ x509 = SSL_get_peer_certificate(sock->ssl);
+ }
+ Unlock(openssl_lock);
+
+ if (x509 == NULL)
+ {
+ // The certificate does not exist on the remote host
+ sock->RemoteX = NULL;
+ }
+ else
+ {
+ // Got a certificate
+ sock->RemoteX = X509ToX(x509);
+ }
+
+ // Get the certificate of local host
+ Lock(openssl_lock);
+ {
+ x509 = SSL_get_certificate(sock->ssl);
+ }
+ Unlock(openssl_lock);
+
+ if (x509 == NULL)
+ {
+ // The certificate does not exist on the remote host
+ sock->LocalX = NULL;
+ }
+ else
+ {
+ X *local_x;
+ // Got a certificate
+ local_x = X509ToX(x509);
+ local_x->do_not_free = true;
+ sock->LocalX = CloneX(local_x);
+ FreeX(local_x);
+ }
+
+ // Automatic retry mode
+ SSL_set_mode(sock->ssl, SSL_MODE_AUTO_RETRY);
+
+ // Strange flag
+ SSL_set_mode(sock->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+
+ sock->ssl_ctx = ssl_ctx;
+
+ // Get the algorithm name used to encrypt
+ Lock(openssl_lock);
+ {
+ sock->CipherName = CopyStr((char *)SSL_get_cipher(sock->ssl));
+ }
+ Unlock(openssl_lock);
+
+ Unlock(sock->ssl_lock);
+
+ return true;
+}
+
+// Set the flag to indicate that the socket doesn't require reading
+void SetNoNeedToRead(SOCK *sock)
+{
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+
+ sock->NoNeedToRead = true;
+}
+
+// TCP-SSL receive
+UINT SecureRecv(SOCK *sock, void *data, UINT size)
+{
+ SOCKET s;
+ int ret, e = 0;
+ SSL *ssl;
+
+#ifdef UNIX_SOLARIS
+ SOCKET_TIMEOUT_PARAM *ttparam;
+#endif //UNIX_SOLARIS
+
+ s = sock->socket;
+ ssl = sock->ssl;
+
+ if (sock->AsyncMode)
+ {
+ // Confirm whether the data is readable even 1 byte in the case of asynchronous mode.
+ // To read data results blocking, if there is no readable data.
+ // We must avoid blocking.
+ char c;
+ Lock(sock->ssl_lock);
+ {
+ if (sock->Connected == false)
+ {
+ Unlock(sock->ssl_lock);
+ Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ return 0;
+ }
+ ret = SSL_peek(ssl, &c, sizeof(c));
+ }
+ Unlock(sock->ssl_lock);
+ if (ret == 0)
+ {
+ // The communication have been disconnected
+ Disconnect(sock);
+ Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ return 0;
+ }
+ if (ret < 0)
+ {
+ // An error has occurred
+ e = SSL_get_error(ssl, ret);
+ if (e == SSL_ERROR_WANT_READ || e == SSL_ERROR_WANT_WRITE || e == SSL_ERROR_SSL)
+ {
+ // Packet has not arrived yet, that is not to be read
+ return SOCK_LATER;
+ }
+ }
+ }
+
+ // Receive
+ Lock(sock->ssl_lock);
+ {
+ if (sock->Connected == false)
+ {
+ Unlock(sock->ssl_lock);
+ Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ return 0;
+ }
+
+#ifdef OS_UNIX
+ if (sock->AsyncMode == false)
+ {
+ sock->CallingThread = pthread_self();
+ }
+#endif // OS_UNIX
+
+// Run the time-out thread for SOLARIS
+#ifdef UNIX_SOLARIS
+ ttparam = NewSocketTimeout(sock);
+#endif // UNIX_SOLARIS
+
+ ret = SSL_read(ssl, data, size);
+
+// Stop the timeout thread
+#ifdef UNIX_SOLARIS
+ FreeSocketTimeout(ttparam);
+#endif // UNIX_SOLARIS
+
+
+#ifdef OS_UNIX
+ if (sock->AsyncMode == false)
+ {
+ sock->CallingThread = 0;
+ }
+#endif // OS_UNIX
+
+ if (ret < 0)
+ {
+ e = SSL_get_error(ssl, ret);
+ }
+
+ }
+ Unlock(sock->ssl_lock);
+ if (ret > 0)
+ {
+ // Successful reception
+ sock->RecvSize += (UINT64)ret;
+ sock->RecvNum++;
+ return (UINT)ret;
+ }
+ if (ret == 0)
+ {
+ // Disconnect the communication
+ Disconnect(sock);
+ //Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ return 0;
+ }
+ if (sock->AsyncMode)
+ {
+ if (e == SSL_ERROR_WANT_READ || e == SSL_ERROR_WANT_WRITE || e == SSL_ERROR_SSL)
+ {
+ // Packet has not yet arrived
+ return SOCK_LATER;
+ }
+ }
+ Disconnect(sock);
+ Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ return 0;
+}
+
+// TCP-SSL transmission
+UINT SecureSend(SOCK *sock, void *data, UINT size)
+{
+ SOCKET s;
+ int ret, e;
+ SSL *ssl;
+ s = sock->socket;
+ ssl = sock->ssl;
+
+ if (sock->AsyncMode)
+ {
+ // Asynchronous mode
+ SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
+ }
+
+ // Transmission
+ Lock(sock->ssl_lock);
+ {
+ if (sock->Connected == false)
+ {
+ Unlock(sock->ssl_lock);
+ Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ return 0;
+ }
+
+ ret = SSL_write(ssl, data, size);
+ if (ret < 0)
+ {
+ e = SSL_get_error(ssl, ret);
+ }
+ }
+ Unlock(sock->ssl_lock);
+
+ if (ret > 0)
+ {
+ // Successful transmission
+ sock->SendSize += (UINT64)ret;
+ sock->SendNum++;
+ sock->WriteBlocked = false;
+ return (UINT)ret;
+ }
+ if (ret == 0)
+ {
+ // Disconnect
+ Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ Disconnect(sock);
+ return 0;
+ }
+
+ if (sock->AsyncMode)
+ {
+ // Confirmation of the error value
+ if (e == SSL_ERROR_WANT_READ || e == SSL_ERROR_WANT_WRITE || e == SSL_ERROR_SSL)
+ {
+ sock->WriteBlocked = true;
+ return SOCK_LATER;
+ }
+ Debug("%s %u e=%u\n", __FILE__, __LINE__, e);
+ }
+ //Debug("%s %u SecureRecv() Disconnect\n", __FILE__, __LINE__);
+ Disconnect(sock);
+ return 0;
+}
+
+// Peep the TCP
+UINT Peek(SOCK *sock, void *data, UINT size)
+{
+ SOCKET s;
+ int ret;
+
+ // Validate arguments
+ if (sock == NULL || data == NULL || size == 0)
+ {
+ return 0;
+ }
+ if (sock->Type == SOCK_INPROC)
+ {
+ return 0;
+ }
+ if (sock->Type != SOCK_TCP || sock->Connected == false || sock->ListenMode != false ||
+ sock->socket == INVALID_SOCKET)
+ {
+ return 0;
+ }
+ if (sock->AsyncMode)
+ {
+ return 0;
+ }
+
+ // Receive
+ s = sock->socket;
+
+ ret = recv(s, data, size, MSG_PEEK);
+
+ //Debug("Peek: %u\n", ret);
+
+ if (ret > 0)
+ {
+ return ret;
+ }
+
+ return 0;
+}
+
+// TCP receive
+UINT Recv(SOCK *sock, void *data, UINT size, bool secure)
+{
+ SOCKET s;
+ int ret;
+
+#ifdef UNIX_SOLARIS
+ SOCKET_TIMEOUT_PARAM *ttparam;
+#endif //UNIX_SOLARIS
+
+ // Validate arguments
+ if (sock == NULL || data == NULL || size == 0)
+ {
+ return 0;
+ }
+
+ sock->NoNeedToRead = false;
+
+ if (sock->Type == SOCK_INPROC)
+ {
+ return RecvInProc(sock, data, size);
+ }
+ if (sock->Type != SOCK_TCP || sock->Connected == false || sock->ListenMode != false ||
+ sock->socket == INVALID_SOCKET)
+ {
+ return 0;
+ }
+ if (secure != false && sock->SecureMode == false)
+ {
+ return 0;
+ }
+
+ if (secure)
+ {
+ return SecureRecv(sock, data, size);
+ }
+
+ // Receive
+ s = sock->socket;
+
+
+#ifdef OS_UNIX
+ if (sock->AsyncMode == false)
+ {
+ sock->CallingThread = pthread_self();
+ }
+#endif // OS_UNIX
+
+// Start of the timeout thread for SOLARIS
+#ifdef UNIX_SOLARIS
+ ttparam = NewSocketTimeout(sock);
+#endif // UNIX_SOLARIS
+
+ ret = recv(s, data, size, 0);
+
+// Stop the timeout thread
+#ifdef UNIX_SOLARIS
+ FreeSocketTimeout(ttparam);
+#endif // UNIX_SOLARIS
+
+#ifdef OS_UNIX
+ if (sock->AsyncMode == false)
+ {
+ sock->CallingThread = 0;
+ }
+#endif // OS_UNIX
+
+ if (ret > 0)
+ {
+ // Successful reception
+ Lock(sock->lock);
+ {
+ sock->RecvSize += (UINT64)ret;
+ sock->SendNum++;
+ }
+ Unlock(sock->lock);
+ return (UINT)ret;
+ }
+
+ // Transmission failure
+ if (sock->AsyncMode)
+ {
+ // In asynchronous mode, examine the error
+ if (ret == SOCKET_ERROR)
+ {
+#ifdef OS_WIN32
+ if (WSAGetLastError() == WSAEWOULDBLOCK)
+ {
+ // In blocking
+ return SOCK_LATER;
+ }
+ else
+ {
+ //Debug("Socket Error: %u\n", WSAGetLastError());
+ }
+#else // OS_WIN32
+ if (errno == EAGAIN)
+ {
+ // In blocking
+ return SOCK_LATER;
+ }
+#endif // OS_WIN32
+ }
+ }
+
+ // Disconnected
+ Disconnect(sock);
+ return 0;
+}
+
+// TCP transmission
+UINT Send(SOCK *sock, void *data, UINT size, bool secure)
+{
+ SOCKET s;
+ int ret;
+ // Validate arguments
+ if (sock == NULL || data == NULL || size == 0)
+ {
+ return 0;
+ }
+ if (sock->Type == SOCK_INPROC)
+ {
+ return SendInProc(sock, data, size);
+ }
+ size = MIN(size, MAX_SEND_BUF_MEM_SIZE);
+ if (sock->Type != SOCK_TCP || sock->Connected == false || sock->ListenMode != false ||
+ sock->socket == INVALID_SOCKET)
+ {
+ return 0;
+ }
+ if (secure != false && sock->SecureMode == false)
+ {
+ return 0;
+ }
+
+ if (secure)
+ {
+ return SecureSend(sock, data, size);
+ }
+
+ // Transmission
+ s = sock->socket;
+ ret = send(s, data, size, 0);
+ if (ret > 0)
+ {
+ // Successful transmission
+ Lock(sock->lock);
+ {
+ sock->SendSize += (UINT64)ret;
+ sock->SendNum++;
+ }
+ Unlock(sock->lock);
+ sock->WriteBlocked = false;
+ return (UINT)ret;
+ }
+
+ // Transmission failure
+ if (sock->AsyncMode)
+ {
+ // In asynchronous mode, examine the error
+ if (ret == SOCKET_ERROR)
+ {
+#ifdef OS_WIN32
+ if (WSAGetLastError() == WSAEWOULDBLOCK)
+ {
+ // In blocking
+ sock->WriteBlocked = true;
+ return SOCK_LATER;
+ }
+ else
+ {
+ //Debug("Socket Error: %u\n", WSAGetLastError());
+ }
+#else // OS_WIN32
+ if (errno == EAGAIN)
+ {
+ // In blocking
+ sock->WriteBlocked = true;
+ return SOCK_LATER;
+ }
+#endif // OS_WIN32
+ }
+ }
+
+ // Disconnected
+ Disconnect(sock);
+ return 0;
+}
+
+// Get the time-out value (in milliseconds)
+UINT GetTimeout(SOCK *sock)
+{
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return INFINITE;
+ }
+ if (sock->Type != SOCK_TCP && sock->Type != SOCK_INPROC)
+ {
+ return INFINITE;
+ }
+
+ return sock->TimeOut;
+}
+
+// Setting the time-out value (in milliseconds)
+void SetTimeout(SOCK *sock, UINT timeout)
+{
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+ if (sock->Type == SOCK_UDP)
+ {
+ return;
+ }
+
+ if (timeout == INFINITE)
+ {
+ timeout = TIMEOUT_INFINITE;
+ }
+
+ sock->TimeOut = timeout;
+
+// Debug("SetTimeout(%u)\n",timeout);
+
+ if (sock->Type != SOCK_INPROC)
+ {
+#ifdef OS_WIN32
+ setsockopt(sock->socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(UINT));
+ setsockopt(sock->socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(UINT));
+#endif
+
+#ifdef OS_UNIX
+#ifndef UNIX_SOLARIS
+ {
+ struct timeval tv_timeout;
+
+ tv_timeout.tv_sec = timeout / 1000; // miliseconds to seconds
+ tv_timeout.tv_usec = (timeout % 1000) * 1000; // miliseconds to microseconds
+
+ setsockopt(sock->socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv_timeout, sizeof(tv_timeout));
+ setsockopt(sock->socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv_timeout, sizeof(tv_timeout));
+ }
+#endif // UNIX_SOLARIS
+#endif // OS_UNIX
+ }
+}
+
+// Initialize the connection acceptance
+void AcceptInit(SOCK *s)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Zero(tmp, sizeof(tmp));
+ if (GetHostName(tmp, sizeof(tmp), &s->RemoteIP) == false ||
+ IsEmptyStr(tmp))
+ {
+ IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
+ }
+
+ if (s->RemoteHostname != NULL)
+ {
+ Free(s->RemoteHostname);
+ }
+
+ s->RemoteHostname = CopyStr(tmp);
+}
+
+// TCP connection acceptance (IPv4)
+SOCK *Accept(SOCK *sock)
+{
+ SOCK *ret;
+ SOCKET s, new_socket;
+ int size;
+ struct sockaddr_in addr;
+ bool true_flag = true;
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return NULL;
+ }
+ if (sock->Type == SOCK_INPROC)
+ {
+ return AcceptInProc(sock);
+ }
+ if (sock->Type == SOCK_REVERSE_LISTEN)
+ {
+ return AcceptReverse(sock);
+ }
+ if (sock->Type == SOCK_RUDP_LISTEN)
+ {
+ return AcceptRUDP(sock);
+ }
+ if (sock->ListenMode == false || sock->Type != SOCK_TCP || sock->ServerMode == false)
+ {
+ return NULL;
+ }
+ if (sock->CancelAccept)
+ {
+ return NULL;
+ }
+ if (sock->IPv6)
+ {
+ return Accept6(sock);
+ }
+
+ s = sock->socket;
+ if (s == INVALID_SOCKET)
+ {
+ return NULL;
+ }
+ Zero(&addr, sizeof(addr));
+ size = sizeof(addr);
+
+#ifdef OS_UNIX
+#ifdef UNIX_LINUX
+ UnixIgnoreSignalForThread(SIGUSR1);
+#endif // UNIX_LINUX
+ sock->CallingThread = pthread_self();
+#endif // OS_UNIX
+
+#ifdef OS_WIN32
+ if (sock->EnableConditionalAccept)
+ {
+ new_socket = Win32Accept(sock, s, (struct sockaddr *)&addr,(int *)&size, false);
+ }
+ else
+ {
+ new_socket = accept(s, (struct sockaddr *)&addr,(int *)&size);
+ }
+#else // OS_WIN32
+ new_socket = accept(s, (struct sockaddr *)&addr,(int *)&size);
+#endif // OS_WIN32
+
+#ifdef OS_UNIX
+ sock->CallingThread = 0;
+#endif // OS_UNIX
+
+ if (new_socket == INVALID_SOCKET)
+ {
+ if (sock->CancelAccept)
+ {
+ sock->AcceptCanceled = true;
+ }
+ return NULL;
+ }
+ if (sock->CancelAccept)
+ {
+ sock->AcceptCanceled = true;
+ closesocket(new_socket);
+ return NULL;
+ }
+
+ ret = NewSock();
+ ret->socket = new_socket;
+ ret->Connected = true;
+ ret->AsyncMode = false;
+ ret->Type = SOCK_TCP;
+ ret->ServerMode = true;
+ ret->SecureMode = false;
+
+ // Configuring the TCP options
+ setsockopt(ret->socket, IPPROTO_TCP, TCP_NODELAY, (char *)&true_flag, sizeof(bool));
+
+ // Initialization of the time-out value
+ SetTimeout(ret, TIMEOUT_INFINITE);
+
+ // Socket information
+ QuerySocketInformation(ret);
+
+ if (IsLocalHostIP(&ret->RemoteIP) == false)
+ {
+ ret->IpClientAdded = true;
+ AddIpClient(&ret->RemoteIP);
+ }
+
+ if (IsZeroIp(&sock->LocalIP) == false && IsLocalHostIP(&sock->LocalIP) == false)
+ {
+ IP current_ip;
+
+ if (GetCurrentGlobalIP(&current_ip, false) == false)
+ {
+ SetCurrentGlobalIP(&sock->LocalIP, false);
+ }
+ }
+
+ StrCpy(ret->UnderlayProtocol, sizeof(ret->UnderlayProtocol), SOCK_UNDERLAY_NATIVE_V4);
+
+ return ret;
+}
+
+// TCP connection acceptance (IPv6)
+SOCK *Accept6(SOCK *sock)
+{
+ SOCK *ret;
+ SOCKET s, new_socket;
+ int size;
+ struct sockaddr_in6 addr;
+ bool true_flag = true;
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return NULL;
+ }
+ if (sock->ListenMode == false || sock->Type != SOCK_TCP || sock->ServerMode == false)
+ {
+ return NULL;
+ }
+ if (sock->CancelAccept)
+ {
+ return NULL;
+ }
+ if (sock->IPv6 == false)
+ {
+ return NULL;
+ }
+
+ s = sock->socket;
+ if (s == INVALID_SOCKET)
+ {
+ return NULL;
+ }
+ Zero(&addr, sizeof(addr));
+ size = sizeof(addr);
+
+#ifdef OS_UNIX
+#ifdef UNIX_LINUX
+ UnixIgnoreSignalForThread(SIGUSR1);
+#endif // UNIX_LINUX
+ sock->CallingThread = pthread_self();
+#endif // OS_UNIX
+
+#ifdef OS_WIN32
+ if (sock->EnableConditionalAccept)
+ {
+ new_socket = Win32Accept(sock, s, (struct sockaddr *)&addr,(int *)&size, true);
+ }
+ else
+ {
+ new_socket = accept(s, (struct sockaddr *)&addr,(int *)&size);
+ }
+#else // OS_WIN32
+ new_socket = accept(s, (struct sockaddr *)&addr,(int *)&size);
+#endif // OS_WIN32
+
+#ifdef OS_UNIX
+ sock->CallingThread = 0;
+#endif // OS_UNIX
+
+ if (new_socket == INVALID_SOCKET)
+ {
+ if (sock->CancelAccept)
+ {
+ sock->AcceptCanceled = true;
+ }
+ return NULL;
+ }
+ if (sock->CancelAccept)
+ {
+ sock->AcceptCanceled = true;
+ closesocket(new_socket);
+ return NULL;
+ }
+
+ ret = NewSock();
+ ret->socket = new_socket;
+ ret->Connected = true;
+ ret->AsyncMode = false;
+ ret->Type = SOCK_TCP;
+ ret->ServerMode = true;
+ ret->SecureMode = false;
+
+ // Configuring the TCP options
+ setsockopt(ret->socket, IPPROTO_TCP, TCP_NODELAY, (char *)&true_flag, sizeof(bool));
+
+ // Initialize the time-out value
+ SetTimeout(ret, TIMEOUT_INFINITE);
+
+ // Socket information
+ QuerySocketInformation(ret);
+
+ if (IsLocalHostIP(&ret->RemoteIP) == false)
+ {
+ ret->IpClientAdded = true;
+ AddIpClient(&ret->RemoteIP);
+ }
+ if (IsZeroIp(&sock->LocalIP) == false && IsLocalHostIP(&sock->LocalIP) == false)
+ {
+ IP current_ip;
+
+ if (GetCurrentGlobalIP(&current_ip, true) == false)
+ {
+ SetCurrentGlobalIP(&sock->LocalIP, true);
+ }
+ }
+
+ StrCpy(ret->UnderlayProtocol, sizeof(ret->UnderlayProtocol), SOCK_UNDERLAY_NATIVE_V6);
+
+ return ret;
+}
+
+// Standby for TCP (IPv6)
+SOCK *Listen6(UINT port)
+{
+ return ListenEx6(port, false);
+}
+SOCK *ListenEx6(UINT port, bool local_only)
+{
+ return ListenEx62(port, local_only, false);
+}
+SOCK *ListenEx62(UINT port, bool local_only, bool enable_ca)
+{
+ SOCKET s;
+ SOCK *sock;
+ struct sockaddr_in6 addr;
+ struct in6_addr in;
+ bool true_flag = true;
+ bool disable_conditional_accept = false;
+ IP localhost;
+ UINT backlog = SOMAXCONN;
+ // Validate arguments
+ if (port == 0 || port >= 65536)
+ {
+ return NULL;
+ }
+
+#ifdef OS_WIN32
+ if (MsIsVista() == false)
+ {
+ // Disable the Conditional Accept due to a bug in Windows
+ enable_ca = false;
+ }
+#endif // OS_WIN32
+
+ // Initialization
+ Zero(&addr, sizeof(addr));
+ Zero(&in, sizeof(in));
+ GetLocalHostIP6(&localhost);
+
+ addr.sin6_port = htons((UINT)port);
+ addr.sin6_family = AF_INET6;
+
+ if (local_only)
+ {
+ IPToInAddr6(&addr.sin6_addr, &localhost);
+
+ enable_ca = false;
+ }
+
+ // Creating a socket
+ s = socket(AF_INET6, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET)
+ {
+ return NULL;
+ }
+
+#ifdef OS_UNIX
+ // It is necessary to set the IPv6 Only flag on a UNIX system
+ setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &true_flag, sizeof(true_flag));
+#endif // OS_UNIX
+
+ //SetSocketSendRecvBufferSize(s, SOCKET_BUFFER_SIZE);
+
+#ifdef OS_UNIX
+ // This only have enabled for UNIX system since there is a bug
+ // in the implementation of REUSEADDR in Windows OS
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
+#endif // OS_UNIX
+
+ if (bind(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) != 0)
+ {
+ // Bind failure
+ closesocket(s);
+ return NULL;
+ }
+
+#ifdef OS_WIN32
+ if (enable_ca)
+ {
+ if (MsIsWinXPOrGreater())
+ {
+ setsockopt(s, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, (char *)&true_flag, sizeof(bool));
+
+ backlog = 1;
+ }
+ }
+#endif // OS_WIN32
+
+ if (listen(s, backlog))
+ {
+ // Listen failure
+ closesocket(s);
+ return NULL;
+ }
+
+ // Success
+ sock = NewSock();
+ sock->Connected = false;
+ sock->AsyncMode = false;
+ sock->ServerMode = true;
+ sock->Type = SOCK_TCP;
+ sock->socket = s;
+ sock->ListenMode = true;
+ sock->SecureMode = false;
+ sock->LocalPort = port;
+ sock->IPv6 = true;
+ sock->LocalOnly = local_only;
+ sock->EnableConditionalAccept = enable_ca;
+
+ return sock;
+}
+
+// Standby for the TCP
+SOCK *Listen(UINT port)
+{
+ return ListenEx(port, false);
+}
+SOCK *ListenEx(UINT port, bool local_only)
+{
+ return ListenEx2(port, local_only, false);
+}
+SOCK *ListenEx2(UINT port, bool local_only, bool enable_ca)
+{
+ SOCKET s;
+ SOCK *sock;
+ struct sockaddr_in addr;
+ struct in_addr in;
+ bool true_flag = true;
+ IP localhost;
+ UINT backlog = SOMAXCONN;
+ // Validate arguments
+ if (port == 0 || port >= 65536)
+ {
+ return NULL;
+ }
+
+#ifdef OS_WIN32
+ if (MsIsVista() == false)
+ {
+ // Disable the Conditional Accept due to a bug in Windows
+ enable_ca = false;
+ }
+#endif // OS_WIN32
+
+ // Initialization
+ Zero(&addr, sizeof(addr));
+ Zero(&in, sizeof(in));
+ SetIP(&localhost, 127, 0, 0, 1);
+
+ addr.sin_port = htons((UINT)port);
+ *((UINT *)&addr.sin_addr) = htonl(INADDR_ANY);
+ addr.sin_family = AF_INET;
+
+ if (local_only)
+ {
+ IPToInAddr(&addr.sin_addr, &localhost);
+
+ enable_ca = false;
+ }
+
+ // Creating a socket
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET)
+ {
+ return NULL;
+ }
+
+ //SetSocketSendRecvBufferSize(s, SOCKET_BUFFER_SIZE);
+
+#ifdef OS_UNIX
+ // This only have enabled for UNIX system since there is a bug
+ // in the implementation of REUSEADDR in Windows OS
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
+#endif // OS_UNIX
+
+ if (bind(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) != 0)
+ {
+ // Bind failure
+ closesocket(s);
+ return NULL;
+ }
+
+#ifdef OS_WIN32
+ if (enable_ca)
+ {
+ if (MsIsWinXPOrGreater())
+ {
+ setsockopt(s, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, (char *)&true_flag, sizeof(bool));
+
+ backlog = 1;
+ }
+ }
+#endif // OS_WIN32
+
+ if (listen(s, backlog))
+ {
+ // Listen failure
+ closesocket(s);
+ return NULL;
+ }
+
+ // Success
+ sock = NewSock();
+ sock->Connected = false;
+ sock->AsyncMode = false;
+ sock->ServerMode = true;
+ sock->Type = SOCK_TCP;
+ sock->socket = s;
+ sock->ListenMode = true;
+ sock->SecureMode = false;
+ sock->LocalPort = port;
+ sock->LocalOnly = local_only;
+ sock->EnableConditionalAccept = enable_ca;
+
+ return sock;
+}
+
+// TCP disconnect
+void Disconnect(SOCK *sock)
+{
+ SOCKET s;
+ bool true_flag = true;
+ bool false_flag = false;
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+
+ sock->Disconnecting = true;
+
+#ifdef OS_UNIX
+ UnixFreeAsyncSocket(sock);
+#endif // UnixFreeAsyncSocket
+
+ if (sock->Type == SOCK_TCP && sock->ListenMode)
+ {
+ bool no_tcp_check_port = false;
+
+ // Connect to localhost if the socket is in listening
+ sock->CancelAccept = true;
+
+#ifdef UNIX_LINUX
+ {
+ pthread_t t = sock->CallingThread;
+
+ // Send a signal to the socket to abort accept() forcibly on Linux
+ if (t != 0)
+ {
+ pthread_kill(t, SIGUSR1);
+
+ SleepThread(200);
+ }
+ }
+#endif // UNIX_LINUX
+
+#ifdef OS_WIN32
+ if (sock->hAcceptEvent != NULL)
+ {
+ SetEvent(sock->hAcceptEvent);
+
+ no_tcp_check_port = true;
+ }
+#endif // OS_WIN32
+
+ if (sock->AcceptCanceled == false)
+ {
+ if (no_tcp_check_port == false)
+ {
+ if (sock->IPv6 == false)
+ {
+ CheckTCPPort("127.0.0.1", sock->LocalPort);
+ }
+ else
+ {
+ CheckTCPPort("::1", sock->LocalPort);
+ }
+ }
+ }
+ }
+
+ Lock(disconnect_function_lock);
+
+ Lock(sock->disconnect_lock);
+
+ if (sock->Type == SOCK_TCP)
+ {
+ if (sock->socket != INVALID_SOCKET)
+ {
+ // Forced disconnection flag
+ #ifdef SO_DONTLINGER
+ setsockopt(sock->socket, SOL_SOCKET, SO_DONTLINGER, (char *)&true_flag, sizeof(bool));
+ #else // SO_DONTLINGER
+ setsockopt(sock->socket, SOL_SOCKET, SO_LINGER, (char *)&false_flag, sizeof(bool));
+ #endif // SO_DONTLINGER
+// setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
+ }
+
+ // TCP socket
+ Lock(sock->lock);
+ {
+ if (sock->socket == INVALID_SOCKET)
+ {
+ Unlock(sock->lock);
+ Unlock(sock->disconnect_lock);
+ Unlock(disconnect_function_lock);
+ return;
+ }
+ s = sock->socket;
+
+ if (sock->Connected)
+ {
+ struct linger ling;
+ Zero(&ling, sizeof(ling));
+
+
+#if 0
+ // SSL disconnect
+ Lock(sock->ssl_lock);
+ {
+ if (sock->SecureMode)
+ {
+ SSL_shutdown(sock->ssl);
+ }
+ }
+ Unlock(sock->ssl_lock);
+#endif
+ // Disconnect
+ shutdown(s, 2);
+ }
+
+ // Close the socket
+ closesocket(s);
+
+#ifdef OS_UNIX
+#ifdef FIX_SSL_BLOCKING
+ if (sock->CallingThread != NULL)
+ {
+ pthread_kill(sock->CallingThread, 64);
+ }
+#endif // FIX_SSL_BLOCKING
+#endif // OS_UNIX
+
+ // Release the SSL
+ Lock(sock->ssl_lock);
+ {
+ if (sock->SecureMode)
+ {
+ if (sock->ssl != NULL)
+ {
+ Lock(openssl_lock);
+ {
+ SSL_free(sock->ssl);
+ FreeSSLCtx(sock->ssl_ctx);
+ }
+ Unlock(openssl_lock);
+ sock->ssl = NULL;
+ sock->ssl_ctx = NULL;
+ }
+ sock->Connected = false;
+ // Release the certificate
+ if (sock->RemoteX != NULL)
+ {
+ FreeX(sock->RemoteX);
+ sock->RemoteX = NULL;
+ }
+ if (sock->LocalX != NULL)
+ {
+ FreeX(sock->LocalX);
+ sock->LocalX = NULL;
+ }
+
+ // Cipher algorithm name
+ if (sock->CipherName != NULL)
+ {
+ Free(sock->CipherName);
+ sock->CipherName = NULL;
+ }
+ sock->SecureMode = false;
+ }
+ }
+ Unlock(sock->ssl_lock);
+
+ // Initialization
+ sock->socket = INVALID_SOCKET;
+ sock->Type = 0;
+ sock->AsyncMode = false;
+ sock->Connected = false;
+ sock->ListenMode = false;
+ sock->SecureMode = false;
+
+ if (sock->IpClientAdded)
+ {
+ DelIpClient(&sock->RemoteIP);
+ sock->IpClientAdded = false;
+ }
+ }
+ Unlock(sock->lock);
+
+ if (sock->BulkSendTube != NULL)
+ {
+ TubeDisconnect(sock->BulkSendTube);
+ }
+
+ if (sock->BulkRecvTube != NULL)
+ {
+ TubeDisconnect(sock->BulkRecvTube);
+ }
+ }
+ else if (sock->Type == SOCK_UDP)
+ {
+ // UDP socket
+ Lock(sock->lock);
+ {
+ if (sock->socket == INVALID_SOCKET)
+ {
+ Unlock(sock->lock);
+ Unlock(sock->disconnect_lock);
+ Unlock(disconnect_function_lock);
+ return;
+ }
+
+ s = sock->socket;
+
+ // Close the socket
+ closesocket(s);
+
+ // Initialization
+ sock->socket = INVALID_SOCKET;
+ sock->Type = 0;
+ sock->AsyncMode = false;
+ sock->Connected = false;
+ sock->ListenMode = false;
+ sock->SecureMode = false;
+ }
+ Unlock(sock->lock);
+ }
+ else if (sock->Type == SOCK_INPROC)
+ {
+ // In-process socket
+ if (sock->ListenMode)
+ {
+ // Stop the Accept process
+ sock->CancelAccept = true;
+
+ Set(sock->InProcAcceptEvent);
+
+ LockQueue(sock->InProcAcceptQueue);
+ {
+ while (true)
+ {
+ SOCK *ss = GetNext(sock->InProcAcceptQueue);
+ if (ss == NULL)
+ {
+ break;
+ }
+
+ Disconnect(ss);
+ ReleaseSock(ss);
+ }
+ }
+ UnlockQueue(sock->InProcAcceptQueue);
+ }
+ else
+ {
+ // Disconnect the Tube
+ TubeDisconnect(sock->SendTube);
+ TubeDisconnect(sock->RecvTube);
+
+ sock->socket = INVALID_SOCKET;
+ sock->AsyncMode = false;
+ sock->Connected = false;
+ sock->ListenMode = false;
+ sock->SecureMode = false;
+ }
+ }
+ else if (sock->Type == SOCK_RUDP_LISTEN)
+ {
+ // RUDP Listen socket
+ if (sock->ListenMode)
+ {
+ // Stop the Accept process
+ sock->CancelAccept = true;
+
+ Set(sock->R_UDP_Stack->NewSockConnectEvent);
+
+ sock->R_UDP_Stack->Halt = true;
+ Set(sock->R_UDP_Stack->HaltEvent);
+ SetSockEvent(sock->R_UDP_Stack->SockEvent);
+ }
+ }
+ else if (sock->Type == SOCK_REVERSE_LISTEN)
+ {
+ // Reverse Listen socket
+ if (sock->ListenMode)
+ {
+ // Stop the Accept process
+ sock->CancelAccept = true;
+
+ Set(sock->ReverseAcceptEvent);
+
+ LockQueue(sock->ReverseAcceptQueue);
+ {
+ while (true)
+ {
+ SOCK *ss = GetNext(sock->ReverseAcceptQueue);
+ if (ss == NULL)
+ {
+ break;
+ }
+
+ Disconnect(ss);
+ ReleaseSock(ss);
+ }
+ }
+ UnlockQueue(sock->ReverseAcceptQueue);
+ }
+ }
+ Unlock(sock->disconnect_lock);
+
+ Unlock(disconnect_function_lock);
+}
+
+typedef struct TCP_PORT_CHECK
+{
+ REF *ref;
+ char hostname[MAX_SIZE];
+ UINT port;
+ bool ok;
+} TCP_PORT_CHECK;
+
+// The thread to check the TCP port
+void CheckTCPPortThread(THREAD *thread, void *param)
+{
+ TCP_PORT_CHECK *c;
+ SOCK *s;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ c = (TCP_PORT_CHECK *)param;
+ AddRef(c->ref);
+ NoticeThreadInit(thread);
+
+ AddWaitThread(thread);
+
+ s = Connect(c->hostname, c->port);
+ if (s != NULL)
+ {
+ c->ok = true;
+ Disconnect(s);
+ ReleaseSock(s);
+ }
+
+ if (Release(c->ref) == 0)
+ {
+ Free(c);
+ }
+
+ DelWaitThread(thread);
+}
+
+// Check whether the TCP port can be connected
+bool CheckTCPPortEx(char *hostname, UINT port, UINT timeout)
+{
+ SOCK *s;
+ // Validate arguments
+ if (hostname == NULL || port == 0 || port >= 65536)
+ {
+ return false;
+ }
+
+ if (timeout == 0)
+ {
+ timeout = TIMEOUT_TCP_PORT_CHECK;
+ }
+
+ s = ConnectEx(hostname, port, timeout);
+ if (s == NULL)
+ {
+ return false;
+ }
+ else
+ {
+ Disconnect(s);
+ ReleaseSock(s);
+ return true;
+ }
+}
+bool CheckTCPPort(char *hostname, UINT port)
+{
+ return CheckTCPPortEx(hostname, port, TIMEOUT_TCP_PORT_CHECK);
+}
+
+#ifdef OS_UNIX
+// Connection with timeout (UNIX version)
+int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool *cancel_flag)
+{
+ SOCKSET set;
+ bool ok = false;
+ UINT64 start_time;
+ // Validate arguments
+ if (s == INVALID_SOCKET || addr == NULL)
+ {
+ return -1;
+ }
+ if (timeout == 0)
+ {
+ timeout = TIMEOUT_TCP_PORT_CHECK;
+ }
+
+ UnixSetSocketNonBlockingMode(s, true);
+
+ start_time = Tick64();
+
+ while (true)
+ {
+ int ret;
+ ret = connect(s, addr, size);
+ if (ret == 0 || errno == EISCONN)
+ {
+ ok = true;
+ break;
+ }
+ else
+ {
+ if (((start_time + (UINT64)timeout) <= Tick64()) || (errno != EAGAIN && errno != EINPROGRESS && errno != EALREADY))
+ {
+ // Failure
+ break;
+ }
+ else if (*cancel_flag)
+ {
+ // Cancel
+ break;
+ }
+ else
+ {
+ // Connecting
+ SleepThread(50);
+ UnixSelectInner(1, (UINT *)&s, 1, (UINT *)&s, 100);
+ }
+ }
+ }
+
+ UnixSetSocketNonBlockingMode(s, false);
+
+ if (ok)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+#else
+// Connection with timeout (Win32 version)
+int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool *cancel_flag)
+{
+ UINT64 start_time;
+ bool ok = false;
+ bool timeouted = false;
+ WSAEVENT hEvent;
+ UINT zero = 0;
+ UINT tmp = 0;
+ UINT ret_size = 0;
+ bool is_nt = false;
+ // Validate arguments
+ if (s == INVALID_SOCKET || addr == NULL)
+ {
+ return -1;
+ }
+ if (timeout == 0)
+ {
+ timeout = TIMEOUT_TCP_PORT_CHECK;
+ }
+
+ is_nt = OS_IS_WINDOWS_NT(GetOsInfo()->OsType);
+
+ // Create an event
+ hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ // Associate the socket with the event
+ WSAEventSelect(s, hEvent, FD_CONNECT);
+
+ start_time = Tick64();
+
+ while (true)
+ {
+ int ret;
+
+ ret = connect(s, addr, size);
+
+ if (ret == 0)
+ {
+ ok = true;
+ break;
+ }
+ else
+ {
+ int err = WSAGetLastError();
+ //Debug("err=%u\n", err);
+ //Debug("cancel_flag=%u\n", *cancel_flag);
+ if (timeouted && ((err == WSAEALREADY) || (err == WSAEWOULDBLOCK && !is_nt)))
+ {
+ // Time-out
+ ok = false;
+ break;
+ }
+ if (*cancel_flag)
+ {
+ // Cancel
+ ok = false;
+ break;
+ }
+ if (err == WSAEISCONN || (err == WSAEINVAL && is_nt))
+ {
+ ok = true;
+ break;
+ }
+ if (((start_time + (UINT64)timeout) <= Tick64()) || (err != WSAEWOULDBLOCK && err != WSAEALREADY && (is_nt || err != WSAEINVAL)))
+ {
+ // Failure (timeout)
+ break;
+ }
+ else
+ {
+ SleepThread(10);
+ // Connecting
+ if (WaitForSingleObject(hEvent, 100) == WAIT_OBJECT_0)
+ {
+ timeouted = true;
+ }
+ }
+ }
+ }
+
+ // Remove the socket from the event
+ WSAEventSelect(s, hEvent, 0);
+
+ // Restore to synchronized socket
+ WSAIoctl(s, FIONBIO, &zero, sizeof(zero), &tmp, sizeof(tmp), &ret_size, NULL, NULL);
+
+ // Close the event
+ CloseHandle(hEvent);
+
+ if (ok)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+#endif // OS_UNIX
+
+// Set the TOS value of the socket
+void SetSockTos(SOCK *s, int tos)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (s->CurrentTos == tos)
+ {
+ return;
+ }
+
+#ifdef IP_TOS
+ setsockopt(s->socket, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int));
+#endif // IP_TOS
+
+ s->CurrentTos = tos;
+}
+
+// Set the priority of the socket
+void SetSockHighPriority(SOCK *s, bool flag)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ SetSockTos(s, (flag ? 16 : 0));
+}
+
+// Connect to the IPv4 host using a socket
+SOCKET ConnectTimeoutIPv4(IP *ip, UINT port, UINT timeout, bool *cancel_flag)
+{
+ SOCKET s;
+ struct sockaddr_in sockaddr4;
+ struct in_addr addr4;
+
+ Zero(&sockaddr4, sizeof(sockaddr4));
+ Zero(&addr4, sizeof(addr4));
+
+ // Generate a sockaddr_in
+ IPToInAddr(&addr4, ip);
+ sockaddr4.sin_port = htons((USHORT)port);
+ sockaddr4.sin_family = AF_INET;
+ sockaddr4.sin_addr.s_addr = addr4.s_addr;
+
+ // Socket creation
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s != INVALID_SOCKET)
+ {
+ // Connection
+ if (connect_timeout(s, (struct sockaddr *)&sockaddr4, sizeof(struct sockaddr_in), timeout, cancel_flag) != 0)
+ {
+ // Connection failure
+ closesocket(s);
+ s = INVALID_SOCKET;
+ }
+ }
+
+ return s;
+}
+
+// Identify whether the HTTPS server to be connected is a SoftEther VPN
+bool DetectIsServerSoftEtherVPN(SOCK *s)
+{
+ HTTP_HEADER *h;
+ char ip_str[MAX_SIZE];
+ char *send_str;
+ UINT content_len;
+ BUF *recv_buf;
+ void *socket_buffer;
+ UINT socket_buffer_size = 32768;
+ bool ok = false;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ IPToStr(ip_str, sizeof(ip_str), &s->RemoteIP);
+
+ // Request generation
+ h = NewHttpHeaderEx("GET", "/", "HTTP/1.1", true);
+ AddHttpValue(h, NewHttpValue("X-VPN", "1"));
+ AddHttpValue(h, NewHttpValue("Host", ip_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Accept-Language", "ja"));
+ AddHttpValue(h, NewHttpValue("User-Agent", DEFAULT_USER_AGENT));
+ AddHttpValue(h, NewHttpValue("Pragma", "no-cache"));
+ AddHttpValue(h, NewHttpValue("Cache-Control", "no-cache"));
+ send_str = HttpHeaderToStr(h);
+ FreeHttpHeader(h);
+
+ // Transmission
+ if (SendAll(s, send_str, StrLen(send_str), true) == false)
+ {
+ Free(send_str);
+ return false;
+ }
+
+ Free(send_str);
+
+ // Receive
+ h = RecvHttpHeader(s);
+ if (h == NULL)
+ {
+ return false;
+ }
+
+ // Get the length of the content
+ content_len = GetContentLength(h);
+ FreeHttpHeader(h);
+
+ if (content_len == 0 || content_len >= (1024 * 1024))
+ {
+ return false;
+ }
+
+ // Receive contents
+ recv_buf = NewBuf();
+ socket_buffer = Malloc(socket_buffer_size);
+
+ while (true)
+ {
+ UINT recvsize = MIN(socket_buffer_size, content_len - recv_buf->Size);
+ UINT size;
+
+ if (recvsize == 0)
+ {
+ ok = true;
+ break;
+ }
+
+ size = Recv(s, socket_buffer, recvsize, true);
+ if (size == 0)
+ {
+ // Disconnected
+ break;
+ }
+
+ WriteBuf(recv_buf, socket_buffer, size);
+ }
+
+ SeekBuf(recv_buf, 0, 0);
+ Free(socket_buffer);
+
+ if (ok)
+ {
+ // Examine to confirm whether the incoming data is a SoftEther VPN protocol
+ char tmp[1024];
+
+ Zero(tmp, sizeof(tmp));
+
+ Copy(tmp, recv_buf->Buf, MIN(recv_buf->Size, (sizeof(tmp) - 1)));
+
+ ok = false;
+
+ if (StartWith(tmp, http_detect_server_startwith))
+ {
+ ok = true;
+ }
+ else if (InStr(tmp, http_detect_server_tag_future))
+ {
+ ok = true;
+ }
+ }
+
+ FreeBuf(recv_buf);
+
+ return ok;
+}
+
+// TCP connection thread
+void ConnectThreadForTcp(THREAD *thread, void *param)
+{
+ SOCK *sock;
+ char hostname[MAX_SIZE];
+ CONNECT_TCP_RUDP_PARAM *p = (CONNECT_TCP_RUDP_PARAM *)param;
+ if (thread == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Delay
+ if (p->Delay >= 1)
+ {
+ WaitEx(NULL, p->Delay, p->CancelFlag);
+ }
+
+ // Connecting process
+ IPToStr(hostname, sizeof(hostname), &p->Ip);
+ sock = ConnectEx3(hostname, p->Port, p->Timeout, p->CancelFlag, NULL, NULL, false, false, true);
+
+ if (sock != NULL && p->Tcp_SslNoTls)
+ {
+ bool ssl_ret = false;
+ // Attempt the SSL negotiation to take this opportunity
+ Lock(p->CancelLock);
+ {
+ if ((*p->CancelFlag) == false)
+ {
+ p->CancelDisconnectSock = sock;
+ AddRef(sock->ref);
+ }
+ else
+ {
+ Debug("User Cancel to StartSSL.\n");
+ goto LABEL_CANCEL;
+ }
+ }
+ Unlock(p->CancelLock);
+
+ // Start the SSL communication
+ ssl_ret = StartSSLEx(sock, NULL, NULL, p->Tcp_SslNoTls, 0, p->Hostname);
+
+ if (ssl_ret)
+ {
+ // Identify whether the HTTPS server to be connected is a SoftEther VPN
+ SetTimeout(sock, (10 * 1000));
+ ssl_ret = DetectIsServerSoftEtherVPN(sock);
+ SetTimeout(sock, INFINITE);
+
+ if (ssl_ret == false)
+ {
+ Debug("DetectIsServerSoftEtherVPN Error.\n");
+ }
+ }
+
+ Lock(p->CancelLock);
+ {
+ ReleaseSock(p->CancelDisconnectSock);
+ p->CancelDisconnectSock = NULL;
+LABEL_CANCEL:
+ DoNothing();
+ }
+ Unlock(p->CancelLock);
+
+ if (ssl_ret == false)
+ {
+ // SSL negotiation failure
+ Disconnect(sock);
+ ReleaseSock(sock);
+
+ Debug("Fail to StartSSL.\n");
+
+ sock = NULL;
+ }
+ }
+
+ p->Result_Tcp_Sock = sock;
+ p->Ok = (p->Result_Tcp_Sock == NULL ? false : true);
+ p->FinishedTick = Tick64();
+ p->Finished = true;
+
+ Set(p->FinishEvent);
+}
+
+// R-UDP over ICMP / over DNS connection thread
+void ConnectThreadForOverDnsOrIcmp(THREAD *thread, void *param)
+{
+ SOCK *sock;
+ CONNECT_TCP_RUDP_PARAM *p = (CONNECT_TCP_RUDP_PARAM *)param;
+ if (thread == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Delay
+ if (p->Delay >= 1)
+ {
+ WaitEx(NULL, p->Delay, p->CancelFlag);
+ }
+
+ // Connecting process
+ sock = NewRUDPClientDirect(p->SvcName, &p->Ip,
+ (p->RUdpProtocol == RUDP_PROTOCOL_DNS ? 53 : MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4)),
+ &p->NatT_ErrorCode, p->Timeout, p->CancelFlag, NULL, NULL,
+ (p->RUdpProtocol == RUDP_PROTOCOL_DNS ? 0 : MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4)),
+ (p->RUdpProtocol == RUDP_PROTOCOL_DNS ? true : false));
+
+ p->Result_Nat_T_Sock = sock;
+ p->Ok = (p->Result_Nat_T_Sock == NULL ? false : true);
+ p->FinishedTick = Tick64();
+ p->Finished = true;
+
+ Set(p->FinishEvent);
+}
+
+// R-UDP (via NAT-T) connection thread
+void ConnectThreadForRUDP(THREAD *thread, void *param)
+{
+ SOCK *sock;
+ CONNECT_TCP_RUDP_PARAM *p = (CONNECT_TCP_RUDP_PARAM *)param;
+ if (thread == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // Delay
+ if (p->Delay >= 1)
+ {
+ WaitEx(NULL, p->Delay, p->CancelFlag);
+ }
+
+ // Connecting process
+ sock = NewRUDPClientNatT(p->SvcName, &p->Ip, &p->NatT_ErrorCode, p->Timeout, p->CancelFlag, p->HintStr, p->TargetHostname);
+
+ p->Result_Nat_T_Sock = sock;
+ p->Ok = (p->Result_Nat_T_Sock == NULL ? false : true);
+ p->FinishedTick = Tick64();
+ p->Finished = true;
+
+ Set(p->FinishEvent);
+}
+
+// TCP connection
+SOCK *Connect(char *hostname, UINT port)
+{
+ return ConnectEx(hostname, port, 0);
+}
+SOCK *ConnectEx(char *hostname, UINT port, UINT timeout)
+{
+ return ConnectEx2(hostname, port, timeout, NULL);
+}
+SOCK *ConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag)
+{
+ return ConnectEx3(hostname, port, timeout, cancel_flag, NULL, NULL, false, false, false);
+}
+SOCK *ConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool ssl_no_tls, bool no_get_hostname)
+{
+ SOCK *sock;
+ SOCKET s;
+ struct linger ling;
+ IP ip4;
+ IP ip6;
+ bool true_flag = true;
+ bool false_flag = false;
+ char tmp[MAX_SIZE];
+ IP current_ip;
+ bool is_ipv6 = false;
+ bool dummy = false;
+ bool use_natt = false;
+ char hostname_original[MAX_SIZE];
+ char hint_str[MAX_SIZE];
+ bool force_use_natt = false;
+ UINT dummy_int = 0;
+ // Validate arguments
+ if (hostname == NULL || port == 0 || port >= 65536 || IsEmptyStr(hostname))
+ {
+ return NULL;
+ }
+ if (timeout == 0)
+ {
+ timeout = TIMEOUT_TCP_PORT_CHECK;
+ }
+ if (cancel_flag == NULL)
+ {
+ cancel_flag = &dummy;
+ }
+ if (nat_t_error_code == NULL)
+ {
+ nat_t_error_code = &dummy_int;
+ }
+
+ Zero(hint_str, sizeof(hint_str));
+ StrCpy(hostname_original, sizeof(hostname_original), hostname);
+
+ use_natt = (IsEmptyStr(nat_t_svc_name) ? false : true);
+
+ if (use_natt)
+ {
+ // In case of using NAT-T, split host name if the '/' is included in the host name
+ UINT i = SearchStrEx(hostname, "/", 0, false);
+
+ if (i == INFINITE)
+ {
+ // Not included
+ StrCpy(hostname_original, sizeof(hostname_original), hostname);
+ }
+ else
+ {
+ // Included
+ StrCpy(hostname_original, sizeof(hostname_original), hostname);
+ hostname_original[i] = 0;
+
+ // Force to use the NAT-T
+ force_use_natt = true;
+
+ // Copy the hint string
+ StrCpy(hint_str, sizeof(hint_str), hostname + i + 1);
+
+ if (StrCmpi(hint_str, "tcp") == 0 || StrCmpi(hint_str, "disable") == 0
+ || StrCmpi(hint_str, "disabled") == 0
+ || StrCmpi(hint_str, "no") == 0 || StrCmpi(hint_str, "none") == 0)
+ {
+ // Force not to use the NAT-T
+ force_use_natt = false;
+ use_natt = false;
+ }
+ }
+ }
+ else
+ {
+ StrCpy(hostname_original, sizeof(hostname_original), hostname);
+ }
+
+ Zero(&current_ip, sizeof(current_ip));
+
+ Zero(&ip4, sizeof(ip4));
+ Zero(&ip6, sizeof(ip6));
+
+ // Forward resolution
+ if (GetIP46Ex(&ip4, &ip6, hostname_original, 0, cancel_flag) == false)
+ {
+ return NULL;
+ }
+
+ if (IsZeroIp(&ip4) == false && IsIPLocalHostOrMySelf(&ip4))
+ {
+ // NAT-T isn't used in the case of connection to localhost
+ force_use_natt = false;
+ use_natt = false;
+ }
+
+ s = INVALID_SOCKET;
+
+ // Attempt to connect with IPv4
+ if (IsZeroIp(&ip4) == false)
+ {
+ if (use_natt == false)
+ {
+ // Normal connection without using NAT-T
+ s = ConnectTimeoutIPv4(&ip4, port, timeout, cancel_flag);
+
+ if (s != INVALID_SOCKET)
+ {
+ Copy(&current_ip, &ip4, sizeof(IP));
+ }
+ }
+ else if (force_use_natt)
+ {
+ // The connection by forcing the use of NAT-T (not to connection with normal TCP)
+ SOCK *nat_t_sock = NewRUDPClientNatT(nat_t_svc_name, &ip4, nat_t_error_code, timeout, cancel_flag,
+ hint_str, hostname);
+
+ if (nat_t_sock != NULL)
+ {
+ StrCpy(nat_t_sock->UnderlayProtocol, sizeof(nat_t_sock->UnderlayProtocol), SOCK_UNDERLAY_NAT_T);
+ }
+
+ return nat_t_sock;
+ }
+ else
+ {
+ // Use the connections using NAT-T with normal TCP connection together
+ // (Use multiple threads to try to connect in four connection methods concurrently)
+ CONNECT_TCP_RUDP_PARAM p1, p2, p3, p4;
+ EVENT *finish_event;
+ THREAD *t1, *t2, *t3, *t4;
+ UINT64 start_tick = Tick64();
+ UINT64 giveup_for_all_tick = start_tick + (UINT64)SOCK_CONNECT_WAIT_FOR_ICMP_AND_DNS_AT_LEAST;
+ bool cancel_flag2 = false;
+ SOCK *cancel_sock = NULL;
+
+ finish_event = NewEvent();
+
+ Zero(&p1, sizeof(p1));
+ Zero(&p2, sizeof(p2));
+ Zero(&p3, sizeof(p3));
+ Zero(&p4, sizeof(p4));
+
+ // p1: TCP
+ StrCpy(p1.Hostname, sizeof(p1.Hostname), hostname_original);
+ Copy(&p1.Ip, &ip4, sizeof(IP));
+ p1.Port = port;
+ p1.Timeout = timeout;
+ p1.CancelFlag = &cancel_flag2;
+ p1.FinishEvent = finish_event;
+ p1.Tcp_TryStartSsl = try_start_ssl;
+ p1.Tcp_SslNoTls = ssl_no_tls;
+ p1.CancelLock = NewLock();
+
+ // p2: NAT-T
+ StrCpy(p2.Hostname, sizeof(p2.Hostname), hostname_original);
+ Copy(&p2.Ip, &ip4, sizeof(IP));
+ p2.Port = port;
+ p2.Timeout = timeout;
+ p2.CancelFlag = &cancel_flag2;
+ p2.FinishEvent = finish_event;
+
+ StrCpy(p2.HintStr, sizeof(p2.HintStr), hint_str);
+ StrCpy(p2.TargetHostname, sizeof(p2.TargetHostname), hostname);
+ StrCpy(p2.SvcName, sizeof(p2.SvcName), nat_t_svc_name);
+ p2.Delay = 30; // Delay by 30ms
+
+ // p3: over ICMP
+ StrCpy(p3.Hostname, sizeof(p3.Hostname), hostname_original);
+ Copy(&p3.Ip, &ip4, sizeof(IP));
+ p3.Port = port;
+ p3.Timeout = timeout;
+ p3.CancelFlag = &cancel_flag2;
+ p3.FinishEvent = finish_event;
+ StrCpy(p3.SvcName, sizeof(p3.SvcName), nat_t_svc_name);
+ p3.RUdpProtocol = RUDP_PROTOCOL_ICMP;
+ p3.Delay = 200; // Delay by 200ms
+
+ // p4: over DNS
+ StrCpy(p4.Hostname, sizeof(p4.Hostname), hostname_original);
+ Copy(&p4.Ip, &ip4, sizeof(IP));
+ p4.Port = port;
+ p4.Timeout = timeout;
+ p4.CancelFlag = &cancel_flag2;
+ p4.FinishEvent = finish_event;
+ StrCpy(p4.SvcName, sizeof(p4.SvcName), nat_t_svc_name);
+ p4.RUdpProtocol = RUDP_PROTOCOL_DNS;
+ p4.Delay = 100; // Delay by 100ms
+
+ t1 = NewThread(ConnectThreadForTcp, &p1);
+ t2 = NewThread(ConnectThreadForRUDP, &p2);
+ t4 = NewThread(ConnectThreadForOverDnsOrIcmp, &p4);
+ t3 = NewThread(ConnectThreadForOverDnsOrIcmp, &p3);
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+
+ if (*cancel_flag)
+ {
+ // Cancel by the user
+ break;
+ }
+
+ if (p1.Finished && p2.Finished)
+ {
+ // Results for both the TCP and the NAT-T were confirmed
+ if (now >= giveup_for_all_tick)
+ {
+ // Wait at least minimum time until successful of the ICMP or the DNS
+ break;
+ }
+
+ if (p3.Ok || p4.Ok)
+ {
+ // Exit the loop immediately if any of the ICMP or the DNS is successful
+ break;
+ }
+ }
+
+ if (p1.Finished && p1.Ok)
+ {
+ // Have successfully connected by TCP
+ break;
+ }
+
+ if (p2.Finished && p2.Ok)
+ {
+ UINT p1_wait_time;
+ UINT64 tcp_giveup_tick;
+ UINT p2_spent_time;
+ // Have successfully connected by R-UDP
+ if (p1.Finished)
+ {
+ // Result of TCP is confirmed
+ break;
+ }
+
+ // Calculate the time takes to complete connection of R-UDP
+ p2_spent_time = (UINT)(p2.FinishedTick - start_tick);
+
+ // Decide the grace time for results of TCP until settled.
+ // The grace time is three times the duration of the R-UDP, and at least 250 milliseconds from the start,
+ // and up to 1500 milliseconds after the R-UDP results settled
+ p1_wait_time = p2_spent_time * 3;
+ p1_wait_time = MAX(p1_wait_time, 250);
+ //Debug("p2_spent_time = %u, p1_wait_time = %u\n", p2_spent_time, p1_wait_time);
+
+ tcp_giveup_tick = start_tick + (UINT64)p1_wait_time;
+ tcp_giveup_tick = MIN(tcp_giveup_tick, (p2.FinishedTick + 1500ULL));
+
+ if (now >= tcp_giveup_tick)
+ {
+ // Result of the TCP is uncertain, but give up
+ break;
+ }
+ }
+
+ Wait(finish_event, 25);
+ }
+
+ cancel_flag2 = true;
+
+ Lock(p1.CancelLock);
+ {
+ if (p1.CancelDisconnectSock != NULL)
+ {
+ cancel_sock = p1.CancelDisconnectSock;
+
+ AddRef(cancel_sock->ref);
+ }
+ }
+ Unlock(p1.CancelLock);
+
+ if (cancel_sock != NULL)
+ {
+ Disconnect(cancel_sock);
+ ReleaseSock(cancel_sock);
+ }
+
+ WaitThread(t1, INFINITE);
+ WaitThread(t2, INFINITE);
+ WaitThread(t3, INFINITE);
+ WaitThread(t4, INFINITE);
+ ReleaseThread(t1);
+ ReleaseThread(t2);
+ ReleaseThread(t3);
+ ReleaseThread(t4);
+ ReleaseEvent(finish_event);
+
+ DeleteLock(p1.CancelLock);
+
+ if (*cancel_flag)
+ {
+ // Abandon all the results because the user canceled
+ Disconnect(p1.Result_Nat_T_Sock);
+ ReleaseSock(p1.Result_Nat_T_Sock);
+ Disconnect(p2.Result_Nat_T_Sock);
+ ReleaseSock(p2.Result_Nat_T_Sock);
+ Disconnect(p3.Result_Nat_T_Sock);
+ ReleaseSock(p3.Result_Nat_T_Sock);
+ Disconnect(p4.Result_Nat_T_Sock);
+ ReleaseSock(p4.Result_Nat_T_Sock);
+
+ return NULL;
+ }
+
+ if (p1.Ok)
+ {
+ char hostname[MAX_SIZE];
+
+ // Use the results of the TCP
+ // Dispose other results
+ Disconnect(p2.Result_Nat_T_Sock);
+ ReleaseSock(p2.Result_Nat_T_Sock);
+ Disconnect(p3.Result_Nat_T_Sock);
+ ReleaseSock(p3.Result_Nat_T_Sock);
+ Disconnect(p4.Result_Nat_T_Sock);
+ ReleaseSock(p4.Result_Nat_T_Sock);
+
+ if (GetHostName(hostname, sizeof(hostname), &ip4))
+ {
+ Free(p1.Result_Tcp_Sock->RemoteHostname);
+ p1.Result_Tcp_Sock->RemoteHostname = CopyStr(hostname);
+ }
+
+ return p1.Result_Tcp_Sock;
+ }
+ else if (p2.Ok)
+ {
+ // Use the results of the R-UDP
+ // Dispose other results
+ Disconnect(p3.Result_Nat_T_Sock);
+ ReleaseSock(p3.Result_Nat_T_Sock);
+ Disconnect(p4.Result_Nat_T_Sock);
+ ReleaseSock(p4.Result_Nat_T_Sock);
+
+ StrCpy(p2.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p2.Result_Nat_T_Sock->UnderlayProtocol),
+ SOCK_UNDERLAY_NAT_T);
+
+ return p2.Result_Nat_T_Sock;
+ }
+ else if (p4.Ok)
+ {
+ // Use this if over-DNS success
+ // Dispose other results
+ Disconnect(p3.Result_Nat_T_Sock);
+ ReleaseSock(p3.Result_Nat_T_Sock);
+
+ StrCpy(p4.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p4.Result_Nat_T_Sock->UnderlayProtocol),
+ SOCK_UNDERLAY_DNS);
+
+ return p4.Result_Nat_T_Sock;
+ }
+ else if (p3.Ok)
+ {
+ // Use this if over ICMP success
+ StrCpy(p3.Result_Nat_T_Sock->UnderlayProtocol, sizeof(p3.Result_Nat_T_Sock->UnderlayProtocol),
+ SOCK_UNDERLAY_ICMP);
+
+ return p3.Result_Nat_T_Sock;
+ }
+ else
+ {
+ // Continue the process if all trials failed
+ *nat_t_error_code = p2.NatT_ErrorCode;
+ }
+ }
+ }
+
+ // Attempt to connect with IPv6
+ if (s == INVALID_SOCKET && IsZeroIp(&ip6) == false)
+ {
+ struct sockaddr_in6 sockaddr6;
+ struct in6_addr addr6;
+
+ Zero(&sockaddr6, sizeof(sockaddr6));
+ Zero(&addr6, sizeof(addr6));
+
+ // Generation of the sockaddr_in6
+ IPToInAddr6(&addr6, &ip6);
+ sockaddr6.sin6_port = htons((USHORT)port);
+ sockaddr6.sin6_family = AF_INET6;
+ sockaddr6.sin6_scope_id = ip6.ipv6_scope_id;
+ Copy(&sockaddr6.sin6_addr, &addr6, sizeof(addr6));
+
+ // Socket creation
+ s = socket(AF_INET6, SOCK_STREAM, 0);
+ if (s != INVALID_SOCKET)
+ {
+ // Connection
+ if (connect_timeout(s, (struct sockaddr *)&sockaddr6, sizeof(struct sockaddr_in6), timeout, cancel_flag) != 0)
+ {
+ // Connection failure
+ closesocket(s);
+ s = INVALID_SOCKET;
+ }
+ else
+ {
+ Copy(&current_ip, &ip6, sizeof(IP));
+
+ is_ipv6 = true;
+ }
+ }
+ }
+
+ if (s == INVALID_SOCKET)
+ {
+ // Connection fails on both of IPv4, IPv6
+ return NULL;
+ }
+
+ // Creating a SOCK
+ sock = NewSock();
+ sock->socket = s;
+ sock->Type = SOCK_TCP;
+ sock->ServerMode = false;
+
+ StrCpy(sock->UnderlayProtocol, sizeof(sock->UnderlayProtocol),
+ (is_ipv6 ? SOCK_UNDERLAY_NATIVE_V6 : SOCK_UNDERLAY_NATIVE_V4));
+
+ // Host name resolution
+ if (no_get_hostname || (GetHostName(tmp, sizeof(tmp), &current_ip) == false))
+ {
+ StrCpy(tmp, sizeof(tmp), hostname_original);
+ }
+
+ //Debug("PTR: %s\n", tmp);
+
+ sock->RemoteHostname = CopyStr(tmp);
+
+// Debug("new socket: %u\n", s);
+
+ Zero(&ling, sizeof(ling));
+ // Forced disconnection flag
+#ifdef SO_DONTLINGER
+ setsockopt(sock->socket, SOL_SOCKET, SO_DONTLINGER, (char *)&true_flag, sizeof(bool));
+#else // SO_DONTLINGER
+ setsockopt(sock->socket, SOL_SOCKET, SO_LINGER, (char *)&false_flag, sizeof(bool));
+#endif // SO_DONTLINGER
+// setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (char *)&true_flag, sizeof(bool));
+
+ // Configuring TCP options
+ setsockopt(sock->socket, IPPROTO_TCP, TCP_NODELAY, (char *)&true_flag, sizeof(bool));
+
+ // Initialization of the time-out value
+ SetTimeout(sock, TIMEOUT_INFINITE);
+
+ // Get the socket information
+ QuerySocketInformation(sock);
+
+ if (IsZeroIp(&sock->LocalIP) == false && IsLocalHostIP(&sock->LocalIP) == false)
+ {
+ IP current_ip;
+
+ if (GetCurrentGlobalIP(&current_ip, is_ipv6) == false)
+ {
+ SetCurrentGlobalIP(&sock->LocalIP, is_ipv6);
+ }
+ }
+
+ sock->Connected = true;
+ sock->AsyncMode = false;
+ sock->SecureMode = false;
+ sock->IPv6 = is_ipv6;
+
+ return sock;
+}
+
+// Maximize the I/O buffer size of the socket
+void SetSocketSendRecvBufferSize(SOCKET s, UINT size)
+{
+ int value = (int)size;
+ // Validate arguments
+ if (s == INVALID_SOCKET)
+ {
+ return;
+ }
+
+ setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&value, sizeof(int));
+ setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&value, sizeof(int));
+}
+
+// Get the buffer size of the socket
+UINT GetSocketBufferSize(SOCKET s, bool send)
+{
+ int value = 0;
+ int len = sizeof(int);
+ // Validate arguments
+ if (s == INVALID_SOCKET)
+ {
+ return 0;
+ }
+
+ if (getsockopt(s, SOL_SOCKET, (send ? SO_SNDBUF : SO_RCVBUF), (char *)&value, &len) != 0)
+ {
+ return 0;
+ }
+
+ return value;
+}
+
+// Setting the buffer size of the socket
+bool SetSocketBufferSize(SOCKET s, bool send, UINT size)
+{
+ int value = (int)size;
+ // Validate arguments
+ if (s == INVALID_SOCKET)
+ {
+ return false;
+ }
+
+ if (setsockopt(s, SOL_SOCKET, (send ? SO_SNDBUF : SO_RCVBUF), (char *)&value, sizeof(int)) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+UINT SetSocketBufferSizeWithBestEffort(SOCKET s, bool send, UINT size)
+{
+ // Validate arguments
+ if (s == INVALID_SOCKET)
+ {
+ return 0;
+ }
+
+ while (true)
+ {
+ if (SetSocketBufferSize(s, send, size))
+ {
+ return size;
+ }
+
+ size = (UINT)((double)size / 1.5);
+
+ if (size <= 32767)
+ {
+ return 0;
+ }
+ }
+}
+
+// Initialize the buffer size of the UDP socket
+void InitUdpSocketBufferSize(SOCKET s)
+{
+ SetSocketBufferSizeWithBestEffort(s, true, UDP_MAX_BUFFER_SIZE);
+ SetSocketBufferSizeWithBestEffort(s, false, UDP_MAX_BUFFER_SIZE);
+}
+
+// Get the socket information
+void QuerySocketInformation(SOCK *sock)
+{
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return;
+ }
+
+ Lock(sock->lock);
+ {
+ struct sockaddr_in6 sockaddr6;
+ struct in6_addr *addr6;
+ int size;
+ DWORD dw;
+ UINT opt_value = 0;
+
+ if (sock->Type == SOCK_TCP)
+ {
+ // Get the information of the remote host
+ size = sizeof(sockaddr6);
+ if (getpeername(sock->socket, (struct sockaddr *)&sockaddr6, (int *)&size) == 0)
+ {
+ if (size >= sizeof(struct sockaddr_in6))
+ {
+ sock->RemotePort = (UINT)ntohs(sockaddr6.sin6_port);
+ addr6 = &sockaddr6.sin6_addr;
+ InAddrToIP6(&sock->RemoteIP, addr6);
+ sock->RemoteIP.ipv6_scope_id = sockaddr6.sin6_scope_id;
+ }
+ else
+ {
+ struct sockaddr_in *sockaddr;
+ struct in_addr *addr;
+
+ sockaddr = (struct sockaddr_in *)&sockaddr6;
+ sock->RemotePort = (UINT)ntohs(sockaddr->sin_port);
+ addr = &sockaddr->sin_addr;
+ InAddrToIP(&sock->RemoteIP, addr);
+ }
+ }
+ }
+
+ // Get the local host information
+ size = sizeof(sockaddr6);
+ if (getsockname(sock->socket, (struct sockaddr *)&sockaddr6, (int *)&size) == 0)
+ {
+ if (size >= sizeof(struct sockaddr_in6))
+ {
+ sock->LocalPort = (UINT)ntohs(sockaddr6.sin6_port);
+ addr6 = &sockaddr6.sin6_addr;
+ InAddrToIP6(&sock->LocalIP, addr6);
+ sock->LocalIP.ipv6_scope_id = sockaddr6.sin6_scope_id;
+ }
+ else
+ {
+ struct sockaddr_in *sockaddr;
+ struct in_addr *addr;
+
+ sockaddr = (struct sockaddr_in *)&sockaddr6;
+ sock->LocalPort = (UINT)ntohs(sockaddr->sin_port);
+ addr = &sockaddr->sin_addr;
+ InAddrToIP(&sock->LocalIP, addr);
+ }
+ }
+
+ if (sock->IsRawSocket)
+ {
+ sock->LocalPort = sock->RemotePort = MAKE_SPECIAL_PORT(sock->RawSocketIPProtocol);
+ }
+
+ if (sock->Type == SOCK_UDP)
+ {
+ sock->UdpMaxMsgSize = UDP_MAX_MSG_SIZE_DEFAULT;
+
+#ifdef OS_WIN32
+ if (true)
+ {
+ // Get the buffer size that can be transmitted and received at once
+ UINT max_value = 0;
+ int len = sizeof(UINT);
+
+ if (getsockopt(sock->socket, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *)&max_value, &len) == 0)
+ {
+ sock->UdpMaxMsgSize = max_value;
+ }
+ }
+#endif // OS_WIN32
+ }
+
+ if (sock->IPv6)
+ {
+#ifdef IPV6_UNICAST_HOPS
+ opt_value = IPV6_UNICAST_HOPS;
+#endif // IPV6_UNICAST_HOPS
+ }
+ else
+ {
+#ifdef IP_TTL
+ opt_value = IP_TTL;
+#endif // IP_TTL
+ }
+
+ // Support of the TTL value
+ size = sizeof(DWORD);
+ if (opt_value == 0 ||
+ getsockopt(sock->socket, (sock->IPv6 ? IPPROTO_IPV6 : IPPROTO_IP), opt_value, (char *)&dw, &size) != 0)
+ {
+ sock->IsTtlSupported = false;
+ }
+ else
+ {
+ sock->IsTtlSupported = true;
+ sock->CurrentTtl = dw;
+ }
+ }
+ Unlock(sock->lock);
+}
+
+// Setting the TTL value
+bool SetTtl(SOCK *sock, UINT ttl)
+{
+ DWORD dw;
+ int size;
+ UINT opt_value = 0;
+ // Validate arguments
+ if (sock == NULL)
+ {
+ return false;
+ }
+
+ if (sock->IsTtlSupported == false)
+ {
+ return false;
+ }
+
+ if (sock->CurrentTtl == ttl)
+ {
+ return true;
+ }
+
+ dw = ttl;
+ size = sizeof(DWORD);
+
+ if (sock->IPv6)
+ {
+#ifdef IPV6_UNICAST_HOPS
+ opt_value = IPV6_UNICAST_HOPS;
+#endif // IPV6_UNICAST_HOPS
+ }
+ else
+ {
+#ifdef IP_TTL
+ opt_value = IP_TTL;
+#endif // IP_TTL
+ }
+
+ if (opt_value == 0 ||
+ setsockopt(sock->socket, (sock->IPv6 ? IPPROTO_IPV6 : IPPROTO_IP), opt_value, (char *)&dw, size) == false)
+ {
+ return false;
+ }
+
+ sock->CurrentTtl = ttl;
+
+ return true;
+}
+
+// Release of the socket
+void ReleaseSock(SOCK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ if (Release(s->ref) == 0)
+ {
+ if (s->ListenMode == false && s->ServerMode)
+ {
+ Print("");
+ }
+ CleanupSock(s);
+ }
+}
+
+// Clean-up of the socket
+void CleanupSock(SOCK *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+// {Debug("CleanupSock: Disconnect() Called: %s %u\n", __FILE__, __LINE__);Disconnect(s);}
+ Disconnect(s);
+
+ if (s->InProcAcceptQueue != NULL)
+ {
+ while (true)
+ {
+ SOCK *ss = GetNext(s->InProcAcceptQueue);
+ if (ss == NULL)
+ {
+ break;
+ }
+
+ Disconnect(ss);
+ ReleaseSock(ss);
+ }
+
+ ReleaseQueue(s->InProcAcceptQueue);
+ }
+
+ if (s->InProcAcceptEvent != NULL)
+ {
+ ReleaseEvent(s->InProcAcceptEvent);
+ }
+
+ if (s->ReverseAcceptQueue != NULL)
+ {
+ while (true)
+ {
+ SOCK *ss = GetNext(s->ReverseAcceptQueue);
+ if (ss == NULL)
+ {
+ break;
+ }
+
+ Disconnect(ss);
+ ReleaseSock(ss);
+ }
+
+ ReleaseQueue(s->ReverseAcceptQueue);
+ }
+
+ if (s->ReverseAcceptEvent != NULL)
+ {
+ ReleaseEvent(s->ReverseAcceptEvent);
+ }
+
+ if (s->SendTube != NULL)
+ {
+ TubeDisconnect(s->SendTube);
+ ReleaseTube(s->SendTube);
+ }
+
+ if (s->RecvTube != NULL)
+ {
+ TubeDisconnect(s->RecvTube);
+ ReleaseTube(s->RecvTube);
+ }
+
+ if (s->BulkRecvTube != NULL)
+ {
+ TubeDisconnect(s->BulkRecvTube);
+ ReleaseTube(s->BulkRecvTube);
+ }
+
+ if (s->BulkSendTube != NULL)
+ {
+ TubeDisconnect(s->BulkSendTube);
+ ReleaseTube(s->BulkSendTube);
+ }
+
+ if (s->BulkSendKey != NULL)
+ {
+ ReleaseSharedBuffer(s->BulkSendKey);
+ }
+
+ if (s->BulkRecvKey != NULL)
+ {
+ ReleaseSharedBuffer(s->BulkRecvKey);
+ }
+
+ if (s->InProcRecvFifo != NULL)
+ {
+ ReleaseFifo(s->InProcRecvFifo);
+ }
+
+ if (s->R_UDP_Stack != NULL)
+ {
+ FreeRUDP(s->R_UDP_Stack);
+ }
+
+#ifdef OS_WIN32
+ Win32FreeAsyncSocket(s);
+#else // OS_WIN32
+ UnixFreeAsyncSocket(s);
+#endif // OS_WIN32
+
+ FreeBuf(s->SendBuf);
+ if (s->socket != INVALID_SOCKET)
+ {
+#ifdef OS_WIN32
+ closesocket(s->socket);
+#else // OS_WIN32
+ close(s->socket);
+#endif // OS_WIN32
+ }
+ Free(s->RemoteHostname);
+
+#ifdef OS_WIN32
+ if (s->hAcceptEvent != NULL)
+ {
+ CloseHandle(s->hAcceptEvent);
+ }
+#endif // OS_WIN32
+
+ Free(s->WaitToUseCipher);
+ DeleteLock(s->lock);
+ DeleteLock(s->ssl_lock);
+ DeleteLock(s->disconnect_lock);
+
+ Dec(num_tcp_connections);
+
+ Free(s);
+}
+
+// Creating a new socket
+SOCK *NewSock()
+{
+ SOCK *s = ZeroMallocFast(sizeof(SOCK));
+
+ s->ref = NewRef();
+ s->lock = NewLock();
+ s->SendBuf = NewBuf();
+ s->socket = INVALID_SOCKET;
+ s->ssl_lock = NewLock();
+ s->disconnect_lock = NewLock();
+
+ Inc(num_tcp_connections);
+
+ return s;
+}
+
+// Convert the IP to UINT
+UINT IPToUINT(IP *ip)
+{
+ UCHAR *b;
+ UINT i, value = 0;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return 0;
+ }
+
+ b = (UCHAR *)&value;
+ for (i = 0;i < 4;i++)
+ {
+ b[i] = ip->addr[i];
+ }
+
+ return value;
+}
+
+// Convert UINT to IP
+void UINTToIP(IP *ip, UINT value)
+{
+ UCHAR *b;
+ UINT i;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ ZeroIP4(ip);
+
+ b = (UCHAR *)&value;
+ for (i = 0;i < 4;i++)
+ {
+ ip->addr[i] = b[i];
+ }
+}
+
+// Get the host name of the computer
+void GetMachineHostName(char *name, UINT size)
+{
+ char tmp[MAX_SIZE];
+ UINT i, len;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ GetMachineName(tmp, sizeof(tmp));
+
+ len = StrLen(tmp);
+ for (i = 0;i < len;i++)
+ {
+ if (tmp[i] == '.')
+ {
+ tmp[i] = 0;
+ }
+ }
+
+ ConvertSafeFileName(name, size, tmp);
+}
+
+// Get the IP address of this computer
+void GetMachineIp(IP *ip)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ Zero(ip, sizeof(IP));
+ SetIP(ip, 127, 0, 0, 1);
+
+ GetMachineName(tmp, sizeof(tmp));
+ GetIP(ip, tmp);
+}
+
+// Get the computer name from 'hosts'
+bool GetMachineNameFromHosts(char *name, UINT size)
+{
+ bool ret = false;
+ char *s;
+ BUF *b;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDump("/etc/hosts");
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ while (true)
+ {
+ s = CfgReadNextLine(b);
+ if (s == NULL)
+ {
+ break;
+ }
+ else
+ {
+ TOKEN_LIST *t = ParseToken(s, " \t");
+
+ if (t != NULL)
+ {
+ if (t->NumTokens >= 2)
+ {
+ if (StrCmpi(t->Token[0], "127.0.0.1") == 0)
+ {
+ UINT i;
+
+ for (i = 1;i < t->NumTokens;i++)
+ {
+ if (StartWith(t->Token[i], "localhost") == false)
+ {
+ StrCpy(name, size, t->Token[i]);
+ ret = true;
+ }
+ }
+ }
+ }
+ }
+ FreeToken(t);
+ }
+
+ Free(s);
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Get the computer name of this computer
+void GetMachineName(char *name, UINT size)
+{
+ GetMachineNameEx(name, size, false);
+}
+void GetMachineNameEx(char *name, UINT size, bool no_load_hosts)
+{
+ static char name_cache[MAX_SIZE];
+ static bool name_cached = false;
+ char tmp[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ Lock(machine_name_lock);
+ {
+ if (name_cached != false)
+ {
+ StrCpy(name, size, name_cache);
+ Unlock(machine_name_lock);
+ return;
+ }
+ ClearStr(tmp, sizeof(tmp));
+ if (gethostname(tmp, MAX_SIZE) != 0)
+ {
+ StrCpy(name, size, "Unknown");
+ Unlock(machine_name_lock);
+ return;
+ }
+ ClearStr(name, size);
+ StrCpy(name, size, tmp);
+ if (IsEmptyStr(name) || StartWith(name, "localhost"))
+ {
+#ifdef OS_WIN32
+ ClearStr(name, size);
+ MsGetComputerName(name, size);
+#endif // OS_WIN32
+ }
+ if (IsEmptyStr(name) || StartWith(name, "localhost"))
+ {
+ if (no_load_hosts == false && OS_IS_UNIX(GetOsInfo()->OsType))
+ {
+ if (GetMachineNameFromHosts(tmp2, sizeof(tmp2)))
+ {
+ StrCpy(name, sizeof(name), tmp2);
+ }
+ }
+ }
+
+ StrCpy(name_cache, sizeof(name_cache), name);
+ name_cached = true;
+ }
+ Unlock(machine_name_lock);
+}
+
+// Host name acquisition thread
+void GetHostNameThread(THREAD *t, void *p)
+{
+ IP *ip;
+ char hostname[256];
+ // Validate arguments
+ if (t == NULL || p == NULL)
+ {
+ return;
+ }
+
+ ip = (IP *)p;
+
+ AddWaitThread(t);
+
+ NoticeThreadInit(t);
+
+ if (GetHostNameInner(hostname, sizeof(hostname), ip))
+ {
+ AddHostCache(ip, hostname);
+ }
+
+ Free(ip);
+
+ DelWaitThread(t);
+}
+
+// Get the host name
+bool GetHostName(char *hostname, UINT size, IP *ip)
+{
+ THREAD *t;
+ IP *p_ip;
+ bool ret;
+ // Validate arguments
+ if (hostname == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ if (GetHostCache(hostname, size, ip))
+ {
+ if (IsEmptyStr(hostname) == false)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ p_ip = ZeroMalloc(sizeof(IP));
+ Copy(p_ip, ip, sizeof(IP));
+
+ t = NewThread(GetHostNameThread, p_ip);
+
+ WaitThreadInit(t);
+
+ WaitThread(t, TIMEOUT_HOSTNAME);
+
+ ReleaseThread(t);
+
+ ret = GetHostCache(hostname, size, ip);
+ if (ret == false)
+ {
+ if (IsIP4(ip))
+ {
+ ret = GetNetBiosName(hostname, size, ip);
+ if (ret)
+ {
+ AddHostCache(ip, hostname);
+ }
+ }
+ }
+ else
+ {
+ if (IsEmptyStr(hostname))
+ {
+ ret = false;
+ }
+ }
+ if (ret == false)
+ {
+ AddHostCache(ip, "");
+ StrCpy(hostname, size, "");
+ }
+
+ return ret;
+}
+
+// Perform a DNS reverse query
+bool GetHostNameInner(char *hostname, UINT size, IP *ip)
+{
+ struct in_addr addr;
+ struct sockaddr_in sa;
+ char tmp[MAX_SIZE];
+ char ip_str[64];
+ // Validate arguments
+ if (hostname == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ if (IsIP6(ip))
+ {
+ return GetHostNameInner6(hostname, size, ip);
+ }
+
+ // Reverse resolution
+ IPToInAddr(&addr, ip);
+ Zero(&sa, sizeof(sa));
+ sa.sin_family = AF_INET;
+
+#if defined(UNIX_BSD) || defined(UNIX_MACOS)
+ sa.sin_len = INET_ADDRSTRLEN;
+#endif // UNIX_BSD || UNIX_MACOS
+
+ Copy(&sa.sin_addr, &addr, sizeof(struct in_addr));
+ sa.sin_port = 0;
+
+ if (getnameinfo((struct sockaddr *)&sa, sizeof(sa), tmp, sizeof(tmp), NULL, 0, 0) != 0)
+ {
+ return false;
+ }
+
+ IPToStr(ip_str, sizeof(ip_str), ip);
+
+ if (StrCmpi(tmp, ip_str) == 0)
+ {
+ return false;
+ }
+
+ if (IsEmptyStr(tmp))
+ {
+ return false;
+ }
+
+ StrCpy(hostname, size, tmp);
+
+ return true;
+}
+bool GetHostNameInner6(char *hostname, UINT size, IP *ip)
+{
+ struct in6_addr addr;
+ struct sockaddr_in6 sa;
+ char tmp[MAX_SIZE];
+ char ip_str[256];
+ // Validate arguments
+ if (hostname == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ // Reverse resolution
+ IPToInAddr6(&addr, ip);
+ Zero(&sa, sizeof(sa));
+ sa.sin6_family = AF_INET6;
+
+#if defined(UNIX_BSD) || defined(UNIX_MACOS)
+ sa.sin6_len = INET6_ADDRSTRLEN;
+#endif // UNIX_BSD || UNIX_MACOS
+
+ Copy(&sa.sin6_addr, &addr, sizeof(struct in6_addr));
+ sa.sin6_port = 0;
+
+ if (getnameinfo((struct sockaddr *)&sa, sizeof(sa), tmp, sizeof(tmp), NULL, 0, 0) != 0)
+ {
+ return false;
+ }
+
+ IPToStr(ip_str, sizeof(ip_str), ip);
+
+ if (StrCmpi(tmp, ip_str) == 0)
+ {
+ return false;
+ }
+
+ if (IsEmptyStr(tmp))
+ {
+ return false;
+ }
+
+ StrCpy(hostname, size, tmp);
+
+ return true;
+}
+
+#define NUM_NBT_QUERYS_SEND 3
+
+// Get the NetBIOS name of the machine from the IP address
+bool GetNetBiosName(char *name, UINT size, IP *ip)
+{
+ SOCK *s;
+ UINT i, j;
+ bool flag = false;
+ bool ok = false;
+ NBTREQUEST req;
+ UCHAR buf[1024];
+ USHORT tran_id[NUM_NBT_QUERYS_SEND];
+ UINT64 timeout_tick;
+ // Validate arguments
+ if (name == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ IPToStr(name, size, ip);
+
+ for (i = 0;i < NUM_NBT_QUERYS_SEND;i++)
+ {
+ tran_id[i] = Rand16();
+ }
+
+ s = NewUDP(0);
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ for (j = 0;j < NUM_NBT_QUERYS_SEND;j++)
+ {
+ Zero(&req, sizeof(req));
+ req.TransactionId = Endian16(tran_id[j]);
+ req.NumQuestions = Endian16(1);
+ req.Query[0] = 0x20;
+ req.Query[1] = 0x43;
+ req.Query[2] = 0x4b;
+ for (i = 3;i <= 32;i++)
+ {
+ req.Query[i] = 0x41;
+ }
+ req.Query[35] = 0x21;
+ req.Query[37] = 0x01;
+
+ if (SendTo(s, ip, 137, &req, sizeof(req)) == 0)
+ {
+ ReleaseSock(s);
+ return false;
+ }
+ }
+
+ timeout_tick = Tick64() + (UINT64)TIMEOUT_NETBIOS_HOSTNAME;
+
+ while (1)
+ {
+ UINT ret;
+ IP src_ip;
+ UINT src_port;
+ SOCKSET set;
+ if (Tick64() >= timeout_tick)
+ {
+ break;
+ }
+ InitSockSet(&set);
+ AddSockSet(&set, s);
+ Select(&set, 100, NULL, NULL);
+
+ if (flag == false)
+ {
+ flag = true;
+ }
+ else
+ {
+ SleepThread(10);
+ }
+
+ ret = RecvFrom(s, &src_ip, &src_port, buf, sizeof(buf));
+
+ if (ret == SOCK_LATER)
+ {
+ continue;
+ }
+ else if (ret == 0)
+ {
+ break;
+ }
+ else
+ {
+ if (ret >= sizeof(NBTRESPONSE))
+ {
+ NBTRESPONSE *r = (NBTRESPONSE *)buf;
+ bool b = false;
+ UINT i;
+ USHORT id = Endian16(r->TransactionId);
+ for (i = 0;i < NUM_NBT_QUERYS_SEND;i++)
+ {
+ if (id == tran_id[i])
+ {
+ b = true;
+ break;
+ }
+ }
+ if (b)
+ {
+ if (r->Flags != 0 && r->NumQuestions == 0 && r->AnswerRRs >= 1)
+ {
+ if (r->Response[0] == 0x20 && r->Response[1] == 0x43 &&
+ r->Response[2] == 0x4b)
+ {
+ if (r->Response[34] == 0x00 && r->Response[35] == 0x21 &&
+ r->Response[36] == 0x00 && r->Response[37] == 0x01)
+ {
+ char *a = (char *)(&r->Response[45]);
+ if (StrCheckLen(a, 15))
+ {
+ if (IsEmptyStr(a) == false)
+ {
+ StrCpy(name, size, a);
+ Trim(name);
+ ok = true;
+ }
+ else
+ {
+ ok = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ReleaseSock(s);
+ return ok;
+}
+
+// Set the IP address
+void SetIP(IP *ip, UCHAR a1, UCHAR a2, UCHAR a3, UCHAR a4)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ Zero(ip, sizeof(IP));
+ ip->addr[0] = a1;
+ ip->addr[1] = a2;
+ ip->addr[2] = a3;
+ ip->addr[3] = a4;
+}
+UINT SetIP32(UCHAR a1, UCHAR a2, UCHAR a3, UCHAR a4)
+{
+ IP ip;
+
+ Zero(&ip, sizeof(ip));
+ SetIP(&ip, a1, a2, a3, a4);
+
+ return IPToUINT(&ip);
+}
+
+// Get either of v4 and v6 results with a DNS forward lookup (The IPv4 precedes in the case of both results)
+bool GetIP46Any4(IP *ip, char *hostname)
+{
+ IP ip4, ip6;
+ bool b = false;
+ // Validate arguments
+ if (ip == NULL || hostname == NULL)
+ {
+ return false;
+ }
+
+ if (GetIP46(&ip4, &ip6, hostname) == false)
+ {
+ return false;
+ }
+
+ if (IsZeroIp(&ip6) == false)
+ {
+ Copy(ip, &ip6, sizeof(IP));
+
+ b = true;
+ }
+
+ if (IsZeroIp(&ip4) == false)
+ {
+ Copy(ip, &ip4, sizeof(IP));
+
+ b = true;
+ }
+
+ return b;
+}
+
+// Get either of v4 and v6 results with a DNS forward lookup (The IPv6 precedes in the case of both)
+bool GetIP46Any6(IP *ip, char *hostname)
+{
+ IP ip4, ip6;
+ bool b = false;
+ // Validate arguments
+ if (ip == NULL || hostname == NULL)
+ {
+ return false;
+ }
+
+ if (GetIP46(&ip4, &ip6, hostname) == false)
+ {
+ return false;
+ }
+
+ if (IsZeroIp(&ip4) == false)
+ {
+ Copy(ip, &ip4, sizeof(IP));
+
+ b = true;
+ }
+
+ if (IsZeroIp(&ip6) == false)
+ {
+ Copy(ip, &ip6, sizeof(IP));
+
+ b = true;
+ }
+
+ return b;
+}
+
+// Obtain in both v4 and v6 results with a DNS forward lookup
+bool GetIP46(IP *ip4, IP *ip6, char *hostname)
+{
+ return GetIP46Ex(ip4, ip6, hostname, 0, NULL);
+}
+bool GetIP46Ex(IP *ip4, IP *ip6, char *hostname, UINT timeout, bool *cancel)
+{
+ IP a, b;
+ bool ok_a, ok_b;
+ // Validate arguments
+ if (ip4 == NULL || ip6 == NULL || hostname == NULL)
+ {
+ return false;
+ }
+
+ ZeroIP4(ip4);
+ ZeroIP6(ip6);
+
+ ok_a = ok_b = false;
+
+ if (GetIP6Ex(&a, hostname, timeout, cancel))
+ {
+ ok_a = true;
+ }
+
+ if (GetIP4Ex(&b, hostname, timeout, cancel))
+ {
+ ok_b = true;
+ }
+
+ if (ok_a)
+ {
+ if (IsIP4(&a))
+ {
+ Copy(ip4, &a, sizeof(IP));
+ }
+ }
+ if (ok_b)
+ {
+ if (IsIP4(&b))
+ {
+ Copy(ip4, &b, sizeof(IP));
+ }
+
+ if (IsIP6(&b))
+ {
+ Copy(ip6, &b, sizeof(IP));
+ }
+ }
+ if (ok_a)
+ {
+ if (IsIP6(&a))
+ {
+ Copy(ip6, &a, sizeof(IP));
+ }
+ }
+
+ if (IsZeroIp(ip4) && IsZeroIp(ip6))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Clean-up of the parameters for GetIP thread
+void CleanupGetIPThreadParam(GETIP_THREAD_PARAM *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ Free(p);
+}
+
+// Release of the parameters of the GetIP for thread
+void ReleaseGetIPThreadParam(GETIP_THREAD_PARAM *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (Release(p->Ref) == 0)
+ {
+ CleanupGetIPThreadParam(p);
+ }
+}
+
+// Thread to perform to query the DNS forward lookup (with timeout)
+void GetIP4Ex6ExThread(THREAD *t, void *param)
+{
+ GETIP_THREAD_PARAM *p;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ p = (GETIP_THREAD_PARAM *)param;
+
+ AddRef(p->Ref);
+
+ NoticeThreadInit(t);
+
+ AddWaitThread(t);
+
+ // Execution of resolution
+ if (p->IPv6 == false)
+ {
+ // IPv4
+ p->Ok = GetIP4Inner(&p->Ip, p->HostName);
+ }
+ else
+ {
+ // IPv6
+ p->Ok = GetIP6Inner(&p->Ip, p->HostName);
+ }
+
+ ReleaseGetIPThreadParam(p);
+
+ DelWaitThread(t);
+}
+
+// Perform a forward DNS query (with timeout)
+bool GetIP4Ex6Ex(IP *ip, char *hostname_arg, UINT timeout, bool ipv6, bool *cancel)
+{
+ return GetIP4Ex6Ex2(ip, hostname_arg, timeout, ipv6, cancel, false);
+}
+bool GetIP4Ex6Ex2(IP *ip, char *hostname_arg, UINT timeout, bool ipv6, bool *cancel, bool only_direct_dns)
+{
+ GETIP_THREAD_PARAM *p;
+ THREAD *t;
+ bool ret = false;
+ UINT64 start_tick = 0;
+ UINT64 end_tick = 0;
+ bool use_dns_proxy = false;
+ char hostname[260];
+ UINT i;
+ // Validate arguments
+ if (ip == NULL || hostname_arg == NULL)
+ {
+ return false;
+ }
+ if (timeout == 0)
+ {
+ timeout = TIMEOUT_GETIP;
+ }
+
+ Zero(hostname, sizeof(hostname));
+ StrCpy(hostname, sizeof(hostname), hostname_arg);
+
+ i = SearchStrEx(hostname, "/", 0, true);
+ if (i != INFINITE)
+ {
+ hostname[i] = 0;
+ }
+
+ if (ipv6 == false)
+ {
+ IP ip2;
+
+ if (StrToIP(&ip2, hostname) && IsZeroIp(&ip2) == false)
+ {
+ if (IsIP4(&ip2))
+ {
+ // IPv4 address direct specification
+ Copy(ip, &ip2, sizeof(IP));
+ return true;
+ }
+ else
+ {
+ // IPv6 address direct specification
+ return false;
+ }
+ }
+ }
+ else
+ {
+ IP ip2;
+
+ if (StrToIP(&ip2, hostname) && IsZeroIp(&ip2) == false)
+ {
+ if (IsIP6(&ip2))
+ {
+ // IPv6 address direct specification
+ Copy(ip, &ip2, sizeof(IP));
+ return true;
+ }
+ else
+ {
+ // IPv4 address direct specification
+ return false;
+ }
+ }
+ }
+
+ if (only_direct_dns == false)
+ {
+ if (ipv6 == false)
+ {
+ if (IsUseDnsProxy())
+ {
+ use_dns_proxy = true;
+ }
+ }
+ }
+
+
+ p = ZeroMalloc(sizeof(GETIP_THREAD_PARAM));
+ p->Ref = NewRef();
+ StrCpy(p->HostName, sizeof(p->HostName), hostname);
+ p->IPv6 = ipv6;
+ p->Timeout = timeout;
+ p->Ok = false;
+
+ t = NewThread(GetIP4Ex6ExThread, p);
+ WaitThreadInit(t);
+
+ if (cancel == NULL)
+ {
+ WaitThread(t, timeout);
+ }
+ else
+ {
+ start_tick = Tick64();
+ end_tick = start_tick + (UINT64)timeout;
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+ UINT64 remain;
+ UINT remain32;
+
+ if (*cancel)
+ {
+ break;
+ }
+
+ if (now >= end_tick)
+ {
+ break;
+ }
+
+ remain = end_tick - now;
+ remain32 = MIN((UINT)remain, 100);
+
+ if (WaitThread(t, remain32))
+ {
+ break;
+ }
+ }
+ }
+
+ ReleaseThread(t);
+
+ if (p->Ok)
+ {
+ ret = true;
+ Copy(ip, &p->Ip, sizeof(IP));
+ }
+ else
+ {
+ IP ip2;
+
+ if (only_direct_dns == false)
+ {
+ if (ipv6)
+ {
+ UINT flets_type = DetectFletsType();
+
+ // if I'm in the FLETs of NTT East,
+ // try to get an IP address using the DNS proxy server
+ if ((flets_type & FLETS_DETECT_TYPE_EAST_BFLETS_PRIVATE) &&
+ GetIPViaDnsProxyForJapanFlets(ip, hostname, true, 0, cancel, NULL))
+ {
+ // B FLETs
+ ret = true;
+ }
+ else if ((flets_type & FLETS_DETECT_TYPE_EAST_NGN_PRIVATE) &&
+ GetIPViaDnsProxyForJapanFlets(ip, hostname, true, 0, cancel, FLETS_NGN_EAST_DNS_PROXY_HOSTNAME))
+ {
+ // FLET'S Hikar-Next (NTT East)
+ ret = true;
+ }
+ else if ((flets_type & FLETS_DETECT_TYPE_WEST_NGN_PRIVATE) &&
+ GetIPViaDnsProxyForJapanFlets(ip, hostname, true, 0, cancel, FLETS_NGN_WEST_DNS_PROXY_HOSTNAME))
+ {
+ // FLET'S Hikar-Next (NTT West)
+ ret = true;
+ }
+ }
+ }
+
+ if (QueryDnsCache(&ip2, hostname))
+ {
+ ret = true;
+
+ Copy(ip, &ip2, sizeof(IP));
+ }
+ }
+
+
+ ReleaseGetIPThreadParam(p);
+
+ return ret;
+}
+bool GetIP4Ex(IP *ip, char *hostname, UINT timeout, bool *cancel)
+{
+ return GetIP4Ex6Ex(ip, hostname, timeout, false, cancel);
+}
+bool GetIP6Ex(IP *ip, char *hostname, UINT timeout, bool *cancel)
+{
+ return GetIP4Ex6Ex(ip, hostname, timeout, true, cancel);
+}
+bool GetIP4(IP *ip, char *hostname)
+{
+ return GetIP4Ex(ip, hostname, 0, NULL);
+}
+bool GetIP6(IP *ip, char *hostname)
+{
+ return GetIP6Ex(ip, hostname, 0, NULL);
+}
+
+// Perform a DNS forward lookup query
+bool GetIP(IP *ip, char *hostname)
+{
+ return GetIPEx(ip, hostname, false);
+}
+bool GetIPEx(IP *ip, char *hostname, bool ipv6)
+{
+ if (ipv6 == false)
+ {
+ return GetIP4(ip, hostname);
+ }
+ else
+ {
+ return GetIP6(ip, hostname);
+ }
+}
+bool GetIP6Inner(IP *ip, char *hostname)
+{
+ struct sockaddr_in6 in;
+ struct in6_addr addr;
+ struct addrinfo hint;
+ struct addrinfo *info;
+ // Validate arguments
+ if (ip == NULL || hostname == NULL)
+ {
+ return false;
+ }
+
+ if (IsEmptyStr(hostname))
+ {
+ return false;
+ }
+
+ if (StrCmpi(hostname, "localhost") == 0)
+ {
+ GetLocalHostIP6(ip);
+ return true;
+ }
+
+ if (StrToIP6(ip, hostname) == false && StrToIP(ip, hostname) == false)
+ {
+ // Forward resolution
+ Zero(&hint, sizeof(hint));
+ hint.ai_family = AF_INET6;
+ hint.ai_socktype = SOCK_STREAM;
+ hint.ai_protocol = IPPROTO_TCP;
+ info = NULL;
+
+ if (getaddrinfo(hostname, NULL, &hint, &info) != 0 ||
+ info->ai_family != AF_INET6)
+ {
+ if (info)
+ {
+ freeaddrinfo(info);
+ }
+ return QueryDnsCacheEx(ip, hostname, true);
+ }
+ // Forward resolution success
+ Copy(&in, info->ai_addr, sizeof(struct sockaddr_in6));
+ freeaddrinfo(info);
+
+ Copy(&addr, &in.sin6_addr, sizeof(addr));
+ InAddrToIP6(ip, &addr);
+ }
+
+ // Save Cache
+ NewDnsCache(hostname, ip);
+
+ return true;
+}
+bool GetIP4Inner(IP *ip, char *hostname)
+{
+ struct sockaddr_in in;
+ struct in_addr addr;
+ struct addrinfo hint;
+ struct addrinfo *info;
+ // Validate arguments
+ if (ip == NULL || hostname == NULL)
+ {
+ return false;
+ }
+
+ if (IsEmptyStr(hostname))
+ {
+ return false;
+ }
+
+ if (StrCmpi(hostname, "localhost") == 0)
+ {
+ SetIP(ip, 127, 0, 0, 1);
+ return true;
+ }
+
+ if (StrToIP6(ip, hostname) == false && StrToIP(ip, hostname) == false)
+ {
+ // Forward resolution
+ Zero(&hint, sizeof(hint));
+ hint.ai_family = AF_INET;
+ hint.ai_socktype = SOCK_STREAM;
+ hint.ai_protocol = IPPROTO_TCP;
+ info = NULL;
+
+ if (getaddrinfo(hostname, NULL, &hint, &info) != 0 ||
+ info->ai_family != AF_INET)
+ {
+ if (info)
+ {
+ freeaddrinfo(info);
+ }
+ return QueryDnsCache(ip, hostname);
+ }
+ // Forward resolution success
+ Copy(&in, info->ai_addr, sizeof(struct sockaddr_in));
+ freeaddrinfo(info);
+ Copy(&addr, &in.sin_addr, sizeof(addr));
+ InAddrToIP(ip, &addr);
+ }
+
+ // Save Cache
+ NewDnsCache(hostname, ip);
+
+ return true;
+}
+
+// Search in the DNS cache
+bool QueryDnsCache(IP *ip, char *hostname)
+{
+ return QueryDnsCacheEx(ip, hostname, false);
+}
+bool QueryDnsCacheEx(IP *ip, char *hostname, bool ipv6)
+{
+ DNSCACHE *c;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (ip == NULL || hostname == NULL)
+ {
+ return false;
+ }
+
+ GenDnsCacheKeyName(tmp, sizeof(tmp), hostname, ipv6);
+
+ c = FindDnsCache(tmp);
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ Copy(ip, &c->IpAddress, sizeof(IP));
+
+ return true;
+}
+
+// Convert the IP to a string
+void IPToUniStr(wchar_t *str, UINT size, IP *ip)
+{
+ char tmp[128];
+
+ IPToStr(tmp, sizeof(tmp), ip);
+ StrToUni(str, size, tmp);
+}
+
+// Convert the IP to a string (32bit UINT)
+void IPToUniStr32(wchar_t *str, UINT size, UINT ip)
+{
+ char tmp[128];
+
+ IPToStr32(tmp, sizeof(tmp), ip);
+ StrToUni(str, size, tmp);
+}
+
+// Convert the IP to a string (128bit byte array)
+void IPToStr128(char *str, UINT size, UCHAR *ip_bytes)
+{
+ IP ip_st;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ SetIP6(&ip_st, ip_bytes);
+ IPToStr(str, size, &ip_st);
+}
+
+// Convert the IP to a string (32bit UINT)
+void IPToStr32(char *str, UINT size, UINT ip)
+{
+ IP ip_st;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ UINTToIP(&ip_st, ip);
+ IPToStr(str, size, &ip_st);
+}
+
+// Convert IPv4 or IPv6 to a string
+void IPToStr4or6(char *str, UINT size, UINT ip_4_uint, UCHAR *ip_6_bytes)
+{
+ IP ip4;
+ IP ip6;
+ IP ip;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ Zero(&ip, sizeof(ip));
+
+ UINTToIP(&ip4, ip_4_uint);
+ SetIP6(&ip6, ip_6_bytes);
+
+ if (IsIP6(&ip4) || (IsZeroIp(&ip4) && (IsZeroIp(&ip6) == false)))
+ {
+ Copy(&ip, &ip6, sizeof(IP));
+ }
+ else
+ {
+ Copy(&ip, &ip4, sizeof(IP));
+ }
+
+ IPToStr(str, size, &ip);
+}
+
+// Convert the IP to a string
+void IPToStr(char *str, UINT size, IP *ip)
+{
+ // Validate arguments
+ if (str == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ if (IsIP6(ip))
+ {
+ IPToStr6(str, size, ip);
+ }
+ else
+ {
+ IPToStr4(str, size, ip);
+ }
+}
+
+// Convert the IPv4 to a string
+void IPToStr4(char *str, UINT size, IP *ip)
+{
+ // Validate arguments
+ if (str == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ // Conversion
+ snprintf(str, size != 0 ? size : 64, "%u.%u.%u.%u", ip->addr[0], ip->addr[1], ip->addr[2], ip->addr[3]);
+}
+
+// Convert the string to an IP
+bool StrToIP(IP *ip, char *str)
+{
+ TOKEN_LIST *token;
+ char *tmp;
+ UINT i;
+ // Validate arguments
+ if (ip == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ if (StrToIP6(ip, str))
+ {
+ return true;
+ }
+
+ Zero(ip, sizeof(IP));
+
+ tmp = CopyStr(str);
+ Trim(tmp);
+ token = ParseToken(tmp, ".");
+ Free(tmp);
+
+ if (token->NumTokens != 4)
+ {
+ FreeToken(token);
+ return false;
+ }
+ for (i = 0;i < 4;i++)
+ {
+ char *s = token->Token[i];
+ if (s[0] < '0' || s[0] > '9' ||
+ (ToInt(s) >= 256))
+ {
+ FreeToken(token);
+ return false;
+ }
+ }
+ Zero(ip, sizeof(IP));
+ for (i = 0;i < 4;i++)
+ {
+ ip->addr[i] = (UCHAR)ToInt(token->Token[i]);
+ }
+
+ FreeToken(token);
+
+ return true;
+}
+UINT StrToIP32(char *str)
+{
+ IP ip;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ if (StrToIP(&ip, str) == false)
+ {
+ return 0;
+ }
+
+ return IPToUINT(&ip);
+}
+bool UniStrToIP(IP *ip, wchar_t *str)
+{
+ char *tmp;
+ bool ret;
+
+ tmp = CopyUniToStr(str);
+ ret = StrToIP(ip, tmp);
+ Free(tmp);
+
+ return ret;
+}
+UINT UniStrToIP32(wchar_t *str)
+{
+ UINT ret;
+ char *tmp;
+
+ tmp = CopyUniToStr(str);
+ ret = StrToIP32(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Convert the IP to the in_addr
+void IPToInAddr(struct in_addr *addr, IP *ip)
+{
+ UINT i;
+ // Validate arguments
+ if (addr == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ Zero(addr, sizeof(struct in_addr));
+
+ if (IsIP6(ip) == false)
+ {
+ for (i = 0;i < 4;i++)
+ {
+ ((UCHAR *)addr)[i] = ip->addr[i];
+ }
+ }
+}
+
+// Convert the IP to the in6_addr
+void IPToInAddr6(struct in6_addr *addr, IP *ip)
+{
+ UINT i;
+ // Validate arguments
+ if (addr == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ Zero(addr, sizeof(struct in_addr));
+
+ if (IsIP6(ip))
+ {
+ for (i = 0;i < 16;i++)
+ {
+ ((UCHAR *)addr)[i] = ip->ipv6_addr[i];
+ }
+ }
+}
+
+// Convert the in_addr to the IP
+void InAddrToIP(IP *ip, struct in_addr *addr)
+{
+ UINT i;
+ // Validate arguments
+ if (ip == NULL || addr == NULL)
+ {
+ return;
+ }
+
+ Zero(ip, sizeof(IP));
+
+ for (i = 0;i < 4;i++)
+ {
+ ip->addr[i] = ((UCHAR *)addr)[i];
+ }
+}
+
+// Convert the in6_addr to the IP
+void InAddrToIP6(IP *ip, struct in6_addr *addr)
+{
+ UINT i;
+ // Validate arguments
+ if (ip == NULL || addr == NULL)
+ {
+ return;
+ }
+
+ ZeroIP6(ip);
+ for (i = 0;i < 16;i++)
+ {
+ ip->ipv6_addr[i] = ((UCHAR *)addr)[i];
+ }
+}
+
+// Search in the DNS cache
+DNSCACHE *FindDnsCache(char *hostname)
+{
+ return FindDnsCacheEx(hostname, false);
+}
+DNSCACHE *FindDnsCacheEx(char *hostname, bool ipv6)
+{
+ DNSCACHE *c;
+ char tmp[MAX_SIZE];
+ if (hostname == NULL)
+ {
+ return NULL;
+ }
+
+ GenDnsCacheKeyName(tmp, sizeof(tmp), hostname, ipv6);
+
+ LockDnsCache();
+ {
+ DNSCACHE t;
+ t.HostName = tmp;
+ c = Search(DnsCache, &t);
+ }
+ UnlockDnsCache();
+
+ return c;
+}
+
+// Generate the IPv4 / IPv6 key name for the DNS cache
+void GenDnsCacheKeyName(char *dst, UINT size, char *src, bool ipv6)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ if (ipv6 == false)
+ {
+ StrCpy(dst, size, src);
+ }
+ else
+ {
+ Format(dst, size, "%s@ipv6", src);
+ }
+}
+
+// Registration of the new DNS cache
+void NewDnsCache(char *hostname, IP *ip)
+{
+ NewDnsCacheEx(hostname, ip, IsIP6(ip));
+}
+void NewDnsCacheEx(char *hostname, IP *ip, bool ipv6)
+{
+ DNSCACHE *c;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (hostname == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ if (IsNetworkNameCacheEnabled() == false)
+ {
+ return;
+ }
+
+ GenDnsCacheKeyName(tmp, sizeof(tmp), hostname, ipv6);
+
+ LockDnsCache();
+ {
+ DNSCACHE t;
+
+ // Search for anything matches to the hostname first
+ t.HostName = tmp;
+ c = Search(DnsCache, &t);
+
+ if (c == NULL)
+ {
+ // Newly register
+ c = ZeroMalloc(sizeof(DNSCACHE));
+ c->HostName = CopyStr(tmp);
+
+ Copy(&c->IpAddress, ip, sizeof(IP));
+
+ Add(DnsCache, c);
+ }
+ else
+ {
+ // Update
+ Copy(&c->IpAddress, ip, sizeof(IP));
+ }
+ }
+ UnlockDnsCache();
+}
+
+// Name comparison of the DNS cache entries
+int CompareDnsCache(void *p1, void *p2)
+{
+ DNSCACHE *c1, *c2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ c1 = *(DNSCACHE **)p1;
+ c2 = *(DNSCACHE **)p2;
+ if (c1 == NULL || c2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(c1->HostName, c2->HostName);
+}
+
+// Initialization of the DNS cache
+void InitDnsCache()
+{
+ // Creating a List
+ DnsCache = NewList(CompareDnsCache);
+}
+
+// Release of the DNS cache
+void FreeDnsCache()
+{
+ LockDnsCache();
+ {
+ DNSCACHE *c;
+ UINT i;
+ for (i = 0;i < LIST_NUM(DnsCache);i++)
+ {
+ // Release the memory for the entry
+ c = LIST_DATA(DnsCache, i);
+ Free(c->HostName);
+ Free(c);
+ }
+ }
+ UnlockDnsCache();
+
+ // Release the list
+ ReleaseList(DnsCache);
+ DnsCache = NULL;
+}
+
+// Lock the DNS cache
+void LockDnsCache()
+{
+ LockList(DnsCache);
+}
+
+// Unlock the DNS cache
+void UnlockDnsCache()
+{
+ UnlockList(DnsCache);
+}
+
+// Create the SSL_CTX
+struct ssl_ctx_st *NewSSLCtx()
+{
+ struct ssl_ctx_st *ctx = SSL_CTX_new(SSLv23_method());
+
+#ifdef SSL_OP_NO_TICKET
+ SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET);
+#endif // SSL_OP_NO_TICKET
+
+ return ctx;
+}
+
+// Release of the SSL_CTX
+void FreeSSLCtx(struct ssl_ctx_st *ctx)
+{
+ // Validate arguments
+ if (ctx == NULL)
+ {
+ return;
+ }
+
+ SSL_CTX_free(ctx);
+}
+
+// Initialize the network communication module
+void InitNetwork()
+{
+
+ InitDynList();
+
+
+ host_ip_address_list_cache_lock = NewLock();
+ host_ip_address_list_cache_last = 0;
+
+ num_tcp_connections = NewCounter();
+
+ // Initialization of client list
+ InitIpClientList();
+
+ // Thread related initialization
+ InitWaitThread();
+
+ // Initialization of the host name cache
+ InitHostCache();
+
+#ifdef OS_WIN32
+ // Initializing the socket library
+ Win32InitSocketLibrary();
+#else
+ UnixInitSocketLibrary();
+#endif // OS_WIN32
+
+ // Initialization of the DNS cache
+ InitDnsCache();
+
+ // Locking initialization
+ machine_name_lock = NewLock();
+ disconnect_function_lock = NewLock();
+ aho = NewLock();
+ machine_ip_process_hash_lock = NewLock();
+ socket_library_lock = NewLock();
+ //ssl_connect_lock = NewLock(); //2012.9.28 Not required for recent OpenSSL
+// ssl_accept_lock = NewLock();
+ dns_lock = NewLock();
+ unix_dns_server_addr_lock = NewLock();
+ Zero(&unix_dns_server, sizeof(unix_dns_server));
+ local_mac_list_lock = NewLock();
+
+ cipher_list_token = ParseToken(cipher_list, " ");
+
+ current_global_ip_lock = NewLock();
+ current_fqdn_lock = NewLock();
+ current_global_ip_set = false;
+
+ disable_cache = false;
+
+
+ Zero(rand_port_numbers, sizeof(rand_port_numbers));
+}
+
+// Enable the network name cache
+void EnableNetworkNameCache()
+{
+ disable_cache = false;
+}
+
+// Disable the network name cache
+void DisableNetworkNameCache()
+{
+ disable_cache = true;
+}
+
+// Get whether the network name cache is enabled
+bool IsNetworkNameCacheEnabled()
+{
+ return !disable_cache;
+}
+
+// Get the cipher algorithm list
+TOKEN_LIST *GetCipherList()
+{
+ return cipher_list_token;
+}
+
+// Get the TCP connections counter
+COUNTER *GetNumTcpConnectionsCounter()
+{
+ return num_tcp_connections;
+}
+
+// Get the current global IP address
+bool GetCurrentGlobalIP(IP *ip, bool ipv6)
+{
+ bool ret = false;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ Zero(ip, sizeof(IP));
+
+ Lock(current_global_ip_lock);
+ {
+ if (ipv6 == false)
+ {
+ Copy(ip, &current_glocal_ipv4, sizeof(IP));
+ }
+ else
+ {
+ Copy(ip, &current_glocal_ipv6, sizeof(IP));
+ }
+
+ ret = current_global_ip_set;
+ }
+ Unlock(current_global_ip_lock);
+
+ return ret;
+}
+
+// Check whether the specified IP address is assigned to the local host
+bool IsIPMyHost(IP *ip)
+{
+ LIST *o;
+ UINT i;
+ bool ret = false;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ if (IsZeroIp(ip))
+ {
+ return false;
+ }
+
+ // Search to check whether it matches to any of the IP of the local host
+ o = GetHostIPAddressList();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *p = LIST_DATA(o, i);
+
+ if (CmpIpAddr(p, ip) == 0)
+ {
+ // Matched
+ ret = true;
+ break;
+ }
+ }
+
+ FreeHostIPAddressList(o);
+
+ if (ret == false)
+ {
+ if (IsLocalHostIP(ip))
+ {
+ // localhost IP addresses
+ ret = true;
+ }
+ }
+
+ return ret;
+}
+
+// Check whether the specified IP address is a private IP address
+bool IsIPPrivate(IP *ip)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ if (ip->addr[0] == 10)
+ {
+ return true;
+ }
+
+ if (ip->addr[0] == 172)
+ {
+ if (ip->addr[1] >= 16 && ip->addr[1] <= 31)
+ {
+ return true;
+ }
+ }
+
+ if (ip->addr[0] == 192 && ip->addr[1] == 168)
+ {
+ return true;
+ }
+
+ if (ip->addr[0] == 169 && ip->addr[1] == 254)
+ {
+ return true;
+ }
+
+ if (ip->addr[0] == 100)
+ {
+ if (ip->addr[1] >= 64 && ip->addr[1] <= 127)
+ {
+ return true;
+ }
+ }
+
+ if (g_private_ip_list != NULL)
+ {
+ if (IsIP4(ip))
+ {
+ UINT ip4 = IPToUINT(ip);
+
+ return IsOnPrivateIPFile(ip4);
+ }
+ }
+
+ return false;
+}
+
+// Read a private IP list file
+void LoadPrivateIPFile()
+{
+ BUF *b = ReadDump(PRIVATE_IP_TXT_FILENAME);
+ LIST *o;
+ if (b == NULL)
+ {
+ return;
+ }
+
+ o = NewList(NULL);
+
+ while (true)
+ {
+ char *line = CfgReadNextLine(b);
+ if (line == NULL)
+ {
+ break;
+ }
+
+ Trim(line);
+
+ if (IsEmptyStr(line) == false)
+ {
+ UINT ip = 0, mask = 0;
+
+ if (ParseIpAndSubnetMask4(line, &ip, &mask))
+ {
+ PRIVATE_IP_SUBNET *p = ZeroMalloc(sizeof(PRIVATE_IP_SUBNET));
+
+ p->Ip = ip;
+ p->Mask = mask;
+ p->Ip2 = ip & mask;
+
+ Add(o, p);
+ }
+ }
+
+ Free(line);
+ }
+
+ g_private_ip_list = o;
+ g_use_privateip_file = true;
+
+ FreeBuf(b);
+}
+
+// Examine whether the specified IP address is in the private IP file
+bool IsOnPrivateIPFile(UINT ip)
+{
+ bool ret = false;
+
+ if (g_private_ip_list != NULL)
+ {
+ LIST *o = g_private_ip_list;
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ PRIVATE_IP_SUBNET *p = LIST_DATA(o, i);
+
+ if ((ip & p->Mask) == p->Ip2)
+ {
+ ret = true;
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Free the private IP file
+void FreePrivateIPFile()
+{
+ if (g_private_ip_list != NULL)
+ {
+ LIST *o = g_private_ip_list;
+ UINT i;
+
+ g_private_ip_list = NULL;
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ PRIVATE_IP_SUBNET *p = LIST_DATA(o, i);
+
+ Free(p);
+ }
+
+ ReleaseList(o);
+ }
+
+ g_use_privateip_file = false;
+}
+
+// Guess the IPv4, IPv6 global address from the IP address list of the current interface
+void GetCurrentGlobalIPGuess(IP *ip, bool ipv6)
+{
+ LIST *o;
+ UINT i;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ Zero(ip, sizeof(IP));
+
+ o = GetHostIPAddressList();
+
+ if (ipv6 == false)
+ {
+ // IPv4
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *p = LIST_DATA(o, i);
+
+ if (IsIP4(p))
+ {
+ if (IsZeroIp(p) == false && IsIPPrivate(p) == false && p->addr[0] != 127)
+ {
+ Copy(ip, p, sizeof(IP));
+ }
+ }
+ }
+
+ if (IsZeroIp(ip))
+ {
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *p = LIST_DATA(o, i);
+
+ if (IsIP4(p))
+ {
+ if (IsZeroIp(p) == false && IsIPPrivate(p) && p->addr[0] != 127)
+ {
+ Copy(ip, p, sizeof(IP));
+ }
+ }
+ }
+ }
+
+ if (IsZeroIp(ip))
+ {
+ SetIP(ip, 127, 0, 0, 1);
+ }
+ }
+ else
+ {
+ // IPv6
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *p = LIST_DATA(o, i);
+
+ if (IsIP6(p))
+ {
+ UINT type = GetIPAddrType6(p);
+
+ if ((type & IPV6_ADDR_GLOBAL_UNICAST) && ((type & IPV6_ADDR_ZERO) == 0) && ((type & IPV6_ADDR_LOOPBACK) == 0))
+ {
+ Copy(ip, p, sizeof(IP));
+ }
+ }
+ }
+ }
+
+ FreeHostIPAddressList(o);
+}
+
+// Record the current global IP address
+void SetCurrentGlobalIP(IP *ip, bool ipv6)
+{
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return;
+ }
+
+ if (IsZeroIp(ip));
+ {
+ return;
+ }
+
+ Lock(current_global_ip_lock);
+ {
+ if (ipv6 == false)
+ {
+ Copy(&current_glocal_ipv4, ip, sizeof(IP));
+ }
+ else
+ {
+ Copy(&current_glocal_ipv6, ip, sizeof(IP));
+ }
+
+ current_global_ip_set = true;
+ }
+ Unlock(current_global_ip_lock);
+}
+
+// Release of the network communication module
+void FreeNetwork()
+{
+
+ // Release of thread-related
+ FreeWaitThread();
+
+ FreeToken(cipher_list_token);
+ cipher_list_token = NULL;
+
+ Zero(&unix_dns_server, sizeof(unix_dns_server));
+
+ // Release the locks
+ DeleteLock(unix_dns_server_addr_lock);
+ DeleteLock(dns_lock);
+ DeleteLock(ssl_accept_lock);
+ DeleteLock(machine_name_lock);
+ DeleteLock(disconnect_function_lock);
+ DeleteLock(aho);
+ DeleteLock(socket_library_lock);
+ DeleteLock(ssl_connect_lock);
+ DeleteLock(machine_ip_process_hash_lock);
+ machine_name_lock = NULL;
+ ssl_accept_lock = machine_name_lock = disconnect_function_lock =
+ aho = socket_library_lock = ssl_connect_lock = machine_ip_process_hash_lock = NULL;
+
+ // Release of the DNS cache
+ FreeDnsCache();
+
+ // Release of the host name cache
+ FreeHostCache();
+
+#ifdef OS_WIN32
+ // Release of the socket library
+ Win32FreeSocketLibrary();
+#else
+ UnixFreeSocketLibrary();
+#endif // OS_WIN32
+
+ DeleteCounter(num_tcp_connections);
+ num_tcp_connections = NULL;
+
+ // Release of client list
+ FreeIpClientList();
+
+ DeleteLock(current_global_ip_lock);
+ current_global_ip_lock = NULL;
+
+ DeleteLock(current_fqdn_lock);
+ current_fqdn_lock = NULL;
+
+ // Release of the local MAC list
+ if (local_mac_list != NULL)
+ {
+ FreeNicList(local_mac_list);
+ local_mac_list = NULL;
+ }
+
+ DeleteLock(local_mac_list_lock);
+ local_mac_list_lock = NULL;
+
+ DeleteLock(host_ip_address_list_cache_lock);
+ host_ip_address_list_cache_lock = NULL;
+
+ FreeHostIPAddressList(host_ip_address_cache);
+ host_ip_address_cache = NULL;
+
+
+ FreeDynList();
+
+}
+
+// Add a socket to socket list
+void AddSockList(SOCKLIST *sl, SOCK *s)
+{
+ // Validate arguments
+ if (sl == NULL || s == NULL)
+ {
+ return;
+ }
+
+ LockList(sl->SockList);
+ {
+ if (IsInList(sl->SockList, s) == false)
+ {
+ AddRef(s->ref);
+
+ Insert(sl->SockList, s);
+ }
+ }
+ UnlockList(sl->SockList);
+}
+
+// Remove the socket from socket list
+void DelSockList(SOCKLIST *sl, SOCK *s)
+{
+ // Validate arguments
+ if (sl == NULL || s == NULL)
+ {
+ return;
+ }
+
+ LockList(sl->SockList);
+ {
+ if (Delete(sl->SockList, s))
+ {
+ ReleaseSock(s);
+ }
+ }
+ UnlockList(sl->SockList);
+}
+
+// Stop all the sockets in the list and delete it
+void StopSockList(SOCKLIST *sl)
+{
+ SOCK **ss;
+ UINT num, i;
+ // Validate arguments
+ if (sl == NULL)
+ {
+ return;
+ }
+
+ LockList(sl->SockList);
+ {
+ num = LIST_NUM(sl->SockList);
+ ss = ToArray(sl->SockList);
+
+ DeleteAll(sl->SockList);
+ }
+ UnlockList(sl->SockList);
+
+ for (i = 0;i < num;i++)
+ {
+ SOCK *s = ss[i];
+
+ Disconnect(s);
+ ReleaseSock(s);
+ }
+
+ Free(ss);
+}
+
+// Delete the socket list
+void FreeSockList(SOCKLIST *sl)
+{
+ // Validate arguments
+ if (sl == NULL)
+ {
+ return;
+ }
+
+ StopSockList(sl);
+
+ ReleaseList(sl->SockList);
+
+ Free(sl);
+}
+
+// Creating a socket list
+SOCKLIST *NewSockList()
+{
+ SOCKLIST *sl = ZeroMallocFast(sizeof(SOCKLIST));
+
+ sl->SockList = NewList(NULL);
+
+ return sl;
+}
+
+// Time-out thread of the socket on Solaris
+void SocketTimeoutThread(THREAD *t, void *param)
+{
+ SOCKET_TIMEOUT_PARAM *ttparam;
+ ttparam = (SOCKET_TIMEOUT_PARAM *)param;
+
+ // Wait for time-out period
+ Select(NULL, ttparam->sock->TimeOut, ttparam->cancel, NULL);
+
+ // Disconnect if it is blocked
+ if(! ttparam->unblocked)
+ {
+// Debug("Socket timeouted\n");
+ closesocket(ttparam->sock->socket);
+ }
+ else
+ {
+// Debug("Socket timeout cancelled\n");
+ }
+}
+
+// Initialize and start the thread for time-out
+SOCKET_TIMEOUT_PARAM *NewSocketTimeout(SOCK *sock)
+{
+ SOCKET_TIMEOUT_PARAM *ttp;
+ if(! sock->AsyncMode && sock->TimeOut != TIMEOUT_INFINITE)
+ {
+// Debug("NewSockTimeout(%u)\n",sock->TimeOut);
+
+ ttp = (SOCKET_TIMEOUT_PARAM*)Malloc(sizeof(SOCKET_TIMEOUT_PARAM));
+
+ // Set the parameters of the time-out thread
+ ttp->cancel = NewCancel();
+ ttp->sock = sock;
+ ttp->unblocked = false;
+ ttp->thread = NewThread(SocketTimeoutThread, ttp);
+ return ttp;
+ }
+ return NULL;
+}
+
+// Stop and free the thread for timeout
+void FreeSocketTimeout(SOCKET_TIMEOUT_PARAM *ttp)
+{
+ if(ttp == NULL)
+ {
+ return;
+ }
+
+ ttp->unblocked = true;
+ Cancel(ttp->cancel);
+ WaitThread(ttp->thread, INFINITE);
+ ReleaseCancel(ttp->cancel);
+ ReleaseThread(ttp->thread);
+ Free(ttp);
+// Debug("FreeSocketTimeout succeed\n");
+ return;
+}
+
+// Parse the IP address and subnet mask
+bool ParseIpAndSubnetMask46(char *src, IP *ip, IP *mask)
+{
+ // Validate arguments
+ if (src == NULL || ip == NULL || mask == NULL)
+ {
+ return false;
+ }
+
+ if (ParseIpAndMask46(src, ip, mask) == false)
+ {
+ return false;
+ }
+
+ if (IsIP4(ip))
+ {
+ return IsSubnetMask4(mask);
+ }
+ else
+ {
+ return IsSubnetMask6(mask);
+ }
+}
+bool ParseIpAndSubnetMask6(char *src, IP *ip, IP *mask)
+{
+ if (ParseIpAndSubnetMask46(src, ip, mask) == false)
+ {
+ return false;
+ }
+
+ if (IsIP6(ip) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+bool ParseIpAndSubnetMask4(char *src, UINT *ip, UINT *mask)
+{
+ IP ip2, mask2;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return false;
+ }
+
+ if (ParseIpAndSubnetMask46(src, &ip2, &mask2) == false)
+ {
+ return false;
+ }
+
+ if (IsIP4(&ip2) == false)
+ {
+ return false;
+ }
+
+ if (ip != NULL)
+ {
+ *ip = IPToUINT(&ip2);
+ }
+
+ if (mask != NULL)
+ {
+ *mask = IPToUINT(&mask2);
+ }
+
+ return true;
+}
+
+
+// Parse the IP address and the mask
+bool ParseIpAndMask46(char *src, IP *ip, IP *mask)
+{
+ TOKEN_LIST *t;
+ char *ipstr;
+ char *subnetstr;
+ bool ret = false;
+ IP ip2;
+ IP mask2;
+ // Validate arguments
+ if (src == NULL || ip == NULL || mask == NULL)
+ {
+ return false;
+ }
+
+ Zero(&ip2, sizeof(IP));
+ Zero(&mask2, sizeof(IP));
+
+ t = ParseToken(src, "/");
+ if (t->NumTokens != 2)
+ {
+ FreeToken(t);
+ return false;
+ }
+
+ ipstr = t->Token[0];
+ subnetstr = t->Token[1];
+ Trim(ipstr);
+ Trim(subnetstr);
+
+ if (StrToIP(&ip2, ipstr))
+ {
+ if (StrToIP(&mask2, subnetstr))
+ {
+ // Compare the kind of the mask part and the IP address part to confirm same
+ if (IsIP6(&ip2) && IsIP6(&mask2))
+ {
+ // Both are IPv6
+ ret = true;
+ Copy(ip, &ip2, sizeof(IP));
+ Copy(mask, &mask2, sizeof(IP));
+ }
+ else if (IsIP4(&ip2) && IsIP4(&mask2))
+ {
+ // Both are IPv4
+ ret = true;
+ Copy(ip, &ip2, sizeof(IP));
+ Copy(mask, &mask2, sizeof(IP));
+ }
+ }
+ else
+ {
+ if (IsNum(subnetstr))
+ {
+ UINT i = ToInt(subnetstr);
+ // Mask part is a number
+ if (IsIP6(&ip2) && i <= 128)
+ {
+ ret = true;
+ Copy(ip, &ip2, sizeof(IP));
+ IntToSubnetMask6(mask, i);
+ }
+ else if (i <= 32)
+ {
+ ret = true;
+ Copy(ip, &ip2, sizeof(IP));
+ IntToSubnetMask4(mask, i);
+ }
+ }
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+bool ParseIpAndMask4(char *src, UINT *ip, UINT *mask)
+{
+ IP ip_ip, ip_mask;
+ if (ParseIpAndMask46(src, &ip_ip, &ip_mask) == false)
+ {
+ return false;
+ }
+
+ if (IsIP4(&ip_ip) == false)
+ {
+ return false;
+ }
+
+ if (ip != NULL)
+ {
+ *ip = IPToUINT(&ip_ip);
+ }
+
+ if (mask != NULL)
+ {
+ *mask = IPToUINT(&ip_mask);
+ }
+
+ return true;
+}
+bool ParseIpAndMask6(char *src, IP *ip, IP *mask)
+{
+ if (ParseIpAndMask46(src, ip, mask) == false)
+ {
+ return false;
+ }
+
+ if (IsIP6(ip) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+// Check whether the specification of the IPv4 address is correct
+bool IsIpStr4(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ if (StrToIP32(str) == 0 && StrCmpi(str, "0.0.0.0") != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Check whether the specification of the IPv6 address is correct
+bool IsIpStr6(char *str)
+{
+ IP ip;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ if (StrToIP6(&ip, str) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Check whether the IP address specification is correct
+bool IsIpStr46(char *str)
+{
+ if (IsIpStr4(str) || IsIpStr6(str))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+
+// Convert the string to an IPv4 mask
+bool StrToMask4(IP *mask, char *str)
+{
+ // Validate arguments
+ if (mask == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ if (str[0] == '/')
+ {
+ str++;
+ }
+
+ if (IsNum(str))
+ {
+ UINT n = ToInt(str);
+
+ if (n <= 32)
+ {
+ IntToSubnetMask4(mask, n);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (StrToIP(mask, str) == false)
+ {
+ return false;
+ }
+ else
+ {
+ return IsIP4(mask);
+ }
+ }
+}
+
+// Convert the string to an IPv6 mask
+bool StrToMask6(IP *mask, char *str)
+{
+ // Validate arguments
+ if (mask == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ if (str[0] == '/')
+ {
+ str++;
+ }
+
+ if (IsNum(str))
+ {
+ UINT n = ToInt(str);
+
+ if (n <= 128)
+ {
+ IntToSubnetMask6(mask, n);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (StrToIP(mask, str) == false)
+ {
+ return false;
+ }
+ else
+ {
+ return IsIP6(mask);
+ }
+ }
+}
+bool StrToMask6Addr(IPV6_ADDR *mask, char *str)
+{
+ IP ip;
+
+ if (StrToMask6(&ip, str) == false)
+ {
+ return false;
+ }
+
+ if (IPToIPv6Addr(mask, &ip) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Convert the string to an IPv4 / IPv6 mask
+bool StrToMask46(IP *mask, char *str, bool ipv6)
+{
+ if (ipv6)
+ {
+ return StrToMask6(mask, str);
+ }
+ else
+ {
+ return StrToMask4(mask, str);
+ }
+}
+
+
+// Convert the IPv4 / IPv6 mask to a string
+void MaskToStr(char *str, UINT size, IP *mask)
+{
+ MaskToStrEx(str, size, mask, false);
+}
+void MaskToStrEx(char *str, UINT size, IP *mask, bool always_full_address)
+{
+ // Validate arguments
+ if (str == NULL || mask == NULL)
+ {
+ return;
+ }
+
+ if (always_full_address == false && IsSubnetMask(mask))
+ {
+ ToStr(str, SubnetMaskToInt(mask));
+ }
+ else
+ {
+ IPToStr(str, size, mask);
+ }
+}
+void MaskToStr32(char *str, UINT size, UINT mask)
+{
+ MaskToStr32Ex(str, size, mask, false);
+}
+void MaskToStr32Ex(char *str, UINT size, UINT mask, bool always_full_address)
+{
+ IP ip;
+
+ UINTToIP(&ip, mask);
+
+ MaskToStrEx(str, size, &ip, always_full_address);
+}
+void Mask6AddrToStrEx(char *str, UINT size, IPV6_ADDR *mask, bool always_full_address)
+{
+ IP ip;
+
+ // Validate arguments
+ if (str == NULL || mask == NULL)
+ {
+ StrCpy(str, size, "");
+ return;
+ }
+
+ IPv6AddrToIP(&ip, mask);
+
+ MaskToStrEx(str, size, &ip, always_full_address);
+}
+void Mask6AddrToStr(char *str, UINT size, IPV6_ADDR *mask)
+{
+ Mask6AddrToStrEx(str, size, mask, false);
+}
+
+// Disconnecting of the tube
+void TubeDisconnect(TUBE *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (t->TubePairData == NULL)
+ {
+ return;
+ }
+
+ Lock(t->TubePairData->Lock);
+ {
+ t->TubePairData->IsDisconnected = true;
+
+ Set(t->TubePairData->Event1);
+ Set(t->TubePairData->Event2);
+ SetSockEvent(t->TubePairData->SockEvent1);
+ SetSockEvent(t->TubePairData->SockEvent2);
+ }
+ Unlock(t->TubePairData->Lock);
+}
+
+// Creating a tube pair
+void NewTubePair(TUBE **t1, TUBE **t2, UINT size_of_header)
+{
+ TUBEPAIR_DATA *d;
+ // Validate arguments
+ if (t1 == NULL || t2 == NULL)
+ {
+ return;
+ }
+
+ *t1 = NewTube(size_of_header);
+ *t2 = NewTube(size_of_header);
+
+ (*t1)->IndexInTubePair = 0;
+ (*t2)->IndexInTubePair = 1;
+
+ d = NewTubePairData();
+ AddRef(d->Ref);
+
+ (*t1)->TubePairData = d;
+ (*t2)->TubePairData = d;
+
+ d->Event1 = (*t1)->Event;
+ d->Event2 = (*t2)->Event;
+
+ AddRef(d->Event1->ref);
+ AddRef(d->Event2->ref);
+}
+
+// Creating a tube pair data
+TUBEPAIR_DATA *NewTubePairData()
+{
+ TUBEPAIR_DATA *d = ZeroMalloc(sizeof(TUBEPAIR_DATA));
+
+ d->Ref = NewRef();
+
+ d->Lock = NewLock();
+
+ return d;
+}
+
+// Set the SockEvent to the tube
+void SetTubeSockEvent(TUBE *t, SOCK_EVENT *e)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ Lock(t->Lock);
+ {
+ TUBEPAIR_DATA *d;
+
+ if (t->SockEvent != e)
+ {
+ if (t->SockEvent != NULL)
+ {
+ ReleaseSockEvent(t->SockEvent);
+ }
+
+ if (e != NULL)
+ {
+ AddRef(e->ref);
+ }
+
+ t->SockEvent = e;
+ }
+
+ d = t->TubePairData;
+
+ if (d != NULL)
+ {
+ Lock(d->Lock);
+ {
+ SOCK_EVENT **sep = (t->IndexInTubePair == 0 ? &d->SockEvent1 : &d->SockEvent2);
+
+ if (*sep != e)
+ {
+ if (*sep != NULL)
+ {
+ ReleaseSockEvent(*sep);
+ }
+
+ if (e != NULL)
+ {
+ AddRef(e->ref);
+ }
+
+ *sep = e;
+ }
+ }
+ Unlock(d->Lock);
+ }
+ }
+ Unlock(t->Lock);
+}
+
+// Release of the tube pair data
+void ReleaseTubePairData(TUBEPAIR_DATA *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ if (Release(d->Ref) == 0)
+ {
+ CleanupTubePairData(d);
+ }
+}
+void CleanupTubePairData(TUBEPAIR_DATA *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ ReleaseEvent(d->Event1);
+ ReleaseEvent(d->Event2);
+
+ ReleaseSockEvent(d->SockEvent1);
+ ReleaseSockEvent(d->SockEvent2);
+
+ DeleteLock(d->Lock);
+
+ Free(d);
+}
+
+// Check whether the tube is connected to the opponent still
+bool IsTubeConnected(TUBE *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+
+ if (t->TubePairData == NULL)
+ {
+ return true;
+ }
+
+ if (t->TubePairData->IsDisconnected)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Send the data to the tube
+bool TubeSend(TUBE *t, void *data, UINT size, void *header)
+{
+ return TubeSendEx(t, data, size, header, false);
+}
+bool TubeSendEx(TUBE *t, void *data, UINT size, void *header, bool no_flush)
+{
+ return TubeSendEx2(t, data, size, header, no_flush, 0);
+}
+bool TubeSendEx2(TUBE *t, void *data, UINT size, void *header, bool no_flush, UINT max_num_in_queue)
+{
+ // Validate arguments
+ if (t == NULL || data == NULL || size == 0)
+ {
+ return false;
+ }
+
+ if (IsTubeConnected(t) == false)
+ {
+ return false;
+ }
+
+ LockQueue(t->Queue);
+ {
+ if (max_num_in_queue == 0 || (t->Queue->num_item <= max_num_in_queue))
+ {
+ InsertQueue(t->Queue, NewTubeData(data, size, header, t->SizeOfHeader));
+ }
+ else
+ {
+ no_flush = true;
+ }
+ }
+ UnlockQueue(t->Queue);
+
+ if (no_flush == false)
+ {
+ Set(t->Event);
+ SetSockEvent(t->SockEvent);
+ }
+
+ return true;
+}
+
+// Flush the tube
+void TubeFlush(TUBE *t)
+{
+ TubeFlushEx(t, false);
+}
+void TubeFlushEx(TUBE *t, bool force)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (IsTubeConnected(t) == false)
+ {
+ return;
+ }
+
+ if (force == false)
+ {
+ if (t->Queue->num_item == 0)
+ {
+ return;
+ }
+ }
+
+ Set(t->Event);
+ SetSockEvent(t->SockEvent);
+}
+
+// Receive the data from the tube (asynchronous)
+TUBEDATA *TubeRecvAsync(TUBE *t)
+{
+ TUBEDATA *d;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsTubeConnected(t) == false)
+ {
+ return NULL;
+ }
+
+ LockQueue(t->Queue);
+ {
+ d = GetNext(t->Queue);
+ }
+ UnlockQueue(t->Queue);
+
+ return d;
+}
+
+// Get the SockEvent associated with the tube
+SOCK_EVENT *GetTubeSockEvent(TUBE *t)
+{
+ SOCK_EVENT *e = NULL;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ Lock(t->Lock);
+ {
+ if (t->SockEvent != NULL)
+ {
+ AddRef(t->SockEvent->ref);
+
+ e = t->SockEvent;
+ }
+ }
+ Unlock(t->Lock);
+
+ return e;
+}
+
+// Receive the data from the tube (synchronous)
+TUBEDATA *TubeRecvSync(TUBE *t, UINT timeout)
+{
+ UINT64 start_tick, timeout_tick;
+ TUBEDATA *d = NULL;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsTubeConnected(t) == false)
+ {
+ return NULL;
+ }
+
+ start_tick = Tick64();
+ timeout_tick = start_tick + (UINT64)timeout;
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+ UINT remain_time;
+ SOCK_EVENT *e;
+ UINT interval;
+
+ d = NULL;
+
+ if (IsTubeConnected(t) == false)
+ {
+ break;
+ }
+
+ LockQueue(t->Queue);
+ {
+ d = GetNext(t->Queue);
+ }
+ UnlockQueue(t->Queue);
+
+ if (d != NULL)
+ {
+ break;
+ }
+
+ if (timeout != INFINITE && now >= timeout_tick)
+ {
+ return NULL;
+ }
+
+ remain_time = (UINT)(timeout_tick - now);
+
+ e = GetTubeSockEvent(t);
+
+ interval = (timeout == INFINITE ? INFINITE : remain_time);
+
+ if (e == NULL)
+ {
+ Wait(t->Event, interval);
+ }
+ else
+ {
+ WaitSockEvent(e, interval);
+
+ ReleaseSockEvent(e);
+ }
+ }
+
+ return d;
+}
+
+// Creating a tube
+TUBE *NewTube(UINT size_of_header)
+{
+ TUBE *t = ZeroMalloc(sizeof(TUBE));
+
+ t->Event = NewEvent();
+ t->Queue = NewQueue();
+ t->Ref = NewRef();
+ t->Lock = NewLock();
+ t->SockEvent = NewSockEvent();
+
+ t->SizeOfHeader = size_of_header;
+
+ return t;
+}
+
+// Release of the tube
+void ReleaseTube(TUBE *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ if (Release(t->Ref) == 0)
+ {
+ CleanupTube(t);
+ }
+}
+void CleanupTube(TUBE *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ TUBEDATA *d = GetNext(t->Queue);
+ if (d == NULL)
+ {
+ break;
+ }
+
+ FreeTubeData(d);
+ }
+
+ ReleaseQueue(t->Queue);
+ ReleaseEvent(t->Event);
+ ReleaseSockEvent(t->SockEvent);
+
+ ReleaseTubePairData(t->TubePairData);
+
+ DeleteLock(t->Lock);
+
+ Free(t);
+}
+
+// Creating a tube data
+TUBEDATA *NewTubeData(void *data, UINT size, void *header, UINT header_size)
+{
+ TUBEDATA *d;
+ // Validate arguments
+ if (size == 0 || data == NULL)
+ {
+ return NULL;
+ }
+
+ d = ZeroMalloc(sizeof(TUBEDATA));
+
+ d->Data = Clone(data, size);
+ d->DataSize = size;
+ if (header != NULL)
+ {
+ d->Header = Clone(header, header_size);
+ d->HeaderSize = header_size;
+ }
+ else
+ {
+ d->Header = ZeroMalloc(header_size);
+ }
+
+ return d;
+}
+
+// Release of the tube data
+void FreeTubeData(TUBEDATA *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ Free(d->Data);
+ Free(d->Header);
+
+ Free(d);
+}
+
+// Release of the IP address list of the host
+void FreeHostIPAddressList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *ip = LIST_DATA(o, i);
+
+ Free(ip);
+ }
+
+ ReleaseList(o);
+}
+
+// Get whether the specified IP address is held by this host
+bool IsMyIPAddress(IP *ip)
+{
+ LIST *o;
+ UINT i;
+ bool ret = false;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ o = GetHostIPAddressList();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *a = LIST_DATA(o, i);
+
+ if (CmpIpAddr(ip, a) == 0)
+ {
+ ret = true;
+ break;
+ }
+ }
+
+ FreeHostIPAddressList(o);
+
+ return ret;
+}
+
+// Add the IP address to the list
+void AddHostIPAddressToList(LIST *o, IP *ip)
+{
+ IP *r;
+ // Validate arguments
+ if (o == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ r = Search(o, ip);
+ if (r != NULL)
+ {
+ return;
+ }
+
+ Insert(o, Clone(ip, sizeof(IP)));
+}
+
+// Comparison of the IP address list items
+int CmpIpAddressList(void *p1, void *p2)
+{
+ IP *ip1, *ip2;
+ UINT r;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ ip1 = *(IP **)p1;
+ ip2 = *(IP **)p2;
+ if (ip1 == NULL || ip2 == NULL)
+ {
+ return 0;
+ }
+
+ // IPv4 < IPv6
+ r = COMPARE_RET(IsIP6(ip1), IsIP6(ip2));
+ if (r != 0)
+ {
+ return r;
+ }
+
+ // any > specified IP
+ if (IsZeroIP(ip1) && IsZeroIP(ip2) == false)
+ {
+ return 1;
+ }
+ if (IsZeroIP(ip1) == false && IsZeroIP(ip2))
+ {
+ return -1;
+ }
+
+ // local > others
+ if (IsLocalHostIP(ip1) && IsLocalHostIP(ip2) == false)
+ {
+ return 1;
+ }
+ if (IsLocalHostIP(ip1) == false && IsLocalHostIP(ip2))
+ {
+ return -1;
+ }
+
+ // ip address
+ r = CmpIpAddr(ip1, ip2);
+ if (r != 0)
+ {
+ return r;
+ }
+
+ // interface index
+ if (IsIP6(ip1))
+ {
+ r = COMPARE_RET(ip1->ipv6_scope_id, ip2->ipv6_scope_id);
+ }
+ else
+ {
+ r = 0;
+ }
+
+ return r;
+}
+
+// Get the IP address list of the host (using cache)
+LIST *GetHostIPAddressList()
+{
+ LIST *o = NULL;
+ if (host_ip_address_list_cache_lock == NULL)
+ {
+ return GetHostIPAddressListInternal();
+ }
+
+ Lock(host_ip_address_list_cache_lock);
+ {
+ UINT64 now = Tick64();
+
+ if (host_ip_address_list_cache_last == 0 ||
+ ((host_ip_address_list_cache_last + (UINT64)HOST_IP_ADDRESS_LIST_CACHE) < now) ||
+ host_ip_address_cache == NULL)
+ {
+ if (host_ip_address_cache != NULL)
+ {
+ FreeHostIPAddressList(host_ip_address_cache);
+ }
+
+ host_ip_address_cache = GetHostIPAddressListInternal();
+
+ host_ip_address_list_cache_last = now;
+ }
+
+ o = CloneIPAddressList(host_ip_address_cache);
+ }
+ Unlock(host_ip_address_list_cache_lock);
+
+ if (o == NULL)
+ {
+ o = GetHostIPAddressListInternal();
+ }
+
+ return o;
+}
+
+// Copy of the IP address list
+LIST *CloneIPAddressList(LIST *o)
+{
+ LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ ret = NewListFast(CmpIpAddressList);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ IP *ip = LIST_DATA(o, i);
+
+ if (ip != NULL)
+ {
+ ip = Clone(ip, sizeof(IP));
+
+ Add(ret, ip);
+ }
+ }
+
+ return ret;
+}
+
+// Get an IP address list of the host
+LIST *GetHostIPAddressListInternal()
+{
+ char hostname[MAX_SIZE];
+ LIST *o;
+ IP any6, any4;
+ IP local6, local4;
+ bool is_v6_supported = IsIPv6Supported();
+
+ GetLocalHostIP4(&local4);
+ GetLocalHostIP6(&local6);
+
+ ZeroIP4(&any4);
+ ZeroIP6(&any6);
+
+ Zero(hostname, sizeof(hostname));
+
+ gethostname(hostname, sizeof(hostname));
+
+ o = NewListFast(CmpIpAddressList);
+
+ // any
+ AddHostIPAddressToList(o, &any4);
+ if (is_v6_supported)
+ {
+ AddHostIPAddressToList(o, &any6);
+ }
+
+ // localhost
+ AddHostIPAddressToList(o, &local4);
+ if (is_v6_supported)
+ {
+ AddHostIPAddressToList(o, &local6);
+ }
+
+#ifndef MAYAQUA_SUPPORTS_GETIFADDRS
+ // IPv4
+ if (true)
+ {
+ struct sockaddr_in in;
+ struct in_addr addr;
+ struct addrinfo hint;
+ struct addrinfo *info;
+
+ Zero(&hint, sizeof(hint));
+ hint.ai_family = AF_INET;
+ hint.ai_socktype = SOCK_DGRAM;
+ hint.ai_protocol = IPPROTO_UDP;
+ info = NULL;
+
+ if (getaddrinfo(hostname, NULL, &hint, &info) == 0)
+ {
+ if (info->ai_family == AF_INET)
+ {
+ struct addrinfo *current = info;
+ while (current != NULL)
+ {
+ IP ip;
+
+ Copy(&in, current->ai_addr, sizeof(in));
+ Copy(&addr, &in.sin_addr, sizeof(addr));
+
+ InAddrToIP(&ip, &addr);
+ AddHostIPAddressToList(o, &ip);
+
+ current = current->ai_next;
+ }
+ }
+
+ freeaddrinfo(info);
+ }
+ }
+
+#ifndef UNIX_LINUX
+ // IPv6
+ if (is_v6_supported)
+ {
+ struct sockaddr_in6 in;
+ struct in6_addr addr;
+ struct addrinfo hint;
+ struct addrinfo *info;
+
+ Zero(&hint, sizeof(hint));
+ hint.ai_family = AF_INET6;
+ hint.ai_socktype = SOCK_DGRAM;
+ hint.ai_protocol = IPPROTO_UDP;
+ info = NULL;
+
+ if (getaddrinfo(hostname, NULL, &hint, &info) == 0)
+ {
+ if (info->ai_family == AF_INET6)
+ {
+ struct addrinfo *current = info;
+ while (current != NULL)
+ {
+ IP ip;
+
+ Copy(&in, current->ai_addr, sizeof(in));
+ Copy(&addr, &in.sin6_addr, sizeof(addr));
+
+ InAddrToIP6(&ip, &addr);
+ ip.ipv6_scope_id = in.sin6_scope_id;
+
+ AddHostIPAddressToList(o, &ip);
+
+ current = current->ai_next;
+ }
+ }
+
+ freeaddrinfo(info);
+ }
+ }
+#endif // UNIX_LINUX
+#endif // MAYAQUA_SUPPORTS_GETIFADDRS
+
+#ifdef MAYAQUA_SUPPORTS_GETIFADDRS
+ // If the getifaddrs is available, use this
+ if (true)
+ {
+ struct ifaddrs *aa = NULL;
+
+ if (getifaddrs(&aa) == 0)
+ {
+ struct ifaddrs *a = aa;
+
+ while (a != NULL)
+ {
+ if (a->ifa_addr != NULL)
+ {
+ struct sockaddr *addr = a->ifa_addr;
+
+ if (addr->sa_family == AF_INET)
+ {
+ IP ip;
+ struct sockaddr_in *d = (struct sockaddr_in *)addr;
+ struct in_addr *addr = &d->sin_addr;
+
+ InAddrToIP(&ip, addr);
+
+ AddHostIPAddressToList(o, &ip);
+ }
+ else if (addr->sa_family == AF_INET6)
+ {
+ IP ip;
+ struct sockaddr_in6 *d = (struct sockaddr_in6 *)addr;
+ UINT scope_id = d->sin6_scope_id;
+ struct in6_addr *addr = &d->sin6_addr;
+
+ InAddrToIP6(&ip, addr);
+ ip.ipv6_scope_id = scope_id;
+
+ AddHostIPAddressToList(o, &ip);
+ }
+ }
+
+ a = a->ifa_next;
+ }
+
+ freeifaddrs(aa);
+ }
+ }
+#endif // MAYAQUA_SUPPORTS_GETIFADDRS
+
+ return o;
+}
+
+// Get whether the UDP listener opens the specified port
+bool IsUdpPortOpened(UDPLISTENER *u, IP *server_ip, UINT port)
+{
+ UINT i;
+ // Validate arguments
+ if (u == NULL || port == 0)
+ {
+ return false;
+ }
+
+ if (server_ip != NULL)
+ {
+ for (i = 0;i < LIST_NUM(u->SockList);i++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, i);
+
+ if (us->Sock != NULL && us->HasError == false)
+ {
+ if (us->Port == port)
+ {
+ if (CmpIpAddr(server_ip, &us->IpAddress) == 0)
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(u->SockList);i++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, i);
+
+ if (us->Sock != NULL && us->HasError == false)
+ {
+ if (us->Port == port)
+ {
+ if (IsZeroIP(&us->IpAddress))
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+// IP address acquisition thread
+void QueryIpThreadMain(THREAD *thread, void *param)
+{
+ QUERYIPTHREAD *t = (QUERYIPTHREAD *)param;
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ while (t->Halt == false)
+ {
+ UINT next_wait_time = 0;
+ IP ip;
+ bool ok = false;
+
+ if (GetIP4Ex(&ip, t->Hostname, 5000, &t->Halt))
+ {
+ if (IsZeroIP(&ip) == false)
+ {
+ Lock(t->Lock);
+ {
+ Copy(&t->Ip, &ip, sizeof(IP));
+ }
+ Unlock(t->Lock);
+
+ ok = true;
+ }
+ }
+
+ if (ok == false)
+ {
+ next_wait_time = t->IntervalLastNg;
+ }
+ else
+ {
+ next_wait_time = t->IntervalLastOk;
+ }
+
+ if (t->Halt)
+ {
+ break;
+ }
+
+ Wait(t->HaltEvent, next_wait_time);
+ }
+}
+
+// Creating an IP address acquisition thread
+QUERYIPTHREAD *NewQueryIpThread(char *hostname, UINT interval_last_ok, UINT interval_last_ng)
+{
+ QUERYIPTHREAD *t;
+
+ t = ZeroMalloc(sizeof(QUERYIPTHREAD));
+
+ t->HaltEvent = NewEvent();
+ t->Lock = NewLock();
+ StrCpy(t->Hostname, sizeof(t->Hostname), hostname);
+ t->IntervalLastOk = interval_last_ok;
+ t->IntervalLastNg = interval_last_ng;
+
+ t->Thread = NewThread(QueryIpThreadMain, t);
+
+ return t;
+}
+
+// Get the results of the IP address acquisition thread
+bool GetQueryIpThreadResult(QUERYIPTHREAD *t, IP *ip)
+{
+ bool ret = false;
+ Zero(ip, sizeof(IP));
+ // Validate arguments
+ if (t == NULL || ip == NULL)
+ {
+ return false;
+ }
+
+ Lock(t->Lock);
+
+ if (IsZero(&t->Ip, sizeof(IP)))
+ {
+ ret = false;
+ }
+ else
+ {
+ Copy(ip, &t->Ip, sizeof(IP));
+ }
+
+ Unlock(t->Lock);
+
+ return ret;
+}
+
+// Release of the IP address acquisition thread
+void FreeQueryIpThread(QUERYIPTHREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ t->Halt = true;
+ Set(t->HaltEvent);
+
+ WaitThread(t->Thread, INFINITE);
+ ReleaseThread(t->Thread);
+
+ ReleaseEvent(t->HaltEvent);
+
+ DeleteLock(t->Lock);
+
+ Free(t);
+}
+
+// Get a public port list which is known by UDP listener
+void UdpListenerGetPublicPortList(UDPLISTENER *u, char *dst, UINT size)
+{
+ UINT k;
+ // Validate arguments
+ ClearStr(dst, size);
+ if (u == NULL || dst == NULL)
+ {
+ return;
+ }
+
+ LockList(u->PortList);
+ {
+ for (k = 0;k < LIST_NUM(u->SockList);k++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, k);
+
+ if (us->PublicPort != 0)
+ {
+ char tmp[64];
+ ToStr(tmp, us->PublicPort);
+ StrCat(dst, size, tmp);
+ StrCat(dst, size, " ");
+ }
+ }
+ }
+ UnlockList(u->PortList);
+
+ Trim(dst);
+}
+
+// UDP listener thread
+void UdpListenerThread(THREAD *thread, void *param)
+{
+ UDPLISTENER *u = (UDPLISTENER *)param;
+ UINT i, j, k;
+ UINT buf_size = 65536;
+ void *buf;
+ bool cont_flag;
+ BUF *ip_list_buf = NewBuf();
+ // Validate arguments
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ buf = Malloc(buf_size);
+
+ // Initializing the socket list
+ u->SockList = NewList(NULL);
+
+ u->LastCheckTick = 0;
+
+// u->PollMyIpAndPort = true;
+
+ // Main loop
+ while (u->Halt == false)
+ {
+ LIST *recv_list;
+ UINT64 now = Tick64();
+ UINT interval;
+ bool stage_changed = false;
+ IP nat_t_ip;
+ Zero(&nat_t_ip, sizeof(nat_t_ip));
+
+ if (u->LastCheckTick == 0 || (now >= (u->LastCheckTick + UDPLISTENER_CHECK_INTERVAL)))
+ {
+ LIST *iplist;
+ LIST *del_us_list = NewListFast(NULL);
+ BUF *ip_list_buf_new = NewBuf();
+
+ u->LastCheckTick = now;
+
+ // Obtain an IP address list
+ iplist = GetHostIPAddressList();
+
+ LockList(u->PortList);
+ {
+ for (k = 0;k < LIST_NUM(u->SockList);k++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, k);
+
+ us->Mark = false;
+ }
+
+ // If the combination of the IP address and the port number doesn't exist in the list, add it to the list
+ for (i = 0;i < LIST_NUM(iplist);i++)
+ {
+ IP *ip = LIST_DATA(iplist, i);
+
+ WriteBuf(ip_list_buf_new, ip, sizeof(IP));
+
+ for (j = 0;j < LIST_NUM(u->PortList);j++)
+ {
+ UINT k;
+ UINT *port = LIST_DATA(u->PortList, j);
+ bool existing = false;
+
+ if (IsZeroIP(ip) && (IS_SPECIAL_PORT(*port)))
+ {
+ continue;
+ }
+
+
+ for (k = 0;k < LIST_NUM(u->SockList);k++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, k);
+
+ if (CmpIpAddr(&us->IpAddress, ip) == 0 && us->Port == *port)
+ {
+ existing = true;
+
+ us->Mark = true;
+
+ break;
+ }
+ }
+
+ if (existing == false)
+ {
+ UDPLISTENER_SOCK *us = ZeroMalloc(sizeof(UDPLISTENER_SOCK));
+
+ Copy(&us->IpAddress, ip, sizeof(IP));
+ us->Port = *port;
+
+ us->Mark = true;
+
+ Add(u->SockList, us);
+ }
+ }
+ }
+
+ // If any errors suspected or the combination of IP address and port number
+ // has been regarded to delete already, delete it
+ for (k = 0;k < LIST_NUM(u->SockList);k++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, k);
+
+ if (us->Mark == false || us->HasError)
+ {
+ Debug("mark=%u error=%u\n", us->Mark, us->HasError);
+ Add(del_us_list, us);
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(del_us_list);i++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(del_us_list, i);
+
+ char ipstr[MAX_SIZE];
+
+ IPToStr(ipstr, sizeof(ipstr), &us->IpAddress);
+ Debug("Closed UDP Port %u at %s.\n", us->Port, ipstr);
+
+ Delete(u->SockList, us);
+
+ if (us->Sock != NULL)
+ {
+ Disconnect(us->Sock);
+ ReleaseSock(us->Sock);
+ }
+
+ Free(us);
+ }
+ }
+ UnlockList(u->PortList);
+
+ // Open the UDP sockets which is not opend yet
+ for (k = 0;k < LIST_NUM(u->SockList);k++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, k);
+
+ if (us->Sock == NULL)
+ {
+ char ipstr[MAX_SIZE];
+
+ IPToStr(ipstr, sizeof(ipstr), &us->IpAddress);
+
+ if (us->ErrorDebugDisplayed == false)
+ {
+ Debug("Opening UDP Port %u at %s ...", us->Port, ipstr);
+ }
+
+ us->Sock = NewUDPEx2(us->Port, IsIP6(&us->IpAddress), &us->IpAddress);
+
+ if (us->Sock != NULL)
+ {
+ if (us->ErrorDebugDisplayed == false)
+ {
+ Debug("Ok.\n");
+ }
+ else
+ {
+ Debug("Opening UDP Port %u at %s ...", us->Port, ipstr);
+ Debug("Ok.\n");
+ }
+ JoinSockToSockEvent(us->Sock, u->Event);
+
+ us->ErrorDebugDisplayed = false;
+ }
+ else
+ {
+ if (us->ErrorDebugDisplayed == false)
+ {
+ Debug("Error.\n");
+ }
+
+ us->ErrorDebugDisplayed = true;
+ }
+ }
+ }
+
+ FreeHostIPAddressList(iplist);
+
+ ReleaseList(del_us_list);
+
+ if (CompareBuf(ip_list_buf, ip_list_buf_new) == false)
+ {
+ u->HostIPAddressListChanged = true;
+ }
+
+ FreeBuf(ip_list_buf);
+ ip_list_buf = ip_list_buf_new;
+ }
+
+LABEL_RESTART:
+
+ stage_changed = false;
+
+ recv_list = NewListFast(NULL);
+
+ if (u->PollMyIpAndPort)
+ {
+ // Create a thread to get a NAT-T IP address if necessary
+ if (u->GetNatTIpThread == NULL)
+ {
+ char natt_hostname[MAX_SIZE];
+
+ RUDPGetRegisterHostNameByIP(natt_hostname, sizeof(natt_hostname), NULL);
+
+ u->GetNatTIpThread = NewQueryIpThread(natt_hostname, QUERYIPTHREAD_INTERVAL_LAST_OK, QUERYIPTHREAD_INTERVAL_LAST_NG);
+ }
+
+ GetQueryIpThreadResult(u->GetNatTIpThread, &nat_t_ip);
+ }
+
+ // Receive the data that is arriving at the socket
+ for (k = 0;k < LIST_NUM(u->SockList);k++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, k);
+
+ if (us->Sock != NULL)
+ {
+ UINT num_ignore_errors = 0;
+
+ if (u->PollMyIpAndPort && IsZeroIP(&nat_t_ip) == false && IsIP4(&us->IpAddress))
+ {
+ if (us->NextMyIpAndPortPollTick == 0 || us->NextMyIpAndPortPollTick <= now)
+ {
+ UCHAR c = 'A';
+
+ // Examine the self IP address and the self port number by using NAT-T server
+ us->NextMyIpAndPortPollTick = now + (UINT64)GenRandInterval(UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MIN, UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MAX);
+
+ SendTo(us->Sock, &nat_t_ip, UDP_NAT_T_PORT, &c, 1);
+ }
+ }
+
+ while (true)
+ {
+ IP src_addr;
+ UINT src_port;
+ UDPPACKET *p;
+
+ UINT size = RecvFrom(us->Sock, &src_addr, &src_port, buf, buf_size);
+ if (size == 0)
+ {
+ // Socket failure
+ if (us->Sock->IgnoreRecvErr == false)
+ {
+LABEL_FATAL_ERROR:
+ Debug("RecvFrom has Error.\n");
+ us->HasError = true;
+ }
+ else
+ {
+ if ((num_ignore_errors++) >= MAX_NUM_IGNORE_ERRORS)
+ {
+ goto LABEL_FATAL_ERROR;
+ }
+ }
+ break;
+ }
+ else if (size == SOCK_LATER)
+ {
+ // No packet
+ break;
+ }
+ //Debug("UDP %u\n", size);
+
+ if (src_port == UDP_NAT_T_PORT && CmpIpAddr(&src_addr, &nat_t_ip) == 0)
+ {
+ // Receive a packet in which the IP address and the port number are written from the NAT-T server
+ if (size >= 8)
+ {
+ IP my_ip;
+ UINT my_port;
+
+ if (RUDPParseIPAndPortStr(buf, size, &my_ip, &my_port))
+ {
+ Copy(&us->PublicIpAddress, &my_ip, sizeof(IP));
+ us->PublicPort = my_port;
+ }
+ }
+ }
+ else
+ {
+ // Receive a regular packet
+ p = NewUdpPacket(&src_addr, src_port, &us->Sock->LocalIP, us->Sock->LocalPort,
+ Clone(buf, size), size);
+
+ if (p->SrcPort == MAKE_SPECIAL_PORT(52))
+ {
+ p->SrcPort = p->DestPort = MAKE_SPECIAL_PORT(50);
+ }
+
+ Add(recv_list, p);
+ }
+
+ stage_changed = true;
+ }
+ }
+ }
+
+ // Pass the received packet to the procedure
+ u->RecvProc(u, recv_list);
+
+ // Release the packet
+ for (i = 0;i < LIST_NUM(recv_list);i++)
+ {
+ UDPPACKET *p = LIST_DATA(recv_list, i);
+
+ FreeUdpPacket(p);
+ }
+
+ ReleaseList(recv_list);
+
+ cont_flag = true;
+
+ do
+ {
+ // When there are packets to be transmitted, transmit it
+ LockList(u->SendPacketList);
+ {
+ UDPLISTENER_SOCK *last_us = NULL;
+ IP last_src_ip;
+ UINT last_src_port;
+
+ Zero(&last_src_ip, sizeof(IP));
+ last_src_port = 0;
+
+ for (i = 0;i < LIST_NUM(u->SendPacketList);i++)
+ {
+ UDPPACKET *p = LIST_DATA(u->SendPacketList, i);
+ UDPLISTENER_SOCK *us;
+
+ if (last_us != NULL && last_src_port == p->SrcPort && CmpIpAddr(&last_src_ip, &p->SrcIP) == 0)
+ {
+ us = last_us;
+ }
+ else
+ {
+ // Search for a good interface for the transmission
+ us = DetermineUdpSocketForSending(u, p);
+
+ if (us != NULL)
+ {
+ last_us = us;
+ last_src_port = p->SrcPort;
+ Copy(&last_src_ip, &p->SrcIP, sizeof(IP));
+ }
+ }
+
+ if (us != NULL)
+ {
+ // Send
+ UINT ret = SendTo(us->Sock, &p->DstIP, p->DestPort, p->Data, p->Size);
+
+ if (ret == 0)
+ {
+ if (us->Sock->IgnoreSendErr == false)
+ {
+ // Socket failure
+ Debug("SendTo has Error.\n");
+ us->HasError = true;
+ last_us = NULL;
+ }
+ }
+ else
+ {
+ if (ret != SOCK_LATER)
+ {
+ stage_changed = true;
+ }
+ }
+ }
+
+ FreeUdpPacket(p);
+ }
+ DeleteAll(u->SendPacketList);
+ }
+ UnlockList(u->SendPacketList);
+
+ if (LIST_NUM(u->SendPacketList) == 0)
+ {
+ cont_flag = false;
+ }
+ }
+ while (cont_flag);
+
+ if (stage_changed && u->Halt == false)
+ {
+ goto LABEL_RESTART;
+ }
+
+ // Timing adjustment
+ interval = GetNextIntervalForInterrupt(u->Interrupts);
+
+ if (interval == INFINITE)
+ {
+ interval = UDPLISTENER_WAIT_INTERVAL;
+ }
+ else
+ {
+ interval = MIN(UDPLISTENER_WAIT_INTERVAL, interval);
+ }
+
+ if (interval >= 1)
+ {
+ WaitSockEvent(u->Event, interval);
+ }
+ }
+
+ if (u->GetNatTIpThread != NULL)
+ {
+ FreeQueryIpThread(u->GetNatTIpThread);
+ }
+
+ // Release of the socket list
+ for (i = 0;i < LIST_NUM(u->SockList);i++)
+ {
+ UDPLISTENER_SOCK *us = (UDPLISTENER_SOCK *)LIST_DATA(u->SockList, i);
+
+ Disconnect(us->Sock);
+ ReleaseSock(us->Sock);
+
+ Free(us);
+ }
+ ReleaseList(u->SockList);
+
+ FreeBuf(ip_list_buf);
+
+ Free(buf);
+}
+
+// Select the best UDP socket to be used for transmission
+UDPLISTENER_SOCK *DetermineUdpSocketForSending(UDPLISTENER *u, UDPPACKET *p)
+{
+ UINT i;
+ // Validate arguments
+ if (u == NULL || p == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(u->SockList);i++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, i);
+
+ if (us->Sock != NULL && us->HasError == false)
+ {
+ if (us->Port == p->SrcPort)
+ {
+ if (CmpIpAddr(&us->IpAddress, &p->SrcIP) == 0)
+ {
+ return us;
+ }
+ }
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(u->SockList);i++)
+ {
+ UDPLISTENER_SOCK *us = LIST_DATA(u->SockList, i);
+
+ if (us->Sock != NULL && us->HasError == false)
+ {
+ if (us->Port == p->SrcPort)
+ {
+ if (IsZeroIP(&us->IpAddress))
+ {
+ if ((IsIP4(&p->DstIP) && IsIP4(&us->IpAddress)) ||
+ (IsIP6(&p->DstIP) && IsIP6(&us->IpAddress)))
+ {
+ return us;
+ }
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// Release of the UDP packet
+void FreeUdpPacket(UDPPACKET *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ Free(p->Data);
+ Free(p);
+}
+
+// Create a new UDP packet
+UDPPACKET *NewUdpPacket(IP *src_ip, UINT src_port, IP *dst_ip, UINT dst_port, void *data, UINT size)
+{
+ UDPPACKET *p;
+ // Validate arguments
+ if (data == NULL || size == 0 || dst_ip == NULL || dst_port == 0)
+ {
+ return NULL;
+ }
+
+ p = ZeroMalloc(sizeof(UDPPACKET));
+
+ p->Data = data;
+ p->Size = size;
+
+ Copy(&p->SrcIP, src_ip, sizeof(IP));
+ p->SrcPort = src_port;
+
+ Copy(&p->DstIP, dst_ip, sizeof(IP));
+ p->DestPort = dst_port;
+
+ return p;
+}
+
+// Transmit the packets via UDP Listener
+void UdpListenerSendPackets(UDPLISTENER *u, LIST *packet_list)
+{
+ UINT num = 0;
+ // Validate arguments
+ if (u == NULL || packet_list == NULL)
+ {
+ return;
+ }
+
+ LockList(u->SendPacketList);
+ {
+ UINT i;
+
+ num = LIST_NUM(packet_list);
+
+ for (i = 0;i < LIST_NUM(packet_list);i++)
+ {
+ UDPPACKET *p = LIST_DATA(packet_list, i);
+
+ Add(u->SendPacketList, p);
+ }
+ }
+ UnlockList(u->SendPacketList);
+
+ if (num >= 1)
+ {
+ SetSockEvent(u->Event);
+ }
+}
+void UdpListenerSendPacket(UDPLISTENER *u, UDPPACKET *packet)
+{
+ LIST *o;
+ // Validate arguments
+ if (u == NULL || packet == NULL)
+ {
+ return;
+ }
+
+ o = NewListFast(NULL);
+ Add(o, packet);
+
+ UdpListenerSendPackets(u, o);
+
+ ReleaseList(o);
+}
+
+// Creating a UDP listener
+UDPLISTENER *NewUdpListener(UDPLISTENER_RECV_PROC *recv_proc, void *param)
+{
+ UDPLISTENER *u;
+ // Validate arguments
+ if (recv_proc == NULL)
+ {
+ return NULL;
+ }
+
+ u = ZeroMalloc(sizeof(UDPLISTENER));
+
+ u->Param = param;
+
+ u->PortList = NewList(NULL);
+ u->Event = NewSockEvent();
+
+ u->RecvProc = recv_proc;
+ u->SendPacketList = NewList(NULL);
+
+ u->Interrupts = NewInterruptManager();
+
+ u->Thread = NewThread(UdpListenerThread, u);
+
+ return u;
+}
+
+// Release the UDP listener
+void FreeUdpListener(UDPLISTENER *u)
+{
+ UINT i;
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ u->Halt = true;
+ SetSockEvent(u->Event);
+
+ WaitThread(u->Thread, INFINITE);
+ ReleaseThread(u->Thread);
+ ReleaseSockEvent(u->Event);
+
+ ReleaseIntList(u->PortList);
+
+ for (i = 0;i < LIST_NUM(u->SendPacketList);i++)
+ {
+ UDPPACKET *p = LIST_DATA(u->SendPacketList, i);
+
+ FreeUdpPacket(p);
+ }
+
+ ReleaseList(u->SendPacketList);
+
+ FreeInterruptManager(u->Interrupts);
+
+ Free(u);
+}
+
+// Add the UDP port
+void AddPortToUdpListener(UDPLISTENER *u, UINT port)
+{
+ // Validate arguments
+ if (u == NULL || port == 0)
+ {
+ return;
+ }
+
+ LockList(u->PortList);
+ {
+ AddIntDistinct(u->PortList, port);
+ }
+ UnlockList(u->PortList);
+
+ SetSockEvent(u->Event);
+}
+
+// Get the port list
+UINT GetUdpListenerPortList(UDPLISTENER *u, UINT **port_list)
+{
+ UINT num_ports;
+ // Validate arguments
+ if (u == NULL || port_list == NULL)
+ {
+ return 0;
+ }
+
+ LockList(u->PortList);
+ {
+ UINT *ports;
+ UINT i;
+
+ num_ports = LIST_NUM(u->PortList);
+ ports = ZeroMalloc(sizeof(UINT) * num_ports);
+
+ for (i = 0;i < num_ports;i++)
+ {
+ ports[i] = *((UINT *)(LIST_DATA(u->PortList, i)));
+ }
+
+ *port_list = ports;
+ }
+ UnlockList(u->PortList);
+
+ return num_ports;
+}
+
+// Dekete all the UDP ports
+void DeleteAllPortFromUdpListener(UDPLISTENER *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ LockList(u->PortList);
+ {
+ UINT num_ports = LIST_NUM(u->PortList);
+ UINT *ports = ZeroMalloc(sizeof(UINT) * num_ports);
+ UINT i;
+
+ for (i = 0;i < num_ports;i++)
+ {
+ ports[i] = *((UINT *)(LIST_DATA(u->PortList, i)));
+ }
+
+ for (i = 0;i < num_ports;i++)
+ {
+ UINT port = ports[i];
+
+ DelInt(u->PortList, port);
+ }
+
+ Free(ports);
+ }
+ UnlockList(u->PortList);
+
+ SetSockEvent(u->Event);
+}
+
+// Delete the UDP port
+void DeletePortFromUdpListener(UDPLISTENER *u, UINT port)
+{
+ // Validate arguments
+ if (u == NULL || port == 0)
+ {
+ return;
+ }
+
+ LockList(u->PortList);
+ {
+ DelInt(u->PortList, port);
+ }
+ UnlockList(u->PortList);
+
+ SetSockEvent(u->Event);
+}
+
+// Sort function of the interrupt management list
+int CmpInterruptManagerTickList(void *p1, void *p2)
+{
+ UINT64 *v1, *v2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+
+ v1 = *(UINT64 **)p1;
+ v2 = *(UINT64 **)p2;
+ if (v1 == NULL || v2 == NULL)
+ {
+ return 0;
+ }
+
+ if (*v1 > *v2)
+ {
+ return 1;
+ }
+ else if (*v1 < *v2)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// Initialization of the interrupt management
+INTERRUPT_MANAGER *NewInterruptManager()
+{
+ INTERRUPT_MANAGER *m = ZeroMalloc(sizeof(INTERRUPT_MANAGER));
+
+ m->TickList = NewList(CmpInterruptManagerTickList);
+
+ return m;
+}
+
+// Release of the interrupt management
+void FreeInterruptManager(INTERRUPT_MANAGER *m)
+{
+ UINT i;
+ // Validate arguments
+ if (m == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(m->TickList);i++)
+ {
+ UINT64 *v = LIST_DATA(m->TickList, i);
+
+ Free(v);
+ }
+
+ ReleaseList(m->TickList);
+
+ Free(m);
+}
+
+// Add a number to the interrupt management
+void AddInterrupt(INTERRUPT_MANAGER *m, UINT64 tick)
+{
+ // Validate arguments
+ if (tick == 0)
+ {
+ return;
+ }
+
+ LockList(m->TickList);
+ {
+ if (Search(m->TickList, &tick) == NULL)
+ {
+ Insert(m->TickList, Clone(&tick, sizeof(UINT64)));
+ }
+ }
+ UnlockList(m->TickList);
+}
+
+// Get the interval to the next calling
+UINT GetNextIntervalForInterrupt(INTERRUPT_MANAGER *m)
+{
+ UINT ret = INFINITE;
+ UINT i;
+ LIST *o = NULL;
+ UINT64 now = Tick64();
+ // Validate arguments
+ if (m == NULL)
+ {
+ return 0;
+ }
+
+ LockList(m->TickList);
+ {
+ // Remove entries older than now already
+ for (i = 0;i < LIST_NUM(m->TickList);i++)
+ {
+ UINT64 *v = LIST_DATA(m->TickList, i);
+
+ if (now >= *v)
+ {
+ ret = 0;
+
+ if (o == NULL)
+ {
+ o = NewListFast(NULL);
+ }
+
+ Add(o, v);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ UINT64 *v = LIST_DATA(o, i);
+
+ Free(v);
+
+ Delete(m->TickList, v);
+ }
+
+ if (o != NULL)
+ {
+ ReleaseList(o);
+ }
+
+ if (ret == INFINITE)
+ {
+ if (LIST_NUM(m->TickList) >= 1)
+ {
+ UINT64 *v = LIST_DATA(m->TickList, 0);
+
+ ret = (UINT)(*v - now);
+ }
+ }
+ }
+ UnlockList(m->TickList);
+
+ return ret;
+}
+
+// Let that the listening socket for the reverse socket to accept the new socket
+void InjectNewReverseSocketToAccept(SOCK *listen_sock, SOCK *s, IP *client_ip, UINT client_port)
+{
+ bool ok = false;
+ // Validate arguments
+ if (listen_sock == NULL || s == NULL)
+ {
+ return;
+ }
+
+ LockQueue(listen_sock->ReverseAcceptQueue);
+ {
+ if (listen_sock->CancelAccept == false && listen_sock->Disconnecting == false)
+ {
+ InsertQueue(listen_sock->ReverseAcceptQueue, s);
+
+ ok = true;
+
+ s->ServerMode = true;
+ s->IsReverseAcceptedSocket = true;
+
+ Copy(&s->RemoteIP, client_ip, sizeof(IP));
+ s->RemotePort = client_port;
+ }
+ }
+ UnlockQueue(listen_sock->ReverseAcceptQueue);
+
+ if (ok == false)
+ {
+ Disconnect(s);
+ ReleaseSock(s);
+ }
+ else
+ {
+ Set(listen_sock->ReverseAcceptEvent);
+ }
+}
+
+// Create a listening socket for the reverse socket
+SOCK *ListenReverse()
+{
+ SOCK *s = NewSock();
+
+ s->Type = SOCK_REVERSE_LISTEN;
+ s->ListenMode = true;
+ s->ReverseAcceptQueue = NewQueue();
+ s->ReverseAcceptEvent = NewEvent();
+ s->Connected = true;
+
+ return s;
+}
+
+// Accept on the reverse socket
+SOCK *AcceptReverse(SOCK *s)
+{
+ // Validate arguments
+ if (s == NULL || s->Type != SOCK_REVERSE_LISTEN || s->ListenMode == false)
+ {
+ return NULL;
+ }
+
+ while (true)
+ {
+ SOCK *ret;
+ if (s->Disconnecting || s->CancelAccept)
+ {
+ return NULL;
+ }
+
+ LockQueue(s->ReverseAcceptQueue);
+ {
+ ret = GetNext(s->ReverseAcceptQueue);
+ }
+ UnlockQueue(s->ReverseAcceptQueue);
+
+ if (ret != NULL)
+ {
+ StrCpy(ret->UnderlayProtocol, sizeof(ret->UnderlayProtocol), SOCK_UNDERLAY_AZURE);
+
+ return ret;
+ }
+
+ Wait(s->ReverseAcceptEvent, INFINITE);
+ }
+}
+
+// Start listening on the in-process socket
+SOCK *ListenInProc()
+{
+ SOCK *s = NewSock();
+
+ s->Type = SOCK_INPROC;
+ s->ListenMode = true;
+ s->InProcAcceptQueue = NewQueue();
+ s->InProcAcceptEvent = NewEvent();
+ s->Connected = true;
+
+ return s;
+}
+
+// Accept at the in-process socket
+SOCK *AcceptInProc(SOCK *s)
+{
+ // Validate arguments
+ if (s == NULL || s->Type != SOCK_INPROC || s->ListenMode == false)
+ {
+ return NULL;
+ }
+
+ while (true)
+ {
+ SOCK *ret;
+ if (s->Disconnecting || s->CancelAccept)
+ {
+ return NULL;
+ }
+
+ LockQueue(s->InProcAcceptQueue);
+ {
+ ret = GetNext(s->InProcAcceptQueue);
+ }
+ UnlockQueue(s->InProcAcceptQueue);
+
+ if (ret != NULL)
+ {
+ StrCpy(ret->UnderlayProtocol, sizeof(ret->UnderlayProtocol), SOCK_UNDERLAY_INPROC);
+
+ return ret;
+ }
+
+ Wait(s->InProcAcceptEvent, INFINITE);
+ }
+}
+
+// Connect by the in-process socket
+SOCK *ConnectInProc(SOCK *listen_sock, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port)
+{
+ SOCK *ss, *sc;
+ bool ok = false;
+ // Validate arguments
+ if (listen_sock == NULL || listen_sock->Type != SOCK_INPROC || listen_sock->ListenMode == false)
+ {
+ return NULL;
+ }
+
+ NewSocketPair(&sc, &ss, client_ip, client_port, server_ip, server_port);
+
+ LockQueue(listen_sock->InProcAcceptQueue);
+ {
+ if (listen_sock->CancelAccept == false && listen_sock->Disconnecting == false)
+ {
+ InsertQueue(listen_sock->InProcAcceptQueue, ss);
+
+ ok = true;
+ }
+ }
+ UnlockQueue(listen_sock->InProcAcceptQueue);
+
+ if (ok == false)
+ {
+ ReleaseSock(ss);
+ ReleaseSock(sc);
+ return NULL;
+ }
+
+ Set(listen_sock->InProcAcceptEvent);
+
+ return sc;
+}
+
+// Creating a new socket pair
+void NewSocketPair(SOCK **client, SOCK **server, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port)
+{
+ IP iptmp;
+ TUBE *t1, *t2;
+ SOCK *sc, *ss;
+ SOCK_EVENT *e1, *e2;
+ // Validate arguments
+ if (client == NULL || server == NULL)
+ {
+ return;
+ }
+
+ SetIP(&iptmp, 127, 0, 0, 1);
+ if (client_ip == NULL)
+ {
+ client_ip = &iptmp;
+ }
+ if (server_ip == NULL)
+ {
+ server_ip = &iptmp;
+ }
+
+ // Creating a tube
+ NewTubePair(&t1, &t2, 0); // t1: C -> S, t2: S -> C
+
+ // Creating a socket event
+ e1 = NewSockEvent();
+ e2 = NewSockEvent();
+
+ SetTubeSockEvent(t1, e1);
+ SetTubeSockEvent(t2, e2);
+
+ sc = NewInProcSocket(t1, t2);
+ ss = NewInProcSocket(t2, t1);
+
+ Copy(&sc->LocalIP, client_ip, sizeof(IP));
+ sc->LocalPort = client_port;
+ Copy(&sc->RemoteIP, server_ip, sizeof(IP));
+ sc->RemotePort = server_port;
+
+ Copy(&ss->LocalIP, server_ip, sizeof(IP));
+ ss->LocalPort = server_port;
+ Copy(&ss->RemoteIP, client_ip, sizeof(IP));
+ ss->RemotePort = client_port;
+
+ sc->Connected = true;
+ sc->ServerMode = false;
+
+ ss->Connected = true;
+ ss->ServerMode = true;
+
+ SetTimeout(sc, INFINITE);
+ SetTimeout(ss, INFINITE);
+
+ QuerySocketInformation(sc);
+ QuerySocketInformation(ss);
+
+ ReleaseSockEvent(e1);
+ ReleaseSockEvent(e2);
+
+ ReleaseTube(t1);
+ ReleaseTube(t2);
+
+ *client = sc;
+ *server = ss;
+}
+
+// Creating a new in-process socket
+SOCK *NewInProcSocket(TUBE *tube_send, TUBE *tube_recv)
+{
+ SOCK *s;
+ // Validate arguments
+ if (tube_recv == NULL || tube_send == NULL)
+ {
+ return NULL;
+ }
+
+ s = NewSock();
+
+ s->Type = SOCK_INPROC;
+
+ s->SendTube = tube_send;
+ s->RecvTube = tube_recv;
+
+ AddRef(tube_send->Ref);
+ AddRef(tube_recv->Ref);
+
+ s->InProcRecvFifo = NewFifo();
+
+ s->Connected = true;
+
+ return s;
+}
+
+// Transmission process for the in-process socket
+UINT SendInProc(SOCK *sock, void *data, UINT size)
+{
+ if (sock == NULL || sock->Type != SOCK_INPROC || sock->Disconnecting || sock->Connected == false)
+ {
+ return 0;
+ }
+
+ if (IsTubeConnected(sock->SendTube) == false)
+ {
+ return 0;
+ }
+
+ if (TubeSend(sock->SendTube, data, size, NULL) == false)
+ {
+ return 0;
+ }
+
+ return size;
+}
+
+// Receiving process for the in-process socket
+UINT RecvInProc(SOCK *sock, void *data, UINT size)
+{
+ FIFO *f;
+ UINT ret;
+ UINT timeout;
+ UINT64 giveup_time;
+ TUBEDATA *d = NULL;
+ if (sock == NULL || sock->Type != SOCK_INPROC || sock->Disconnecting || sock->Connected == false)
+ {
+ return 0;
+ }
+
+ if (IsTubeConnected(sock->SendTube) == false)
+ {
+ return 0;
+ }
+
+ f = sock->InProcRecvFifo;
+ if (f == NULL)
+ {
+ return 0;
+ }
+
+ // If there is data in the FIFO, return it immediately
+ ret = ReadFifo(f, data, size);
+ if (ret != 0)
+ {
+ return ret;
+ }
+
+ timeout = GetTimeout(sock);
+
+ giveup_time = Tick64() + (UINT)timeout;
+
+ // When there is no data in the FIFO, read the next data from the tube
+ d = NULL;
+
+ while (true)
+ {
+ UINT64 now = 0;
+ UINT interval;
+
+ if (sock->AsyncMode == false)
+ {
+ now = Tick64();
+
+ if (now >= giveup_time)
+ {
+ break;
+ }
+ }
+
+ d = TubeRecvAsync(sock->RecvTube);
+
+ if (d != NULL)
+ {
+ break;
+ }
+
+ if (IsTubeConnected(sock->RecvTube) == false)
+ {
+ break;
+ }
+
+ if (sock->AsyncMode)
+ {
+ break;
+ }
+
+ interval = (UINT)(giveup_time - now);
+
+ Wait(sock->RecvTube->Event, interval);
+ }
+
+ if (d == NULL)
+ {
+ if (IsTubeConnected(sock->RecvTube) == false)
+ {
+ return 0;
+ }
+
+ if (sock->AsyncMode == false)
+ {
+ // If a timeout occurs in synchronous mode, disconnect ir
+ Disconnect(sock);
+
+ return 0;
+ }
+ else
+ {
+ // If a timeout occurs in asynchronous mode, returns the blocking error
+ return SOCK_LATER;
+ }
+ }
+ else
+ {
+ // If the received data is larger than the requested size, write the rest to FIFO
+ if (d->DataSize > size)
+ {
+ WriteFifo(f, ((UCHAR *)d->Data) + size, d->DataSize - size);
+ ret = size;
+ }
+ else
+ {
+ ret = d->DataSize;
+ }
+
+ Copy(data, d->Data, ret);
+
+ FreeTubeData(d);
+
+ return ret;
+ }
+}
+
+// Wait for the arrival of data on multiple tubes
+void WaitForTubes(TUBE **tubes, UINT num, UINT timeout)
+{
+ // Validate arguments
+ if (num != 0 && tubes == NULL)
+ {
+ return;
+ }
+ if (timeout == 0)
+ {
+ return;
+ }
+ if (num == 0)
+ {
+ SleepThread(timeout);
+ return;
+ }
+
+#ifdef OS_WIN32
+ Win32WaitForTubes(tubes, num, timeout);
+#else // OS_WIN32
+ UnixWaitForTubes(tubes, num, timeout);
+#endif // OS_WIN32
+}
+
+#ifdef OS_WIN32
+void Win32WaitForTubes(TUBE **tubes, UINT num, UINT timeout)
+{
+ HANDLE array[MAXIMUM_WAIT_OBJECTS];
+ UINT i;
+
+ Zero(array, sizeof(array));
+
+ for (i = 0;i < num;i++)
+ {
+ TUBE *t = tubes[i];
+
+ array[i] = t->Event->pData;
+ }
+
+ if (num == 1)
+ {
+ WaitForSingleObject(array[0], timeout);
+ }
+ else
+ {
+ WaitForMultipleObjects(num, array, false, timeout);
+ }
+}
+#else // OS_WIN32
+void UnixWaitForTubes(TUBE **tubes, UINT num, UINT timeout)
+{
+ int *fds;
+ UINT i;
+ char tmp[MAX_SIZE];
+ bool any_of_tubes_are_readable = false;
+
+ fds = ZeroMalloc(sizeof(int) * num);
+
+ for (i = 0;i < num;i++)
+ {
+ fds[i] = tubes[i]->SockEvent->pipe_read;
+
+ if (tubes[i]->SockEvent->current_pipe_data != 0)
+ {
+ any_of_tubes_are_readable = true;
+ }
+ }
+
+ if (any_of_tubes_are_readable == false)
+ {
+ UnixSelectInner(num, fds, 0, NULL, timeout);
+ }
+
+ for (i = 0;i < num;i++)
+ {
+ int fd = fds[i];
+ int readret;
+
+ tubes[i]->SockEvent->current_pipe_data = 0;
+
+ do
+ {
+ readret = read(fd, tmp, sizeof(tmp));
+ }
+ while (readret >= 1);
+ }
+
+ Free(fds);
+}
+#endif // OS_WIN32
+
+// Creating a Tube Flush List
+TUBE_FLUSH_LIST *NewTubeFlushList()
+{
+ TUBE_FLUSH_LIST *f = ZeroMalloc(sizeof(TUBE_FLUSH_LIST));
+
+ f->List = NewListFast(NULL);
+
+ return f;
+}
+
+// Release of the Tube Flush List
+void FreeTubeFlushList(TUBE_FLUSH_LIST *f)
+{
+ UINT i;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(f->List);i++)
+ {
+ TUBE *t = LIST_DATA(f->List, i);
+
+ ReleaseTube(t);
+ }
+
+ ReleaseList(f->List);
+
+ Free(f);
+}
+
+// Add a Tube to the Tube Flush List
+void AddTubeToFlushList(TUBE_FLUSH_LIST *f, TUBE *t)
+{
+ // Validate arguments
+ if (f == NULL || t == NULL)
+ {
+ return;
+ }
+
+ if (t->IsInFlushList)
+ {
+ return;
+ }
+
+ if (IsInList(f->List, t) == false)
+ {
+ Add(f->List, t);
+
+ AddRef(t->Ref);
+
+ t->IsInFlushList = true;
+ }
+}
+
+// Flush the all tubes in the Tube Flush List
+void FlushTubeFlushList(TUBE_FLUSH_LIST *f)
+{
+ UINT i;
+ // Validate arguments
+ if (f == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(f->List);i++)
+ {
+ TUBE *t = LIST_DATA(f->List, i);
+
+ TubeFlush(t);
+ t->IsInFlushList = false;
+
+ ReleaseTube(t);
+ }
+
+ DeleteAll(f->List);
+}
+
+// The server receives a PACK from the client
+PACK *HttpServerRecv(SOCK *s)
+{
+ BUF *b;
+ PACK *p;
+ HTTP_HEADER *h;
+ UINT size;
+ UCHAR *tmp;
+ HTTP_VALUE *v;
+ UINT num_noop = 0;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+START:
+
+ h = RecvHttpHeader(s);
+ if (h == NULL)
+ {
+ goto BAD_REQUEST;
+ }
+
+ if (StrCmpi(h->Method, "POST") != 0 ||
+ StrCmpi(h->Target, HTTP_VPN_TARGET) != 0 ||
+ StrCmpi(h->Version, "HTTP/1.1") != 0)
+ {
+ FreeHttpHeader(h);
+ goto BAD_REQUEST;
+ }
+
+ v = GetHttpValue(h, "Content-Type");
+ if (v == NULL || StrCmpi(v->Data, HTTP_CONTENT_TYPE2) != 0)
+ {
+ FreeHttpHeader(h);
+ goto BAD_REQUEST;
+ }
+
+ size = GetContentLength(h);
+ if (size == 0 || size > HTTP_PACK_MAX_SIZE)
+ {
+ FreeHttpHeader(h);
+ goto BAD_REQUEST;
+ }
+
+ tmp = MallocEx(size, true);
+ if (RecvAll(s, tmp, size, s->SecureMode) == false)
+ {
+ Free(tmp);
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size);
+ Free(tmp);
+ FreeHttpHeader(h);
+
+ SeekBuf(b, 0, 0);
+ p = BufToPack(b);
+ FreeBuf(b);
+
+ // Determine whether it's a NOOP
+ if (PackGetInt(p, "noop") != 0)
+ {
+ Debug("recv: noop\n");
+ FreePack(p);
+
+ p = PackError(0);
+ PackAddInt(p, "noop", 1);
+ if (HttpServerSend(s, p) == false)
+ {
+ FreePack(p);
+ return NULL;
+ }
+
+ FreePack(p);
+
+ num_noop++;
+
+ if (num_noop > MAX_NOOP_PER_SESSION)
+ {
+ return NULL;
+ }
+
+ goto START;
+ }
+
+ return p;
+
+BAD_REQUEST:
+ // Return an error
+
+
+ return NULL;
+}
+
+// Store the error value into PACK
+PACK *PackError(UINT error)
+{
+ PACK *p;
+
+ p = NewPack();
+ PackAddInt(p, "error", error);
+
+ return p;
+}
+
+// Get the error value from PACK
+UINT GetErrorFromPack(PACK *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return 0;
+ }
+
+ return PackGetInt(p, "error");
+}
+
+// Client receives a PACK from the server
+PACK *HttpClientRecv(SOCK *s)
+{
+ BUF *b;
+ PACK *p;
+ HTTP_HEADER *h;
+ UINT size;
+ UCHAR *tmp;
+ HTTP_VALUE *v;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ h = RecvHttpHeader(s);
+ if (h == NULL)
+ {
+ return NULL;
+ }
+
+ if (StrCmpi(h->Method, "HTTP/1.1") != 0 ||
+ StrCmpi(h->Target, "200") != 0)
+ {
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ v = GetHttpValue(h, "Content-Type");
+ if (v == NULL || StrCmpi(v->Data, HTTP_CONTENT_TYPE2) != 0)
+ {
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ size = GetContentLength(h);
+ if (size == 0 || size > MAX_PACK_SIZE)
+ {
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ tmp = MallocEx(size, true);
+ if (RecvAll(s, tmp, size, s->SecureMode) == false)
+ {
+ Free(tmp);
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size);
+ Free(tmp);
+ FreeHttpHeader(h);
+
+ SeekBuf(b, 0, 0);
+ p = BufToPack(b);
+ FreeBuf(b);
+
+ return p;
+}
+
+// Create an entry to PACK for the dummy
+void CreateDummyValue(PACK *p)
+{
+ UINT size;
+ UCHAR *buf;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ size = Rand32() % HTTP_PACK_RAND_SIZE_MAX;
+ buf = Malloc(size);
+ Rand(buf, size);
+
+ PackAddData(p, "pencore", buf, size);
+
+ Free(buf);
+}
+
+// Client send a PACK to the server
+bool HttpClientSend(SOCK *s, PACK *p)
+{
+ BUF *b;
+ bool ret;
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ CreateDummyValue(p);
+
+ b = PackToBuf(p);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ h = NewHttpHeader("POST", HTTP_VPN_TARGET, "HTTP/1.1");
+
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE2));
+
+ ret = PostHttp(s, h, b->Buf, b->Size);
+
+ FreeHttpHeader(h);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Server sends a PACK to the client
+bool HttpServerSend(SOCK *s, PACK *p)
+{
+ BUF *b;
+ bool ret;
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ // Validate arguments
+ if (s == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ CreateDummyValue(p);
+
+ b = PackToBuf(p);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ h = NewHttpHeader("HTTP/1.1", "200", "OK");
+
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE2));
+
+ ret = PostHttp(s, h, b->Buf, b->Size);
+
+ FreeHttpHeader(h);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Replace unsafe characters in target
+void ReplaceUnsafeCharInTarget(char *target){
+ UINT i;
+ for(i = 0; target[i] ; i++) {
+ if(target[i] == '<')
+ target[i] = '(';
+ else if(target[i] == '>')
+ target[i] = ')';
+ }
+}
+
+// Sending the 501 Not Implemented error
+bool HttpSendNotImplemented(SOCK *s, char *method, char *target, char *version)
+{
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ char *str;
+ UINT str_size;
+ char port_str[MAX_SIZE];
+ bool ret;
+ char host[MAX_SIZE];
+ UINT port;
+ // Validate arguments
+ if (s == NULL || target == NULL)
+ {
+ return false;
+ }
+
+ // Get the host name
+ //GetMachineName(host, MAX_SIZE);
+ Zero(host, sizeof(host));
+ IPToStr(host, sizeof(host), &s->LocalIP);
+ // Get the port number
+ port = s->LocalPort;
+
+ // Creating a header
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+
+ h = NewHttpHeader("HTTP/1.1", "501", "Method Not Implemented");
+
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
+
+ // Creating a Data
+ str_size = sizeof(http_501_str) * 2 + StrLen(target) + StrLen(host) + StrLen(method) + StrLen(version);
+ str = Malloc(str_size);
+ StrCpy(str, str_size, http_501_str);
+
+ // TARGET
+ ReplaceUnsafeCharInTarget(target);
+ ReplaceStri(str, str_size, str, "$TARGET$", target);
+
+ // HOST
+ ReplaceStri(str, str_size, str, "$HOST$", host);
+
+ // PORT
+ ToStr(port_str, port);
+ ReplaceStri(str, str_size, str, "$PORT$", port_str);
+
+ // METHOD
+ ReplaceStri(str, str_size, str, "$METHOD$", method);
+
+ // VERSION
+ ReplaceStri(str, str_size, str, "$VERSION$", version);
+
+ // Transmission
+ ret = PostHttp(s, h, str, StrLen(str));
+
+ FreeHttpHeader(h);
+ Free(str);
+
+ return ret;
+}
+
+// Sending a 404 Not Found error
+bool HttpSendNotFound(SOCK *s, char *target)
+{
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ char *str;
+ UINT str_size;
+ char port_str[MAX_SIZE];
+ bool ret;
+ char host[MAX_SIZE];
+ UINT port;
+ // Validate arguments
+ if (s == NULL || target == NULL)
+ {
+ return false;
+ }
+
+ // Get the host name
+ //GetMachineName(host, MAX_SIZE);
+ Zero(host, sizeof(host));
+ IPToStr(host, sizeof(host), &s->LocalIP);
+ // Get the port number
+ port = s->LocalPort;
+
+ // Creating a header
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+
+ h = NewHttpHeader("HTTP/1.1", "404", "Not Found");
+
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
+
+ // Creating a Data
+ str_size = sizeof(http_404_str) * 2 + StrLen(target) + StrLen(host);
+ str = Malloc(str_size);
+ StrCpy(str, str_size, http_404_str);
+
+ // TARGET
+ ReplaceUnsafeCharInTarget(target);
+ ReplaceStri(str, str_size, str, "$TARGET$", target);
+
+ // HOST
+ ReplaceStri(str, str_size, str, "$HOST$", host);
+
+ // PORT
+ ToStr(port_str, port);
+ ReplaceStri(str, str_size, str, "$PORT$", port_str);
+
+ // Transmission
+ ret = PostHttp(s, h, str, StrLen(str));
+
+ FreeHttpHeader(h);
+ Free(str);
+
+ return ret;
+}
+
+// Sending a 500 Server Error
+bool HttpSendServerError(SOCK *s, char *target)
+{
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ char *str;
+ UINT str_size;
+ char port_str[MAX_SIZE];
+ bool ret;
+ char host[MAX_SIZE];
+ UINT port;
+ // Validate arguments
+ if (s == NULL || target == NULL)
+ {
+ return false;
+ }
+
+ // Get the host name
+ //GetMachineName(host, MAX_SIZE);
+ Zero(host, sizeof(host));
+ IPToStr(host, sizeof(host), &s->LocalIP);
+ // Get the port number
+ port = s->LocalPort;
+
+ // Creating a header
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+
+ h = NewHttpHeader("HTTP/1.1", "500", "Server Error");
+
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
+
+ // Creating a Data
+ str_size = sizeof(http_500_str) * 2 + StrLen(target) + StrLen(host);
+ str = Malloc(str_size);
+ StrCpy(str, str_size, http_500_str);
+
+ // TARGET
+ ReplaceUnsafeCharInTarget(target);
+ ReplaceStri(str, str_size, str, "$TARGET$", target);
+
+ // HOST
+ ReplaceStri(str, str_size, str, "$HOST$", host);
+
+ // PORT
+ ToStr(port_str, port);
+ ReplaceStri(str, str_size, str, "$PORT$", port_str);
+
+ // Transmission
+ ret = PostHttp(s, h, str, StrLen(str));
+
+ FreeHttpHeader(h);
+ Free(str);
+
+ return ret;
+}
+
+// Sending a 403 Forbidden error
+bool HttpSendForbidden(SOCK *s, char *target, char *server_id)
+{
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ char *str;
+ UINT str_size;
+ char port_str[MAX_SIZE];
+ bool ret;
+ char host[MAX_SIZE];
+ UINT port;
+ // Validate arguments
+ if (s == NULL || target == NULL)
+ {
+ return false;
+ }
+
+ // Get the host name
+ //GetMachineName(host, MAX_SIZE);
+ Zero(host, sizeof(host));
+ IPToStr(host, sizeof(host), &s->LocalIP);
+ // Get the port number
+ port = s->LocalPort;
+
+ // Creating a header
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+
+ h = NewHttpHeader("HTTP/1.1", "403", "Forbidden");
+
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
+
+ // Creating a Data
+ str_size = sizeof(http_403_str) * 2 + StrLen(target) + StrLen(host);
+ str = Malloc(str_size);
+ StrCpy(str, str_size, http_403_str);
+
+ // TARGET
+ ReplaceUnsafeCharInTarget(target);
+ ReplaceStri(str, str_size, str, "$TARGET$", target);
+
+ // HOST
+ ReplaceStri(str, str_size, str, "$HOST$", host);
+
+ // PORT
+ ToStr(port_str, port);
+ ReplaceStri(str, str_size, str, "$PORT$", port_str);
+
+ // Transmission
+ ret = PostHttp(s, h, str, StrLen(str));
+
+ FreeHttpHeader(h);
+ Free(str);
+
+ return ret;
+}
+
+// Get the date and time string for the HTTP header
+void GetHttpDateStr(char *str, UINT size, UINT64 t)
+{
+ SYSTEMTIME s;
+ static char *wday[] =
+ {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+ };
+ static char *month[] =
+ {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
+ "Nov", "Dec",
+ };
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ UINT64ToSystem(&s, t);
+
+ Format(str, size, "%s, %02u %s %04u %02u:%02u:%02u GMT",
+ wday[s.wDayOfWeek], s.wDay, month[s.wMonth - 1], s.wYear,
+ s.wHour, s.wMinute, s.wSecond);
+}
+
+// Get the Content-Length from the HTTP header
+UINT GetContentLength(HTTP_HEADER *header)
+{
+ UINT ret;
+ HTTP_VALUE *v;
+ // Validate arguments
+ if (header == NULL)
+ {
+ return 0;
+ }
+
+ v = GetHttpValue(header, "Content-Length");
+ if (v == NULL)
+ {
+ return 0;
+ }
+
+ ret = ToInt(v->Data);
+
+ return ret;
+}
+
+// Send the data in the HTTP
+bool PostHttp(SOCK *s, HTTP_HEADER *header, void *post_data, UINT post_size)
+{
+ char *header_str;
+ BUF *b;
+ bool ret;
+ // Validate arguments
+ if (s == NULL || header == NULL || (post_size != 0 && post_data == NULL))
+ {
+ return false;
+ }
+
+ // Check whether the Content-Lentgh exists?
+ if (GetHttpValue(header, "Content-Length") == NULL)
+ {
+ char tmp[MAX_SIZE];
+ // Add because it does not exist
+ ToStr(tmp, post_size);
+ AddHttpValue(header, NewHttpValue("Content-Length", tmp));
+ }
+
+ // Convert the header to string
+ header_str = HttpHeaderToStr(header);
+ if (header_str == NULL)
+ {
+ return false;
+ }
+ b = NewBuf();
+ WriteBuf(b, header_str, StrLen(header_str));
+ Free(header_str);
+
+ // Append the data
+ WriteBuf(b, post_data, post_size);
+
+ // Send
+ ret = SendAll(s, b->Buf, b->Size, s->SecureMode);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Convert a HTTP header to a string
+char *HttpHeaderToStr(HTTP_HEADER *header)
+{
+ BUF *b;
+ char *tmp;
+ UINT i;
+ char *s;
+ // Validate arguments
+ if (header == NULL)
+ {
+ return NULL;
+ }
+
+ tmp = Malloc(HTTP_HEADER_LINE_MAX_SIZE);
+ b = NewBuf();
+
+ // Header
+ Format(tmp, HTTP_HEADER_LINE_MAX_SIZE,
+ "%s %s %s\r\n", header->Method, header->Target, header->Version);
+ WriteBuf(b, tmp, StrLen(tmp));
+
+ // Value
+ for (i = 0;i < LIST_NUM(header->ValueList);i++)
+ {
+ HTTP_VALUE *v = (HTTP_VALUE *)LIST_DATA(header->ValueList, i);
+ Format(tmp, HTTP_HEADER_LINE_MAX_SIZE,
+ "%s: %s\r\n", v->Name, v->Data);
+ WriteBuf(b, tmp, StrLen(tmp));
+ }
+
+ // Trailing newline
+ WriteBuf(b, "\r\n", 2);
+ s = Malloc(b->Size + 1);
+ Copy(s, b->Buf, b->Size);
+ s[b->Size] = 0;
+
+ FreeBuf(b);
+ Free(tmp);
+
+ return s;
+}
+
+// Send the HTTP header
+bool SendHttpHeader(SOCK *s, HTTP_HEADER *header)
+{
+ char *str;
+ bool ret;
+ // Validate arguments
+ if (s == NULL || header == NULL)
+ {
+ return false;
+ }
+
+ // Convert to string
+ str = HttpHeaderToStr(header);
+
+ // Transmission
+ ret = SendAll(s, str, StrLen(str), s->SecureMode);
+
+ Free(str);
+
+ return ret;
+}
+
+// Receive an HTTP header
+HTTP_HEADER *RecvHttpHeader(SOCK *s)
+{
+ TOKEN_LIST *token = NULL;
+ char *str = NULL;
+ HTTP_HEADER *header = NULL;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ // Get the first line
+ str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
+ if (str == NULL)
+ {
+ goto LABEL_ERROR;
+ }
+
+ // Split into tokens
+ token = ParseToken(str, " ");
+ if (token->NumTokens < 3)
+ {
+ goto LABEL_ERROR;
+ }
+
+ Free(str);
+ str = NULL;
+
+ // Creating a header object
+ header = NewHttpHeader(token->Token[0], token->Token[1], token->Token[2]);
+
+ if (StrCmpi(header->Version, "HTTP/0.9") == 0)
+ {
+ // The header ends with this line
+ FreeToken(token);
+ return header;
+ }
+
+ // Get the subsequent lines
+ while (true)
+ {
+ UINT pos;
+ HTTP_VALUE *v;
+ char *value_name, *value_data;
+ str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
+ if (str == NULL)
+ {
+ goto LABEL_ERROR;
+ }
+ Trim(str);
+
+ if (StrLen(str) == 0)
+ {
+ // End of header
+ Free(str);
+ str = NULL;
+ break;
+ }
+
+ // Get the position of the colon
+ pos = SearchStr(str, ":", 0);
+ if (pos == INFINITE)
+ {
+ // The colon does not exist
+ goto LABEL_ERROR;
+ }
+ if ((pos + 1) >= StrLen(str))
+ {
+ // There is no data
+ goto LABEL_ERROR;
+ }
+
+ // Divide into the name and the data
+ value_name = Malloc(pos + 1);
+ Copy(value_name, str, pos);
+ value_name[pos] = 0;
+ value_data = &str[pos + 1];
+
+ v = NewHttpValue(value_name, value_data);
+ if (v == NULL)
+ {
+ Free(value_name);
+ goto LABEL_ERROR;
+ }
+
+ Free(value_name);
+
+ AddHttpValue(header, v);
+ Free(str);
+ }
+
+ FreeToken(token);
+
+ return header;
+
+LABEL_ERROR:
+ // Memory release
+ if (token)
+ {
+ FreeToken(token);
+ }
+ if (str)
+ {
+ Free(str);
+ }
+ if (header)
+ {
+ FreeHttpHeader(header);
+ }
+ return NULL;
+}
+
+// Receive a line
+char *RecvLine(SOCK *s, UINT max_size)
+{
+ BUF *b;
+ char c;
+ char *str;
+ // Validate arguments
+ if (s == NULL || max_size == 0)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ while (true)
+ {
+ UCHAR *buf;
+ if (RecvAll(s, &c, sizeof(c), s->SecureMode) == false)
+ {
+ FreeBuf(b);
+ return NULL;
+ }
+ WriteBuf(b, &c, sizeof(c));
+ buf = (UCHAR *)b->Buf;
+ if (b->Size > max_size)
+ {
+ FreeBuf(b);
+ return NULL;
+ }
+ if (b->Size >= 1)
+ {
+ if (buf[b->Size - 1] == '\n')
+ {
+ b->Size--;
+ if (b->Size >= 1)
+ {
+ if (buf[b->Size - 1] == '\r')
+ {
+ b->Size--;
+ }
+ }
+ str = Malloc(b->Size + 1);
+ Copy(str, b->Buf, b->Size);
+ str[b->Size] = 0;
+ FreeBuf(b);
+
+ return str;
+ }
+ }
+ }
+}
+
+// Creating a new HTTP value
+HTTP_VALUE *NewHttpValue(char *name, char *data)
+{
+ HTTP_VALUE *v;
+ // Validate arguments
+ if (name == NULL || data == NULL)
+ {
+ return NULL;
+ }
+
+ v = ZeroMalloc(sizeof(HTTP_VALUE));
+
+ v->Name = CopyStr(name);
+ v->Data = CopyStr(data);
+
+ Trim(v->Name);
+ Trim(v->Data);
+
+ return v;
+}
+
+// Look for the HTTP value from the HTTP header
+HTTP_VALUE *GetHttpValue(HTTP_HEADER *header, char *name)
+{
+ HTTP_VALUE *v, t;
+ // Validate arguments
+ if (header == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ t.Name = name;
+ v = Search(header->ValueList, &t);
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ return v;
+}
+
+// Add a HTTP value to the HTTP header
+void AddHttpValue(HTTP_HEADER *header, HTTP_VALUE *value)
+{
+ // Validate arguments
+ if (header == NULL || value == NULL)
+ {
+ return;
+ }
+
+ if (LIST_NUM(header->ValueList) < HTTP_HEADER_MAX_LINES)
+ {
+ Insert(header->ValueList, value);
+ }
+ else
+ {
+ FreeHttpValue(value);
+ }
+}
+
+// Create an HTTP header
+HTTP_HEADER *NewHttpHeader(char *method, char *target, char *version)
+{
+ return NewHttpHeaderEx(method, target, version, false);
+}
+HTTP_HEADER *NewHttpHeaderEx(char *method, char *target, char *version, bool no_sort)
+{
+ HTTP_HEADER *header;
+ // Validate arguments
+ if (method == NULL || target == NULL || version == NULL)
+ {
+ return NULL;
+ }
+
+ header = ZeroMalloc(sizeof(HTTP_HEADER));
+
+ header->Method = CopyStr(method);
+ header->Target = CopyStr(target);
+ header->Version = CopyStr(version);
+ header->ValueList = NewListFast(no_sort ? NULL : CompareHttpValue);
+
+ return header;
+}
+
+// Comparison function of the HTTP value
+int CompareHttpValue(void *p1, void *p2)
+{
+ HTTP_VALUE *v1, *v2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ v1 = *(HTTP_VALUE **)p1;
+ v2 = *(HTTP_VALUE **)p2;
+ if (v1 == NULL || v2 == NULL)
+ {
+ return 0;
+ }
+ return StrCmpi(v1->Name, v2->Name);
+}
+
+// Release the HTTP value
+void FreeHttpValue(HTTP_VALUE *value)
+{
+ // Validate arguments
+ if (value == NULL)
+ {
+ return;
+ }
+
+ Free(value->Data);
+ Free(value->Name);
+
+ Free(value);
+}
+
+// Release the HTTP header
+void FreeHttpHeader(HTTP_HEADER *header)
+{
+ UINT i;
+ HTTP_VALUE **values;
+ // Validate arguments
+ if (header == NULL)
+ {
+ return;
+ }
+
+ Free(header->Method);
+ Free(header->Target);
+ Free(header->Version);
+
+ values = ToArray(header->ValueList);
+ for (i = 0;i < LIST_NUM(header->ValueList);i++)
+ {
+ FreeHttpValue(values[i]);
+ }
+ Free(values);
+
+ ReleaseList(header->ValueList);
+
+ Free(header);
+}
+
+// Receive a PACK
+PACK *RecvPack(SOCK *s)
+{
+ PACK *p;
+ BUF *b;
+ void *data;
+ UINT sz;
+ // Validate arguments
+ if (s == NULL || s->Type != SOCK_TCP)
+ {
+ return false;
+ }
+
+ if (RecvAll(s, &sz, sizeof(UINT), s->SecureMode) == false)
+ {
+ return false;
+ }
+ sz = Endian32(sz);
+ if (sz > MAX_PACK_SIZE)
+ {
+ return false;
+ }
+ data = MallocEx(sz, true);
+ if (RecvAll(s, data, sz, s->SecureMode) == false)
+ {
+ Free(data);
+ return false;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, data, sz);
+ SeekBuf(b, 0, 0);
+ p = BufToPack(b);
+ FreeBuf(b);
+ Free(data);
+
+ return p;
+}
+
+// Receive a PACK (with checking the hash)
+PACK *RecvPackWithHash(SOCK *s)
+{
+ PACK *p;
+ BUF *b;
+ void *data;
+ UINT sz;
+ UCHAR hash1[SHA1_SIZE];
+ UCHAR hash2[SHA1_SIZE];
+ // Validate arguments
+ if (s == NULL || s->Type != SOCK_TCP)
+ {
+ return false;
+ }
+
+ if (RecvAll(s, &sz, sizeof(UINT), s->SecureMode) == false)
+ {
+ return false;
+ }
+ sz = Endian32(sz);
+ if (sz > MAX_PACK_SIZE)
+ {
+ return false;
+ }
+ data = MallocEx(sz, true);
+ if (RecvAll(s, data, sz, s->SecureMode) == false)
+ {
+ Free(data);
+ return false;
+ }
+
+ HashSha1(hash1, data, sz);
+ if (RecvAll(s, hash2, sizeof(hash2), s->SecureMode) == false)
+ {
+ Free(data);
+ return false;
+ }
+
+ if (Cmp(hash1, hash2, SHA1_SIZE) != 0)
+ {
+ Free(data);
+ return false;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, data, sz);
+ SeekBuf(b, 0, 0);
+ p = BufToPack(b);
+ FreeBuf(b);
+ Free(data);
+
+ return p;
+}
+
+// Send a PACK
+bool SendPack(SOCK *s, PACK *p)
+{
+ BUF *b;
+ UINT sz;
+ // Validate arguments
+ if (s == NULL || p == NULL || s->Type != SOCK_TCP)
+ {
+ return false;
+ }
+
+ b = PackToBuf(p);
+ sz = Endian32(b->Size);
+
+ SendAdd(s, &sz, sizeof(UINT));
+ SendAdd(s, b->Buf, b->Size);
+ FreeBuf(b);
+
+ return SendNow(s, s->SecureMode);
+}
+
+// Send a Pack (with adding a hash)
+bool SendPackWithHash(SOCK *s, PACK *p)
+{
+ BUF *b;
+ UINT sz;
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (s == NULL || p == NULL || s->Type != SOCK_TCP)
+ {
+ return false;
+ }
+
+ b = PackToBuf(p);
+ sz = Endian32(b->Size);
+
+ SendAdd(s, &sz, sizeof(UINT));
+ SendAdd(s, b->Buf, b->Size);
+ HashSha1(hash, b->Buf, b->Size);
+ SendAdd(s, hash, sizeof(hash));
+
+ FreeBuf(b);
+
+ return SendNow(s, s->SecureMode);
+}
+
+// Get SNI name from the data that has arrived to the TCP connection before accepting an SSL connection
+bool GetSniNameFromPreSslConnection(SOCK *s, char *sni, UINT sni_size)
+{
+ UCHAR tmp[1500];
+ UINT size;
+ // Validate arguments
+ if (s == NULL || sni == NULL)
+ {
+ return false;
+ }
+
+ size = Peek(s, tmp, sizeof(tmp));
+ if (size == 0)
+ {
+ return false;
+ }
+
+ return GetSniNameFromSslPacket(tmp, size, sni, sni_size);
+}
+
+// Get SNI name from the SSL packet
+bool GetSniNameFromSslPacket(UCHAR *packet_buf, UINT packet_size, char *sni, UINT sni_size)
+{
+ BUF *buf;
+ bool ret = false;
+ UCHAR content_type;
+ USHORT version;
+ USHORT handshake_length;
+
+ // Validate arguments
+ if (packet_buf == NULL || packet_size == 0)
+ {
+ return false;
+ }
+
+ buf = NewBufFromMemory(packet_buf, packet_size);
+
+ if (ReadBuf(buf, &content_type, sizeof(UCHAR)) == sizeof(UCHAR) &&
+ ReadBuf(buf, &version, sizeof(USHORT)) == sizeof(USHORT) &&
+ ReadBuf(buf, &handshake_length, sizeof(USHORT)) == sizeof(USHORT))
+ {
+ version = Endian16(version);
+ handshake_length = Endian16(handshake_length);
+
+ if (version >= 0x0301)
+ {
+ UCHAR *handshake_data = Malloc(handshake_length);
+
+ if (ReadBuf(buf, handshake_data, handshake_length) == handshake_length)
+ {
+ BUF *buf2 = NewBufFromMemory(handshake_data, handshake_length);
+ USHORT handshake_type;
+ USHORT handshake_length_2;
+
+ if (ReadBuf(buf2, &handshake_type, sizeof(USHORT)) == sizeof(USHORT) &&
+ ReadBuf(buf2, &handshake_length_2, sizeof(USHORT)) == sizeof(USHORT))
+ {
+ handshake_type = Endian16(handshake_type);
+ handshake_length_2 = Endian16(handshake_length_2);
+
+ if (handshake_type == 0x0100 && handshake_length_2 <= (handshake_length - 4))
+ {
+ USHORT version2;
+
+ if (ReadBuf(buf2, &version2, sizeof(USHORT)) == sizeof(USHORT))
+ {
+ version2 = Endian16(version2);
+
+ if (version2 >= 0x0301)
+ {
+ UCHAR rand[32];
+
+ if (ReadBuf(buf2, rand, sizeof(rand)) == sizeof(rand))
+ {
+ UCHAR session_id_len;
+
+ if (ReadBuf(buf2, &session_id_len, sizeof(UCHAR)) == sizeof(UCHAR))
+ {
+ if (ReadBuf(buf2, NULL, session_id_len) == session_id_len)
+ {
+ USHORT cipher_len;
+
+ if (ReadBuf(buf2, &cipher_len, sizeof(USHORT)) == sizeof(USHORT))
+ {
+ cipher_len = Endian16(cipher_len);
+
+ if (ReadBuf(buf2, NULL, cipher_len) == cipher_len)
+ {
+ UCHAR comps_len;
+
+ if (ReadBuf(buf2, &comps_len, sizeof(UCHAR)) == sizeof(UCHAR))
+ {
+ if (ReadBuf(buf2, NULL, comps_len) == comps_len)
+ {
+ USHORT ext_length;
+
+ if (ReadBuf(buf2, &ext_length, sizeof(USHORT)) == sizeof(USHORT))
+ {
+ UCHAR *ext_buf;
+
+ ext_length = Endian16(ext_length);
+
+ ext_buf = Malloc(ext_length);
+
+ if (ReadBuf(buf2, ext_buf, ext_length) == ext_length)
+ {
+ BUF *ebuf = NewBufFromMemory(ext_buf, ext_length);
+
+ while (ret == false)
+ {
+ USHORT type;
+ USHORT data_len;
+ UCHAR *data;
+
+ if (ReadBuf(ebuf, &type, sizeof(USHORT)) != sizeof(USHORT))
+ {
+ break;
+ }
+
+ if (ReadBuf(ebuf, &data_len, sizeof(USHORT)) != sizeof(USHORT))
+ {
+ break;
+ }
+
+ type = Endian16(type);
+ data_len = Endian16(data_len);
+
+ data = Malloc(data_len);
+
+ if (ReadBuf(ebuf, data, data_len) != data_len)
+ {
+ Free(data);
+ break;
+ }
+
+ if (type == 0x0000)
+ {
+ BUF *dbuf = NewBufFromMemory(data, data_len);
+
+ USHORT total_len;
+
+ if (ReadBuf(dbuf, &total_len, sizeof(USHORT)) == sizeof(USHORT))
+ {
+ UCHAR c;
+ total_len = Endian16(total_len);
+
+ if (ReadBuf(dbuf, &c, sizeof(UCHAR)) == sizeof(UCHAR))
+ {
+ if (c == 0)
+ {
+ USHORT name_len;
+
+ if (ReadBuf(dbuf, &name_len, sizeof(USHORT)) == sizeof(USHORT))
+ {
+ char *name_buf;
+ name_len = Endian16(name_len);
+
+ name_buf = ZeroMalloc(name_len + 1);
+
+ if (ReadBuf(dbuf, name_buf, name_len) == name_len)
+ {
+ ret = true;
+
+ StrCpy(sni, sni_size, name_buf);
+ }
+
+ Free(name_buf);
+ }
+ }
+ }
+ }
+
+ FreeBuf(dbuf);
+ }
+
+ Free(data);
+ }
+
+ FreeBuf(ebuf);
+ }
+
+ Free(ext_buf);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ FreeBuf(buf2);
+ }
+
+ Free(handshake_data);
+ }
+ }
+
+ FreeBuf(buf);
+
+ if (ret)
+ {
+ Trim(sni);
+
+ if (IsEmptyStr(sni))
+ {
+ ret = false;
+ }
+ }
+
+ return ret;
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Network.h b/src/Mayaqua/Network.h
new file mode 100644
index 00000000..20be8619
--- /dev/null
+++ b/src/Mayaqua/Network.h
@@ -0,0 +1,1582 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Network.h
+// Header of Network.c
+
+#ifndef NETWORK_H
+#define NETWORK_H
+
+// Dynamic Value
+struct DYN_VALUE
+{
+ char Name[256]; // Name
+ UINT64 Value; // Value
+};
+
+#define DYN64(id, default_value) ( (UINT64)GetDynValueOrDefaultSafe ( #id , (UINT64)( default_value )))
+#define DYN32(id, default_value) (UINT)DYN64(id, (UINT)default_value)
+
+#define MAX_HOST_NAME_LEN 255 // Maximum length of the host name
+
+#define TIMEOUT_GETIP 2300
+
+#define TIMEOUT_INFINITE (0x7fffffff)
+#define TIMEOUT_TCP_PORT_CHECK (10 * 1000)
+#define TIMEOUT_SSL_CONNECT (15 * 1000)
+
+#define TIMEOUT_HOSTNAME (500)
+#define TIMEOUT_NETBIOS_HOSTNAME (100)
+#define EXPIRES_HOSTNAME (10 * 60 * 1000)
+
+#define SOCKET_BUFFER_SIZE 0x10000000
+
+#define IPV6_DUMMY_FOR_IPV4 0xFEFFFFDF
+
+#define UDPLISTENER_CHECK_INTERVAL 1000ULL
+#define UDPLISTENER_WAIT_INTERVAL 1234
+
+#define UDP_MAX_MSG_SIZE_DEFAULT 65507
+
+#define MAX_NUM_IGNORE_ERRORS 1024
+
+// Private IP list file
+#define PRIVATE_IP_TXT_FILENAME "@private_ip.txt"
+
+// Start range of the random UDP port
+#define RAND_UDP_PORT_START 5000
+#define RAND_UDP_PORT_END 65530
+#define RAND_UDP_PORT_DEFAULT_NUM_RETRY 64
+
+// Special Port
+#define MAKE_SPECIAL_PORT(p) (UINT)((UINT)0x10000 | (UINT)(p))
+#define IS_SPECIAL_PORT(p) (MAKEBOOL((p) & (UINT)0x10000))
+#define GET_SPECIAL_PORT(p) (UINT)((UINT)(p) & (UINT)0xffff)
+
+// Random R-UDP port ID
+#define RAND_PORT_ID_SERVER_LISTEN 1
+
+// UDP buffer size
+#define UDP_MAX_BUFFER_SIZE 11911168
+
+// Expiration of the cache acquired from the IP address list of the host
+#define HOST_IP_ADDRESS_LIST_CACHE (5 * 1000)
+
+// IP address
+struct IP
+{
+ UCHAR addr[4]; // IPv4 address, (meaning that 223.255.255.254 = IPv6)
+ UCHAR ipv6_addr[16]; // IPv6 address
+ UINT ipv6_scope_id; // IPv6 scope ID
+};
+
+// Size when comparing the IP structures only in the address part
+#define SIZE_OF_IP_FOR_ADDR (sizeof(UCHAR) * 20)
+
+// Compare the IP address part
+#define CmpIpAddr(ip1, ip2) (Cmp((ip1), (ip2), SIZE_OF_IP_FOR_ADDR))
+
+// IPv6 address (different format)
+struct IPV6_ADDR
+{
+ UCHAR Value[16]; // Value
+} GCC_PACKED;
+
+// IPv6 Address Types
+#define IPV6_ADDR_UNICAST 1 // Unicast
+#define IPV6_ADDR_LOCAL_UNICAST 2 // Local unicast
+#define IPV6_ADDR_GLOBAL_UNICAST 4 // Global Unicast
+#define IPV6_ADDR_MULTICAST 8 // Multicast
+#define IPV6_ADDR_ALL_NODE_MULTICAST 16 // All-nodes multicast
+#define IPV6_ADDR_ALL_ROUTER_MULTICAST 32 // All routers multicast
+#define IPV6_ADDR_SOLICIATION_MULTICAST 64 // Solicited-node multicast
+#define IPV6_ADDR_ZERO 128 // All zeros
+#define IPV6_ADDR_LOOPBACK 256 // Loop-back
+
+
+// DNS cache list
+struct DNSCACHE
+{
+ char *HostName;
+ IP IpAddress;
+};
+
+// Client list
+struct IP_CLIENT
+{
+ IP IpAddress; // IP address
+ UINT NumConnections; // The number of connections
+};
+
+// Socket event
+struct SOCK_EVENT
+{
+ REF *ref; // Reference counter
+#ifdef OS_WIN32
+ void *hEvent; // Pointer to a Win32 event handle
+#else // OS_WIN32
+ LIST *SockList; // Socket list
+ int pipe_read, pipe_write; // Pipe
+ UINT current_pipe_data; // Amount of data in the current pipe
+#endif // OS_WIN32
+};
+
+// Type of socket
+#define SOCK_TCP 1
+#define SOCK_UDP 2
+#define SOCK_INPROC 3
+#define SOCK_RUDP_LISTEN 5
+#define SOCK_REVERSE_LISTEN 6
+
+// Socket
+struct SOCK
+{
+ REF *ref; // Reference counter
+ LOCK *lock; // Lock
+ LOCK *ssl_lock; // Lock related to the SSL
+ LOCK *disconnect_lock; // Disconnection lock
+ SOCKET socket; // Socket number
+ SSL *ssl; // SSL object
+ struct ssl_ctx_st *ssl_ctx; // SSL_CTX
+ char SniHostname[256]; // SNI host name
+ UINT Type; // Type of socket
+ bool Connected; // Connecting flag
+ bool ServerMode; // Server mode
+ bool AsyncMode; // Asynchronous mode
+ bool SecureMode; // SSL communication mode
+ bool ListenMode; // In listening
+ BUF *SendBuf; // Transmission buffer
+ bool IpClientAdded; // Whether it has been added to the list IP_CLIENT
+ bool LocalOnly; // Only local
+ bool EnableConditionalAccept; // Conditional Accept is Enabled
+ IP RemoteIP; // IP address of the remote host
+ IP LocalIP; // IP address of the local host
+ char *RemoteHostname; // Remote host name
+ UINT RemotePort; // Port number of the remote side
+ UINT LocalPort; // Port number of the local side
+ UINT64 SendSize; // Total size of the sent data
+ UINT64 RecvSize; // Total size of received data
+ UINT64 SendNum; // Number of sent data blocks
+ UINT64 RecvNum; // Number of received data blocks
+ X *RemoteX; // Certificate of the remote host
+ X *LocalX; // Certificate of the local host
+ char *CipherName; // Cipher algorithm name
+ char *WaitToUseCipher; // Set the algorithm name to want to use
+ bool IgnoreRecvErr; // Whether the RecvFrom error is ignorable
+ bool IgnoreSendErr; // Whether the SendTo error is ignorable
+ UINT TimeOut; // Time-out value
+ SOCK_EVENT *SockEvent; // Associated socket-event
+ bool CancelAccept; // Cancel flag of the Accept
+ bool AcceptCanceled; // Flag which shows canceling of the Accept
+ bool WriteBlocked; // Previous write is blocked
+ bool NoNeedToRead; // Is not required to read
+ bool Disconnecting; // Disconnecting
+ bool UdpBroadcast; // UDP broadcast mode
+ void *Param; // Any parameters
+ bool IPv6; // IPv6
+ bool IsRawSocket; // Whether it is a raw socket
+ UINT RawSocketIPProtocol; // IP protocol number if it's a raw socket
+ TUBE *SendTube; // Tube for transmission
+ TUBE *RecvTube; // Tube for reception
+ QUEUE *InProcAcceptQueue; // Accept queue of the in-process socket
+ EVENT *InProcAcceptEvent; // Accept event of the in-process socket
+ FIFO *InProcRecvFifo; // Receive FIFO of the in-process socket
+ UINT UdpMaxMsgSize; // Maximum transmitting and receiving size at a time on UDP
+ int CurrentTos; // Current ToS value
+ bool IsTtlSupported; // Whether the TTL value is supported
+ UINT CurrentTtl; // Current TTL value
+ RUDP_STACK *R_UDP_Stack; // R-UDP stack
+ char UnderlayProtocol[64]; // Underlying protocol
+ QUEUE *ReverseAcceptQueue; // Accept queue for the reverse socket
+ EVENT *ReverseAcceptEvent; // Accept event for the reverse socket
+ bool IsReverseAcceptedSocket; // Whether it is a reverse socket
+ IP Reverse_MyServerGlobalIp; // Self global IP address when using the reverse socket
+ UINT Reverse_MyServerPort; // Self port number when using the reverse socket
+
+ void *hAcceptEvent; // Event for Accept
+
+ // R-UDP socket related
+ bool IsRUDPSocket; // Whether this is R-UDP socket
+ TUBE *BulkSendTube; // Tube for Bulk send
+ TUBE *BulkRecvTube; // Tube for Bulk receive
+ SHARED_BUFFER *BulkSendKey; // Bulk send key
+ SHARED_BUFFER *BulkRecvKey; // Bulk receive key
+ UINT RUDP_OptimizedMss; // Optimal MSS value
+
+#ifdef OS_UNIX
+ pthread_t CallingThread; // Thread that is calling the system call
+#endif // OS_UNIX
+
+#ifdef OS_WIN32
+ void *hEvent; // Event for asynchronous mode
+#endif // OS_WIN32
+};
+
+// Underlying protocol description string of socket
+#define SOCK_UNDERLAY_NATIVE_V6 "Standard TCP/IP (IPv6)"
+#define SOCK_UNDERLAY_NATIVE_V4 "Standard TCP/IP (IPv4)"
+#define SOCK_UNDERLAY_NAT_T "VPN over UDP with NAT-T (IPv4)"
+#define SOCK_UNDERLAY_DNS "VPN over DNS (IPv4)"
+#define SOCK_UNDERLAY_ICMP "VPN over ICMP (IPv4)"
+#define SOCK_UNDERLAY_INPROC "In-Process Pipe"
+#define SOCK_UNDERLAY_INPROC_EX "Legacy VPN - %s"
+#define SOCK_UNDERLAY_AZURE "TCP/IP via VPN Azure (IPv4)"
+
+// Constant of the return value
+#define SOCK_LATER (0xffffffff) // In blocking
+
+// Socket Set
+#define MAX_SOCKSET_NUM 60 // Number of sockets that can be stored in a socket set
+struct SOCKSET
+{
+ UINT NumSocket; // The number of sockets
+ SOCK *Sock[MAX_SOCKSET_NUM]; // Array of pointers to the socket
+};
+
+// Cancel object
+struct CANCEL
+{
+ REF *ref; // Reference counter
+ bool SpecialFlag; // Special flag (associated to the event which is generated by Win32 driver)
+#ifdef OS_WIN32
+ void *hEvent; // Pointer to a Win32 event handle
+#else // OS_WIN32
+ int pipe_read, pipe_write; // Pipe
+#endif // OS_WIN32
+};
+
+// Routing table entry
+struct ROUTE_ENTRY
+{
+ IP DestIP;
+ IP DestMask;
+ IP GatewayIP;
+ bool LocalRouting;
+ bool PPPConnection;
+ UINT Metric;
+ UINT OldIfMetric;
+ UINT InterfaceID;
+ UINT64 InnerScore;
+};
+
+// Routing table
+struct ROUTE_TABLE
+{
+ UINT NumEntry;
+ UINT HashedValue;
+ ROUTE_ENTRY **Entry;
+};
+
+// ICMP response result
+struct ICMP_RESULT
+{
+ bool Ok; // Whether a correct response returned
+ bool Timeout; // Whether a time-out is occurred
+ UCHAR Type; // Message type
+ UCHAR Code; // Message code
+ UCHAR Ttl; // TTL
+ UCHAR *Data; // Data body
+ UINT DataSize; // Data size
+ UINT Rtt; // Round Trip Time
+ IP IpAddress; // IP address
+};
+
+
+// Host name cache list
+typedef struct HOSTCACHE
+{
+ UINT64 Expires; // Expiration
+ IP IpAddress; // IP address
+ char HostName[256]; // Host name
+} HOSTCACHE;
+
+// NETBIOS name requests
+typedef struct NBTREQUEST
+{
+ USHORT TransactionId;
+ USHORT Flags;
+ USHORT NumQuestions;
+ USHORT AnswerRRs;
+ USHORT AuthorityRRs;
+ USHORT AdditionalRRs;
+ UCHAR Query[38];
+} NBTREQUEST;
+
+// NETBIOS name response
+typedef struct NBTRESPONSE
+{
+ USHORT TransactionId;
+ USHORT Flags;
+ USHORT NumQuestions;
+ USHORT AnswerRRs;
+ USHORT AuthorityRRs;
+ USHORT AdditionalRRs;
+ UCHAR Response[61];
+} NBTRESPONSE;
+
+// Socket list
+typedef struct SOCKLIST
+{
+ LIST *SockList;
+} SOCKLIST;
+
+
+// Parameters for timeout thread for Solaris
+typedef struct SOCKET_TIMEOUT_PARAM{
+ SOCK *sock;
+ CANCEL *cancel;
+ THREAD *thread;
+ bool unblocked;
+} SOCKET_TIMEOUT_PARAM;
+
+// Parameters for GetIP thread
+struct GETIP_THREAD_PARAM
+{
+ REF *Ref;
+ char HostName[MAX_PATH];
+ bool IPv6;
+ UINT Timeout;
+ IP Ip;
+ bool Ok;
+};
+
+// Parameters for the IP address release thread
+struct WIN32_RELEASEADDRESS_THREAD_PARAM
+{
+ REF *Ref;
+ char Guid[MAX_SIZE];
+ UINT Timeout;
+ bool Ok;
+ bool Renew;
+};
+
+// TCP table entry
+typedef struct TCPTABLE
+{
+ UINT Status;
+ IP LocalIP;
+ UINT LocalPort;
+ IP RemoteIP;
+ UINT RemotePort;
+ UINT ProcessId;
+} TCPTABLE;
+
+// State of TCP
+#define TCP_STATE_CLOSED 1
+#define TCP_STATE_LISTEN 2
+#define TCP_STATE_SYN_SENT 3
+#define TCP_STATE_SYN_RCVD 4
+#define TCP_STATE_ESTAB 5
+#define TCP_STATE_FIN_WAIT1 6
+#define TCP_STATE_FIN_WAIT2 7
+#define TCP_STATE_CLOSE_WAIT 8
+#define TCP_STATE_CLOSING 9
+#define TCP_STATE_LAST_ACK 10
+#define TCP_STATE_TIME_WAIT 11
+#define TCP_STATE_DELETE_TCB 12
+
+// Routing table changing notification
+struct ROUTE_CHANGE
+{
+ ROUTE_CHANGE_DATA *Data;
+};
+
+// Tube flush list
+struct TUBE_FLUSH_LIST
+{
+ LIST *List; // List
+};
+
+// Tube
+struct TUBE
+{
+ REF *Ref; // Reference counter
+ LOCK *Lock; // Lock
+ QUEUE *Queue; // Packet queue
+ EVENT *Event; // Event
+ SOCK_EVENT *SockEvent; // SockEvent
+ UINT SizeOfHeader; // Header size
+ TUBEPAIR_DATA *TubePairData; // Tube pair data
+ UINT IndexInTubePair; // Number in the tube pair
+ bool IsInFlushList; // Whether it is registered in the Tube Flush List
+ void *Param1, *Param2, *Param3;
+ UINT IntParam1, IntParam2, IntParam3;
+};
+
+// Data that is to send and to receive in the tube
+struct TUBEDATA
+{
+ void *Data; // Body of data
+ UINT DataSize; // The size of the data
+ void *Header; // The body of the header
+ UINT HeaderSize; // Size of the header
+};
+
+// Tube pair data
+struct TUBEPAIR_DATA
+{
+ bool IsDisconnected; // Disconnection flag
+ REF *Ref; // Reference counter
+ LOCK *Lock; // Lock
+ EVENT *Event1, *Event2; // Event
+ SOCK_EVENT *SockEvent1, *SockEvent2; // SockEvent
+};
+
+// UDP listener socket entry
+struct UDPLISTENER_SOCK
+{
+ IP IpAddress; // IP address
+ UINT Port; // Port number
+ SOCK *Sock; // Socket
+ bool HasError; // Whether an error occurs
+ bool Mark; // Mark
+ bool ErrorDebugDisplayed; // Whether the error has been displayed
+ UINT64 NextMyIpAndPortPollTick; // Time to check the self IP address and port number next
+ IP PublicIpAddress; // Global IP address
+ UINT PublicPort; // Global port number
+};
+
+// UDP packet
+struct UDPPACKET
+{
+ IP SrcIP; // Source IP address
+ IP DstIP; // Destination IP address
+ UINT SrcPort; // Source port
+ UINT DestPort; // Destination port
+ UINT Size; // Data size
+ void *Data; // Data body
+ UINT Type; // Type
+};
+
+// UDP listener packet receipt notification procedure
+typedef void (UDPLISTENER_RECV_PROC)(UDPLISTENER *u, LIST *packet_list);
+
+// UDP listener
+struct UDPLISTENER
+{
+ bool Halt; // Halting flag
+ SOCK_EVENT *Event; // Event
+ THREAD *Thread; // Thread
+ LIST *PortList; // Port list
+ LIST *SockList; // Socket list
+ UINT64 LastCheckTick; // Time which the socket list was checked last
+ UDPLISTENER_RECV_PROC *RecvProc; // Receive procedure
+ LIST *SendPacketList; // Transmission packet list
+ void *Param; // Parameters
+ INTERRUPT_MANAGER *Interrupts; // Interrupt manager
+ bool HostIPAddressListChanged; // IP address list of the host has changed
+ bool IsEspRawPortOpened; // Whether the raw port opens
+ bool PollMyIpAndPort; // Examine whether the global IP and the port number of its own
+ QUERYIPTHREAD *GetNatTIpThread; // NAT-T IP address acquisition thread
+};
+
+#define QUERYIPTHREAD_INTERVAL_LAST_OK (3 * 60 * 60 * 1000)
+#define QUERYIPTHREAD_INTERVAL_LAST_NG (30 * 1000)
+
+// IP address acquisition thread
+struct QUERYIPTHREAD
+{
+ THREAD *Thread; // Thread
+ EVENT *HaltEvent; // Halting event
+ bool Halt; // Halting flag
+ LOCK *Lock; // Lock
+ IP Ip; // Get the IP address
+ char Hostname[MAX_SIZE]; // Host name
+ UINT IntervalLastOk; // Interval if last was OK
+ UINT IntervalLastNg; // Interval if last was NG
+};
+
+// Interrupt management
+struct INTERRUPT_MANAGER
+{
+ LIST *TickList; // Time list
+};
+
+// SSL BIO
+struct SSL_BIO
+{
+ BIO *bio; // BIO
+ FIFO *SendFifo; // Transmission FIFO
+ FIFO *RecvFifo; // Reception FIFO
+ bool IsDisconnected; // Disconnected
+ bool NoFree; // Not to release the BIO
+};
+
+// SSL pipe
+struct SSL_PIPE
+{
+ bool ServerMode; // Whether it's in the server mode
+ bool IsDisconnected; // Disconnected
+ SSL *ssl; // SSL object
+ struct ssl_ctx_st *ssl_ctx; // SSL_CTX
+ SSL_BIO *SslInOut; // I/O BIO for the data in the SSL tunnel
+ SSL_BIO *RawIn, *RawOut; // Input and output BIO of the data flowing through the physical network
+};
+
+// IP address block list
+struct IPBLOCK
+{
+ IP Ip; // IP address
+ IP Mask; // Subnet mask
+};
+
+
+// R-UDP related constants
+#define RUDP_RESEND_TIMER 200 // Retransmission timer (initial value)
+#define RUDP_RESEND_TIMER_MAX 4792 // Retransmission timer (maximum value)
+#define RUDP_KEEPALIVE_INTERVAL_MIN 2500 // Transmission interval of Keep Alive (minimum)
+#define RUDP_KEEPALIVE_INTERVAL_MAX 4792 // Transmission interval of Keep Alive (maximum)
+#define RUDP_TIMEOUT 12000 // Time-out of R-UDP communication
+#define RUDP_DIRECT_CONNECT_TIMEOUT 5000 // R-UDP direct connection time-out
+#define RUDP_MAX_SEGMENT_SIZE 512 // Maximum segment size
+// Maximum R-UDP packet size
+#define RUDP_MAX_PACKET_SIZE (RUDP_MAX_SEGMENT_SIZE + sizeof(UINT64) * RUDP_MAX_NUM_ACK + SHA1_SIZE * 2 + sizeof(UINT64) * 4 + sizeof(UINT) + 255)
+#define RUDP_MAX_NUM_ACK 64 // Maximum number of ACKs
+#define RUDP_LOOP_WAIT_INTERVAL_S 1234 // Waiting time in the thread main loop (in server side)
+#define RUDP_LOOP_WAIT_INTERVAL_C 100 // Waiting time in the thread main loop (in client side)
+#define RUDP_MAX_FIFO_SIZE (1600 * 1600) // The maximum FIFO buffer size
+
+// Interval for sending ICMP Echo from the client side when R-UDP used in ICMP mode
+#define RUDP_CLIENT_ECHO_REQUEST_SEND_INTERVAL_MIN 1000
+#define RUDP_CLIENT_ECHO_REQUEST_SEND_INTERVAL_MAX 3000
+
+// R-UDP error code
+#define RUDP_ERROR_OK 0 // Success
+#define RUDP_ERROR_UNKNOWN 1 // Unknown Error
+#define RUDP_ERROR_TIMEOUT 2 // Time-out
+#define RUDP_ERROR_NAT_T_GETIP_FAILED 3 // IP address acquisition failure of NAT-T server
+#define RUDP_ERROR_NAT_T_NO_RESPONSE 4 // There is no response from the NAT-T server
+#define RUDP_ERROR_NAT_T_TWO_OR_MORE 5 // There are two or more hosts on the same destination IP address
+#define RUDP_ERROR_NAT_T_NOT_FOUND 6 // Host does not exist at the specified IP address
+#define RUDP_ERROR_USER_CANCELED 7 // Cancel by the user
+
+// R-UDP segment
+struct RUDP_SEGMENT
+{
+ UINT64 SeqNo; // Sequence number
+ UINT Size; // Size
+ UCHAR Data[RUDP_MAX_SEGMENT_SIZE]; // Data
+ UINT64 NextSendTick; // Next transmission time
+ UINT NumSent; // Number of times sent
+};
+
+// Status of R-UDP session
+#define RUDP_SESSION_STATUS_CONNECT_SENT 0 // Connection request sent
+#define RUDP_SESSION_STATUS_ESTABLISHED 1 // Connection established
+
+// Quota
+#define RUDP_QUOTA_MAX_NUM_SESSIONS_PER_IP DYN32(RUDP_QUOTA_MAX_NUM_SESSIONS_PER_IP, 1000) // The number of R-UDP sessions per an IP address
+#define RUDP_QUOTA_MAX_NUM_SESSIONS DYN32(RUDP_QUOTA_MAX_NUM_SESSIONS, 30000) // Limit of the Number of sessions
+
+// Range of the sequence numbers of bulk packet
+#define RUDP_BULK_SEQ_NO_RANGE 16384ULL
+#define RUDP_BULK_MAX_RECV_PKTS_IN_QUEUE 8192
+
+// R-UDP session
+struct RUDP_SESSION
+{
+ UINT Status; // Status
+ bool ServerMode; // Whether it's in the server mode
+ bool DisconnectFlag; // Disconnection flag
+ bool DisconnectedByYou; // Disconnected from opponent
+ bool UseHMac;
+ IP MyIp; // IP address of itself
+ UINT MyPort; // Port number of itself
+ IP YourIp; // Opponent IP address
+ UINT YourPort; // Opponent port number
+ LIST *SendSegmentList; // Transmission segment list
+ LIST *RecvSegmentList; // Received segments list
+ LIST *ReplyAckList; // List of ACKs in response
+ SOCK *TcpSock; // Corresponding TCP socket
+ UINT64 LastSentTick; // Time which the data has been sent last
+ UINT64 LastRecvTick; // Time which the data has been received last
+ UCHAR Key_Init[SHA1_SIZE]; // Initial key
+ UCHAR Key_Send[SHA1_SIZE]; // Key that is used to send
+ UCHAR Key_Recv[SHA1_SIZE]; // Key that is used to receive
+ UCHAR Magic_KeepAliveRequest[SHA1_SIZE]; // The magic number for the KeepAlive request
+ UCHAR Magic_KeepAliveResponse[SHA1_SIZE]; // The magic number for KeepAlive response
+ UINT64 Magic_Disconnect; // Disconnection Signal
+ UINT64 NextSendSeqNo; // Transmission sequence number to be used next
+ UINT64 LastRecvCompleteSeqNo; // Sequence number of receiving complete
+ // (This indicates all segments which have sequence number up to this number are received completely)
+ UCHAR NextIv[SHA1_SIZE]; // IV value to be used next
+ UINT NextKeepAliveInterval; // Interval value of KeepAlive to be used next
+ FIFO *RecvFifo; // Reception FIFO
+ FIFO *SendFifo; // Transmission FIFO
+ UINT64 YourTick; // The largest value among received Tick from the opponent
+ UINT64 LatestRecvMyTick; // Value of the last tick among the received tick values
+ UINT64 LatestRecvMyTick2; // Variable for confirming whether LatestRecvMyTick2 changes
+ UINT CurrentRtt; // Current RTT value
+
+ UINT Icmp_Type; // Number of Type to be used in the ICMP
+ USHORT Dns_TranId; // Value of transaction ID used in DNS
+ UINT64 Client_Icmp_NextSendEchoRequest; // Time to send the next Echo Request in the ICMP
+ SHARED_BUFFER *BulkSendKey; // Bulk send key
+ SHARED_BUFFER *BulkRecvKey; // Bulk receive key
+ UCHAR BulkNextIv[SHA1_SIZE]; // Next IV to the bulk send
+ UINT64 BulkNextSeqNo; // Next SEQ NO to the bulk send
+ bool FlushBulkSendTube; // Flag to be Flush the bulk send Tube
+ UINT64 BulkRecvSeqNoMax; // Highest sequence number received
+};
+
+// NAT Traversal Server Information
+#define UDP_NAT_T_SERVER_TAG "x%c.x%c.x%c.x%c.servers.nat-traversal.softether-network.net."
+#define UDP_NAT_T_SERVER_TAG_ALT "x%c.x%c.x%c.x%c.servers.nat-traversal.uxcom.jp."
+#define UDP_NAT_T_PORT 5004
+
+// Related to processing to get the IP address of the NAT-T server
+#define UDP_NAT_T_GET_IP_INTERVAL DYN32(UDP_NAT_T_GET_IP_INTERVAL, (5 * 1000)) // IP address acquisition interval of NAT-T server (before success)
+#define UDP_NAT_T_GET_IP_INTERVAL_AFTER DYN32(UDP_NAT_T_GET_IP_INTERVAL_AFTER, (5 * 60 * 1000)) // IP address acquisition interval of NAT-T server (after success)
+
+// Related to process to get the private IP address of itself with making a TCP connection to the NAT-T server
+#define UDP_NAT_T_GET_PRIVATE_IP_TCP_SERVER "get-my-ip.nat-traversal.softether-network.net."
+#define UDP_NAT_T_GET_PRIVATE_IP_TCP_SERVER_ALT "get-my-ip.nat-traversal.uxcom.jp."
+
+#define UDP_NAT_T_PORT_FOR_TCP_1 992
+#define UDP_NAT_T_PORT_FOR_TCP_2 80
+#define UDP_NAT_T_PORT_FOR_TCP_3 443
+
+#define UDP_NAT_TRAVERSAL_VERSION 1
+
+#define UDP_NAT_T_GET_PRIVATE_IP_INTERVAL DYN32(UDP_NAT_T_GET_PRIVATE_IP_INTERVAL, (15 * 60 * 1000)) // Polling interval (before success)
+#define UDP_NAT_T_GET_PRIVATE_IP_INTERVAL_AFTER_MIN DYN32(UDP_NAT_T_GET_PRIVATE_IP_INTERVAL_AFTER_MIN, (30 * 60 * 1000)) // Polling interval (after success)
+#define UDP_NAT_T_GET_PRIVATE_IP_INTERVAL_AFTER_MAX DYN32(UDP_NAT_T_GET_PRIVATE_IP_INTERVAL_AFTER_MAX, (60 * 60 * 1000)) // Polling interval (after success)
+#define UDP_NAT_T_GET_PRIVATE_IP_CONNECT_TIMEOUT DYN32(UDP_NAT_T_GET_PRIVATE_IP_CONNECT_TIMEOUT, (5 * 1000)) // TCP connection time-out
+
+// About token acquisition from the NAT-T server
+#define UDP_NAT_T_GET_TOKEN_INTERVAL_1 DYN32(UDP_NAT_T_GET_TOKEN_INTERVAL_1, (5 * 1000)) // Token acquisition interval from the NAT-T server (If not acquired)
+#define UDP_NAT_T_GET_TOKEN_INTERVAL_FAIL_MAX DYN32(UDP_NAT_T_GET_TOKEN_INTERVAL_FAIL_MAX, 20)
+#define UDP_NAT_T_GET_TOKEN_INTERVAL_2_MIN DYN32(UDP_NAT_T_GET_TOKEN_INTERVAL_2_MIN, (20 * 60 * 1000)) // Token acquisition interval minimum value from the NAT-T server (If token have been obtained)
+#define UDP_NAT_T_GET_TOKEN_INTERVAL_2_MAX DYN32(UDP_NAT_T_GET_TOKEN_INTERVAL_2_MAX, (30 * 60 * 1000)) // Token acquisition interval maximum value from the NAT-T server (If token have been obtained)
+
+// The Register interval for NAT-T server
+#define UDP_NAT_T_REGISTER_INTERVAL_INITIAL DYN32(UDP_NAT_T_REGISTER_INTERVAL_INITIAL, (5 * 1000)) // Transmission interval when the Register is not completed
+#define UDP_NAT_T_REGISTER_INTERVAL_FAIL_MAX DYN32(UDP_NAT_T_REGISTER_INTERVAL_FAIL_MAX, 20)
+#define UDP_NAT_T_REGISTER_INTERVAL_MIN DYN32(UDP_NAT_T_REGISTER_INTERVAL_MIN, (220 * 1000)) // Minimum value of the Register interval
+#define UDP_NAT_T_REGISTER_INTERVAL_MAX DYN32(UDP_NAT_T_REGISTER_INTERVAL_MAX, (240 * 1000)) // Maximum value of the Register interval
+
+// Interval for checking whether the port number or the IP address is changed
+#define UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MIN DYN32(UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MIN, (24 * 1000))
+#define UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MAX DYN32(UDP_NAT_T_NAT_STATUS_CHECK_INTERVAL_MAX, (28 * 1000))
+
+// The Connect Request interval for NAT-T server
+#define UDP_NAT_T_CONNECT_INTERVAL DYN32(UDP_NAT_T_CONNECT_INTERVAL, 200)
+
+// Polling interval for its own IP information acquisition to the NAT-T server in regular communication between the client and the server
+#define UDP_NAT_T_INTERVAL_MIN DYN32(UDP_NAT_T_INTERVAL_MIN, (5 * 60 * 1000))
+#define UDP_NAT_T_INTERVAL_MAX DYN32(UDP_NAT_T_INTERVAL_MAX, (10 * 60 * 1000))
+#define UDP_NAT_T_INTERVAL_INITIAL DYN32(UDP_NAT_T_INTERVAL_INITIAL, (3 * 1000))
+#define UDP_NAT_T_INTERVAL_FAIL_MAX DYN32(UDP_NAT_T_INTERVAL_FAIL_MAX, 60)
+
+// R-UDP stack callback function definition
+typedef void (RUDP_STACK_INTERRUPTS_PROC)(RUDP_STACK *r);
+typedef bool (RUDP_STACK_RPC_RECV_PROC)(RUDP_STACK *r, UDPPACKET *p);
+
+// ICMP protocol number
+#define IP_PROTO_ICMPV4 0x01 // ICMPv4 protocol
+#define IP_PROTO_ICMPV6 0x3a // ICMPv6 protocol
+
+// R-UDP protocol
+#define RUDP_PROTOCOL_UDP 0 // UDP
+#define RUDP_PROTOCOL_ICMP 1 // ICMP
+#define RUDP_PROTOCOL_DNS 2 // DNS
+
+// Minimum time to wait for a trial to connect by ICMP and DNS in case failing to connect by TCP
+#define SOCK_CONNECT_WAIT_FOR_ICMP_AND_DNS_AT_LEAST 5000
+
+// R-UDP stack
+struct RUDP_STACK
+{
+ bool ServerMode; // Whether it's in the server mode
+ char SvcName[MAX_SIZE]; // Service name
+ UCHAR SvcNameHash[SHA1_SIZE]; // Hash of the service name
+ bool Halt; // Halting flag
+ void *Param; // Parameters that can be used by developers
+ UINT64 Now; // Current time
+ EVENT *HaltEvent; // Halting event
+ INTERRUPT_MANAGER *Interrupt; // Interrupt manager
+ LIST *SessionList; // Session List
+ SOCK *UdpSock; // UDP socket
+ UINT Port; // Port number
+ UINT Protocol; // Protocol
+ SOCK_EVENT *SockEvent; // Socket event
+ THREAD *Thread; // Thread
+ LOCK *Lock; // Lock
+ RUDP_STACK_INTERRUPTS_PROC *ProcInterrupts; // Interrupt notification callback
+ RUDP_STACK_RPC_RECV_PROC *ProcRpcRecv; // RPC reception notification callback
+ THREAD *IpQueryThread; // NAT-T server IP inquiry thread
+ UCHAR TmpBuf[65536]; // Temporary buffer
+ LIST *SendPacketList; // Transmission UDP packet list
+ EVENT *NewSockConnectEvent; // Event to inform that a new socket is connected
+ QUEUE *NewSockQueue; // Queue of new socket
+ UINT64 TotalPhysicalReceived; // Physical amount of data received
+ UINT64 TotalLogicalReceived; // Logical amount of data received
+ UINT64 TotalPhysicalSent; // Physical amount of data transmitted
+ UINT64 TotalLogicalSent; // Logical amount of data transmitted
+ char CurrentRegisterHostname[MAX_SIZE]; // The host name of the the current destination of registration
+
+ // NAT-T server related
+ bool NoNatTRegister; // Flag not to register with the NAT-T server
+ UINT64 NatT_TranId; // Transaction ID is used to communicate with the NAT-T server
+ IP NatT_IP; // IP address of the NAT-T server
+ IP NatT_IP_Safe; // IP address of the NAT-T server (thread-safe)
+ IP My_Private_IP; // Private IP address of itself
+ IP My_Private_IP_Safe; // Private IP address of itself (thread-safe)
+ UINT64 NatT_GetTokenNextTick; // Time to get the next token
+ UINT NatT_GetTokenFailNum; // Token acquisition failure times
+ char NatT_Token[MAX_SIZE]; // Token needed to communicate with NAT-T Server
+ bool NatT_Token_Ok; // Flag of whether it have a valid token
+ UINT64 NatT_RegisterNextTick; // Time to register next
+ UINT NatT_RegisterFailNum; // The number of Register failures
+ bool NatT_Register_Ok; // Is a successful registration
+ char NatT_Registered_IPAndPort[128]; // IP address and port number at the time of registration success
+ UINT64 NatT_NextNatStatusCheckTick; // Time to check the NAT state next
+ UINT LastDDnsFqdnHash; // DNS FQDN hash value when last checked
+ volatile UINT *NatTGlobalUdpPort; // NAT-T global UDP port
+ UCHAR RandPortId; // Random UDP port ID
+
+ // For Client
+ bool TargetIpAndPortInited; // The target IP address and the port number are initialized
+ IP TargetIp; // Target IP address
+ UINT TargetPort; // Target port number
+ EVENT *TargetConnectedEvent; // Event to be set when the connection to the target is successful
+ SOCK *TargetConnectedSock; // Connected socket
+ bool ClientInitiated; // Flag to indicate that the connection is initiated
+ bool DoNotSetTargetConnectedSock; // Flag indicating that it should not set the TargetConnectedSock
+ USHORT Client_IcmpId, Client_IcmpSeqNo; // Sequence number and ICMP ID that is randomly generated on the client side
+};
+
+// Data for the thread for concurrent connection attempts for the R-UDP and TCP
+struct CONNECT_TCP_RUDP_PARAM
+{
+ IP Ip;
+ UINT Port;
+ UINT Timeout;
+ char Hostname[MAX_SIZE];
+ bool *CancelFlag;
+ UINT NatT_ErrorCode;
+ char SvcName[MAX_SIZE];
+ char HintStr[MAX_SIZE];
+ char TargetHostname[MAX_SIZE];
+ SOCK *Result_Nat_T_Sock;
+ SOCK *Result_Tcp_Sock;
+ bool Finished;
+ bool Ok;
+ UINT64 FinishedTick;
+ EVENT *FinishEvent;
+ UINT RUdpProtocol;
+ UINT Delay;
+ bool Tcp_TryStartSsl;
+ bool Tcp_SslNoTls;
+ LOCK *CancelLock;
+ SOCK *CancelDisconnectSock;
+};
+
+#define SSL_DEFAULT_CONNECT_TIMEOUT (15 * 1000) // SSL default timeout
+
+// Header for TCP Pair
+struct TCP_PAIR_HEADER
+{
+ bool EnableHMac;
+};
+
+// The constants for file query by using UDP
+#define UDP_FILE_QUERY_RETRY_INTERVAL 100 // Retry interval
+#define UDP_FILE_QUERY_DST_PORT 5004 // Destination UDP port number
+#define UDP_FILE_QUERY_MAGIC_NUMBER "{5E465695-7923-4CCD-9B51-44444BE1E758}" // Magic number
+#define UDP_FILE_QUERY_BFLETS_TXT_FILENAME "|BFletsUdpList.txt" // Text file name of the IPv6 node list
+
+// The constant for DNS proxy for the B FLETs
+#define BFLETS_DNS_PROXY_PORT 443
+#define BFLETS_DNS_PROXY_PATH "/ddns/queryhost.aspx"
+#define BFLETS_DNS_PROXY_CERT_HASH "EFAC5FA0CDD14E0F864EED58A73C35D7E33B62F3"
+#define BFLETS_DNS_PROXY_TIMEOUT_FOR_GET_F 500 // Timeout when searching for the server by UDP
+#define BFLETS_DNS_PROXY_TIMEOUT_FOR_QUERY 3000 // Timeout for the response from the proxy DNS server
+
+// FLET'S Hikar-Next (East) DNS proxy host name
+#define FLETS_NGN_EAST_DNS_PROXY_HOSTNAME "senet.aoi.flets-east.jp"
+#define FLETS_NGN_WEST_DNS_PROXY_HOSTNAME "senet.p-ns.flets-west.jp"
+#define FLETS_NGN_DNS_QUERY_TIMEOUT 1000 // FLET'S Hikar-Next host name query timeout
+
+// Detection result of the type of FLET'S line
+#define FLETS_DETECT_TYPE_EAST_BFLETS_PRIVATE 1 // NTT East B-FLETs
+#define FLETS_DETECT_TYPE_EAST_NGN_PRIVATE 2 // Wrapping in network of NTT East NGN
+#define FLETS_DETECT_TYPE_WEST_NGN_PRIVATE 4 // Wrapping in network of NTT West NGN
+
+// NIC adapter entry
+struct NIC_ENTRY
+{
+ char IfName[MAX_SIZE];
+ UCHAR MacAddress[6];
+};
+
+
+// HTTP value
+struct HTTP_VALUE
+{
+ char *Name; // Name
+ char *Data; // Data
+};
+
+// HTTP header
+struct HTTP_HEADER
+{
+ char *Method; // Method
+ char *Target; // Target
+ char *Version; // Version
+ LIST *ValueList; // Value list
+};
+
+// HTTPS server / client related string constant
+#define DEFAULT_USER_AGENT "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)"
+#define DEFAULT_ACCEPT "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/msword, application/vnd.ms-powerpoint, application/vnd.ms-excel, */*"
+#define DEFAULT_ENCODING "gzip, deflate"
+#define HTTP_CONTENT_TYPE "text/html; charset=iso-8859-1"
+#define HTTP_CONTENT_TYPE2 "application/octet-stream"
+#define HTTP_CONTENT_TYPE3 "image/jpeg"
+#define HTTP_CONTENT_TYPE4 "text/html"
+#define HTTP_CONTENT_TYPE5 "message/rfc822"
+#define HTTP_KEEP_ALIVE "timeout=15; max=19"
+#define HTTP_VPN_TARGET "/vpnsvc/vpn.cgi"
+#define HTTP_VPN_TARGET2 "/vpnsvc/connect.cgi"
+#define HTTP_VPN_TARGET_POSTDATA "VPNCONNECT"
+#define HTTP_SAITAMA "/saitama.jpg"
+#define HTTP_PICTURES "/picture"
+// Maximum size of a single line in the HTTP header
+#define HTTP_HEADER_LINE_MAX_SIZE 4096
+// Maximum number of lines in the HTTP header
+#define HTTP_HEADER_MAX_LINES 128
+// Maximum size of the random number to be included in the PACK
+#define HTTP_PACK_RAND_SIZE_MAX 1000
+// Maximum PACK size in the HTTP
+#define HTTP_PACK_MAX_SIZE 65536
+
+
+
+
+
+int GetCurrentTimezone();
+
+bool GetSniNameFromSslPacket(UCHAR *packet_buf, UINT packet_size, char *sni, UINT sni_size);
+bool GetSniNameFromPreSslConnection(SOCK *s, char *sni, UINT sni_size);
+
+bool IsUseDnsProxy();
+bool IsUseAlternativeHostname();
+
+#ifdef OS_WIN32
+int GetCurrentTimezoneWin32();
+#endif // OS_WIN32
+
+HTTP_VALUE *GetHttpValue(HTTP_HEADER *header, char *name);
+void AddHttpValue(HTTP_HEADER *header, HTTP_VALUE *value);
+HTTP_HEADER *NewHttpHeader(char *method, char *target, char *version);
+HTTP_HEADER *NewHttpHeaderEx(char *method, char *target, char *version, bool no_sort);
+int CompareHttpValue(void *p1, void *p2);
+void FreeHttpValue(HTTP_VALUE *value);
+void FreeHttpHeader(HTTP_HEADER *header);
+
+bool SendPack(SOCK *s, PACK *p);
+PACK *RecvPack(SOCK *s);
+PACK *RecvPackWithHash(SOCK *s);
+bool SendPackWithHash(SOCK *s, PACK *p);
+
+UINT GetErrorFromPack(PACK *p);
+PACK *PackError(UINT error);
+
+void CreateDummyValue(PACK *p);
+
+HTTP_VALUE *NewHttpValue(char *name, char *data);
+char *RecvLine(SOCK *s, UINT max_size);
+HTTP_HEADER *RecvHttpHeader(SOCK *s);
+bool SendHttpHeader(SOCK *s, HTTP_HEADER *header);
+char *HttpHeaderToStr(HTTP_HEADER *header);
+bool PostHttp(SOCK *s, HTTP_HEADER *header, void *post_data, UINT post_size);
+UINT GetContentLength(HTTP_HEADER *header);
+void GetHttpDateStr(char *str, UINT size, UINT64 t);
+bool HttpSendForbidden(SOCK *s, char *target, char *server_id);
+bool HttpSendNotFound(SOCK *s, char *target);
+bool HttpSendNotImplemented(SOCK *s, char *method, char *target, char *version);
+bool HttpServerSend(SOCK *s, PACK *p);
+bool HttpClientSend(SOCK *s, PACK *p);
+PACK *HttpServerRecv(SOCK *s);
+PACK *HttpClientRecv(SOCK *s);
+
+bool HttpSendServerError(SOCK *s, char *target);
+
+bool GetIPViaDnsProxyForJapanFlets(IP *ip_ret, char *hostname, bool ipv6, UINT timeout, bool *cancel, char *dns_proxy_hostname);
+bool GetDnsProxyIPAddressForJapanBFlets(IP *ip_ret, UINT timeout, bool *cancel);
+BUF *QueryFileByUdpForJapanBFlets(UINT timeout, bool *cancel);
+BUF *QueryFileByIPv6Udp(LIST *ip_list, UINT timeout, bool *cancel);
+UINT DetectFletsType();
+
+void ListenTcpForPopupFirewallDialog();
+
+bool DetectIsServerSoftEtherVPN(SOCK *s);
+void ConnectThreadForTcp(THREAD *thread, void *param);
+void ConnectThreadForRUDP(THREAD *thread, void *param);
+void ConnectThreadForOverDnsOrIcmp(THREAD *thread, void *param);
+SOCK *NewRUDPClientNatT(char *svc_name, IP *ip, UINT *error_code, UINT timeout, bool *cancel, char *hint_str, char *target_hostname);
+RUDP_STACK *NewRUDPServer(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode, volatile UINT *natt_global_udp_port, UCHAR rand_port_id);
+SOCK *NewRUDPClientDirect(char *svc_name, IP *ip, UINT port, UINT *error_code, UINT timeout, bool *cancel, SOCK *sock, SOCK_EVENT *sock_event, UINT local_port, bool over_dns_mode);
+RUDP_STACK *NewRUDP(bool server_mode, char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, SOCK *sock, SOCK_EVENT *sock_event, bool server_no_natt_register, bool over_dns_mode, IP *client_target_ip, volatile UINT *natt_global_udp_port, UCHAR rand_port_id);
+void FreeRUDP(RUDP_STACK *r);
+void RUDPMainThread(THREAD *thread, void *param);
+void RUDPRecvProc(RUDP_STACK *r, UDPPACKET *p);
+void RUDPInterruptProc(RUDP_STACK *r);
+void RUDPIpQueryThread(THREAD *thread, void *param);
+void RUDPSendPacket(RUDP_STACK *r, IP *dest_ip, UINT dest_port, void *data, UINT size, UINT icmp_type);
+void GetCurrentMachineIpProcessHash(void *hash);
+void GetCurrentMachineIpProcessHashInternal(void *hash);
+int RUDPCompareSessionList(void *p1, void *p2);
+RUDP_SESSION *RUDPNewSession(bool server_mode, IP *my_ip, UINT my_port, IP *your_ip, UINT your_port, UCHAR *init_key);
+void RUDPFreeSession(RUDP_SESSION *se);
+int RUDPCompareSegmentList(void *p1, void *p2);
+RUDP_SESSION *RUDPSearchSession(RUDP_STACK *r, IP *my_ip, UINT my_port, IP *your_ip, UINT your_port);
+void RUDPSendSegmentNow(RUDP_STACK *r, RUDP_SESSION *se, UINT64 seq_no, void *data, UINT size);
+void RUDPSendSegment(RUDP_STACK *r, RUDP_SESSION *se, void *data, UINT size);
+bool RUDPProcessRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data, UINT recv_size);
+bool RUDPCheckSignOfRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data, UINT recv_size);
+void RUDPProcessAck(RUDP_STACK *r, RUDP_SESSION *se, UINT64 seq);
+void RUDPProcessAck2(RUDP_STACK *r, RUDP_SESSION *se, UINT64 max_seq);
+void RUDPProcessRecvPayload(RUDP_STACK *r, RUDP_SESSION *se, UINT64 seq, void *payload_data, UINT payload_size);
+void RUDPInitSock(RUDP_STACK *r, RUDP_SESSION *se);
+void RUDPDisconnectSession(RUDP_STACK *r, RUDP_SESSION *se, bool disconnected_by_you);
+UINT64 RUDPGetCurrentSendingMinSeqNo(RUDP_SESSION *se);
+UINT64 RUDPGetCurrentSendingMaxSeqNo(RUDP_SESSION *se);
+SOCK *ListenRUDP(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode);
+SOCK *ListenRUDPEx(char *svc_name, RUDP_STACK_INTERRUPTS_PROC *proc_interrupts, RUDP_STACK_RPC_RECV_PROC *proc_rpc_recv, void *param, UINT port, bool no_natt_register, bool over_dns_mode,
+ volatile UINT *natt_global_udp_port, UCHAR rand_port_id);
+SOCK *AcceptRUDP(SOCK *s);
+void *InitWaitUntilHostIPAddressChanged();
+void FreeWaitUntilHostIPAddressChanged(void *p);
+void WaitUntilHostIPAddressChanged(void *p, EVENT *event, UINT timeout, UINT ip_check_interval);
+UINT GetHostIPAddressHash32();
+bool GetMyPrivateIP(IP *ip);
+UINT GenRandInterval(UINT min, UINT max);
+void RUDPProcess_NatT_Recv(RUDP_STACK *r, UDPPACKET *udp);
+void RUDPDo_NatT_Interrupt(RUDP_STACK *r);
+void RUDPGetRegisterHostNameByIP(char *dst, UINT size, IP *ip);
+bool RUDPParseIPAndPortStr(void *data, UINT data_size, IP *ip, UINT *port);
+void ParseNtUsername(char *src_username, char *dst_username, UINT dst_username_size, char *dst_domain, UINT dst_domain_size, bool do_not_parse_atmark);
+void RUDPBulkSend(RUDP_STACK *r, RUDP_SESSION *se, void *data, UINT data_size);
+bool RUDPProcessBulkRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data, UINT recv_size);
+UINT RUDPCalcBestMssForBulk(RUDP_STACK *r, RUDP_SESSION *se);
+bool IsIPLocalHostOrMySelf(IP *ip);
+UINT RUDPGetRandPortNumber(UCHAR rand_port_id);
+
+bool GetBestLocalIpForTarget(IP *local_ip, IP *target_ip);
+SOCK *NewUDP4ForSpecificIp(IP *target_ip, UINT port);
+
+#ifdef OS_WIN32
+
+// Function prototype for Win32
+void Win32InitSocketLibrary();
+void Win32FreeSocketLibrary();
+void Win32Select(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2);
+void Win32InitAsyncSocket(SOCK *sock);
+void Win32JoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event);
+void Win32FreeAsyncSocket(SOCK *sock);
+void Win32IpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row);
+void Win32RouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry);
+int Win32CompareRouteEntryByMetric(void *p1, void *p2);
+ROUTE_TABLE *Win32GetRouteTable();
+bool Win32AddRouteEntry(ROUTE_ENTRY *e, bool *already_exists);
+void Win32DeleteRouteEntry(ROUTE_ENTRY *e);
+void Win32UINTToIP(IP *ip, UINT i);
+UINT Win32IPToUINT(IP *ip);
+UINT Win32GetVLanInterfaceID(char *instance_name);
+char **Win32EnumVLan(char *tag_name);
+void Win32Cancel(CANCEL *c);
+void Win32CleanupCancel(CANCEL *c);
+CANCEL *Win32NewCancel();
+SOCK_EVENT *Win32NewSockEvent();
+void Win32SetSockEvent(SOCK_EVENT *event);
+void Win32CleanupSockEvent(SOCK_EVENT *event);
+bool Win32WaitSockEvent(SOCK_EVENT *event, UINT timeout);
+bool Win32GetDefaultDns(IP *ip, char *domain, UINT size);
+bool Win32GetDnsSuffix(char *domain, UINT size);
+void Win32RenewDhcp();
+void Win32RenewDhcp9x(UINT if_id);
+void Win32ReleaseDhcp9x(UINT if_id, bool wait);
+void Win32FlushDnsCache();
+int CompareIpAdapterIndexMap(void *p1, void *p2);
+LIST *Win32GetTcpTableList();
+LIST *Win32GetTcpTableListByGetExtendedTcpTable();
+LIST *Win32GetTcpTableListByAllocateAndGetTcpExTableFromStack();
+LIST *Win32GetTcpTableListByGetTcpTable();
+ROUTE_CHANGE *Win32NewRouteChange();
+void Win32FreeRouteChange(ROUTE_CHANGE *r);
+bool Win32IsRouteChanged(ROUTE_CHANGE *r);
+bool Win32GetAdapterFromGuid(void *a, char *guid);
+SOCKET Win32Accept(SOCK *sock, SOCKET s, struct sockaddr *addr, int *addrlen, bool ipv6);
+
+bool Win32ReleaseAddress(void *a);
+bool Win32ReleaseAddressByGuid(char *guid);
+bool Win32ReleaseAddressByGuidEx(char *guid, UINT timeout);
+void Win32ReleaseAddressByGuidExThread(THREAD *t, void *param);
+void ReleaseWin32ReleaseAddressByGuidThreadParam(WIN32_RELEASEADDRESS_THREAD_PARAM *p);
+bool Win32ReleaseOrRenewAddressByGuidEx(char *guid, UINT timeout, bool renew);
+bool Win32RenewAddress(void *a);
+bool Win32RenewAddressByGuid(char *guid);
+bool Win32RenewAddressByGuidEx(char *guid, UINT timeout);
+
+
+#else // OS_WIN32
+
+// Function prototype for UNIX
+void UnixInitSocketLibrary();
+void UnixFreeSocketLibrary();
+void UnixSelect(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2);
+void UnixInitAsyncSocket(SOCK *sock);
+void UnixJoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event);
+void UnixFreeAsyncSocket(SOCK *sock);
+void UnixIpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row);
+void UnixRouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry);
+int UnixCompareRouteEntryByMetric(void *p1, void *p2);
+ROUTE_TABLE *UnixGetRouteTable();
+bool UnixAddRouteEntry(ROUTE_ENTRY *e, bool *already_exists);
+void UnixDeleteRouteEntry(ROUTE_ENTRY *e);
+UINT UnixGetVLanInterfaceID(char *instance_name);
+char **UnixEnumVLan(char *tag_name);
+void UnixCancel(CANCEL *c);
+void UnixCleanupCancel(CANCEL *c);
+CANCEL *UnixNewCancel();
+SOCK_EVENT *UnixNewSockEvent();
+void UnixSetSockEvent(SOCK_EVENT *event);
+void UnixCleanupSockEvent(SOCK_EVENT *event);
+bool UnixWaitSockEvent(SOCK_EVENT *event, UINT timeout);
+bool UnixGetDefaultDns(IP *ip);
+void UnixRenewDhcp();
+void UnixNewPipe(int *pipe_read, int *pipe_write);
+void UnixWritePipe(int pipe_write);
+void UnixDeletePipe(int p1, int p2);
+void UnixSelectInner(UINT num_read, UINT *reads, UINT num_write, UINT *writes, UINT timeout);
+void UnixSetSocketNonBlockingMode(int fd, bool nonblock);
+
+#endif // OS_WIN32
+
+// Function prototype
+void InitNetwork();
+void FreeNetwork();
+void InitDnsCache();
+void FreeDnsCache();
+void LockDnsCache();
+void UnlockDnsCache();
+int CompareDnsCache(void *p1, void *p2);
+void GenDnsCacheKeyName(char *dst, UINT size, char *src, bool ipv6);
+void NewDnsCacheEx(char *hostname, IP *ip, bool ipv6);
+DNSCACHE *FindDnsCacheEx(char *hostname, bool ipv6);
+bool QueryDnsCacheEx(IP *ip, char *hostname, bool ipv6);
+void NewDnsCache(char *hostname, IP *ip);
+DNSCACHE *FindDnsCache(char *hostname);
+bool QueryDnsCache(IP *ip, char *hostname);
+void InAddrToIP(IP *ip, struct in_addr *addr);
+void InAddrToIP6(IP *ip, struct in6_addr *addr);
+void IPToInAddr(struct in_addr *addr, IP *ip);
+void IPToInAddr6(struct in6_addr *addr, IP *ip);
+bool StrToIP(IP *ip, char *str);
+UINT StrToIP32(char *str);
+bool UniStrToIP(IP *ip, wchar_t *str);
+UINT UniStrToIP32(wchar_t *str);
+void IPToStr(char *str, UINT size, IP *ip);
+void IPToStr4(char *str, UINT size, IP *ip);
+void IPToStr32(char *str, UINT size, UINT ip);
+void IPToStr128(char *str, UINT size, UCHAR *ip_bytes);
+void IPToStr4or6(char *str, UINT size, UINT ip_4_uint, UCHAR *ip_6_bytes);
+void IPToUniStr(wchar_t *str, UINT size, IP *ip);
+void IPToUniStr32(wchar_t *str, UINT size, UINT ip);
+bool GetIPEx(IP *ip, char *hostname, bool ipv6);
+bool GetIP46(IP *ip4, IP *ip6, char *hostname);
+bool GetIP46Ex(IP *ip4, IP *ip6, char *hostname, UINT timeout, bool *cancel);
+bool GetIP46Any4(IP *ip, char *hostname);
+bool GetIP46Any6(IP *ip, char *hostname);
+bool GetIP(IP *ip, char *hostname);
+bool GetIP4(IP *ip, char *hostname);
+bool GetIP6(IP *ip, char *hostname);
+bool GetIP4Ex(IP *ip, char *hostname, UINT timeout, bool *cancel);
+bool GetIP6Ex(IP *ip, char *hostname, UINT timeout, bool *cancel);
+bool GetIP4Ex6Ex(IP *ip, char *hostname, UINT timeout, bool ipv6, bool *cancel);
+bool GetIP4Ex6Ex2(IP *ip, char *hostname, UINT timeout, bool ipv6, bool *cancel, bool only_direct_dns);
+void GetIP4Ex6ExThread(THREAD *t, void *param);
+void ReleaseGetIPThreadParam(GETIP_THREAD_PARAM *p);
+void CleanupGetIPThreadParam(GETIP_THREAD_PARAM *p);
+bool GetIP4Inner(IP *ip, char *hostname);
+bool GetIP6Inner(IP *ip, char *hostname);
+bool GetHostNameInner(char *hostname, UINT size, IP *ip);
+bool GetHostNameInner6(char *hostname, UINT size, IP *ip);
+bool GetHostName(char *hostname, UINT size, IP *ip);
+void GetHostNameThread(THREAD *t, void *p);
+void GetMachineName(char *name, UINT size);
+void GetMachineNameEx(char *name, UINT size, bool no_load_hosts);
+bool GetMachineNameFromHosts(char *name, UINT size);
+void GetMachineIp(IP *ip);
+void GetMachineHostName(char *name, UINT size);
+void UINTToIP(IP *ip, UINT value);
+UINT IPToUINT(IP *ip);
+SOCK *NewSock();
+void ReleaseSock(SOCK *s);
+void CleanupSock(SOCK *s);
+SOCK *Connect(char *hostname, UINT port);
+SOCK *ConnectEx(char *hostname, UINT port, UINT timeout);
+SOCK *ConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag);
+SOCK *ConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool ssl_no_tls, bool no_get_hostname);
+SOCKET ConnectTimeoutIPv4(IP *ip, UINT port, UINT timeout, bool *cancel_flag);
+void SetSocketSendRecvBufferSize(SOCKET s, UINT size);
+UINT GetSocketBufferSize(SOCKET s, bool send);
+bool SetSocketBufferSize(SOCKET s, bool send, UINT size);
+UINT SetSocketBufferSizeWithBestEffort(SOCKET s, bool send, UINT size);
+void InitUdpSocketBufferSize(SOCKET s);
+void QuerySocketInformation(SOCK *sock);
+bool SetTtl(SOCK *sock, UINT ttl);
+void Disconnect(SOCK *sock);
+SOCK *Listen(UINT port);
+SOCK *ListenEx(UINT port, bool local_only);
+SOCK *ListenEx2(UINT port, bool local_only, bool enable_ca);
+SOCK *Listen6(UINT port);
+SOCK *ListenEx6(UINT port, bool local_only);
+SOCK *ListenEx62(UINT port, bool local_only, bool enable_ca);
+SOCK *Accept(SOCK *sock);
+SOCK *Accept6(SOCK *sock);
+UINT Send(SOCK *sock, void *data, UINT size, bool secure);
+UINT Recv(SOCK *sock, void *data, UINT size, bool secure);
+UINT Peek(SOCK *sock, void *data, UINT size);
+void SetNoNeedToRead(SOCK *sock);
+UINT SecureSend(SOCK *sock, void *data, UINT size);
+UINT SecureRecv(SOCK *sock, void *data, UINT size);
+bool StartSSL(SOCK *sock, X *x, K *priv);
+bool StartSSLEx(SOCK *sock, X *x, K *priv, bool client_tls, UINT ssl_timeout, char *sni_hostname);
+bool AddChainSslCert(struct ssl_ctx_st *ctx, X *x);
+void AddChainSslCertOnDirectory(struct ssl_ctx_st *ctx);
+bool SendAll(SOCK *sock, void *data, UINT size, bool secure);
+void SendAdd(SOCK *sock, void *data, UINT size);
+bool SendNow(SOCK *sock, int secure);
+bool RecvAll(SOCK *sock, void *data, UINT size, bool secure);
+bool RecvAllEx(SOCK *sock, void **data_new_ptr, UINT size, bool secure);
+void InitSockSet(SOCKSET *set);
+void AddSockSet(SOCKSET *set, SOCK *sock);
+CANCEL *NewCancel();
+CANCEL *NewCancelSpecial(void *hEvent);
+void ReleaseCancel(CANCEL *c);
+void CleanupCancel(CANCEL *c);
+void Cancel(CANCEL *c);
+void Select(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2);
+void SetWantToUseCipher(SOCK *sock, char *name);
+void InitAsyncSocket(SOCK *sock);
+SOCK *NewUDP(UINT port);
+SOCK *NewUDPEx(UINT port, bool ipv6);
+SOCK *NewUDPEx2(UINT port, bool ipv6, IP *ip);
+SOCK *NewUDPEx3(UINT port, IP *ip);
+SOCK *NewUDP4(UINT port, IP *ip);
+SOCK *NewUDP6(UINT port, IP *ip);
+SOCK *NewUDPEx2Rand(bool ipv6, IP *ip, void *rand_seed, UINT rand_seed_size, UINT num_retry);
+SOCK *NewUDPEx2RandMachineAndExePath(bool ipv6, IP *ip, UINT num_retry, UCHAR rand_port_id);
+UINT NewRandPortByMachineAndExePath(UINT start_port, UINT end_port, UINT additional_int);
+void DisableUDPChecksum(SOCK *s);
+UINT SendTo(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size);
+UINT SendToEx(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size, bool broadcast);
+UINT SendTo6(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size);
+UINT SendTo6Ex(SOCK *sock, IP *dest_addr, UINT dest_port, void *data, UINT size, bool broadcast);
+UINT RecvFrom(SOCK *sock, IP *src_addr, UINT *src_port, void *data, UINT size);
+UINT RecvFrom6(SOCK *sock, IP *src_addr, UINT *src_port, void *data, UINT size);
+void SetTimeout(SOCK *sock, UINT timeout);
+UINT GetTimeout(SOCK *sock);
+bool CheckTCPPort(char *hostname, UINT port);
+bool CheckTCPPortEx(char *hostname, UINT port, UINT timeout);
+void CheckTCPPortThread(THREAD *thread, void *param);
+ROUTE_TABLE *GetRouteTable();
+void FreeRouteTable(ROUTE_TABLE *t);
+bool AddRouteEntryEx(ROUTE_ENTRY *e, bool *already_exists);
+bool AddRouteEntry(ROUTE_ENTRY *e);
+void DeleteRouteEntry(ROUTE_ENTRY *e);
+char **EnumVLan(char *tag_name);
+void FreeEnumVLan(char **s);
+UINT GetVLanInterfaceID(char *tag_name);
+ROUTE_ENTRY *GetBestRouteEntry(IP *ip);
+ROUTE_ENTRY *GetBestRouteEntryEx(IP *ip, UINT exclude_if_id);
+ROUTE_ENTRY *GetBestRouteEntryFromRouteTable(ROUTE_TABLE *table, IP *ip);
+ROUTE_ENTRY *GetBestRouteEntryFromRouteTableEx(ROUTE_TABLE *table, IP *ip, UINT exclude_if_id);
+void FreeRouteEntry(ROUTE_ENTRY *e);
+void JoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event);
+SOCK_EVENT *NewSockEvent();
+void SetSockEvent(SOCK_EVENT *event);
+void CleanupSockEvent(SOCK_EVENT *event);
+bool WaitSockEvent(SOCK_EVENT *event, UINT timeout);
+void ReleaseSockEvent(SOCK_EVENT *event);
+void SetIP(IP *ip, UCHAR a1, UCHAR a2, UCHAR a3, UCHAR a4);
+UINT SetIP32(UCHAR a1, UCHAR a2, UCHAR a3, UCHAR a4);
+bool GetDefaultDns(IP *ip);
+bool GetDomainName(char *name, UINT size);
+bool UnixGetDomainName(char *name, UINT size);
+void RenewDhcp();
+void AcceptInit(SOCK *s);
+bool CheckCipherListName(char *name);
+TOKEN_LIST *GetCipherList();
+COUNTER *GetNumTcpConnectionsCounter();
+void InitWaitThread();
+void FreeWaitThread();
+void AddWaitThread(THREAD *t);
+void DelWaitThread(THREAD *t);
+void InitHostCache();
+void FreeHostCache();
+int CompareHostCache(void *p1, void *p2);
+void AddHostCache(IP *ip, char *hostname);
+bool GetHostCache(char *hostname, UINT size, IP *ip);
+bool IsSubnetMask(IP *ip);
+bool IsSubnetMask4(IP *ip);
+bool IsSubnetMask32(UINT ip);
+bool IsNetworkAddress(IP *ip, IP *mask);
+bool IsNetworkAddress4(IP *ip, IP *mask);
+bool IsNetworkAddress32(UINT ip, UINT mask);
+bool IsHostIPAddress4(IP *ip);
+bool IsHostIPAddress32(UINT ip);
+bool IsZeroIp(IP *ip);
+bool IsZeroIP(IP *ip);
+bool IsZeroIP6Addr(IPV6_ADDR *addr);
+UINT IntToSubnetMask32(UINT i);
+void IntToSubnetMask4(IP *ip, UINT i);
+bool GetNetBiosName(char *name, UINT size, IP *ip);
+bool NormalizeMacAddress(char *dst, UINT size, char *src);
+SOCKLIST *NewSockList();
+void AddSockList(SOCKLIST *sl, SOCK *s);
+void DelSockList(SOCKLIST *sl, SOCK *s);
+void StopSockList(SOCKLIST *sl);
+void FreeSockList(SOCKLIST *sl);
+bool IsIPv6Supported();
+void SetSockTos(SOCK *s, int tos);
+void SetSockHighPriority(SOCK *s, bool flag);
+void InitIpClientList();
+void FreeIpClientList();
+int CompareIpClientList(void *p1, void *p2);
+void AddIpClient(IP *ip);
+void DelIpClient(IP *ip);
+IP_CLIENT *SearchIpClient(IP *ip);
+UINT GetNumIpClient(IP *ip);
+void SetLinuxArpFilter();
+LIST *GetTcpTableList();
+void FreeTcpTableList(LIST *o);
+int CompareTcpTable(void *p1, void *p2);
+void PrintTcpTableList(LIST *o);
+TCPTABLE *GetTcpTableFromEndPoint(LIST *o, IP *local_ip, UINT local_port, IP *remote_ip, UINT remote_port);
+UINT GetTcpProcessIdFromSocket(SOCK *s);
+UINT GetTcpProcessIdFromSocketReverse(SOCK *s);
+bool CanGetTcpProcessId();
+int connect_timeout(SOCKET s, struct sockaddr *addr, int size, int timeout, bool *cancel_flag);
+void EnableNetworkNameCache();
+void DisableNetworkNameCache();
+bool IsNetworkNameCacheEnabled();
+ROUTE_CHANGE *NewRouteChange();
+void FreeRouteChange(ROUTE_CHANGE *r);
+bool IsRouteChanged(ROUTE_CHANGE *r);
+void RouteToStr(char *str, UINT str_size, ROUTE_ENTRY *e);
+void DebugPrintRoute(ROUTE_ENTRY *e);
+void DebugPrintRouteTable(ROUTE_TABLE *r);
+bool IsIPv6LocalNetworkAddress(IP *ip);
+
+void SocketTimeoutThread(THREAD *t, void *param);
+SOCKET_TIMEOUT_PARAM *NewSocketTimeout(SOCK *sock);
+void FreeSocketTimeout(SOCKET_TIMEOUT_PARAM *ttp);
+
+void CopyIP(IP *dst, IP *src);
+bool CheckSubnetLength6(UINT i);
+bool IsIP6(IP *ip);
+bool IsIP4(IP *ip);
+bool IsSameIPVer(IP *ip1, IP *ip2);
+void IPv6AddrToIP(IP *ip, IPV6_ADDR *addr);
+bool IPToIPv6Addr(IPV6_ADDR *addr, IP *ip);
+void SetIP6(IP *ip, UCHAR *value);
+void GetLocalHostIP6(IP *ip);
+void GetLocalHostIP4(IP *ip);
+bool IsLocalHostIP6(IP *ip);
+bool IsLocalHostIP4(IP *ip);
+bool IsLocalHostIP(IP *ip);
+void ZeroIP6(IP *ip);
+void ZeroIP4(IP *ip);
+bool CheckIPItemStr6(char *str);
+void IPItemStrToChars6(UCHAR *chars, char *str);
+bool StrToIP6(IP *ip, char *str);
+bool StrToIP6Addr(IPV6_ADDR *ip, char *str);
+void IPToStr6(char *str, UINT size, IP *ip);
+void IP6AddrToStr(char *str, UINT size, IPV6_ADDR *addr);
+void IPToStr6Array(char *str, UINT size, UCHAR *bytes);
+void IPToStr6Inner(char *str, IP *ip);
+void IntToSubnetMask6(IP *ip, UINT i);
+void IPNot6(IP *dst, IP *a);
+void IPOr6(IP *dst, IP *a, IP *b);
+void IPAnd6(IP *dst, IP *a, IP *b);
+void GetAllRouterMulticastAddress6(IP *ip);
+void GetAllNodeMulticaseAddress6(IP *ip);
+void GetLoopbackAddress6(IP *ip);
+void GetAllFilledAddress6(IP *ip);
+UINT GetIPAddrType6(IP *ip);
+UINT GetIPv6AddrType(IPV6_ADDR *addr);
+void GenerateMulticastMacAddress6(UCHAR *mac, IP *ip);
+void GetSoliciationMulticastAddr6(IP *dst, IP *src);
+bool CheckUnicastAddress(IP *ip);
+bool IsNetworkPrefixAddress6(IP *ip, IP *subnet);
+bool IsNetworkAddress6(IP *ip, IP *subnet);
+void GetHostAddress6(IP *dst, IP *ip, IP *subnet);
+void GetPrefixAddress6(IP *dst, IP *ip, IP *subnet);
+bool IsNetworkPrefixAddress6(IP *ip, IP *subnet);
+bool IsInSameNetwork6(IP *a1, IP *a2, IP *subnet);
+bool IsInSameNetwork6ByStr(char *ip1, char *ip2, char *subnet);
+void GenerateEui64Address6(UCHAR *dst, UCHAR *mac);
+void GenerateEui64LocalAddress(IP *a, UCHAR *mac);
+void GenerateEui64GlobalAddress(IP *ip, IP *prefix, IP *subnet, UCHAR *mac);
+bool IsSubnetMask6(IP *a);
+UINT SubnetMaskToInt(IP *a);
+UINT SubnetMaskToInt6(IP *a);
+UINT SubnetMaskToInt4(IP *a);
+bool IsStrIPv6Address(char *str);
+void IPNot4(IP *dst, IP *a);
+void IPOr4(IP *dst, IP *a, IP *b);
+void IPAnd4(IP *dst, IP *a, IP *b);
+bool IsInSameNetwork4(IP *a1, IP *a2, IP *subnet);
+
+bool ParseIpAndSubnetMask4(char *src, UINT *ip, UINT *mask);
+bool ParseIpAndSubnetMask6(char *src, IP *ip, IP *mask);
+bool ParseIpAndSubnetMask46(char *src, IP *ip, IP *mask);
+bool ParseIpAndMask4(char *src, UINT *ip, UINT *mask);
+bool ParseIpAndMask6(char *src, IP *ip, IP *mask);
+bool ParseIpAndMask46(char *src, IP *ip, IP *mask);
+bool IsIpStr4(char *str);
+bool IsIpStr6(char *str);
+bool IsIpMask6(char *str);
+bool IsIpStr46(char *str);
+bool StrToMask4(IP *mask, char *str);
+bool StrToMask6(IP *mask, char *str);
+bool StrToMask6Addr(IPV6_ADDR *mask, char *str);
+bool StrToMask46(IP *mask, char *str, bool ipv6);
+void MaskToStr(char *str, UINT size, IP *mask);
+void Mask6AddrToStrEx(char *str, UINT size, IPV6_ADDR *mask, bool always_full_address);
+void Mask6AddrToStr(char *str, UINT size, IPV6_ADDR *mask);
+void MaskToStr32(char *str, UINT size, UINT mask);
+void MaskToStr32Ex(char *str, UINT size, UINT mask, bool always_full_address);
+void MaskToStrEx(char *str, UINT size, IP *mask, bool always_full_address);
+
+TUBEDATA *NewTubeData(void *data, UINT size, void *header, UINT header_size);
+void FreeTubeData(TUBEDATA *d);
+TUBE *NewTube(UINT size_of_header);
+void ReleaseTube(TUBE *t);
+void CleanupTube(TUBE *t);
+bool TubeSend(TUBE *t, void *data, UINT size, void *header);
+bool TubeSendEx(TUBE *t, void *data, UINT size, void *header, bool no_flush);
+bool TubeSendEx2(TUBE *t, void *data, UINT size, void *header, bool no_flush, UINT max_num_in_queue);
+void TubeFlush(TUBE *t);
+void TubeFlushEx(TUBE *t, bool force);
+TUBEDATA *TubeRecvAsync(TUBE *t);
+TUBEDATA *TubeRecvSync(TUBE *t, UINT timeout);
+TUBEPAIR_DATA *NewTubePairData();
+void ReleaseTubePairData(TUBEPAIR_DATA *d);
+void CleanupTubePairData(TUBEPAIR_DATA *d);
+void NewTubePair(TUBE **t1, TUBE **t2, UINT size_of_header);
+void TubeDisconnect(TUBE *t);
+bool IsTubeConnected(TUBE *t);
+void SetTubeSockEvent(TUBE *t, SOCK_EVENT *e);
+SOCK_EVENT *GetTubeSockEvent(TUBE *t);
+
+TUBE_FLUSH_LIST *NewTubeFlushList();
+void FreeTubeFlushList(TUBE_FLUSH_LIST *f);
+void AddTubeToFlushList(TUBE_FLUSH_LIST *f, TUBE *t);
+void FlushTubeFlushList(TUBE_FLUSH_LIST *f);
+
+LIST *GetHostIPAddressListInternal();
+LIST *GetHostIPAddressList();
+LIST *CloneIPAddressList(LIST *o);
+bool IsMyIPAddress(IP *ip);
+void FreeHostIPAddressList(LIST *o);
+void AddHostIPAddressToList(LIST *o, IP *ip);
+int CmpIpAddressList(void *p1, void *p2);
+
+UDPLISTENER *NewUdpListener(UDPLISTENER_RECV_PROC *recv_proc, void *param);
+void UdpListenerThread(THREAD *thread, void *param);
+void UdpListenerGetPublicPortList(UDPLISTENER *u, char *dst, UINT size);
+void FreeUdpListener(UDPLISTENER *u);
+void AddPortToUdpListener(UDPLISTENER *u, UINT port);
+void DeletePortFromUdpListener(UDPLISTENER *u, UINT port);
+void DeleteAllPortFromUdpListener(UDPLISTENER *u);
+UINT GetUdpListenerPortList(UDPLISTENER *u, UINT **port_list);
+void UdpListenerSendPackets(UDPLISTENER *u, LIST *packet_list);
+void UdpListenerSendPacket(UDPLISTENER *u, UDPPACKET *packet);
+UDPPACKET *NewUdpPacket(IP *src_ip, UINT src_port, IP *dst_ip, UINT dst_port, void *data, UINT size);
+void FreeUdpPacket(UDPPACKET *p);
+UDPLISTENER_SOCK *DetermineUdpSocketForSending(UDPLISTENER *u, UDPPACKET *p);
+bool IsUdpPortOpened(UDPLISTENER *u, IP *server_ip, UINT port);
+
+INTERRUPT_MANAGER *NewInterruptManager();
+void FreeInterruptManager(INTERRUPT_MANAGER *m);
+void AddInterrupt(INTERRUPT_MANAGER *m, UINT64 tick);
+UINT GetNextIntervalForInterrupt(INTERRUPT_MANAGER *m);
+
+void NewSocketPair(SOCK **client, SOCK **server, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port);
+SOCK *NewInProcSocket(TUBE *tube_send, TUBE *tube_recv);
+SOCK *ListenInProc();
+SOCK *AcceptInProc(SOCK *s);
+SOCK *ConnectInProc(SOCK *listen_sock, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port);
+UINT SendInProc(SOCK *sock, void *data, UINT size);
+UINT RecvInProc(SOCK *sock, void *data, UINT size);
+void WaitForTubes(TUBE **tubes, UINT num, UINT timeout);
+
+SOCK *ListenReverse();
+SOCK *AcceptReverse(SOCK *s);
+void InjectNewReverseSocketToAccept(SOCK *listen_sock, SOCK *s, IP *client_ip, UINT client_port);
+
+bool NewTcpPair(SOCK **s1, SOCK **s2);
+SOCK *ListenAnyPortEx(bool local_only);
+SOCK *ListenAnyPortEx2(bool local_only, bool disable_ca);
+
+bool IsIcmpApiSupported();
+ICMP_RESULT *IcmpApiEchoSend(IP *dest_ip, UCHAR ttl, UCHAR *data, UINT size, UINT timeout);
+void IcmpApiFreeResult(ICMP_RESULT *ret);
+
+#ifdef OS_WIN32
+void Win32WaitForTubes(TUBE **tubes, UINT num, UINT timeout);
+#else // OS_WIN32
+void UnixWaitForTubes(TUBE **tubes, UINT num, UINT timeout);
+#endif // OS_WIN32
+
+SSL_PIPE *NewSslPipe(bool server_mode, X *x, K *k, DH_CTX *dh);
+void FreeSslPipe(SSL_PIPE *s);
+bool SyncSslPipe(SSL_PIPE *s);
+
+SSL_BIO *NewSslBioMem();
+SSL_BIO *NewSslBioSsl();
+void FreeSslBio(SSL_BIO *b);
+bool SslBioSync(SSL_BIO *b, bool sync_send, bool sync_recv);
+
+void SetCurrentGlobalIP(IP *ip, bool ipv6);
+bool GetCurrentGlobalIP(IP *ip, bool ipv6);
+void GetCurrentGlobalIPGuess(IP *ip, bool ipv6);
+
+bool IsIPPrivate(IP *ip);
+bool IsIPMyHost(IP *ip);
+void LoadPrivateIPFile();
+bool IsOnPrivateIPFile(UINT ip);
+void FreePrivateIPFile();
+
+LIST *GetNicList();
+void FreeNicList(LIST *o);
+bool IsMacAddressLocal(void *addr);
+bool IsMacAddressLocalInner(LIST *o, void *addr);
+bool IsMacAddressLocalFast(void *addr);
+void RefreshLocalMacAddressList();
+
+struct ssl_ctx_st *NewSSLCtx();
+void FreeSSLCtx(struct ssl_ctx_st *ctx);
+
+void SetCurrentDDnsFqdn(char *name);
+void GetCurrentDDnsFqdn(char *name, UINT size);
+UINT GetCurrentDDnsFqdnHash();
+
+void GetSimpleHostname(char *hostname, UINT hostname_size, char *fqdn);
+
+void DisableRDUPServerGlobally();
+void DisableRUDPRegisterGlobally();
+void SetNatTLowPriority();
+
+void QueryIpThreadMain(THREAD *thread, void *param);
+QUERYIPTHREAD *NewQueryIpThread(char *hostname, UINT interval_last_ok, UINT interval_last_ng);
+bool GetQueryIpThreadResult(QUERYIPTHREAD *t, IP *ip);
+void FreeQueryIpThread(QUERYIPTHREAD *t);
+
+
+bool IsIpInStrList(IP *ip, char *ip_list);
+bool IsInStrByStrList(char *str, char *str_list);
+
+#ifdef OS_WIN32
+LIST *Win32GetNicList();
+#endif // OS_WIN32
+
+
+void InitDynList();
+void FreeDynList();
+void AddDynList(BUF *b);
+void ExtractAndApplyDynList(PACK *p);
+void SetDynListValue(char *name, UINT64 value);
+UINT64 GetDynValue(char *name);
+UINT64 GetDynValueOrDefault(char *name, UINT64 default_value, UINT64 min_value, UINT64 max_value);
+UINT64 GetDynValueOrDefaultSafe(char *name, UINT64 default_value);
+
+
+#endif // NETWORK_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/OS.c b/src/Mayaqua/OS.c
new file mode 100644
index 00000000..66042798
--- /dev/null
+++ b/src/Mayaqua/OS.c
@@ -0,0 +1,527 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// OS.c
+// Operating system dependent code
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+#undef Lock
+#undef Unlock
+
+// Dispatch table
+static OS_DISPATCH_TABLE *os = NULL;
+
+// Convert OS type to a string
+char *OsTypeToStr(UINT type)
+{
+ switch (type)
+ {
+ case 0:
+ return "Unsupported OS by SoftEther VPN\0\n";
+ case OSTYPE_WINDOWS_95:
+ return "Windows 95\0\n";
+ case OSTYPE_WINDOWS_98:
+ return "Windows 98\0\n";
+ case OSTYPE_WINDOWS_ME:
+ return "Windows Millennium Edition\0\n";
+ case OSTYPE_WINDOWS_UNKNOWN:
+ return "Windows 9x Unknown Version\0\n";
+ case OSTYPE_WINDOWS_NT_4_WORKSTATION:
+ return "Windows NT 4.0 Workstation\0\n";
+ case OSTYPE_WINDOWS_NT_4_SERVER:
+ return "Windows NT 4.0 Server\0\n";
+ case OSTYPE_WINDOWS_NT_4_SERVER_ENTERPRISE:
+ return "Windows NT 4.0 Server, Enterprise Edition\0\n";
+ case OSTYPE_WINDOWS_NT_4_BACKOFFICE:
+ return "BackOffice Server 4.5\0\n";
+ case OSTYPE_WINDOWS_NT_4_SMS:
+ return "Small Business Server 4.5\0\n";
+ case OSTYPE_WINDOWS_2000_PROFESSIONAL:
+ return "Windows 2000 Professional\0\n";
+ case OSTYPE_WINDOWS_2000_SERVER:
+ return "Windows 2000 Server\0\n";
+ case OSTYPE_WINDOWS_2000_ADVANCED_SERVER:
+ return "Windows 2000 Advanced Server\0\n";
+ case OSTYPE_WINDOWS_2000_DATACENTER_SERVER:
+ return "Windows 2000 Datacenter Server\0\n";
+ case OSTYPE_WINDOWS_2000_BACKOFFICE:
+ return "BackOffice Server 2000\0\n";
+ case OSTYPE_WINDOWS_2000_SBS:
+ return "Small Business Server 2000\0\n";
+ case OSTYPE_WINDOWS_XP_HOME:
+ return "Windows XP Home Edition\0\n";
+ case OSTYPE_WINDOWS_XP_PROFESSIONAL:
+ return "Windows XP Professional\0\n";
+ case OSTYPE_WINDOWS_2003_WEB:
+ return "Windows Server 2003 Web Edition\0\n";
+ case OSTYPE_WINDOWS_2003_STANDARD:
+ return "Windows Server 2003 Standard Edition\0\n";
+ case OSTYPE_WINDOWS_2003_ENTERPRISE:
+ return "Windows Server 2003 Enterprise Edition\0\n";
+ case OSTYPE_WINDOWS_2003_DATACENTER:
+ return "Windows Server 2003 Datacenter Edition\0\n";
+ case OSTYPE_WINDOWS_2003_BACKOFFICE:
+ return "BackOffice Server 2003\0\n";
+ case OSTYPE_WINDOWS_2003_SBS:
+ return "Small Business Server 2003\0\n";
+ case OSTYPE_WINDOWS_LONGHORN_PROFESSIONAL:
+ return "Windows Vista\0\n";
+ case OSTYPE_WINDOWS_LONGHORN_SERVER:
+ return "Windows Server 2008\0\n";
+ case OSTYPE_WINDOWS_7:
+ return "Windows 7\0\n";
+ case OSTYPE_WINDOWS_SERVER_2008_R2:
+ return "Windows Server 2008 R2\0\n";
+ case OSTYPE_WINDOWS_8:
+ return "Windows 8\0\n";
+ case OSTYPE_WINDOWS_SERVER_8:
+ return "Windows Server 2012\0\n";
+ case OSTYPE_WINDOWS_81:
+ return "Windows 8.1\0\n";
+ case OSTYPE_WINDOWS_SERVER_81:
+ return "Windows Server 2012 R2\0\n";
+ case OSTYPE_WINDOWS_9:
+ return "Windows 8.2 or later\0\n";
+ case OSTYPE_WINDOWS_SERVER_9:
+ return "Windows Server 8.2 or later\0\n";
+ case OSTYPE_UNIX_UNKNOWN:
+ return "UNIX System\0\n";
+ case OSTYPE_LINUX:
+ return "Linux\0\n";
+ case OSTYPE_SOLARIS:
+ return "Sun Solaris\0\n";
+ case OSTYPE_CYGWIN:
+ return "Gnu Cygwin\0\n";
+ case OSTYPE_BSD:
+ return "BSD System\0\n";
+ case OSTYPE_MACOS_X:
+ return "Mac OS X\0\n";
+ }
+
+ return "Unknown OS";
+}
+
+// Initialization
+void OSInit()
+{
+ // Get the dispatch table
+#ifdef OS_WIN32
+ os = Win32GetDispatchTable();
+#else // OS_WIN32
+ os = UnixGetDispatchTable();
+#endif // OS_WIN32
+
+ // Calling the OS-specific initialization function
+ os->Init();
+}
+
+// Release
+void OSFree()
+{
+ os->Free();
+}
+
+// Get the memory information
+void OSGetMemInfo(MEMINFO *info)
+{
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ os->GetMemInfo(info);
+}
+
+// Yield
+void OSYield()
+{
+ os->Yield();
+}
+
+// Start a Single instance
+void *OSNewSingleInstance(char *instance_name)
+{
+ return os->NewSingleInstance(instance_name);
+}
+
+void OSFreeSingleInstance(void *data)
+{
+ os->FreeSingleInstance(data);
+}
+
+// Raise the priority
+void OSSetHighPriority()
+{
+ os->SetHighPriority();
+}
+
+// Restore the priority
+void OSRestorePriority()
+{
+ os->RestorePriority();
+}
+
+// Get the product ID
+char* OSGetProductId()
+{
+ return os->GetProductId();
+}
+
+// Check whether the OS is supported
+bool OSIsSupportedOs()
+{
+ return os->IsSupportedOs();
+}
+
+// Getting OS information
+void OSGetOsInfo(OS_INFO *info)
+{
+ os->GetOsInfo(info);
+}
+
+// Show an alert
+void OSAlert(char *msg, char *caption)
+{
+ os->Alert(msg, caption);
+}
+void OSAlertW(wchar_t *msg, wchar_t *caption)
+{
+ os->AlertW(msg, caption);
+}
+
+// Run a process
+bool OSRun(char *filename, char *arg, bool hide, bool wait)
+{
+ return os->Run(filename, arg, hide, wait);
+}
+bool OSRunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
+{
+ return os->RunW(filename, arg, hide, wait);
+}
+
+// Get the Thread ID
+UINT OSThreadId()
+{
+ return os->ThreadId();
+}
+
+// Rename
+bool OSFileRename(char *old_name, char *new_name)
+{
+ return os->FileRename(old_name, new_name);
+}
+bool OSFileRenameW(wchar_t *old_name, wchar_t *new_name)
+{
+ return os->FileRenameW(old_name, new_name);
+}
+
+// Get the file size
+UINT64 OSFileSize(void *pData)
+{
+ return os->FileSize(pData);
+}
+
+// Seek the file
+bool OSFileSeek(void *pData, UINT mode, int offset)
+{
+ return os->FileSeek(pData, mode, offset);
+}
+
+// Delete the file
+bool OSFileDelete(char *name)
+{
+ return os->FileDelete(name);
+}
+bool OSFileDeleteW(wchar_t *name)
+{
+ return os->FileDeleteW(name);
+}
+
+// Create a directory
+bool OSMakeDir(char *name)
+{
+ return os->MakeDir(name);
+}
+bool OSMakeDirW(wchar_t *name)
+{
+ return os->MakeDirW(name);
+}
+
+// Delete the directory
+bool OSDeleteDir(char *name)
+{
+ return os->DeleteDir(name);
+}
+bool OSDeleteDirW(wchar_t *name)
+{
+ return os->DeleteDirW(name);
+}
+
+// Open the file
+void *OSFileOpen(char *name, bool write_mode, bool read_lock)
+{
+ return os->FileOpen(name, write_mode, read_lock);
+}
+void *OSFileOpenW(wchar_t *name, bool write_mode, bool read_lock)
+{
+ return os->FileOpenW(name, write_mode, read_lock);
+}
+
+// Create a file
+void *OSFileCreate(char *name)
+{
+ return os->FileCreate(name);
+}
+void *OSFileCreateW(wchar_t *name)
+{
+ return os->FileCreateW(name);
+}
+
+// Write to a file
+bool OSFileWrite(void *pData, void *buf, UINT size)
+{
+ return os->FileWrite(pData, buf, size);
+}
+
+// Read from a file
+bool OSFileRead(void *pData, void *buf, UINT size)
+{
+ return os->FileRead(pData, buf, size);
+}
+
+// Close the file
+void OSFileClose(void *pData, bool no_flush)
+{
+ os->FileClose(pData, no_flush);
+}
+
+// Flush to the file
+void OSFileFlush(void *pData)
+{
+ os->FileFlush(pData);
+}
+
+// Get the call stack
+CALLSTACK_DATA *OSGetCallStack()
+{
+ return os->GetCallStack();
+}
+
+// Get the symbol information
+bool OSGetCallStackSymbolInfo(CALLSTACK_DATA *s)
+{
+ return os->GetCallStackSymbolInfo(s);
+}
+
+// Wait for the termination of the thread
+bool OSWaitThread(THREAD *t)
+{
+ return os->WaitThread(t);
+}
+
+// Release of thread
+void OSFreeThread(THREAD *t)
+{
+ os->FreeThread(t);
+}
+
+// Thread initialization
+bool OSInitThread(THREAD *t)
+{
+ return os->InitThread(t);
+}
+
+// Memory allocation
+void *OSMemoryAlloc(UINT size)
+{
+ return os->MemoryAlloc(size);
+}
+
+// Memory reallocation
+void *OSMemoryReAlloc(void *addr, UINT size)
+{
+ return os->MemoryReAlloc(addr, size);
+}
+
+// Memory release
+void OSMemoryFree(void *addr)
+{
+ os->MemoryFree(addr);
+}
+
+// Get the system timer
+UINT OSGetTick()
+{
+ return os->GetTick();
+}
+
+// Get the System Time
+void OSGetSystemTime(SYSTEMTIME *system_time)
+{
+ os->GetSystemTime(system_time);
+}
+
+// 32bit increment
+void OSInc32(UINT *value)
+{
+ os->Inc32(value);
+}
+
+// 32bit decrement
+void OSDec32(UINT *value)
+{
+ os->Dec32(value);
+}
+
+// Sleep the thread
+void OSSleep(UINT time)
+{
+ os->Sleep(time);
+}
+
+// Create a Lock
+LOCK *OSNewLock()
+{
+ return os->NewLock();
+}
+
+// Lock
+bool OSLock(LOCK *lock)
+{
+ return os->Lock(lock);
+}
+
+// Unlock
+void OSUnlock(LOCK *lock)
+{
+ os->Unlock(lock);
+}
+
+// Delete the lock
+void OSDeleteLock(LOCK *lock)
+{
+ os->DeleteLock(lock);
+}
+
+// Event initialization
+void OSInitEvent(EVENT *event)
+{
+ os->InitEvent(event);
+}
+
+// Set event
+void OSSetEvent(EVENT *event)
+{
+ os->SetEvent(event);
+}
+
+// Reset event
+void OSResetEvent(EVENT *event)
+{
+ os->ResetEvent(event);
+}
+
+// Wait for event
+bool OSWaitEvent(EVENT *event, UINT timeout)
+{
+ return os->WaitEvent(event, timeout);
+}
+
+// Release of the event
+void OSFreeEvent(EVENT *event)
+{
+ os->FreeEvent(event);
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/OS.h b/src/Mayaqua/OS.h
new file mode 100644
index 00000000..0dc0a31e
--- /dev/null
+++ b/src/Mayaqua/OS.h
@@ -0,0 +1,220 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// OS.h
+// Header of OS.c
+
+#ifndef OS_H
+#define OS_H
+
+// Function prototype
+char *OsTypeToStr(UINT type);
+
+void OSInit();
+void OSFree();
+void *OSMemoryAlloc(UINT size);
+void *OSMemoryReAlloc(void *addr, UINT size);
+void OSMemoryFree(void *addr);
+UINT OSGetTick();
+void OSGetSystemTime(SYSTEMTIME *system_time);
+void OSInc32(UINT *value);
+void OSDec32(UINT *value);
+void OSSleep(UINT time);
+LOCK *OSNewLock();
+bool OSLock(LOCK *lock);
+void OSUnlock(LOCK *lock);
+void OSDeleteLock(LOCK *lock);
+void OSInitEvent(EVENT *event);
+void OSSetEvent(EVENT *event);
+void OSResetEvent(EVENT *event);
+bool OSWaitEvent(EVENT *event, UINT timeout);
+void OSFreeEvent(EVENT *event);
+bool OSWaitThread(THREAD *t);
+void OSFreeThread(THREAD *t);
+bool OSInitThread(THREAD *t);
+void *OSFileOpen(char *name, bool write_mode, bool read_lock);
+void *OSFileOpenW(wchar_t *name, bool write_mode, bool read_lock);
+void *OSFileCreate(char *name);
+void *OSFileCreateW(wchar_t *name);
+bool OSFileWrite(void *pData, void *buf, UINT size);
+bool OSFileRead(void *pData, void *buf, UINT size);
+void OSFileClose(void *pData, bool no_flush);
+void OSFileFlush(void *pData);
+UINT64 OSFileSize(void *pData);
+bool OSFileSeek(void *pData, UINT mode, int offset);
+bool OSFileDelete(char *name);
+bool OSFileDeleteW(wchar_t *name);
+bool OSMakeDir(char *name);
+bool OSMakeDirW(wchar_t *name);
+bool OSDeleteDir(char *name);
+bool OSDeleteDirW(wchar_t *name);
+CALLSTACK_DATA *OSGetCallStack();
+bool OSGetCallStackSymbolInfo(CALLSTACK_DATA *s);
+bool OSFileRename(char *old_name, char *new_name);
+bool OSFileRenameW(wchar_t *old_name, wchar_t *new_name);
+UINT OSThreadId();
+bool OSRun(char *filename, char *arg, bool hide, bool wait);
+bool OSRunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait);
+bool OSIsSupportedOs();
+void OSGetOsInfo(OS_INFO *info);
+void OSAlert(char *msg, char *caption);
+void OSAlertW(wchar_t *msg, wchar_t *caption);
+char* OSGetProductId();
+void OSSetHighPriority();
+void OSRestorePriority();
+void *OSNewSingleInstance(char *instance_name);
+void OSFreeSingleInstance(void *data);
+void OSGetMemInfo(MEMINFO *info);
+void OSYield();
+
+// Dispatch table
+typedef struct OS_DISPATCH_TABLE
+{
+ void (*Init)();
+ void (*Free)();
+ void *(*MemoryAlloc)(UINT size);
+ void *(*MemoryReAlloc)(void *addr, UINT size);
+ void (*MemoryFree)(void *addr);
+ UINT (*GetTick)();
+ void (*GetSystemTime)(SYSTEMTIME *system_time);
+ void (*Inc32)(UINT *value);
+ void (*Dec32)(UINT *value);
+ void (*Sleep)(UINT time);
+ LOCK *(*NewLock)();
+ bool (*Lock)(LOCK *lock);
+ void (*Unlock)(LOCK *lock);
+ void (*DeleteLock)(LOCK *lock);
+ void (*InitEvent)(EVENT *event);
+ void (*SetEvent)(EVENT *event);
+ void (*ResetEvent)(EVENT *event);
+ bool (*WaitEvent)(EVENT *event, UINT timeout);
+ void (*FreeEvent)(EVENT *event);
+ bool (*WaitThread)(THREAD *t);
+ void (*FreeThread)(THREAD *t);
+ bool (*InitThread)(THREAD *t);
+ UINT (*ThreadId)();
+ void *(*FileOpen)(char *name, bool write_mode, bool read_lock);
+ void *(*FileOpenW)(wchar_t *name, bool write_mode, bool read_lock);
+ void *(*FileCreate)(char *name);
+ void *(*FileCreateW)(wchar_t *name);
+ bool (*FileWrite)(void *pData, void *buf, UINT size);
+ bool (*FileRead)(void *pData, void *buf, UINT size);
+ void (*FileClose)(void *pData, bool no_flush);
+ void (*FileFlush)(void *pData);
+ UINT64 (*FileSize)(void *pData);
+ bool (*FileSeek)(void *pData, UINT mode, int offset);
+ bool (*FileDelete)(char *name);
+ bool (*FileDeleteW)(wchar_t *name);
+ bool (*MakeDir)(char *name);
+ bool (*MakeDirW)(wchar_t *name);
+ bool (*DeleteDir)(char *name);
+ bool (*DeleteDirW)(wchar_t *name);
+ CALLSTACK_DATA *(*GetCallStack)();
+ bool (*GetCallStackSymbolInfo)(CALLSTACK_DATA *s);
+ bool (*FileRename)(char *old_name, char *new_name);
+ bool (*FileRenameW)(wchar_t *old_name, wchar_t *new_name);
+ bool (*Run)(char *filename, char *arg, bool hide, bool wait);
+ bool (*RunW)(wchar_t *filename, wchar_t *arg, bool hide, bool wait);
+ bool (*IsSupportedOs)();
+ void (*GetOsInfo)(OS_INFO *info);
+ void (*Alert)(char *msg, char *caption);
+ void (*AlertW)(wchar_t *msg, wchar_t *caption);
+ char *(*GetProductId)();
+ void (*SetHighPriority)();
+ void (*RestorePriority)();
+ void *(*NewSingleInstance)(char *instance_name);
+ void (*FreeSingleInstance)(void *data);
+ void (*GetMemInfo)(MEMINFO *info);
+ void (*Yield)();
+} OS_DISPATCH_TABLE;
+
+// Include the OS-specific header
+#ifdef OS_WIN32
+#include <Mayaqua/Win32.h>
+#else //OS_WIN32
+#include <Mayaqua/Unix.h>
+#endif // OS_WIN32
+
+#endif // OS_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Object.c b/src/Mayaqua/Object.c
new file mode 100644
index 00000000..b4a7bc0b
--- /dev/null
+++ b/src/Mayaqua/Object.c
@@ -0,0 +1,596 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Object.c
+// Object management code
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// Thread to try to lock
+void CheckDeadLockThread(THREAD *t, void *param)
+{
+ DEADCHECK *c = (DEADCHECK *)param;
+
+ if (t == NULL || c == NULL)
+ {
+ return;
+ }
+
+ NoticeThreadInit(t);
+
+ Lock(c->Lock);
+ Unlock(c->Lock);
+ c->Unlocked = true;
+}
+
+// Deadlock Detection
+void CheckDeadLock(LOCK *lock, UINT timeout, char *name)
+{
+ DEADCHECK c;
+ THREAD *t;
+ char msg[MAX_PATH];
+
+ if (lock == NULL)
+ {
+ return;
+ }
+ if (name == NULL)
+ {
+ name = "Unknown";
+ }
+
+ Format(msg, sizeof(msg), "error: CheckDeadLock() Failed: %s\n", name);
+
+ Zero(&c, sizeof(c));
+ c.Lock = lock;
+ c.Timeout = timeout;
+ c.Unlocked = false;
+
+ t = NewThread(CheckDeadLockThread, &c);
+ WaitThreadInit(t);
+ if (WaitThread(t, timeout) == false)
+ {
+ if (c.Unlocked == false)
+ {
+ // Deadlock occured
+ AbortExitEx(msg);
+ }
+ else
+ {
+ WaitThread(t, INFINITE);
+ }
+ }
+
+ ReleaseThread(t);
+}
+
+// Create a lock object
+LOCK *NewLockMain()
+{
+ LOCK *lock;
+ UINT retry = 0;
+
+ while (true)
+ {
+ if ((retry++) > OBJECT_ALLOC__MAX_RETRY)
+ {
+ AbortExitEx("error: OSNewLock() failed.\n\n");
+ }
+ lock = OSNewLock();
+ if (lock != NULL)
+ {
+ break;
+ }
+ SleepThread(OBJECT_ALLOC_FAIL_SLEEP_TIME);
+ }
+
+ return lock;
+}
+LOCK *NewLock()
+{
+ LOCK *lock = NewLockMain();
+
+ // KS
+ KS_INC(KS_NEWLOCK_COUNT);
+ KS_INC(KS_CURRENT_LOCK_COUNT);
+
+ return lock;
+}
+
+// Delete the lock object
+void DeleteLock(LOCK *lock)
+{
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_DELETELOCK_COUNT);
+ KS_DEC(KS_CURRENT_LOCK_COUNT);
+
+ OSDeleteLock(lock);
+}
+
+// Lock
+bool LockInner(LOCK *lock)
+{
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return false;
+ }
+
+ // KS
+ KS_INC(KS_LOCK_COUNT);
+ KS_INC(KS_CURRENT_LOCKED_COUNT);
+
+ return OSLock(lock);
+}
+
+// Unlock
+void UnlockInner(LOCK *lock)
+{
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_UNLOCK_COUNT);
+ KS_DEC(KS_CURRENT_LOCKED_COUNT);
+
+ OSUnlock(lock);
+}
+
+// Creating a counter
+COUNTER *NewCounter()
+{
+ COUNTER *c;
+
+ // Memory allocation
+ c = Malloc(sizeof(COUNTER));
+
+ // Initialization
+ c->Ready = true;
+ c->c = 0;
+
+ // Lock created
+ c->lock = NewLock();
+
+ // KS
+ KS_INC(KS_NEW_COUNTER_COUNT);
+
+ return c;
+}
+
+// Delete the counter
+void DeleteCounter(COUNTER *c)
+{
+ // Validate arguments
+ if (c == NULL)
+ {
+ return;
+ }
+
+ // KS
+ KS_INC(KS_DELETE_COUNTER_COUNT);
+ KS_SUB(KS_CURRENT_COUNT, c->c);
+
+ DeleteLock(c->lock);
+ Free(c);
+}
+
+// Get the count value
+UINT Count(COUNTER *c)
+{
+ UINT ret;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return 0;
+ }
+ if (c->Ready == false)
+ {
+ return 0;
+ }
+
+ Lock(c->lock);
+ {
+ if (c->Ready == false)
+ {
+ ret = 0;
+ }
+ else
+ {
+ ret = c->c;
+ }
+ }
+ Unlock(c->lock);
+
+ return ret;
+}
+
+// Increment
+UINT Inc(COUNTER *c)
+{
+ UINT ret;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return 0;
+ }
+ if (c->Ready == false)
+ {
+ return 0;
+ }
+
+ Lock(c->lock);
+ {
+ if (c->Ready == false)
+ {
+ ret = 0;
+ }
+ else
+ {
+ c->c++;
+ ret = c->c;
+ }
+ }
+ Unlock(c->lock);
+
+ // KS
+ KS_INC(KS_INC_COUNT);
+ KS_INC(KS_CURRENT_COUNT);
+
+ return ret;
+}
+
+// Decrement
+UINT Dec(COUNTER *c)
+{
+ UINT ret;
+ // Validate arguments
+ if (c == NULL)
+ {
+ return 0;
+ }
+ if (c->Ready == false)
+ {
+ return 0;
+ }
+
+ Lock(c->lock);
+ {
+ if (c->Ready == false)
+ {
+ ret = 0;
+ }
+ else
+ {
+ if (c->c != 0)
+ {
+ c->c--;
+ ret = c->c;
+ }
+ else
+ {
+ ret = 0;
+ }
+ }
+ }
+ Unlock(c->lock);
+
+ // KS
+ KS_INC(KS_DEC_COUNT);
+ KS_DEC(KS_CURRENT_COUNT);
+
+ return ret;
+}
+
+
+// Release of the reference counter
+UINT Release(REF *ref)
+{
+ UINT c;
+ // Validate arguments
+ if (ref == NULL)
+ {
+ return 0;
+ }
+
+ // KS
+ KS_INC(KS_RELEASE_COUNT);
+ KS_DEC(KS_CURRENT_REFED_COUNT);
+
+ c = Dec(ref->c);
+ if (c == 0)
+ {
+ // KS
+ KS_DEC(KS_CURRENT_REF_COUNT);
+ KS_INC(KS_FREEREF_COUNT);
+
+ DeleteCounter(ref->c);
+ ref->c = 0;
+ Free(ref);
+ }
+ return c;
+}
+
+// Increase of the reference counter
+UINT AddRef(REF *ref)
+{
+ UINT c;
+ // Validate arguments
+ if (ref == NULL)
+ {
+ return 0;
+ }
+
+ c = Inc(ref->c);
+
+ // KS
+ KS_INC(KS_ADDREF_COUNT);
+ KS_INC(KS_CURRENT_REFED_COUNT);
+
+ return c;
+}
+
+// Create a reference counter
+REF *NewRef()
+{
+ REF *ref;
+
+ // Memory allocation
+ ref = Malloc(sizeof(REF));
+
+ // Create a Counter
+ ref->c = NewCounter();
+
+ // Increment only once
+ Inc(ref->c);
+
+ // KS
+ KS_INC(KS_NEWREF_COUNT);
+ KS_INC(KS_CURRENT_REF_COUNT);
+ KS_INC(KS_ADDREF_COUNT);
+ KS_INC(KS_CURRENT_REFED_COUNT);
+
+ return ref;
+}
+
+// Creating an event object
+EVENT *NewEvent()
+{
+ // Memory allocation
+ EVENT *e = Malloc(sizeof(EVENT));
+
+ // Reference counter
+ e->ref = NewRef();
+
+ // Event initialization
+ OSInitEvent(e);
+
+ // KS
+ KS_INC(KS_NEWEVENT_COUNT);
+
+ return e;
+}
+
+// Release of the event
+void ReleaseEvent(EVENT *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ if (Release(e->ref) == 0)
+ {
+ CleanupEvent(e);
+ }
+}
+
+// Delete the event
+void CleanupEvent(EVENT *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ // Release event
+ OSFreeEvent(e);
+
+ // Memory release
+ Free(e);
+
+ // KS
+ KS_INC(KS_FREEEVENT_COUNT);
+}
+
+// Set event
+void Set(EVENT *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ OSSetEvent(e);
+}
+
+// Wait for event
+bool Wait(EVENT *e, UINT timeout)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return false;
+ }
+
+ // KS
+ KS_INC(KS_WAIT_COUNT);
+
+ return OSWaitEvent(e, timeout);
+}
+
+// Wait for a event until the cancel flag becomes true
+bool WaitEx(EVENT *e, UINT timeout, volatile bool *cancel)
+{
+ bool dummy_bool = false;
+ UINT64 start, giveup;
+ // Validate arguments
+ if (cancel == NULL)
+ {
+ cancel = &dummy_bool;
+ }
+
+ start = Tick64();
+
+ if (timeout == INFINITE || timeout == 0x7FFFFFFF)
+ {
+ giveup = 0;
+ }
+ else
+ {
+ giveup = start + (UINT64)timeout;
+ }
+
+ while (true)
+ {
+ UINT64 now = Tick64();
+ UINT interval_to_giveup = (UINT)(giveup - now);
+ if (giveup == 0)
+ {
+ interval_to_giveup = INFINITE;
+ }
+ else
+ {
+ if (now >= giveup)
+ {
+ // Time-out occurs
+ return false;
+ }
+ }
+
+ interval_to_giveup = MIN(interval_to_giveup, 25);
+
+ if (*cancel)
+ {
+ // Cancel flag is set to true. Time-out occurs
+ return false;
+ }
+
+ if (e != NULL)
+ {
+ if (Wait(e, interval_to_giveup))
+ {
+ // Event is set
+ return true;
+ }
+ }
+ else
+ {
+ SleepThread(interval_to_giveup);
+ }
+ }
+}
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Object.h b/src/Mayaqua/Object.h
new file mode 100644
index 00000000..d5f90694
--- /dev/null
+++ b/src/Mayaqua/Object.h
@@ -0,0 +1,189 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Object.h
+// Header of Object.c
+
+#ifndef OBJECT_H
+#define OBJECT_H
+
+
+// Constants
+#define OBJECT_ALLOC_FAIL_SLEEP_TIME 150
+#define OBJECT_ALLOC__MAX_RETRY 30
+
+// Lock object
+struct LOCK
+{
+ void *pData;
+ BOOL Ready;
+#ifdef OS_UNIX
+ UINT thread_id;
+ UINT locked_count;
+#endif // OS_UNIX
+#ifdef _DEBUG
+ char *FileName;
+ UINT Line;
+ UINT ThreadId;
+#endif // _DEBUG
+};
+
+// Counter object
+struct COUNTER
+{
+ LOCK *lock;
+ UINT c;
+ bool Ready;
+};
+
+// Reference counter
+struct REF
+{
+ COUNTER *c;
+};
+
+// Event object
+struct EVENT
+{
+ REF *ref;
+ void *pData;
+};
+
+// Deadlock detection
+struct DEADCHECK
+{
+ LOCK *Lock;
+ UINT Timeout;
+ bool Unlocked;
+};
+
+
+// Lock function
+#ifndef _DEBUG
+
+#define Lock(lock) LockInner((lock))
+#define Unlock(lock) UnlockInner((lock))
+
+#else // _DEBUG
+
+#define Lock(lock) \
+ { \
+ LockInner(lock); \
+ if (lock != NULL) { lock->FileName = __FILE__; lock->Line = __LINE__; lock->ThreadId = ThreadId();} \
+ }
+
+#define Unlock(lock) \
+ { \
+ if (lock != NULL) { lock->FileName = NULL; lock->Line = 0; lock->ThreadId = 0;} \
+ UnlockInner(lock); \
+ }
+
+#endif // _DEBUG
+
+
+// Function prototype
+LOCK *NewLock();
+LOCK *NewLockMain();
+void DeleteLock(LOCK *lock);
+COUNTER *NewCounter();
+void UnlockInner(LOCK *lock);
+bool LockInner(LOCK *lock);
+void DeleteCounter(COUNTER *c);
+UINT Count(COUNTER *c);
+UINT Inc(COUNTER *c);
+UINT Dec(COUNTER *c);
+UINT Release(REF *ref);
+UINT AddRef(REF *ref);
+REF *NewRef();
+EVENT *NewEvent();
+void ReleaseEvent(EVENT *e);
+void CleanupEvent(EVENT *e);
+void Set(EVENT *e);
+bool Wait(EVENT *e, UINT timeout);
+bool WaitEx(EVENT *e, UINT timeout, volatile bool *cancel);
+void CheckDeadLock(LOCK *lock, UINT timeout, char *name);
+void CheckDeadLockThread(THREAD *t, void *param);
+
+#endif // OBJECT_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Pack.c b/src/Mayaqua/Pack.c
new file mode 100644
index 00000000..a72c71a4
--- /dev/null
+++ b/src/Mayaqua/Pack.c
@@ -0,0 +1,1671 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Pack.c
+// Data package code
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// Get a list of the element names in the PACK
+TOKEN_LIST *GetPackElementNames(PACK *p)
+{
+ TOKEN_LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+
+ ret->NumTokens = LIST_NUM(p->elements);
+ ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
+
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ ELEMENT *e = LIST_DATA(p->elements, i);
+
+ ret->Token[i] = CopyStr(e->name);
+ }
+
+ return ret;
+}
+
+// Convert the BUF to a PACK
+PACK *BufToPack(BUF *b)
+{
+ PACK *p;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ if (ReadPack(b, p) == false)
+ {
+ FreePack(p);
+ return NULL;
+ }
+
+ return p;
+}
+
+// Convert the PACK to the BUF
+BUF *PackToBuf(PACK *p)
+{
+ BUF *b;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ WritePack(b, p);
+
+ return b;
+}
+
+// Read the PACK
+bool ReadPack(BUF *b, PACK *p)
+{
+ UINT i, num;
+ // Validate arguments
+ if (b == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ // The number of ELEMENTs
+ num = ReadBufInt(b);
+ if (num > MAX_ELEMENT_NUM)
+ {
+ // Number exceeds
+ return false;
+ }
+
+ // Read the ELEMENT
+ for (i = 0;i < num;i++)
+ {
+ ELEMENT *e;
+ e = ReadElement(b);
+ if (AddElement(p, e) == false)
+ {
+ // Adding error
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Write down the PACK
+void WritePack(BUF *b, PACK *p)
+{
+ UINT i;
+ // Validate arguments
+ if (b == NULL || p == NULL)
+ {
+ return;
+ }
+
+ // The number of ELEMENTs
+ WriteBufInt(b, LIST_NUM(p->elements));
+
+ // Write the ELEMENT
+ for (i = 0;i < LIST_NUM(p->elements);i++)
+ {
+ ELEMENT *e = LIST_DATA(p->elements, i);
+ WriteElement(b, e);
+ }
+}
+
+// Read the ELEMENT
+ELEMENT *ReadElement(BUF *b)
+{
+ UINT i;
+ char name[MAX_ELEMENT_NAME_LEN + 1];
+ UINT type, num_value;
+ VALUE **values;
+ ELEMENT *e;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ // Name
+ if (ReadBufStr(b, name, sizeof(name)) == false)
+ {
+ return NULL;
+ }
+
+ // Type of item
+ type = ReadBufInt(b);
+
+ // Number of items
+ num_value = ReadBufInt(b);
+ if (num_value > MAX_VALUE_NUM)
+ {
+ // Number exceeds
+ return NULL;
+ }
+
+ // VALUE
+ values = (VALUE **)Malloc(sizeof(VALUE *) * num_value);
+ for (i = 0;i < num_value;i++)
+ {
+ values[i] = ReadValue(b, type);
+ }
+
+ // Create a ELEMENT
+ e = NewElement(name, type, num_value, values);
+
+ Free(values);
+
+ return e;
+}
+
+// Write the ELEMENT
+void WriteElement(BUF *b, ELEMENT *e)
+{
+ UINT i;
+ // Validate arguments
+ if (b == NULL || e == NULL)
+ {
+ return;
+ }
+
+ // Name
+ WriteBufStr(b, e->name);
+ // Type of item
+ WriteBufInt(b, e->type);
+ // Number of items
+ WriteBufInt(b, e->num_value);
+ // VALUE
+ for (i = 0;i < e->num_value;i++)
+ {
+ VALUE *v = e->values[i];
+ WriteValue(b, v, e->type);
+ }
+}
+
+// Read the VALUE
+VALUE *ReadValue(BUF *b, UINT type)
+{
+ UINT len;
+ BYTE *u;
+ void *data;
+ char *str;
+ wchar_t *unistr;
+ UINT unistr_size;
+ UINT size;
+ UINT u_size;
+ VALUE *v = NULL;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ // Data item
+ switch (type)
+ {
+ case VALUE_INT: // Integer
+ v = NewIntValue(ReadBufInt(b));
+ break;
+ case VALUE_INT64:
+ v = NewInt64Value(ReadBufInt64(b));
+ break;
+ case VALUE_DATA: // Data
+ size = ReadBufInt(b);
+ if (size > MAX_VALUE_SIZE)
+ {
+ // Size over
+ break;
+ }
+ data = Malloc(size);
+ if (ReadBuf(b, data, size) != size)
+ {
+ // Read failure
+ Free(data);
+ break;
+ }
+ v = NewDataValue(data, size);
+ Free(data);
+ break;
+ case VALUE_STR: // ANSI string
+ len = ReadBufInt(b);
+ if ((len + 1) > MAX_VALUE_SIZE)
+ {
+ // Size over
+ break;
+ }
+ str = Malloc(len + 1);
+ // String body
+ if (ReadBuf(b, str, len) != len)
+ {
+ // Read failure
+ Free(str);
+ break;
+ }
+ str[len] = 0;
+ v = NewStrValue(str);
+ Free(str);
+ break;
+ case VALUE_UNISTR: // Unicode string
+ u_size = ReadBufInt(b);
+ if (u_size > MAX_VALUE_SIZE)
+ {
+ // Size over
+ break;
+ }
+ // Reading an UTF-8 string
+ u = ZeroMalloc(u_size + 1);
+ if (ReadBuf(b, u, u_size) != u_size)
+ {
+ // Read failure
+ Free(u);
+ break;
+ }
+ // Convert to a Unicode string
+ unistr_size = CalcUtf8ToUni(u, u_size);
+ if (unistr_size == 0)
+ {
+ Free(u);
+ break;
+ }
+ unistr = Malloc(unistr_size);
+ Utf8ToUni(unistr, unistr_size, u, u_size);
+ Free(u);
+ v = NewUniStrValue(unistr);
+ Free(unistr);
+ break;
+ }
+
+ return v;
+}
+
+// Write the VALUE
+void WriteValue(BUF *b, VALUE *v, UINT type)
+{
+ UINT len;
+ BYTE *u;
+ UINT u_size;
+ // Validate arguments
+ if (b == NULL || v == NULL)
+ {
+ return;
+ }
+
+ // Data item
+ switch (type)
+ {
+ case VALUE_INT: // Integer
+ WriteBufInt(b, v->IntValue);
+ break;
+ case VALUE_INT64: // 64 bit integer
+ WriteBufInt64(b, v->Int64Value);
+ break;
+ case VALUE_DATA: // Data
+ // Size
+ WriteBufInt(b, v->Size);
+ // Body
+ WriteBuf(b, v->Data, v->Size);
+ break;
+ case VALUE_STR: // ANSI string
+ len = StrLen(v->Str);
+ // Length
+ WriteBufInt(b, len);
+ // String body
+ WriteBuf(b, v->Str, len);
+ break;
+ case VALUE_UNISTR: // Unicode string
+ // Convert to UTF-8
+ u_size = CalcUniToUtf8(v->UniStr) + 1;
+ u = ZeroMalloc(u_size);
+ UniToUtf8(u, u_size, v->UniStr);
+ // Size
+ WriteBufInt(b, u_size);
+ // UTF-8 string body
+ WriteBuf(b, u, u_size);
+ Free(u);
+ break;
+ }
+}
+
+// Get data size
+UINT GetDataValueSize(ELEMENT *e, UINT index)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return 0;
+ }
+ if (e->values == NULL)
+ {
+ return 0;
+ }
+ if (index >= e->num_value)
+ {
+ return 0;
+ }
+ if (e->values[index] == NULL)
+ {
+ return 0;
+ }
+
+ return e->values[index]->Size;
+}
+
+// Get the data
+void *GetDataValue(ELEMENT *e, UINT index)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return NULL;
+ }
+ if (e->values == NULL)
+ {
+ return NULL;
+ }
+ if (index >= e->num_value)
+ {
+ return NULL;
+ }
+ if (e->values[index] == NULL)
+ {
+ return NULL;
+ }
+
+ return e->values[index]->Data;
+}
+
+// Get the Unicode string type
+wchar_t *GetUniStrValue(ELEMENT *e, UINT index)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return 0;
+ }
+ if (index >= e->num_value)
+ {
+ return 0;
+ }
+ if (e->values[index] == NULL)
+ {
+ return NULL;
+ }
+
+ return e->values[index]->UniStr;
+}
+
+// Get the ANSI string type
+char *GetStrValue(ELEMENT *e, UINT index)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return 0;
+ }
+ if (index >= e->num_value)
+ {
+ return 0;
+ }
+ if (e->values[index] == NULL)
+ {
+ return NULL;
+ }
+
+ return e->values[index]->Str;
+}
+
+// Get the 64 bit integer value
+UINT64 GetInt64Value(ELEMENT *e, UINT index)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return 0;
+ }
+ if (index >= e->num_value)
+ {
+ return 0;
+ }
+ if (e->values[index] == NULL)
+ {
+ return 0;
+ }
+
+ return e->values[index]->Int64Value;
+}
+
+// Get the integer value
+UINT GetIntValue(ELEMENT *e, UINT index)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return 0;
+ }
+ if (index >= e->num_value)
+ {
+ return 0;
+ }
+ if (e->values[index] == NULL)
+ {
+ return 0;
+ }
+
+ return e->values[index]->IntValue;
+}
+
+// Function of sort for PACK
+int ComparePackName(void *p1, void *p2)
+{
+ ELEMENT *o1, *o2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ o1 = *(ELEMENT **)p1;
+ o2 = *(ELEMENT **)p2;
+ if (o1 == NULL || o2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(o1->name, o2->name);
+}
+
+// Delete the VALUE
+void FreeValue(VALUE *v, UINT type)
+{
+ // Validate arguments
+ if (v == NULL)
+ {
+ return;
+ }
+
+ switch (type)
+ {
+ case VALUE_INT:
+ case VALUE_INT64:
+ break;
+ case VALUE_DATA:
+ Free(v->Data);
+ break;
+ case VALUE_STR:
+ Free(v->Str);
+ break;
+ case VALUE_UNISTR:
+ Free(v->UniStr);
+ break;
+ }
+
+ // Memory release
+ Free(v);
+}
+
+// Create a VALUE of Unicode String type
+VALUE *NewUniStrValue(wchar_t *str)
+{
+ VALUE *v;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ v = Malloc(sizeof(VALUE));
+
+ // String copy
+ v->Size = UniStrSize(str);
+ v->UniStr = Malloc(v->Size);
+ UniStrCpy(v->UniStr, v->Size, str);
+
+ UniTrim(v->UniStr);
+
+ return v;
+}
+
+// Creation of the VALUE of ANSI string type
+VALUE *NewStrValue(char *str)
+{
+ VALUE *v;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ v = Malloc(sizeof(VALUE));
+
+ // String copy
+ v->Size = StrLen(str) + 1;
+ v->Str = Malloc(v->Size);
+ StrCpy(v->Str, v->Size, str);
+
+ Trim(v->Str);
+
+ return v;
+}
+
+// Create the VALUE of the data type
+VALUE *NewDataValue(void *data, UINT size)
+{
+ VALUE *v;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ v = Malloc(sizeof(VALUE));
+
+ // Data copy
+ v->Size = size;
+ v->Data = Malloc(v->Size);
+ Copy(v->Data, data, size);
+
+ return v;
+}
+
+// Create the VALUE of 64 bit integer type
+VALUE *NewInt64Value(UINT64 i)
+{
+ VALUE *v;
+
+ v = Malloc(sizeof(VALUE));
+ v->Int64Value = i;
+ v->Size = sizeof(UINT64);
+
+ return v;
+}
+
+// Create the VALUE of integer type
+VALUE *NewIntValue(UINT i)
+{
+ VALUE *v;
+
+ // Memory allocation
+ v = Malloc(sizeof(VALUE));
+ v->IntValue = i;
+ v->Size = sizeof(UINT);
+
+ return v;
+}
+
+// Delete the ELEMENT
+void FreeElement(ELEMENT *e)
+{
+ UINT i;
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < e->num_value;i++)
+ {
+ FreeValue(e->values[i], e->type);
+ }
+ Free(e->values);
+
+ Free(e);
+}
+
+// Create a ELEMENT
+ELEMENT *NewElement(char *name, UINT type, UINT num_value, VALUE **values)
+{
+ ELEMENT *e;
+ UINT i;
+ // Validate arguments
+ if (name == NULL || num_value == 0 || values == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ e = Malloc(sizeof(ELEMENT));
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = num_value;
+ e->type = type;
+
+ // Copy of the pointer list to the element
+ e->values = (VALUE **)Malloc(sizeof(VALUE *) * num_value);
+ for (i = 0;i < e->num_value;i++)
+ {
+ e->values[i] = values[i];
+ }
+
+ return e;
+}
+
+// Search and retrieve a ELEMENT from the PACK
+ELEMENT *GetElement(PACK *p, char *name, UINT type)
+{
+ ELEMENT t;
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ // Search
+ StrCpy(t.name, sizeof(t.name), name);
+ e = Search(p->elements, &t);
+
+ if (e == NULL)
+ {
+ return NULL;
+ }
+
+ // Type checking
+ if (type != INFINITE)
+ {
+ if (e->type != type)
+ {
+ return NULL;
+ }
+ }
+
+ return e;
+}
+
+// Remove the ELEMENT from the PACK
+void DelElement(PACK *p, char *name)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return;
+ }
+
+ e = GetElement(p, name, INFINITE);
+ if (e != NULL)
+ {
+ Delete(p->elements, e);
+
+ FreeElement(e);
+ }
+}
+
+// Add an ELEMENT to the PACK
+bool AddElement(PACK *p, ELEMENT *e)
+{
+ // Validate arguments
+ if (p == NULL || e == NULL)
+ {
+ return false;
+ }
+
+ // Size Check
+ if (LIST_NUM(p->elements) >= MAX_ELEMENT_NUM)
+ {
+ // Can not add any more
+ FreeElement(e);
+ return false;
+ }
+
+ // Check whether there is another item which have same name
+ if (GetElement(p, e->name, INFINITE))
+ {
+ // Exists
+ FreeElement(e);
+ return false;
+ }
+
+ if (e->num_value == 0)
+ {
+ // VALUE without any items can not be added
+ FreeElement(e);
+ return false;
+ }
+
+ // Adding
+ Add(p->elements, e);
+ return true;
+}
+
+// Release of the PACK object
+void FreePack(PACK *p)
+{
+ UINT i;
+ ELEMENT **elements;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ elements = ToArray(p->elements);
+ for (i = 0;i < LIST_NUM(p->elements);i++)
+ {
+ FreeElement(elements[i]);
+ }
+ Free(elements);
+
+ ReleaseList(p->elements);
+ Free(p);
+}
+
+// Create a PACK object
+PACK *NewPack()
+{
+ PACK *p;
+
+ // Memory allocation
+ p = MallocEx(sizeof(PACK), true);
+
+ // Creating a List
+ p->elements = NewListFast(ComparePackName);
+
+ return p;
+}
+
+// Get the K from the PACK
+K *PackGetK(PACK *p, char *name)
+{
+ K *k;
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ b = PackGetBuf(p, name);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ k = BufToK(b, true, false, NULL);
+ FreeBuf(b);
+
+ return k;
+}
+
+// Get the X from the PACK
+X *PackGetX(PACK *p, char *name)
+{
+ X *x;
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ b = PackGetBuf(p, name);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ x = BufToX(b, false);
+ FreeBuf(b);
+
+ return x;
+}
+
+// Add the K to the PACK
+void PackAddK(PACK *p, char *name, K *k)
+{
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || name == NULL || k == NULL)
+ {
+ return;
+ }
+
+ b = KToBuf(k, false, NULL);
+ if (b == NULL)
+ {
+ return;
+ }
+
+ PackAddBuf(p, name, b);
+ FreeBuf(b);
+}
+
+// Add an X into the PACK
+void PackAddX(PACK *p, char *name, X *x)
+{
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || name == NULL || x == NULL)
+ {
+ return;
+ }
+
+ b = XToBuf(x, false);
+ if (b == NULL)
+ {
+ return;
+ }
+
+ PackAddBuf(p, name, b);
+ FreeBuf(b);
+}
+
+// Get a buffer from the PACK
+BUF *PackGetBuf(PACK *p, char *name)
+{
+ return PackGetBufEx(p, name, 0);
+}
+BUF *PackGetBufEx(PACK *p, char *name, UINT index)
+{
+ UINT size;
+ void *tmp;
+ BUF *b;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ size = PackGetDataSizeEx(p, name, index);
+ tmp = MallocEx(size, true);
+ if (PackGetDataEx(p, name, tmp, index) == false)
+ {
+ Free(tmp);
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size);
+ SeekBuf(b, 0, 0);
+
+ Free(tmp);
+
+ return b;
+}
+
+// Get the data from the PACK
+bool PackGetData(PACK *p, char *name, void *data)
+{
+ return PackGetDataEx(p, name, data, 0);
+}
+bool PackGetDataEx(PACK *p, char *name, void *data, UINT index)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ e = GetElement(p, name, VALUE_DATA);
+ if (e == NULL)
+ {
+ return false;
+ }
+ Copy(data, GetDataValue(e, index), GetDataValueSize(e, index));
+ return true;
+}
+bool PackGetData2(PACK *p, char *name, void *data, UINT size)
+{
+ return PackGetDataEx2(p, name, data, size, 0);
+}
+bool PackGetDataEx2(PACK *p, char *name, void *data, UINT size, UINT index)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ e = GetElement(p, name, VALUE_DATA);
+ if (e == NULL)
+ {
+ return false;
+ }
+ if (GetDataValueSize(e, index) != size)
+ {
+ return false;
+ }
+ Copy(data, GetDataValue(e, index), GetDataValueSize(e, index));
+ return true;
+}
+
+// Get the data size from the PACK
+UINT PackGetDataSize(PACK *p, char *name)
+{
+ return PackGetDataSizeEx(p, name, 0);
+}
+UINT PackGetDataSizeEx(PACK *p, char *name, UINT index)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ e = GetElement(p, name, VALUE_DATA);
+ if (e == NULL)
+ {
+ return 0;
+ }
+ return GetDataValueSize(e, index);
+}
+
+// Get an integer from the PACK
+UINT64 PackGetInt64(PACK *p, char *name)
+{
+ return PackGetInt64Ex(p, name, 0);
+}
+UINT64 PackGetInt64Ex(PACK *p, char *name, UINT index)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ e = GetElement(p, name, VALUE_INT64);
+ if (e == NULL)
+ {
+ return 0;
+ }
+ return GetInt64Value(e, index);
+}
+
+// Get the index number from the PACK
+UINT PackGetIndexCount(PACK *p, char *name)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ e = GetElement(p, name, INFINITE);
+ if (e == NULL)
+ {
+ return 0;
+ }
+
+ return e->num_value;
+}
+
+// Get the number from the PACK
+UINT PackGetNum(PACK *p, char *name)
+{
+ return MIN(PackGetInt(p, name), 65536);
+}
+
+// Get a bool type from the PACK
+bool PackGetBool(PACK *p, char *name)
+{
+ return PackGetInt(p, name) == 0 ? false : true;
+}
+bool PackGetBoolEx(PACK *p, char *name, UINT index)
+{
+ return PackGetIntEx(p, name, index) == 0 ? false : true;
+}
+
+// Add a bool type into the PACK
+void PackAddBool(PACK *p, char *name, bool b)
+{
+ PackAddInt(p, name, b ? 1 : 0);
+}
+void PackAddBoolEx(PACK *p, char *name, bool b, UINT index, UINT total)
+{
+ PackAddIntEx(p, name, b ? 1 : 0, index, total);
+}
+
+// Add the IPV6_ADDR to the PACK
+void PackAddIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index, UINT total)
+{
+ // Validate arguments
+ if (p == NULL || name == NULL || addr == NULL)
+ {
+ return;
+ }
+
+ PackAddDataEx(p, name, addr, sizeof(IPV6_ADDR), index, total);
+}
+void PackAddIp6Addr(PACK *p, char *name, IPV6_ADDR *addr)
+{
+ PackAddIp6AddrEx(p, name, addr, 0, 1);
+}
+
+// Get an IPV6_ADDR from the PACK
+bool PackGetIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index)
+{
+ // Validate arguments
+ if (p == NULL || name == NULL || addr == NULL)
+ {
+ Zero(addr, sizeof(IPV6_ADDR));
+ return false;
+ }
+
+ return PackGetDataEx2(p, name, addr, sizeof(IPV6_ADDR), index);
+}
+bool PackGetIp6Addr(PACK *p, char *name, IPV6_ADDR *addr)
+{
+ return PackGetIp6AddrEx(p, name, addr, 0);
+}
+
+// Add the IP to the PACK
+void PackAddIp32Ex(PACK *p, char *name, UINT ip32, UINT index, UINT total)
+{
+ IP ip;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return;
+ }
+
+ UINTToIP(&ip, ip32);
+
+ PackAddIpEx(p, name, &ip, index, total);
+}
+void PackAddIp32(PACK *p, char *name, UINT ip32)
+{
+ PackAddIp32Ex(p, name, ip32, 0, 1);
+}
+void PackAddIpEx(PACK *p, char *name, IP *ip, UINT index, UINT total)
+{
+ UINT i;
+ bool b = false;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (p == NULL || name == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ b = IsIP6(ip);
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_bool", name);
+ PackAddBoolEx(p, tmp, b, index, total);
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_array", name);
+ if (b)
+ {
+ PackAddDataEx(p, tmp, ip->ipv6_addr, sizeof(ip->ipv6_addr), index, total);
+ }
+ else
+ {
+ UCHAR dummy[16];
+
+ Zero(dummy, sizeof(dummy));
+
+ PackAddDataEx(p, tmp, dummy, sizeof(dummy), index, total);
+ }
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_scope_id", name);
+ if (b)
+ {
+ PackAddIntEx(p, tmp, ip->ipv6_scope_id, index, total);
+ }
+ else
+ {
+ PackAddIntEx(p, tmp, 0, index, total);
+ }
+
+ i = IPToUINT(ip);
+
+ if (IsBigEndian())
+ {
+ i = Swap32(i);
+ }
+
+ PackAddIntEx(p, name, i, index, total);
+}
+void PackAddIp(PACK *p, char *name, IP *ip)
+{
+ PackAddIpEx(p, name, ip, 0, 1);
+}
+
+// Get an IP from the PACK
+UINT PackGetIp32Ex(PACK *p, char *name, UINT index)
+{
+ IP ip;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ if (PackGetIpEx(p, name, &ip, index) == false)
+ {
+ return 0;
+ }
+
+ return IPToUINT(&ip);
+}
+UINT PackGetIp32(PACK *p, char *name)
+{
+ return PackGetIp32Ex(p, name, 0);
+}
+bool PackGetIpEx(PACK *p, char *name, IP *ip, UINT index)
+{
+ UINT i;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (p == NULL || ip == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_bool", name);
+ if (PackGetBoolEx(p, tmp, index))
+ {
+ UCHAR data[16];
+ UINT scope_id;
+
+ Zero(data, sizeof(data));
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_array", name);
+ PackGetDataEx2(p, tmp, data, sizeof(data), index);
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_scope_id", name);
+ scope_id = PackGetIntEx(p, tmp, index);
+
+ SetIP6(ip, data);
+ ip->ipv6_scope_id = scope_id;
+ }
+ else
+ {
+ if (GetElement(p, name, VALUE_INT) == NULL)
+ {
+ Zero(ip, sizeof(IP));
+ return false;
+ }
+
+ i = PackGetIntEx(p, name, index);
+
+ if (IsBigEndian())
+ {
+ i = Swap32(i);
+ }
+
+ UINTToIP(ip, i);
+ }
+
+ return true;
+}
+bool PackGetIp(PACK *p, char *name, IP *ip)
+{
+ return PackGetIpEx(p, name, ip, 0);
+}
+
+// Get an integer from the PACK
+UINT PackGetInt(PACK *p, char *name)
+{
+ return PackGetIntEx(p, name, 0);
+}
+UINT PackGetIntEx(PACK *p, char *name, UINT index)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ e = GetElement(p, name, VALUE_INT);
+ if (e == NULL)
+ {
+ return 0;
+ }
+ return GetIntValue(e, index);
+}
+
+// Get an Unicode string from the PACK
+bool PackGetUniStr(PACK *p, char *name, wchar_t *unistr, UINT size)
+{
+ return PackGetUniStrEx(p, name, unistr, size, 0);
+}
+bool PackGetUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT size, UINT index)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL || unistr == NULL || size == 0)
+ {
+ return false;
+ }
+
+ unistr[0] = 0;
+
+ e = GetElement(p, name, VALUE_UNISTR);
+ if (e == NULL)
+ {
+ return false;
+ }
+ UniStrCpy(unistr, size, GetUniStrValue(e, index));
+ return true;
+}
+
+// Compare strings in the PACK
+bool PackCmpStr(PACK *p, char *name, char *str)
+{
+ char tmp[MAX_SIZE];
+
+ if (PackGetStr(p, name, tmp, sizeof(tmp)) == false)
+ {
+ return false;
+ }
+
+ if (StrCmpi(tmp, str) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Get a string from the PACK
+bool PackGetStr(PACK *p, char *name, char *str, UINT size)
+{
+ return PackGetStrEx(p, name, str, size, 0);
+}
+bool PackGetStrEx(PACK *p, char *name, char *str, UINT size, UINT index)
+{
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL || str == NULL || size == 0)
+ {
+ return false;
+ }
+
+ str[0] = 0;
+
+ e = GetElement(p, name, VALUE_STR);
+ if (e == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(str, size, GetStrValue(e, index));
+ return true;
+}
+
+// Add the buffer to the PACK (array)
+void PackAddBufEx(PACK *p, char *name, BUF *b, UINT index, UINT total)
+{
+ // Validate arguments
+ if (p == NULL || name == NULL || b == NULL || total == 0)
+ {
+ return;
+ }
+
+ PackAddDataEx(p, name, b->Buf, b->Size, index, total);
+}
+
+// Add the data to the PACK (array)
+void PackAddDataEx(PACK *p, char *name, void *data, UINT size, UINT index, UINT total)
+{
+ VALUE *v;
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || data == NULL || name == NULL || total == 0)
+ {
+ return;
+ }
+
+ v = NewDataValue(data, size);
+ e = GetElement(p, name, VALUE_DATA);
+ if (e != NULL)
+ {
+ if (e->num_value <= total)
+ {
+ e->values[index] = v;
+ }
+ else
+ {
+ FreeValue(v, VALUE_DATA);
+ }
+ }
+ else
+ {
+ e = ZeroMallocEx(sizeof(ELEMENT), true);
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = total;
+ e->type = VALUE_DATA;
+ e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
+ e->values[index] = v;
+ AddElement(p, e);
+ }
+}
+
+// Add the buffer to the PACK
+void PackAddBuf(PACK *p, char *name, BUF *b)
+{
+ // Validate arguments
+ if (p == NULL || name == NULL || b == NULL)
+ {
+ return;
+ }
+
+ PackAddData(p, name, b->Buf, b->Size);
+}
+
+// Add the data to the PACK
+void PackAddData(PACK *p, char *name, void *data, UINT size)
+{
+ VALUE *v;
+ // Validate arguments
+ if (p == NULL || data == NULL || name == NULL)
+ {
+ return;
+ }
+
+ v = NewDataValue(data, size);
+ AddElement(p, NewElement(name, VALUE_DATA, 1, &v));
+}
+
+// Add a 64 bit integer (array) to the PACK
+void PackAddInt64Ex(PACK *p, char *name, UINT64 i, UINT index, UINT total)
+{
+ VALUE *v;
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL || total == 0)
+ {
+ return;
+ }
+
+ v = NewInt64Value(i);
+ e = GetElement(p, name, VALUE_INT64);
+ if (e != NULL)
+ {
+ if (e->num_value <= total)
+ {
+ e->values[index] = v;
+ }
+ else
+ {
+ FreeValue(v, VALUE_INT64);
+ }
+ }
+ else
+ {
+ e = ZeroMallocEx(sizeof(ELEMENT), true);
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = total;
+ e->type = VALUE_INT64;
+ e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
+ e->values[index] = v;
+ AddElement(p, e);
+ }
+}
+
+// Add an integer to the PACK (array)
+void PackAddIntEx(PACK *p, char *name, UINT i, UINT index, UINT total)
+{
+ VALUE *v;
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL || total == 0)
+ {
+ return;
+ }
+
+ v = NewIntValue(i);
+ e = GetElement(p, name, VALUE_INT);
+ if (e != NULL)
+ {
+ if (e->num_value <= total)
+ {
+ e->values[index] = v;
+ }
+ else
+ {
+ FreeValue(v, VALUE_INT);
+ }
+ }
+ else
+ {
+ e = ZeroMallocEx(sizeof(ELEMENT), true);
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = total;
+ e->type = VALUE_INT;
+ e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
+ e->values[index] = v;
+ AddElement(p, e);
+ }
+}
+
+// Add a 64 bit integer to the PACK
+void PackAddInt64(PACK *p, char *name, UINT64 i)
+{
+ VALUE *v;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return;
+ }
+
+ v = NewInt64Value(i);
+ AddElement(p, NewElement(name, VALUE_INT64, 1, &v));
+}
+
+// Add the number of items to the PACK
+void PackAddNum(PACK *p, char *name, UINT num)
+{
+ PackAddInt(p, name, num);
+}
+
+// Add an integer to the PACK
+void PackAddInt(PACK *p, char *name, UINT i)
+{
+ VALUE *v;
+ // Validate arguments
+ if (p == NULL || name == NULL)
+ {
+ return;
+ }
+
+ v = NewIntValue(i);
+ AddElement(p, NewElement(name, VALUE_INT, 1, &v));
+}
+
+// Add a Unicode string (array) to the PACK
+void PackAddUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT index, UINT total)
+{
+ VALUE *v;
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL || unistr == NULL || total == 0)
+ {
+ return;
+ }
+
+ v = NewUniStrValue(unistr);
+ e = GetElement(p, name, VALUE_UNISTR);
+ if (e != NULL)
+ {
+ if (e->num_value <= total)
+ {
+ e->values[index] = v;
+ }
+ else
+ {
+ FreeValue(v, VALUE_UNISTR);
+ }
+ }
+ else
+ {
+ e = ZeroMallocEx(sizeof(ELEMENT), true);
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = total;
+ e->type = VALUE_UNISTR;
+ e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
+ e->values[index] = v;
+ AddElement(p, e);
+ }
+}
+
+// Add a Unicode string to the PACK
+void PackAddUniStr(PACK *p, char *name, wchar_t *unistr)
+{
+ VALUE *v;
+ // Validate arguments
+ if (p == NULL || name == NULL || unistr == NULL)
+ {
+ return;
+ }
+
+ v = NewUniStrValue(unistr);
+ AddElement(p, NewElement(name, VALUE_UNISTR, 1, &v));
+}
+
+// Add a string to the PACK (array)
+void PackAddStrEx(PACK *p, char *name, char *str, UINT index, UINT total)
+{
+ VALUE *v;
+ ELEMENT *e;
+ // Validate arguments
+ if (p == NULL || name == NULL || str == NULL || total == 0)
+ {
+ return;
+ }
+
+ v = NewStrValue(str);
+ e = GetElement(p, name, VALUE_STR);
+ if (e != NULL)
+ {
+ if (e->num_value <= total)
+ {
+ e->values[index] = v;
+ }
+ else
+ {
+ FreeValue(v, VALUE_STR);
+ }
+ }
+ else
+ {
+ e = ZeroMallocEx(sizeof(ELEMENT), true);
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = total;
+ e->type = VALUE_STR;
+ e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
+ e->values[index] = v;
+ AddElement(p, e);
+ }
+}
+
+// Add a string to the PACK
+void PackAddStr(PACK *p, char *name, char *str)
+{
+ VALUE *v;
+ // Validate arguments
+ if (p == NULL || name == NULL || str == NULL)
+ {
+ return;
+ }
+
+ v = NewStrValue(str);
+ AddElement(p, NewElement(name, VALUE_STR, 1, &v));
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Pack.h b/src/Mayaqua/Pack.h
new file mode 100644
index 00000000..5cd70d26
--- /dev/null
+++ b/src/Mayaqua/Pack.h
@@ -0,0 +1,234 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Pack.h
+// Header of Pack.c
+
+#ifndef PACK_H
+#define PACK_H
+
+// Constant
+#ifdef CPU_64
+
+#define MAX_VALUE_SIZE (384 * 1024 * 1024) // Maximum Data size that can be stored in a single VALUE
+#define MAX_VALUE_NUM 262144 // Maximum VALUE number that can be stored in a single ELEMENT
+#define MAX_ELEMENT_NAME_LEN 63 // The length of the name that can be attached to the ELEMENT
+#define MAX_ELEMENT_NUM 262144 // Maximum ELEMENT number that can be stored in a single PACK
+#define MAX_PACK_SIZE (512 * 1024 * 1024) // Maximum size of a serialized PACK
+
+#else // CPU_64
+
+#define MAX_VALUE_SIZE (96 * 1024 * 1024) // Maximum Data size that can be stored in a single VALUE
+#define MAX_VALUE_NUM 65536 // Maximum VALUE number that can be stored in a single ELEMENT
+#define MAX_ELEMENT_NAME_LEN 63 // The length of the name that can be attached to the ELEMENT
+#define MAX_ELEMENT_NUM 131072 // Maximum ELEMENT number that can be stored in a single PACK
+#define MAX_PACK_SIZE (128 * 1024 * 1024) // Maximum size of a serialized PACK
+
+#endif // CPU_64
+
+// Type of VALUE
+#define VALUE_INT 0 // Integer type
+#define VALUE_DATA 1 // Data type
+#define VALUE_STR 2 // ANSI string type
+#define VALUE_UNISTR 3 // Unicode string type
+#define VALUE_INT64 4 // 64 bit integer type
+
+// The number of allowable NOOP
+#define MAX_NOOP_PER_SESSION 30
+
+// VALUE object
+struct VALUE
+{
+ UINT Size; // Size
+ UINT IntValue; // Integer value
+ void *Data; // Data
+ char *Str; // ANSI string
+ wchar_t *UniStr; // Unicode strings
+ UINT64 Int64Value; // 64 bit integer type
+};
+
+// ELEMENT object
+struct ELEMENT
+{
+ char name[MAX_ELEMENT_NAME_LEN + 1]; // Element name
+ UINT num_value; // Number of values (>=1)
+ UINT type; // Type
+ VALUE **values; // List of pointers to the value
+};
+
+// PACK object
+struct PACK
+{
+ LIST *elements; // Element list
+};
+
+
+// Function prototype
+PACK *NewPack();
+bool AddElement(PACK *p, ELEMENT *e);
+void DelElement(PACK *p, char *name);
+ELEMENT *GetElement(PACK *p, char *name, UINT type);
+void FreePack(PACK *p);
+ELEMENT *NewElement(char *name, UINT type, UINT num_value, VALUE **values);
+VALUE *NewIntValue(UINT i);
+VALUE *NewDataValue(void *data, UINT size);
+VALUE *NewStrValue(char *str);
+VALUE *NewUniStrValue(wchar_t *str);
+void FreeValue(VALUE *v, UINT type);
+int ComparePackName(void *p1, void *p2);
+void FreeElement(ELEMENT *e);
+UINT GetValueNum(ELEMENT *e);
+UINT GetIntValue(ELEMENT *e, UINT index);
+UINT64 GetInt64Value(ELEMENT *e, UINT index);
+char *GetStrValue(ELEMENT *e, UINT index);
+wchar_t *GetUniStrValue(ELEMENT *e, UINT index);
+UINT GetDataValueSize(ELEMENT *e, UINT index);
+void *GetDataValue(ELEMENT *e, UINT index);
+BUF *PackToBuf(PACK *p);
+void WritePack(BUF *b, PACK *p);
+void WriteElement(BUF *b, ELEMENT *e);
+void WriteValue(BUF *b, VALUE *v, UINT type);
+PACK *BufToPack(BUF *b);
+bool ReadPack(BUF *b, PACK *p);
+ELEMENT *ReadElement(BUF *b);
+VALUE *ReadValue(BUF *b, UINT type);
+void Bit160ToStr(char *str, UCHAR *data);
+void Bit128ToStr(char *str, UCHAR *data);
+VALUE *NewInt64Value(UINT64 i);
+TOKEN_LIST *GetPackElementNames(PACK *p);
+
+X *PackGetX(PACK *p, char *name);
+K *PackGetK(PACK *p, char *name);
+void PackAddX(PACK *p, char *name, X *x);
+void PackAddK(PACK *p, char *name, K *k);
+void PackAddStr(PACK *p, char *name, char *str);
+void PackAddStrEx(PACK *p, char *name, char *str, UINT index, UINT total);
+void PackAddUniStr(PACK *p, char *name, wchar_t *unistr);
+void PackAddUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT index, UINT total);
+void PackAddInt(PACK *p, char *name, UINT i);
+void PackAddNum(PACK *p, char *name, UINT num);
+void PackAddIntEx(PACK *p, char *name, UINT i, UINT index, UINT total);
+void PackAddInt64(PACK *p, char *name, UINT64 i);
+void PackAddInt64Ex(PACK *p, char *name, UINT64 i, UINT index, UINT total);
+void PackAddData(PACK *p, char *name, void *data, UINT size);
+void PackAddDataEx(PACK *p, char *name, void *data, UINT size, UINT index, UINT total);
+void PackAddBuf(PACK *p, char *name, BUF *b);
+void PackAddBufEx(PACK *p, char *name, BUF *b, UINT index, UINT total);
+bool PackGetStr(PACK *p, char *name, char *str, UINT size);
+bool PackGetStrEx(PACK *p, char *name, char *str, UINT size, UINT index);
+bool PackGetUniStr(PACK *p, char *name, wchar_t *unistr, UINT size);
+bool PackGetUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT size, UINT index);
+bool PackCmpStr(PACK *p, char *name, char *str);
+UINT PackGetIndexCount(PACK *p, char *name);
+UINT PackGetInt(PACK *p, char *name);
+UINT PackGetNum(PACK *p, char *name);
+UINT PackGetIntEx(PACK *p, char *name, UINT index);
+UINT64 PackGetInt64(PACK *p, char *name);
+UINT64 PackGetInt64Ex(PACK *p, char *name, UINT index);
+UINT PackGetDataSizeEx(PACK *p, char *name, UINT index);
+UINT PackGetDataSize(PACK *p, char *name);
+bool PackGetData(PACK *p, char *name, void *data);
+bool PackGetDataEx(PACK *p, char *name, void *data, UINT index);
+BUF *PackGetBuf(PACK *p, char *name);
+BUF *PackGetBufEx(PACK *p, char *name, UINT index);
+bool PackGetBool(PACK *p, char *name);
+void PackAddBool(PACK *p, char *name, bool b);
+void PackAddBoolEx(PACK *p, char *name, bool b, UINT index, UINT total);
+bool PackGetBoolEx(PACK *p, char *name, UINT index);
+void PackAddIp(PACK *p, char *name, IP *ip);
+void PackAddIpEx(PACK *p, char *name, IP *ip, UINT index, UINT total);
+bool PackGetIp(PACK *p, char *name, IP *ip);
+bool PackGetIpEx(PACK *p, char *name, IP *ip, UINT index);
+UINT PackGetIp32(PACK *p, char *name);
+UINT PackGetIp32Ex(PACK *p, char *name, UINT index);
+void PackAddIp32(PACK *p, char *name, UINT ip32);
+void PackAddIp32Ex(PACK *p, char *name, UINT ip32, UINT index, UINT total);
+void PackAddIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index, UINT total);
+bool PackGetIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index);
+void PackAddIp6Addr(PACK *p, char *name, IPV6_ADDR *addr);
+bool PackGetIp6Addr(PACK *p, char *name, IPV6_ADDR *addr);
+bool PackGetData2(PACK *p, char *name, void *data, UINT size);
+bool PackGetDataEx2(PACK *p, char *name, void *data, UINT size, UINT index);
+
+#endif // PACK_H
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Secure.c b/src/Mayaqua/Secure.c
new file mode 100644
index 00000000..e970062f
--- /dev/null
+++ b/src/Mayaqua/Secure.c
@@ -0,0 +1,2197 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Secure.c
+// Security token management module
+
+#include <GlobalConst.h>
+
+#define SECURE_C
+#define ENCRYPT_C
+
+#ifdef WIN32
+#include <windows.h>
+#endif // WIN32
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/engine.h>
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs7.h>
+#include <openssl/pkcs12.h>
+#include <openssl/rc4.h>
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+#include <Mayaqua/Mayaqua.h>
+#include <Mayaqua/cryptoki.h>
+
+
+#define MAX_OBJ 1024 // Maximum number of objects in the hardware (assumed)
+
+#define A_SIZE(a, i) (a[(i)].ulValueLen)
+#define A_SET(a, i, value, size) (a[i].pValue = value;a[i].ulValueLen = size;)
+
+#ifdef OS_WIN32
+// Code for Win32
+
+// DLL reading for Win32
+HINSTANCE Win32SecureLoadLibraryEx(char *dllname, DWORD flags)
+{
+ char tmp1[MAX_PATH];
+ char tmp2[MAX_PATH];
+ char tmp3[MAX_PATH];
+ HINSTANCE h;
+ // Validate arguments
+ if (dllname == NULL)
+ {
+ return NULL;
+ }
+
+ Format(tmp1, sizeof(tmp1), "%s\\%s", MsGetSystem32Dir(), dllname);
+ Format(tmp2, sizeof(tmp2), "%s\\JPKI\\%s", MsGetProgramFilesDir(), dllname);
+ Format(tmp3, sizeof(tmp3), "%s\\LGWAN\\%s", MsGetProgramFilesDir(), dllname);
+
+ h = LoadLibraryEx(dllname, NULL, flags);
+ if (h != NULL)
+ {
+ return h;
+ }
+
+ h = LoadLibraryEx(tmp1, NULL, flags);
+ if (h != NULL)
+ {
+ return h;
+ }
+
+ h = LoadLibraryEx(tmp2, NULL, flags);
+ if (h != NULL)
+ {
+ return h;
+ }
+
+ h = LoadLibraryEx(tmp3, NULL, flags);
+ if (h != NULL)
+ {
+ return h;
+ }
+
+ return NULL;
+}
+
+// Examine whether the specified device is installed
+bool Win32IsDeviceSupported(SECURE_DEVICE *dev)
+{
+ HINSTANCE hInst;
+ // Validate arguments
+ if (dev == NULL)
+ {
+ return false;
+ }
+
+ // Check whether the DLL is readable
+ hInst = Win32SecureLoadLibraryEx(dev->ModuleName, DONT_RESOLVE_DLL_REFERENCES);
+ if (hInst == NULL)
+ {
+ return false;
+ }
+
+ FreeLibrary(hInst);
+
+ return true;
+}
+
+// Load the device module
+bool Win32LoadSecModule(SECURE *sec)
+{
+ SEC_DATA_WIN32 *w;
+ HINSTANCE hInst;
+ CK_FUNCTION_LIST_PTR api = NULL;
+ CK_RV (*get_function_list)(CK_FUNCTION_LIST_PTR_PTR);
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+
+ if (sec->Dev->Id == 9)
+ {
+ char username[MAX_SIZE];
+ DWORD size;
+ // Because the device driver of Juki-Net needs the contents
+ // of the Software\JPKI registry key on HKLU of SYSTEM,
+ // if there is no key, copy the key from the value of other user
+// if (MsRegIsValue(REG_CURRENT_USER, "Software\\JPKI", "Name") == false ||
+// MsRegIsValue(REG_CURRENT_USER, "Software\\JPKI", "RWType") == false)
+ size = sizeof(username);
+ GetUserName(username, &size);
+ if (StrCmpi(username, "System") == 0)
+ {
+ TOKEN_LIST *t = MsRegEnumKey(REG_USERS, NULL);
+
+ if (t != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char tmp[MAX_PATH];
+
+ if (StrCmpi(t->Token[i], ".DEFAULT") != 0 && StrCmpi(t->Token[i], "S-1-5-18") != 0)
+ {
+ Format(tmp, sizeof(tmp), "%s\\Software\\JPKI", t->Token[i]);
+
+ if (MsRegIsValue(REG_USERS, tmp, "Name") && MsRegIsValue(REG_USERS, tmp, "RWType"))
+ {
+ char *name = MsRegReadStr(REG_USERS, tmp, "Name");
+ char *port = MsRegReadStr(REG_USERS, tmp, "Port");
+ UINT type = MsRegReadInt(REG_USERS, tmp, "RWType");
+
+ MsRegWriteStr(REG_CURRENT_USER, "Software\\JPKI", "Name", name);
+ MsRegWriteStr(REG_CURRENT_USER, "Software\\JPKI", "Port", port);
+ MsRegWriteInt(REG_CURRENT_USER, "Software\\JPKI", "RWType", type);
+
+ Free(name);
+ Free(port);
+ break;
+ }
+ }
+ }
+
+ FreeToken(t);
+ }
+ }
+ }
+
+ // Load the Library
+ hInst = Win32SecureLoadLibraryEx(sec->Dev->ModuleName, 0);
+ if (hInst == NULL)
+ {
+ // Failure
+ return false;
+ }
+
+ // Get the API
+ get_function_list = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR))
+ GetProcAddress(hInst, "C_GetFunctionList");
+
+ if (get_function_list == NULL)
+ {
+ // Failure
+ FreeLibrary(hInst);
+ return false;
+ }
+
+ get_function_list(&api);
+ if (api == NULL)
+ {
+ // Failure
+ FreeLibrary(hInst);
+ return false;
+ }
+
+ sec->Data = ZeroMalloc(sizeof(SEC_DATA_WIN32));
+ w = sec->Data;
+
+ w->hInst = hInst;
+ sec->Api = api;
+
+ return true;
+}
+
+// Unload the device module
+void Win32FreeSecModule(SECURE *sec)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+ if (sec->Data == NULL)
+ {
+ return;
+ }
+
+ // Unload
+ FreeLibrary(sec->Data->hInst);
+ Free(sec->Data);
+
+ sec->Data = NULL;
+}
+
+#endif // OS_WIN32
+
+
+// Whether the specified device is a JPKI
+bool IsJPKI(bool id)
+{
+ if (id == 9 || id == 13)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Sign with the private key which is specified by the name in the secure device
+bool SignSec(SECURE *sec, char *name, void *dst, void *src, UINT size)
+{
+ SEC_OBJ *obj;
+ UINT ret;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (name == NULL || dst == NULL || src == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+
+ obj = FindSecObject(sec, name, SEC_K);
+ if (obj == NULL)
+ {
+ return false;
+ }
+
+ ret = SignSecByObject(sec, obj, dst, src, size);
+
+ FreeSecObject(obj);
+
+ return ret;
+}
+
+// Sign with the private key of the secure device
+bool SignSecByObject(SECURE *sec, SEC_OBJ *obj, void *dst, void *src, UINT size)
+{
+ CK_MECHANISM mechanism = {CKM_RSA_PKCS, NULL, 0};
+ UINT ret;
+ UCHAR hash[SIGN_HASH_SIZE];
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (obj == NULL || dst == NULL || src == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+ if (sec->LoginFlag == false && obj->Private)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return false;
+ }
+ if (obj->Type != SEC_K)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+
+ // Hash
+ HashForSign(hash, sizeof(hash), src, size);
+
+ // Signature initialization
+ ret = sec->Api->C_SignInit(sec->SessionId, &mechanism, obj->Object);
+ if (ret != CKR_OK)
+ {
+ // Failure
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ Debug("C_SignInit Error: 0x%x\n", ret);
+ return false;
+ }
+
+ // Perform Signing
+ size = 128;
+ ret = sec->Api->C_Sign(sec->SessionId, hash, sizeof(hash), dst, &size);
+ if (ret != CKR_OK || size != 128)
+ {
+ // Failure
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ Debug("C_Sign Error: 0x%x\n", ret);
+ return false;
+ }
+
+ return true;
+}
+
+// Changing the PIN code
+bool ChangePin(SECURE *sec, char *old_pin, char *new_pin)
+{
+ // Validate arguments
+ if (sec == NULL || old_pin == NULL || new_pin == NULL)
+ {
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+ if (sec->LoginFlag == false)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return false;
+ }
+ if (sec->IsReadOnly)
+ {
+ sec->Error = SEC_ERROR_OPEN_SESSION;
+ return false;
+ }
+
+ // Change then PIN
+ if (sec->Api->C_SetPIN(sec->SessionId, old_pin, StrLen(old_pin),
+ new_pin, StrLen(new_pin)) != CKR_OK)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Write the private key object
+bool WriteSecKey(SECURE *sec, bool private_obj, char *name, K *k)
+{
+ UINT key_type = CKK_RSA;
+ CK_BBOOL b_true = true, b_false = false, b_private_obj = private_obj;
+ UINT obj_class = CKO_PRIVATE_KEY;
+ UINT object;
+ UINT ret;
+ BUF *b;
+ RSA *rsa;
+ UCHAR modules[MAX_SIZE], pub[MAX_SIZE], pri[MAX_SIZE], prime1[MAX_SIZE], prime2[MAX_SIZE];
+ CK_ATTRIBUTE a[] =
+ {
+ {CKA_MODULUS, modules, 0}, // 0
+ {CKA_PUBLIC_EXPONENT, pub, 0}, // 1
+ {CKA_PRIVATE_EXPONENT, pri, 0}, // 2
+ {CKA_PRIME_1, prime1, 0}, // 3
+ {CKA_PRIME_2, prime2, 0}, // 4
+ {CKA_CLASS, &obj_class, sizeof(obj_class)},
+ {CKA_TOKEN, &b_true, sizeof(b_true)},
+ {CKA_PRIVATE, &b_private_obj, sizeof(b_private_obj)},
+ {CKA_LABEL, name, StrLen(name)},
+ {CKA_KEY_TYPE, &key_type, sizeof(key_type)},
+ {CKA_DERIVE, &b_false, sizeof(b_false)},
+ {CKA_SUBJECT, name, StrLen(name)},
+ {CKA_SENSITIVE, &b_true, sizeof(b_true)},
+ {CKA_DECRYPT, &b_true, sizeof(b_true)},
+ {CKA_SIGN, &b_true, sizeof(b_true)},
+ {CKA_SIGN_RECOVER, &b_false, sizeof(b_false)},
+ {CKA_EXTRACTABLE, &b_false, sizeof(b_false)},
+ {CKA_MODIFIABLE, &b_false, sizeof(b_false)},
+ };
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (name == NULL || k == NULL || k->private_key == false)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+ if (sec->LoginFlag == false && private_obj)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return false;
+ }
+
+ // Numeric data generation
+ rsa = k->pkey->pkey.rsa;
+ if (rsa == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ b = BigNumToBuf(rsa->n);
+ ReadBuf(b, modules, sizeof(modules));
+ A_SIZE(a, 0) = b->Size;
+ FreeBuf(b);
+
+ b = BigNumToBuf(rsa->e);
+ ReadBuf(b, pub, sizeof(pub));
+ A_SIZE(a, 1) = b->Size;
+ FreeBuf(b);
+
+ b = BigNumToBuf(rsa->d);
+ ReadBuf(b, pri, sizeof(pri));
+ A_SIZE(a, 2) = b->Size;
+ FreeBuf(b);
+
+ b = BigNumToBuf(rsa->p);
+ ReadBuf(b, prime1, sizeof(prime1));
+ A_SIZE(a, 3) = b->Size;
+ FreeBuf(b);
+
+ b = BigNumToBuf(rsa->q);
+ ReadBuf(b, prime2, sizeof(prime2));
+ A_SIZE(a, 4) = b->Size;
+ FreeBuf(b);
+
+ // Delete the old key if it exists
+ if (CheckSecObject(sec, name, SEC_K))
+ {
+ DeleteSecKey(sec, name);
+ }
+
+ // Creating
+ if ((ret = sec->Api->C_CreateObject(sec->SessionId, a, sizeof(a) / sizeof(a[0]), &object)) != CKR_OK)
+ {
+ // Failure
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ Debug("ret: 0x%x\n", ret);
+ return false;
+ }
+
+ // Clear Cache
+ EraseEnumSecObjectCache(sec);
+
+ return true;
+}
+
+// Read the certificate object by specifying the name
+X *ReadSecCert(SECURE *sec, char *name)
+{
+ SEC_OBJ *obj;
+ X *x;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+
+ // Search
+ obj = FindSecObject(sec, name, SEC_X);
+ if (obj == NULL)
+ {
+ return false;
+ }
+
+ // Acquisition
+ x = ReadSecCertFromObject(sec, obj);
+
+ FreeSecObject(obj);
+
+ return x;
+}
+
+// Read the certificate object
+X *ReadSecCertFromObject(SECURE *sec, SEC_OBJ *obj)
+{
+ UINT size;
+ X *x;
+ UCHAR value[4096];
+ BUF *b;
+ CK_ATTRIBUTE get[] =
+ {
+ {CKA_VALUE, value, sizeof(value)},
+ };
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+ if (sec->LoginFlag == false && obj->Private)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return false;
+ }
+ if (obj->Type != SEC_X)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+
+ // Acquisition
+ if (sec->Api->C_GetAttributeValue(
+ sec->SessionId, obj->Object, get, sizeof(get) / sizeof(get[0])) != CKR_OK)
+ {
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ return 0;
+ }
+
+ size = A_SIZE(get, 0);
+
+ // Conversion
+ b = NewBuf();
+ WriteBuf(b, value, size);
+ SeekBuf(b, 0, 0);
+
+ x = BufToX(b, false);
+ if (x == NULL)
+ {
+ sec->Error = SEC_ERROR_INVALID_CERT;
+ }
+
+ FreeBuf(b);
+
+ return x;
+}
+
+// Write the certificate object
+bool WriteSecCert(SECURE *sec, bool private_obj, char *name, X *x)
+{
+ UINT obj_class = CKO_CERTIFICATE;
+ CK_BBOOL b_true = true, b_false = false, b_private_obj = private_obj;
+ UINT cert_type = CKC_X_509;
+ CK_DATE start_date, end_date;
+ UCHAR subject[MAX_SIZE];
+ UCHAR issuer[MAX_SIZE];
+ wchar_t w_subject[MAX_SIZE];
+ wchar_t w_issuer[MAX_SIZE];
+ UCHAR serial_number[MAX_SIZE];
+ UCHAR value[4096];
+ UINT ret;
+ BUF *b;
+ UINT object;
+ CK_ATTRIBUTE a[] =
+ {
+ {CKA_SUBJECT, subject, 0}, // 0
+ {CKA_ISSUER, issuer, 0}, // 1
+ {CKA_SERIAL_NUMBER, serial_number, 0}, // 2
+ {CKA_VALUE, value, 0}, // 3
+ {CKA_CLASS, &obj_class, sizeof(obj_class)},
+ {CKA_TOKEN, &b_true, sizeof(b_true)},
+ {CKA_PRIVATE, &b_private_obj, sizeof(b_private_obj)},
+ {CKA_LABEL, name, StrLen(name)},
+ {CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type)},
+#if 0 // Don't use these because some tokens fail
+ {CKA_START_DATE, &start_date, sizeof(start_date)},
+ {CKA_END_DATE, &end_date, sizeof(end_date)},
+#endif
+ };
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (name == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+ if (sec->LoginFlag == false && private_obj)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return false;
+ }
+
+ // Copy the certificate to the buffer
+ b = XToBuf(x, false);
+ if (b == NULL)
+ {
+ sec->Error = SEC_ERROR_INVALID_CERT;
+ return false;
+ }
+ if (b->Size > sizeof(value))
+ {
+ // Size is too large
+ FreeBuf(b);
+ sec->Error = SEC_ERROR_DATA_TOO_BIG;
+ return false;
+ }
+ Copy(value, b->Buf, b->Size);
+ A_SIZE(a, 3) = b->Size;
+ FreeBuf(b);
+
+ // Store the Subject and the Issuer by encoding into UTF-8
+ GetPrintNameFromName(w_subject, sizeof(w_subject), x->subject_name);
+ UniToUtf8(subject, sizeof(subject), w_subject);
+ A_SIZE(a, 0) = StrLen(subject);
+ if (x->root_cert == false)
+ {
+ GetPrintNameFromName(w_issuer, sizeof(w_issuer), x->issuer_name);
+ UniToUtf8(issuer, sizeof(issuer), w_issuer);
+ A_SIZE(a, 1) = StrLen(issuer);
+ }
+
+ // Copy the serial number
+ Copy(serial_number, x->serial->data, MIN(x->serial->size, sizeof(serial_number)));
+ A_SIZE(a, 2) = MIN(x->serial->size, sizeof(serial_number));
+
+ // Expiration date information
+ UINT64ToCkDate(&start_date, SystemToLocal64(x->notBefore));
+ UINT64ToCkDate(&end_date, SystemToLocal64(x->notAfter));
+
+ // Remove objects which have the same name
+ if (CheckSecObject(sec, name, SEC_X))
+ {
+ DeleteSecCert(sec, name);
+ }
+
+ // Creating
+ if ((ret = sec->Api->C_CreateObject(sec->SessionId, a, sizeof(a) / sizeof(a[0]), &object)) != CKR_OK)
+ {
+ // Failure
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ Debug("Error: 0x%02x\n", ret);
+ return false;
+ }
+
+ // Clear Cache
+ EraseEnumSecObjectCache(sec);
+
+ return true;
+}
+
+// Delete the private key object
+bool DeleteSecKey(SECURE *sec, char *name)
+{
+ return DeleteSecObjectByName(sec, name, SEC_K);
+}
+
+// Delete the certificate object
+bool DeleteSecCert(SECURE *sec, char *name)
+{
+ return DeleteSecObjectByName(sec, name, SEC_X);
+}
+
+// Convert the the CK_DATE to the 64 bit time
+UINT64 CkDateToUINT64(struct CK_DATE *ck_date)
+{
+ SYSTEMTIME st;
+ char year[32], month[32], day[32];
+ // Validate arguments
+ if (ck_date == NULL)
+ {
+ return 0;
+ }
+
+ Zero(year, sizeof(year));
+ Zero(month, sizeof(month));
+ Zero(day, sizeof(day));
+
+ Copy(year, ck_date->year, 4);
+ Copy(month, ck_date->month, 2);
+ Copy(day, ck_date->day, 2);
+
+ st.wYear = ToInt(year);
+ st.wMonth = ToInt(month);
+ st.wDay = ToInt(day);
+
+ return SystemToUINT64(&st);
+}
+
+// Convert the 64 bit time to the CK_DATE
+void UINT64ToCkDate(void *p_ck_date, UINT64 time64)
+{
+ SYSTEMTIME st;
+ char year[32], month[32], day[32];
+ struct CK_DATE *ck_date = (CK_DATE *)p_ck_date;
+ // Validate arguments
+ if (ck_date == NULL)
+ {
+ return;
+ }
+
+ UINT64ToSystem(&st, time64);
+
+ Format(year, sizeof(year), "%04u", st.wYear);
+ Format(month, sizeof(month), "%04u", st.wMonth);
+ Format(day, sizeof(day), "%04u", st.wDay);
+
+ Zero(ck_date, sizeof(CK_DATE));
+
+ Copy(ck_date->year, year, 4);
+ Copy(ck_date->month, month, 2);
+ Copy(ck_date->day, day, 2);
+}
+
+// Delete the object by specifying the name
+bool DeleteSecObjectByName(SECURE *sec, char *name, UINT type)
+{
+ bool ret;
+ SEC_OBJ *obj;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (name == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+
+ // Get the Object
+ obj = FindSecObject(sec, name, type);
+ if (obj == NULL)
+ {
+ // Failure
+ return false;
+ }
+
+ // Delete the Object
+ ret = DeleteSecObject(sec, obj);
+
+ // Memory release
+ FreeSecObject(obj);
+
+ return ret;
+}
+
+// Delete the Data
+bool DeleteSecData(SECURE *sec, char *name)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (name == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+
+ return DeleteSecObjectByName(sec, name, SEC_DATA);
+}
+
+// Delete the secure object
+bool DeleteSecObject(SECURE *sec, SEC_OBJ *obj)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (obj == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+ if (sec->LoginFlag == false && obj->Private)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return false;
+ }
+
+ // Delete the Object
+ if (sec->Api->C_DestroyObject(sec->SessionId, obj->Object) != CKR_OK)
+ {
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ return false;
+ }
+
+ // Clear the Cache
+ DeleteSecObjFromEnumCache(sec, obj->Name, obj->Type);
+
+ return true;
+}
+
+// Remove the object which have the specified name from the cache
+void DeleteSecObjFromEnumCache(SECURE *sec, char *name, UINT type)
+{
+ UINT i;
+ // Validate arguments
+ if (sec == NULL || name == NULL || sec->EnumCache == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(sec->EnumCache);i++)
+ {
+ SEC_OBJ *obj = LIST_DATA(sec->EnumCache, i);
+
+ if (StrCmpi(obj->Name, name) == 0)
+ {
+ if (obj->Type == type)
+ {
+ Delete(sec->EnumCache, obj);
+ FreeSecObject(obj);
+ break;
+ }
+ }
+ }
+}
+
+// Read by searching a secure object by name
+int ReadSecData(SECURE *sec, char *name, void *data, UINT size)
+{
+ UINT ret = 0;
+ SEC_OBJ *obj;
+ // Validate arguments
+ if (sec == NULL || name == NULL || data == NULL)
+ {
+ return 0;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return 0;
+ }
+
+ // Read
+ obj = FindSecObject(sec, name, SEC_DATA);
+ if (obj == NULL)
+ {
+ // Not found
+ return 0;
+ }
+
+ // Read
+ ret = ReadSecDataFromObject(sec, obj, data, size);
+
+ FreeSecObject(obj);
+
+ return ret;
+}
+
+// Clear the cache
+void EraseEnumSecObjectCache(SECURE *sec)
+{
+ // Validate arguments
+ if (sec == NULL || sec->EnumCache == NULL)
+ {
+ return;
+ }
+
+ FreeEnumSecObject(sec->EnumCache);
+ sec->EnumCache = NULL;
+}
+
+// Check for the existence of a secure object
+bool CheckSecObject(SECURE *sec, char *name, UINT type)
+{
+ SEC_OBJ *obj;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (name == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return 0;
+ }
+
+ obj = FindSecObject(sec, name, type);
+
+ if (obj == NULL)
+ {
+ return false;
+ }
+ else
+ {
+ FreeSecObject(obj);
+ return true;
+ }
+}
+
+// Cloning a secure object structure
+SEC_OBJ *CloneSecObject(SEC_OBJ *obj)
+{
+ SEC_OBJ *ret;
+ // Validate arguments
+ if (obj == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(SEC_OBJ));
+ ret->Name = CopyStr(obj->Name);
+ ret->Object = obj->Object;
+ ret->Private = obj->Private;
+ ret->Type = obj->Type;
+
+ return ret;
+}
+
+// Search a secure object by the name
+SEC_OBJ *FindSecObject(SECURE *sec, char *name, UINT type)
+{
+ LIST *o;
+ UINT i;
+ SEC_OBJ *ret = NULL;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return NULL;
+ }
+ if (name == NULL)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return NULL;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return 0;
+ }
+
+ // Enumeration
+ o = EnumSecObject(sec);
+ if (o == NULL)
+ {
+ return NULL;
+ }
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SEC_OBJ *obj = LIST_DATA(o, i);
+
+ if (obj->Type == type || type == INFINITE)
+ {
+ if (StrCmpi(obj->Name, name) == 0)
+ {
+ ret = CloneSecObject(obj);
+ break;
+ }
+ }
+ }
+ FreeEnumSecObject(o);
+
+ if (ret == NULL)
+ {
+ sec->Error = SEC_ERROR_OBJ_NOT_FOUND;
+ }
+
+ return ret;
+}
+
+// Reading a secure object
+int ReadSecDataFromObject(SECURE *sec, SEC_OBJ *obj, void *data, UINT size)
+{
+ UCHAR buf[MAX_SEC_DATA_SIZE];
+ UINT i;
+ CK_ATTRIBUTE get[] =
+ {
+ {CKA_VALUE, buf, sizeof(buf)},
+ };
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return 0;
+ }
+ if (obj == NULL || data == NULL || size == 0)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return 0;
+ }
+ if (obj->Type != SEC_DATA)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return 0;
+ }
+ if (sec->LoginFlag == false && obj->Private)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return 0;
+ }
+
+ // Acquisition
+ if (sec->Api->C_GetAttributeValue(
+ sec->SessionId, obj->Object, get, sizeof(get) / sizeof(get[0])) != CKR_OK)
+ {
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ return 0;
+ }
+
+ // Return the result
+ i = get[0].ulValueLen;
+ if (i > MAX_SEC_DATA_SIZE || i > size)
+ {
+ // Data is too large
+ sec->Error = SEC_ERROR_DATA_TOO_BIG;
+ return 0;
+ }
+
+ // Memory copy
+ Copy(data, buf, i);
+
+ return i;
+}
+
+// Release of enumeration results of the secure object
+void FreeEnumSecObject(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SEC_OBJ *obj = LIST_DATA(o, i);
+
+ FreeSecObject(obj);
+ }
+
+ ReleaseList(o);
+}
+
+// Release the secure object
+void FreeSecObject(SEC_OBJ *obj)
+{
+ // Validate arguments
+ if (obj == NULL)
+ {
+ return;
+ }
+
+ Free(obj->Name);
+ Free(obj);
+}
+
+// Clone the secure object enumeration results
+LIST *CloneEnumSecObject(LIST *o)
+{
+ LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ ret = NewListFast(NULL);
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SEC_OBJ *obj = LIST_DATA(o, i);
+
+ Add(ret, CloneSecObject(obj));
+ }
+
+ return ret;
+}
+
+// Enumeration of the secure objects
+LIST *EnumSecObject(SECURE *sec)
+{
+ CK_BBOOL b_true = true, b_false = false;
+ UINT objects[MAX_OBJ];
+ UINT i;
+ UINT ret;
+ LIST *o;
+ CK_ATTRIBUTE dummy[1];
+ CK_ATTRIBUTE a[] =
+ {
+ {CKA_TOKEN, &b_true, sizeof(b_true)},
+ };
+ UINT num_objects = MAX_OBJ;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return NULL;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return NULL;
+ }
+
+ Zero(dummy, sizeof(dummy));
+
+ // If there is a cache, return it
+ if (sec->EnumCache != NULL)
+ {
+ return CloneEnumSecObject(sec->EnumCache);
+ }
+
+ // Enumerate
+// if (sec->Dev->Id != 2 && sec->Dev->Id != 14)
+// {
+ // Normal tokens
+ ret = sec->Api->C_FindObjectsInit(sec->SessionId, a, sizeof(a) / sizeof(a[0]));
+// }
+// else
+// {
+ // ePass and SafeSign
+// ret = sec->Api->C_FindObjectsInit(sec->SessionId, dummy, 0);
+// }
+
+ if (ret != CKR_OK)
+ {
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ return NULL;
+ }
+ if (sec->Api->C_FindObjects(sec->SessionId, objects, sizeof(objects) / sizeof(objects[0]), &num_objects) != CKR_OK)
+ {
+ sec->Api->C_FindObjectsFinal(sec->SessionId);
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ return NULL;
+ }
+ sec->Api->C_FindObjectsFinal(sec->SessionId);
+
+ o = NewListFast(NULL);
+
+ for (i = 0;i < num_objects;i++)
+ {
+ char label[MAX_SIZE];
+ UINT obj_class = 0;
+ bool priv = false;
+ CK_ATTRIBUTE get[] =
+ {
+ {CKA_LABEL, label, sizeof(label) - 1},
+ {CKA_CLASS, &obj_class, sizeof(obj_class)},
+ {CKA_PRIVATE, &priv, sizeof(priv)},
+ };
+
+ Zero(label, sizeof(label));
+
+ if (sec->Api->C_GetAttributeValue(sec->SessionId, objects[i],
+ get, sizeof(get) / sizeof(get[0])) == CKR_OK)
+ {
+ UINT type = INFINITE;
+
+ switch (obj_class)
+ {
+ case CKO_DATA:
+ // Data
+ type = SEC_DATA;
+ break;
+
+ case CKO_CERTIFICATE:
+ // Certificate
+ type = SEC_X;
+ break;
+
+ case CKO_PUBLIC_KEY:
+ // Public key
+ type = SEC_P;
+ break;
+
+ case CKO_PRIVATE_KEY:
+ // Secret key
+ type = SEC_K;
+ break;
+ }
+
+ if (type != INFINITE)
+ {
+ SEC_OBJ *obj = ZeroMalloc(sizeof(SEC_OBJ));
+
+ obj->Type = type;
+ obj->Object = objects[i];
+ obj->Private = (priv == false) ? false : true;
+ EnSafeStr(label, '?');
+ TruncateCharFromStr(label, '?');
+ obj->Name = CopyStr(label);
+
+ Add(o, obj);
+ }
+ }
+ }
+
+ // Creating a cache
+ sec->EnumCache = CloneEnumSecObject(o);
+
+ return o;
+}
+
+// Write the data
+bool WriteSecData(SECURE *sec, bool private_obj, char *name, void *data, UINT size)
+{
+ UINT object_class = CKO_DATA;
+ CK_BBOOL b_true = true, b_false = false, b_private_obj = private_obj;
+ UINT object;
+ CK_ATTRIBUTE a[] =
+ {
+ {CKA_TOKEN, &b_true, sizeof(b_true)},
+ {CKA_CLASS, &object_class, sizeof(object_class)},
+ {CKA_PRIVATE, &b_private_obj, sizeof(b_private_obj)},
+ {CKA_LABEL, name, StrLen(name)},
+ {CKA_VALUE, data, size},
+ };
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+ }
+ if (private_obj && sec->LoginFlag == false)
+ {
+ sec->Error = SEC_ERROR_NOT_LOGIN;
+ return false;
+ }
+ if (name == NULL || data == NULL || size == 0)
+ {
+ sec->Error = SEC_ERROR_BAD_PARAMETER;
+ return false;
+ }
+ if (size > MAX_SEC_DATA_SIZE)
+ {
+ sec->Error = SEC_ERROR_DATA_TOO_BIG;
+ return false;
+ }
+
+ // Delete any objects with the same name
+ if (CheckSecObject(sec, name, SEC_DATA))
+ {
+ DeleteSecData(sec, name);
+ }
+
+ // Object creation
+ if (sec->Api->C_CreateObject(sec->SessionId, a, sizeof(a) / sizeof(a[0]), &object) != CKR_OK)
+ {
+ sec->Error = SEC_ERROR_HARDWARE_ERROR;
+ return false;
+ }
+
+ // Clear the cache
+ EraseEnumSecObjectCache(sec);
+
+ return true;
+}
+
+// Add the information of the newly created object to the cache
+void AddSecObjToEnumCache(SECURE *sec, char *name, UINT type, bool private_obj, UINT object)
+{
+ SEC_OBJ *obj;
+ // Validate arguments
+ if (sec == NULL || name == NULL || sec->EnumCache == NULL)
+ {
+ return;
+ }
+
+ obj = ZeroMalloc(sizeof(SEC_OBJ));
+ obj->Name = CopyStr(name);
+ obj->Object = object;
+ obj->Private = private_obj;
+ obj->Type = type;
+
+ Add(sec->EnumCache, obj);
+}
+
+// Display the token information
+void PrintSecInfo(SECURE *sec)
+{
+ SEC_INFO *s;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+
+ s = sec->Info;
+ if (s == NULL)
+ {
+ Print("No Token Info.\n");
+ return;
+ }
+
+ Print(
+ " Label: %S\n"
+ " ManufacturerId: %S\n"
+ " Model: %S\n"
+ " SerialNumber: %S\n"
+ " MaxSession: %u\n"
+ " MaxRWSession: %u\n"
+ " MinPinLen: %u\n"
+ " MaxPinLen: %u\n"
+ " TotalPublicMemory: %u\n"
+ " FreePublicMemory: %u\n"
+ " TotalPrivateMemory: %u\n"
+ " FreePrivateMemory: %u\n"
+ " HardwareVersion: %s\n"
+ " FirmwareVersion: %s\n",
+ s->Label, s->ManufacturerId, s->Model, s->SerialNumber,
+ s->MaxSession, s->MaxRWSession, s->MinPinLen, s->MaxPinLen,
+ s->TotalPublicMemory, s->FreePublicMemory, s->TotalPrivateMemory,
+ s->FreePrivateMemory, s->HardwareVersion, s->FirmwareVersion
+ );
+}
+
+// Get the token information
+void GetSecInfo(SECURE *sec)
+{
+ CK_TOKEN_INFO token_info;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+ if (sec->Info != NULL)
+ {
+ return;
+ }
+
+ // Acquisition
+ Zero(&token_info, sizeof(token_info));
+ if (sec->Api->C_GetTokenInfo(sec->SlotIdList[sec->SessionSlotNumber], &token_info) != CKR_OK)
+ {
+ // Failure
+ return;
+ }
+
+ sec->Info = TokenInfoToSecInfo(&token_info);
+}
+
+// Release the token information
+void FreeSecInfo(SECURE *sec)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+ if (sec->Info == NULL)
+ {
+ return;
+ }
+
+ FreeSecInfoMemory(sec->Info);
+ sec->Info = NULL;
+}
+
+// Convert the token information to the SEC_INFO
+SEC_INFO *TokenInfoToSecInfo(void *p_t)
+{
+ SEC_INFO *s;
+ char buf[MAX_SIZE];
+ CK_TOKEN_INFO *t = (CK_TOKEN_INFO *)p_t;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ s = ZeroMalloc(sizeof(SEC_INFO));
+
+ // Label
+ Zero(buf, sizeof(buf));
+ Copy(buf, t->label, sizeof(t->label));
+ s->Label = ZeroMalloc(CalcUtf8ToUni(buf, 0));
+ Utf8ToUni(s->Label, 0, buf, 0);
+
+ // ManufacturerId
+ Zero(buf, sizeof(buf));
+ Copy(buf, t->manufacturerID, sizeof(t->manufacturerID));
+ s->ManufacturerId = ZeroMalloc(CalcUtf8ToUni(buf, 0));
+ Utf8ToUni(s->ManufacturerId, 0, buf, 0);
+
+ // Model
+ Zero(buf, sizeof(buf));
+ Copy(buf, t->model, sizeof(t->model));
+ s->Model = ZeroMalloc(CalcUtf8ToUni(buf, 0));
+ Utf8ToUni(s->Model, 0, buf, 0);
+
+ // SerialNumber
+ Zero(buf, sizeof(buf));
+ Copy(buf, t->serialNumber, sizeof(t->serialNumber));
+ s->SerialNumber = ZeroMalloc(CalcUtf8ToUni(buf, 0));
+ Utf8ToUni(s->SerialNumber, 0, buf, 0);
+
+ // Numeric value
+ s->MaxSession = t->ulMaxSessionCount;
+ s->MaxRWSession = t->ulMaxRwSessionCount;
+ s->MinPinLen = t->ulMinPinLen;
+ s->MaxPinLen = t->ulMaxPinLen;
+ s->TotalPublicMemory = t->ulTotalPublicMemory;
+ s->FreePublicMemory = t->ulFreePublicMemory;
+ s->TotalPrivateMemory = t->ulTotalPrivateMemory;
+ s->FreePrivateMemory = t->ulFreePrivateMemory;
+
+ // Hardware version
+ Format(buf, sizeof(buf), "%u.%02u", t->hardwareVersion.major, t->hardwareVersion.minor);
+ s->HardwareVersion = CopyStr(buf);
+
+ // Firmware version
+ Format(buf, sizeof(buf), "%u.%02u", t->firmwareVersion.major, t->firmwareVersion.minor);
+ s->FirmwareVersion = CopyStr(buf);
+
+ return s;
+}
+
+// Release the memory of the SEC_INFO
+void FreeSecInfoMemory(SEC_INFO *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ Free(s->Label);
+ Free(s->ManufacturerId);
+ Free(s->Model);
+ Free(s->SerialNumber);
+ Free(s->HardwareVersion);
+ Free(s->FirmwareVersion);
+ Free(s);
+}
+
+// Log-out
+void LogoutSec(SECURE *sec)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+ if (sec->LoginFlag == false)
+ {
+ return;
+ }
+
+ // Log-out
+ sec->Api->C_Logout(sec->SessionId);
+
+ // Clear Cache
+ EraseEnumSecObjectCache(sec);
+
+ sec->LoginFlag = false;
+}
+
+// Log-in
+bool LoginSec(SECURE *sec, char *pin)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (sec->SessionCreated == false)
+ {
+ sec->Error = SEC_ERROR_NO_SESSION;
+ return false;
+
+ }
+ if (sec->LoginFlag)
+ {
+ sec->Error = SEC_ERROR_ALREADY_LOGIN;
+ return false;
+ }
+ if (pin == NULL)
+ {
+ sec->Error = SEC_ERROR_NO_PIN_STR;
+ return false;
+ }
+
+ // Log-in
+ if (sec->Api->C_Login(sec->SessionId, CKU_USER, pin, StrLen(pin)) != CKR_OK)
+ {
+ // Login failure
+ sec->Error = SEC_ERROR_BAD_PIN_CODE;
+ return false;
+ }
+
+ // Clear the cache
+ EraseEnumSecObjectCache(sec);
+
+ sec->LoginFlag = true;
+
+ return true;
+}
+
+// Close the session
+void CloseSecSession(SECURE *sec)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+ if (sec->SessionCreated == false)
+ {
+ return;
+ }
+
+ // Close the session
+ sec->Api->C_CloseSession(sec->SessionId);
+
+ sec->SessionCreated = false;
+ sec->SessionId = 0;
+ sec->SessionSlotNumber = 0;
+
+ FreeSecInfo(sec);
+
+ // Clear the cache
+ EraseEnumSecObjectCache(sec);
+}
+
+// Open the session
+bool OpenSecSession(SECURE *sec, UINT slot_number)
+{
+ UINT err = 0;
+ UINT session;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+ if (sec->SessionCreated)
+ {
+ // Already been created
+ sec->Error = SEC_ERROR_SESSION_EXISTS;
+ return false;
+ }
+ if (slot_number >= sec->NumSlot)
+ {
+ // Slot number is invalid
+ sec->Error = SEC_ERROR_INVALID_SLOT_NUMBER;
+ return false;
+ }
+
+ // Create a session
+ if ((err = sec->Api->C_OpenSession(sec->SlotIdList[slot_number],
+ CKF_RW_SESSION | CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK)
+ {
+ // Failed to initialize session in read / write mode
+ // Read-only mode?
+ if ((err = sec->Api->C_OpenSession(sec->SlotIdList[slot_number],
+ CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK)
+ {
+ // Failure to create
+ sec->Error = SEC_ERROR_OPEN_SESSION;
+ return false;
+ }
+ else
+ {
+ sec->IsReadOnly = true;
+ }
+ }
+
+ sec->SessionCreated = true;
+ sec->SessionId = session;
+ sec->SessionSlotNumber = slot_number;
+
+ // Get the token information
+ GetSecInfo(sec);
+
+ return true;
+}
+
+// Close the secure device
+void CloseSec(SECURE *sec)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+
+ // Log out
+ LogoutSec(sec);
+
+ // Close the session
+ CloseSecSession(sec);
+
+ // Release the token information
+ FreeSecInfo(sec);
+
+ // Release of the slot list memory
+ if (sec->SlotIdList != NULL)
+ {
+ Free(sec->SlotIdList);
+ sec->SlotIdList = NULL;
+ }
+
+ // Unload the module
+ FreeSecModule(sec);
+
+ // Memory release
+ DeleteLock(sec->lock);
+ Free(sec);
+}
+
+// Open a secure device
+SECURE *OpenSec(UINT id)
+{
+ SECURE_DEVICE *dev = GetSecureDevice(id);
+ SECURE *sec;
+ UINT err;
+
+ if (dev == NULL)
+ {
+ return NULL;
+ }
+
+ sec = ZeroMalloc(sizeof(SECURE));
+
+ sec->lock = NewLock();
+ sec->Error = SEC_ERROR_NOERROR;
+ sec->Dev = dev;
+
+ // Get whether it's a ePass or not
+ if (SearchStrEx(dev->DeviceName, "epass", 0, false) != INFINITE)
+ {
+ sec->IsEPass1000 = true;
+ }
+
+ // Load the module
+ if (LoadSecModule(sec) == false)
+ {
+ CloseSec(sec);
+ return NULL;
+ }
+
+ // Get the slot list
+ sec->NumSlot = 0;
+ if ((err = sec->Api->C_GetSlotList(true, NULL, &sec->NumSlot)) != CKR_OK || sec->NumSlot == 0)
+ {
+ // Failure
+ FreeSecModule(sec);
+ CloseSec(sec);
+ return NULL;
+ }
+
+ sec->SlotIdList = (UINT *)ZeroMalloc(sizeof(UINT *) * sec->NumSlot);
+
+ if (sec->Api->C_GetSlotList(TRUE, sec->SlotIdList, &sec->NumSlot) != CKR_OK)
+ {
+ // Failure
+ Free(sec->SlotIdList);
+ sec->SlotIdList = NULL;
+ FreeSecModule(sec);
+ CloseSec(sec);
+ return NULL;
+ }
+
+ return sec;
+}
+
+// Load the module of the secure device
+bool LoadSecModule(SECURE *sec)
+{
+ bool ret = false;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return false;
+ }
+
+#ifdef OS_WIN32
+ ret = Win32LoadSecModule(sec);
+#endif // OS_WIN32
+
+ // Initialization
+ if (sec->Api->C_Initialize(NULL) != CKR_OK)
+ {
+ // Initialization Failed
+ FreeSecModule(sec);
+ return false;
+ }
+
+ sec->Initialized = true;
+
+ return ret;
+}
+
+// Unload the module of the secure device
+void FreeSecModule(SECURE *sec)
+{
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+
+ if (sec->Initialized)
+ {
+ // Release because it is initialized
+ sec->Api->C_Finalize(NULL);
+ sec->Initialized = false;
+ }
+
+#ifdef OS_WIN32
+ Win32FreeSecModule(sec);
+#endif // OS_WIN32
+
+}
+
+
+// Get a secure device
+SECURE_DEVICE *GetSecureDevice(UINT id)
+{
+ UINT i;
+
+ if (id == 0)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(SecureDeviceList);i++)
+ {
+ SECURE_DEVICE *dev = LIST_DATA(SecureDeviceList, i);
+
+ if (dev->Id == id)
+ {
+ return dev;
+ }
+ }
+
+ return NULL;
+}
+
+// Confirm the ID of the secure device
+bool CheckSecureDeviceId(UINT id)
+{
+ UINT i;
+
+ for (i = 0;i < LIST_NUM(SecureDeviceList);i++)
+ {
+ SECURE_DEVICE *dev = LIST_DATA(SecureDeviceList, i);
+
+ if (dev->Id == id)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Get a list of supported devices
+LIST *GetSecureDeviceList()
+{
+ return GetSupportedDeviceList();
+}
+
+// Get a list of supported devices
+LIST *GetSupportedDeviceList()
+{
+ // Increase the reference count
+ AddRef(SecureDeviceList->ref);
+
+ return SecureDeviceList;
+}
+
+// Examine whether the specified device is installed and available
+bool IsDeviceSupported(SECURE_DEVICE *dev)
+{
+ bool b = false;
+#ifdef OS_WIN32
+ b = Win32IsDeviceSupported(dev);
+#endif // OS_WIN32
+ return b;
+}
+
+// Initialization of the secure device list
+void InitSecureDeviceList()
+{
+ UINT i, num_supported_list;
+ SecureDeviceList = NewList(NULL);
+
+ num_supported_list = sizeof(SupportedList) / sizeof(SECURE_DEVICE);
+ for (i = 0; i < num_supported_list;i++)
+ {
+ SECURE_DEVICE *dev = &SupportedList[i];
+
+ // Support Checking
+ if (IsDeviceSupported(dev))
+ {
+ // Add the device to the list because it is supported
+ Add(SecureDeviceList, dev);
+ }
+ }
+}
+
+// Test main procedure
+void TestSecMain(SECURE *sec)
+{
+ char *test_str = CEDAR_PRODUCT_STR " VPN";
+ K *public_key, *private_key;
+ // Validate arguments
+ if (sec == NULL)
+ {
+ return;
+ }
+
+ Print("test_str: \"%s\"\n", test_str);
+
+ Print("Writing Data...\n");
+ if (WriteSecData(sec, true, "test_str", test_str, StrLen(test_str)) == false)
+ {
+ Print("WriteSecData() Failed.\n");
+ }
+ else
+ {
+ char data[MAX_SIZE];
+ Zero(data, sizeof(data));
+ Print("Reading Data...\n");
+ if (ReadSecData(sec, "test_str", data, sizeof(data)) == false)
+ {
+ Print("ReadSecData() Failed.\n");
+ }
+ else
+ {
+ Print("test_str: \"%s\"\n", data);
+ }
+ Print("Deleting Data...\n");
+ DeleteSecData(sec, "test_str");
+ }
+
+ Print("Generating Key...\n");
+ if (RsaGen(&private_key, &public_key, 1024) == false)
+ {
+ Print("RsaGen() Failed.\n");
+ }
+ else
+ {
+ X *cert;
+ NAME *name;
+ X_SERIAL *serial;
+ UINT num = 0x11220000;
+
+ Print("Creating Cert...\n");
+ serial = NewXSerial(&num, sizeof(UINT));
+ name = NewName(L"Test", L"Test", L"Test", L"JP", L"Test", L"Test");
+ cert = NewRootX(public_key, private_key, name, 365, NULL);
+ FreeXSerial(serial);
+ if (cert == NULL)
+ {
+ Print("NewRootX() Failed.\n");
+ }
+ else
+ {
+ Print("Writing Cert...\n");
+ DeleteSecData(sec, "test_cer");
+ if (WriteSecCert(sec, true, "test_cer", cert) == false)
+ {
+ Print("WriteSecCert() Failed.\n");
+ }
+ else
+ {
+ X *x;
+ Print("Reading Cert...\n");
+ x = ReadSecCert(sec, "test_cer");
+ if (x == NULL)
+ {
+ Print("ReadSecCert() Failed.\n");
+ }
+ else
+ {
+ Print("Checking two Certs... ");
+ if (CompareX(x, cert) == false)
+ {
+ Print("[FAILED]\n");
+ }
+ else
+ {
+ Print("Ok.\n");
+ }
+ FreeX(x);
+ }
+ if (cert != NULL)
+ {
+ X *x;
+ XToFile(cert, "cert_tmp.cer", true);
+ x = FileToX("cert_tmp.cer");
+ if (CompareX(x, cert) == false)
+ {
+ Print("[FAILED]\n");
+ }
+ else
+ {
+ Print("Ok.\n");
+ Print("Writing Private Key...\n");
+ DeleteSecKey(sec, "test_key");
+ if (WriteSecKey(sec, true, "test_key", private_key) == false)
+ {
+ Print("WriteSecKey() Failed.\n");
+ }
+ else
+ {
+ UCHAR sign_cpu[128];
+ UCHAR sign_sec[128];
+ K *pub = GetKFromX(cert);
+ Print("Ok.\n");
+ Print("Signing Data by CPU...\n");
+ if (RsaSign(sign_cpu, test_str, StrLen(test_str), private_key) == false)
+ {
+ Print("RsaSign() Failed.\n");
+ }
+ else
+ {
+ Print("Ok.\n");
+ Print("sign_cpu: ");
+ PrintBin(sign_cpu, sizeof(sign_cpu));
+ Print("Signing Data by %s..\n", sec->Dev->DeviceName);
+ if (SignSec(sec, "test_key", sign_sec, test_str, StrLen(test_str)) == false)
+ {
+ Print("SignSec() Failed.\n");
+ }
+ else
+ {
+ Print("Ok.\n");
+ Print("sign_sec: ");
+ PrintBin(sign_sec, sizeof(sign_sec));
+ Print("Compare...");
+ if (Cmp(sign_sec, sign_cpu, sizeof(sign_cpu)) == 0)
+ {
+ Print("Ok.\n");
+ Print("Verify...");
+ if (RsaVerify(test_str, StrLen(test_str),
+ sign_sec, pub) == false)
+ {
+ Print("[FAILED]\n");
+ }
+ else
+ {
+ Print("Ok.\n");
+ }
+ }
+ else
+ {
+ Print("[DIFFIRENT]\n");
+ }
+ }
+ }
+ Print("Deleting test_key...\n");
+// DeleteSecKey(sec, "test_key");
+ FreeK(pub);
+ }
+ }
+ FreeX(x);
+ }
+ }
+ Print("Deleting Cert..\n");
+// DeleteSecCert(sec, "test_cer");
+ FreeX(cert);
+ }
+ FreeName(name);
+ FreeK(private_key);
+ FreeK(public_key);
+ }
+}
+
+// Test the security device
+void TestSec()
+{
+ UINT i;
+ LIST *secure_device_list;
+ Print("Secure Device Test Program\n"
+ "Copyright (c) SoftEther Corporation. All Rights Reserved.\n\n");
+
+ // Get the secure device list
+ secure_device_list = GetSecureDeviceList();
+ if (secure_device_list != NULL)
+ {
+ UINT use_device_id;
+ char tmp[MAX_SIZE];
+ Print("--- Secure Device List ---\n");
+ for (i = 0;i < LIST_NUM(secure_device_list);i++)
+ {
+ SECURE_DEVICE *dev = LIST_DATA(secure_device_list, i);
+ Print("%2u - %s\n", dev->Id, dev->DeviceName);
+ }
+ Print("\n");
+ Print("Device ID >");
+ GetLine(tmp, sizeof(tmp));
+ use_device_id = ToInt(tmp);
+ if (use_device_id == 0)
+ {
+ Print("Canceled.\n");
+ }
+ else
+ {
+ SECURE *sec = OpenSec(use_device_id);
+ Print("Opening Device...\n");
+ if (sec == NULL)
+ {
+ Print("OpenSec() Failed.\n");
+ }
+ else
+ {
+ Print("Opening Session...\n");
+ if (OpenSecSession(sec, 0) == false)
+ {
+ Print("OpenSecSession() Failed.\n");
+ }
+ else
+ {
+ while (true)
+ {
+ char pin[MAX_SIZE];
+ Print("PIN Code >");
+ GetLine(pin, sizeof(pin));
+ Trim(pin);
+ if (StrLen(pin) == 0)
+ {
+ Print("Canceled.\n");
+ break;
+ }
+ else
+ {
+ Print("Login...\n");
+ if (LoginSec(sec, pin))
+ {
+ TestSecMain(sec);
+ Print("Logout...\n");
+ LogoutSec(sec);
+ break;
+ }
+ else
+ {
+ Print("Login Failed. Please Try Again.\n");
+ }
+ }
+ }
+ Print("Closing Session...\n");
+ CloseSecSession(sec);
+ }
+ Print("Closing Device...\n");
+ CloseSec(sec);
+ }
+ }
+ ReleaseList(secure_device_list);
+ }
+ else
+ {
+ Print("GetSecureDeviceList() Error.\n");
+ }
+}
+
+// Release of the secure device list
+void FreeSecureDeviceList()
+{
+ ReleaseList(SecureDeviceList);
+}
+
+// Initialization of the security token module
+void InitSecure()
+{
+ // Initialization of the secure device list
+ InitSecureDeviceList();
+}
+
+// Release of the security token module
+void FreeSecure()
+{
+ // Release of the secure device list
+ FreeSecureDeviceList();
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Secure.h b/src/Mayaqua/Secure.h
new file mode 100644
index 00000000..f9fd0fdd
--- /dev/null
+++ b/src/Mayaqua/Secure.h
@@ -0,0 +1,297 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Secure.h
+// Header of Secure.c
+
+#ifndef SECURE_H
+#define SECURE_H
+
+// Constant
+#define MAX_SEC_DATA_SIZE 4096
+
+// Type declaration related to PKCS#11
+#ifndef SECURE_C
+typedef struct CK_FUNCTION_LIST *CK_FUNCTION_LIST_PTR;
+typedef struct SEC_DATA_WIN32 SEC_DATA_WIN32;
+typedef struct CK_TOKEN_INFO CK_TOKEN_INFO;
+typedef struct CK_DATE CK_DATE;
+#endif // SECURE_C
+
+// Secure device
+struct SECURE_DEVICE
+{
+ UINT Id; // Device ID
+ UINT Type; // Type
+ char *DeviceName; // Device name
+ char *Manufacturer; // Manufacturer
+ char *ModuleName; // Module name
+};
+
+// Type of secure device
+#define SECURE_IC_CARD 0 // IC card
+#define SECURE_USB_TOKEN 1 // USB token
+
+// Secure device information
+struct SEC_INFO
+{
+ wchar_t *Label; // Label
+ wchar_t *ManufacturerId; // Vendor ID
+ wchar_t *Model; // Model
+ wchar_t *SerialNumber; // Serial number
+ UINT MaxSession; // Maximum number of sessions
+ UINT MaxRWSession; // Maximum Number of R/W sessions
+ UINT MinPinLen; // Minimum length of the PIN string
+ UINT MaxPinLen; // Maximum length of the PIN string
+ UINT TotalPublicMemory; // Total memory capacity (Public)
+ UINT FreePublicMemory; // Free memory capacity (Public)
+ UINT TotalPrivateMemory; // Total memory capacity (Private)
+ UINT FreePrivateMemory; // Free memory capacity (Private)
+ char *HardwareVersion; // Hardware version
+ char *FirmwareVersion; // Firmware version
+};
+
+// Secure device structure
+struct SECURE
+{
+ LOCK *lock; // Lock
+ SECURE_DEVICE *Dev; // Device Information
+ UINT Error; // The error that last occurred
+ struct CK_FUNCTION_LIST *Api; // API
+ bool Initialized; // Initialization flag
+ UINT NumSlot; // The number of slots
+ UINT *SlotIdList; // Slot ID list
+ bool SessionCreated; // Session creation flags
+ UINT SessionId; // Session ID
+ UINT SessionSlotNumber; // Slot ID of the session
+ bool LoginFlag; // Logged-in flag
+ SEC_INFO *Info; // Token information
+ LIST *EnumCache; // Enumeration cache
+
+ // Attribute value for the different behavior for each driver
+ bool IsEPass1000; // ePass 1000
+ bool IsReadOnly; // Read-only mode
+
+#ifdef OS_WIN32
+ struct SEC_DATA_WIN32 *Data; // Data
+#endif // OS_WIN32
+};
+
+// Secure device object structure
+struct SEC_OBJ
+{
+ UINT Type; // Type of object
+ UINT Object; // Object handle
+ bool Private; // Private flag
+ char *Name; // Name
+};
+
+#define SEC_ERROR_NOERROR 0 // No Error
+#define SEC_ERROR_INVALID_SLOT_NUMBER 1 // Slot number is invalid
+#define SEC_ERROR_OPEN_SESSION 2 // Session creation failure
+#define SEC_ERROR_SESSION_EXISTS 3 // The session already exists
+#define SEC_ERROR_NO_PIN_STR 4 // PIN string is not specified
+#define SEC_ERROR_ALREADY_LOGIN 5 // Already logged in
+#define SEC_ERROR_BAD_PIN_CODE 6 // PIN code is invalid
+#define SEC_ERROR_NO_SESSION 7 // There is no session
+#define SEC_ERROR_DATA_TOO_BIG 8 // Data is too large
+#define SEC_ERROR_NOT_LOGIN 9 // Not logged in
+#define SEC_ERROR_BAD_PARAMETER 10 // Invalid Parameters
+#define SEC_ERROR_HARDWARE_ERROR 11 // Hardware error
+#define SEC_ERROR_OBJ_NOT_FOUND 12 // Object is not found
+#define SEC_ERROR_INVALID_CERT 13 // The certificate is invalid
+
+
+#define SEC_DATA 0 // Data
+#define SEC_X 1 // Certificate
+#define SEC_K 2 // Secret key
+#define SEC_P 3 // Public key
+
+
+
+// Function prototype
+void InitSecure();
+void FreeSecure();
+void InitSecureDeviceList();
+void FreeSecureDeviceList();
+bool IsDeviceSupported(SECURE_DEVICE *dev);
+LIST *GetSupportedDeviceList();
+LIST *GetSecureDeviceList();
+bool CheckSecureDeviceId(UINT id);
+SECURE_DEVICE *GetSecureDevice(UINT id);
+SECURE *OpenSec(UINT id);
+void CloseSec(SECURE *sec);
+bool OpenSecSession(SECURE *sec, UINT slot_number);
+void CloseSecSession(SECURE *sec);
+bool LoginSec(SECURE *sec, char *pin);
+void LogoutSec(SECURE *sec);
+void PrintSecInfo(SECURE *sec);
+LIST *EnumSecObject(SECURE *sec);
+void FreeSecObject(SEC_OBJ *obj);
+void FreeEnumSecObject(LIST *o);
+SEC_OBJ *FindSecObject(SECURE *sec, char *name, UINT type);
+bool CheckSecObject(SECURE *sec, char *name, UINT type);
+bool DeleteSecObjectByName(SECURE *sec, char *name, UINT type);
+SEC_OBJ *CloneSecObject(SEC_OBJ *obj);
+LIST *CloneEnumSecObject(LIST *o);
+void EraseEnumSecObjectCache(SECURE *sec);
+void DeleteSecObjFromEnumCache(SECURE *sec, char *name, UINT type);
+void AddSecObjToEnumCache(SECURE *sec, char *name, UINT type, bool private_obj, UINT object);
+bool WriteSecData(SECURE *sec, bool private_obj, char *name, void *data, UINT size);
+int ReadSecDataFromObject(SECURE *sec, SEC_OBJ *obj, void *data, UINT size);
+int ReadSecData(SECURE *sec, char *name, void *data, UINT size);
+bool DeleteSecObject(SECURE *sec, SEC_OBJ *obj);
+bool DeleteSecData(SECURE *sec, char *name);
+void UINT64ToCkDate(void *p_ck_date, UINT64 time64);
+bool WriteSecCert(SECURE *sec, bool private_obj, char *name, X *x);
+bool DeleteSecCert(SECURE *sec, char *name);
+X *ReadSecCertFromObject(SECURE *sec, SEC_OBJ *obj);
+X *ReadSecCert(SECURE *sec, char *name);
+bool WriteSecKey(SECURE *sec, bool private_obj, char *name, K *k);
+bool DeleteSecKey(SECURE *sec, char *name);
+bool SignSecByObject(SECURE *sec, SEC_OBJ *obj, void *dst, void *src, UINT size);
+bool SignSec(SECURE *sec, char *name, void *dst, void *src, UINT size);
+bool ChangePin(SECURE *sec, char *old_pin, char *new_pin);
+void TestSec();
+void TestSecMain(SECURE *sec);
+bool IsJPKI(bool id);
+
+bool LoadSecModule(SECURE *sec);
+void FreeSecModule(SECURE *sec);
+void GetSecInfo(SECURE *sec);
+void FreeSecInfo(SECURE *sec);
+SEC_INFO *TokenInfoToSecInfo(void *p_t);
+void FreeSecInfoMemory(SEC_INFO *s);
+
+#ifdef OS_WIN32
+
+bool Win32IsDeviceSupported(SECURE_DEVICE *dev);
+bool Win32LoadSecModule(SECURE *sec);
+void Win32FreeSecModule(SECURE *sec);
+
+#endif // OS_WIN32
+
+
+#ifdef SECURE_C
+// Internal data structure
+// The list of supported secure devices
+static LIST *SecureDeviceList = NULL;
+
+// Supported hardware list
+SECURE_DEVICE SupportedList[] =
+{
+ {1, SECURE_IC_CARD, "Standard-9 IC Card", "Dai Nippon Printing", "DNPS9P11.DLL"},
+ {2, SECURE_USB_TOKEN, "ePass 1000", "Feitian Technologies", "EP1PK111.DLL"},
+ {3, SECURE_IC_CARD, "DNP Felica", "Dai Nippon Printing", "DNPFP11.DLL"},
+ {4, SECURE_USB_TOKEN, "eToken", "Aladdin", "ETPKCS11.DLL"},
+ {5, SECURE_IC_CARD, "Standard-9 IC Card", "Fujitsu", "F3EZSCL2.DLL"},
+ {6, SECURE_IC_CARD, "ASECard", "Athena", "ASEPKCS.DLL"},
+ {7, SECURE_IC_CARD, "Gemplus IC Card", "Gemplus", "PK2PRIV.DLL"},
+ {8, SECURE_IC_CARD, "1-Wire & iButton", "DALLAS SEMICONDUCTOR", "DSPKCS.DLL"},
+ {9, SECURE_IC_CARD, "JPKI IC Card", "Japanese Government", "JPKIPKCS11.DLL"},
+ {10, SECURE_IC_CARD, "LGWAN IC Card", "Japanese Government", "P11STD9.DLL"},
+ {11, SECURE_IC_CARD, "LGWAN IC Card", "Japanese Government", "P11STD9A.DLL"},
+ {12, SECURE_USB_TOKEN, "iKey 1000", "Rainbow Technologies", "K1PK112.DLL"},
+ {13, SECURE_IC_CARD, "JPKI IC Card #2", "Japanese Government", "libmusclepkcs11.dll"},
+ {14, SECURE_USB_TOKEN, "SafeSign", "A.E.T.", "aetpkss1.dll"},
+ {15, SECURE_USB_TOKEN, "LOCK STAR-PKI", "Logicaltech Co.,LTD", "LTPKCS11.dll"},
+ {16, SECURE_USB_TOKEN, "ePass 2000", "Feitian Technologies", "ep2pk11.dll"},
+ {17, SECURE_IC_CARD, "myuToken", "iCanal Inc.", "icardmodpk.dll"},
+ {18, SECURE_IC_CARD, "Gemalto .NET", "Gemalto", "gtop11dotnet.dll"},
+ {19, SECURE_IC_CARD, "Gemalto .NET 64bit", "Gemalto", "gtop11dotnet64.dll"},
+};
+
+#ifdef OS_WIN32
+
+// Win32 internal data
+typedef struct SEC_DATA_WIN32
+{
+ HINSTANCE hInst;
+} SEC_DATA_WIN32;
+
+#endif // OS_WIN32
+
+#endif // SECURE_C
+
+#endif // SECURE_H
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Str.c b/src/Mayaqua/Str.c
new file mode 100644
index 00000000..a85edaf9
--- /dev/null
+++ b/src/Mayaqua/Str.c
@@ -0,0 +1,3391 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Str.c
+// String processing routine
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// Locking for call the token handling function
+LOCK *token_lock = NULL;
+static char *default_spliter = " ,\t\r\n";
+
+typedef struct BYTESTR
+{
+ UINT64 base_value;
+ char *string;
+} BYTESTR;
+
+static BYTESTR bytestr[] =
+{
+ {0, "PBytes"},
+ {0, "TBytes"},
+ {0, "GBytes"},
+ {0, "MBytes"},
+ {0, "KBytes"},
+ {0, "Bytes"},
+};
+
+// Change the case of the string by the bit array
+void SetStrCaseAccordingToBits(char *str, UINT bits)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ len = StrLen(str);
+
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ if (bits & 0x01)
+ {
+ c = ToUpper(c);
+ }
+ else
+ {
+ c = ToLower(c);
+ }
+
+ str[i] = c;
+
+ bits = bits / 2;
+ }
+}
+
+// Normalize the integer list string
+void NormalizeIntListStr(char *dst, UINT dst_size, char *src, bool sorted, char *separate_str)
+{
+ LIST *o;
+
+ o = StrToIntList(src, sorted);
+
+ IntListToStr(dst, dst_size, o, separate_str);
+
+ ReleaseIntList(o);
+}
+
+// Convert the string to an integer list
+LIST *StrToIntList(char *str, bool sorted)
+{
+ LIST *o;
+ TOKEN_LIST *t;
+
+ o = NewIntList(sorted);
+
+ t = ParseTokenWithoutNullStr(str, " ,/;\t");
+
+ if (t != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *s = t->Token[i];
+
+ if (IsEmptyStr(s) == false)
+ {
+ if (IsNum(s))
+ {
+ InsertIntDistinct(o, ToInt(s));
+ }
+ }
+ }
+
+ FreeToken(t);
+ }
+
+ return o;
+}
+
+// Convert an integer list to a string
+void IntListToStr(char *str, UINT str_size, LIST *o, char *separate_str)
+{
+ UINT i;
+ ClearStr(str, str_size);
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+ if (IsEmptyStr(separate_str))
+ {
+ separate_str = ", ";
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char tmp[MAX_SIZE];
+ UINT *v = LIST_DATA(o, i);
+
+ ToStr(tmp, *v);
+
+ StrCat(str, str_size, tmp);
+
+ if (i != (LIST_NUM(o) - 1))
+ {
+ StrCat(str, str_size, separate_str);
+ }
+ }
+}
+
+// Initialize the string
+void ClearStr(char *str, UINT str_size)
+{
+ StrCpy(str, str_size, "");
+}
+
+// Search for the ASCII string in the binary data sequence
+UINT SearchAsciiInBinary(void *data, UINT size, char *str, bool case_sensitive)
+{
+ UINT ret = INFINITE;
+ char *tmp;
+ // Validate arguments
+ if (data == NULL || size == 0 || str == NULL)
+ {
+ return INFINITE;
+ }
+
+ tmp = ZeroMalloc(size + 1);
+ Copy(tmp, data, size);
+
+ ret = SearchStrEx(tmp, str, 0, case_sensitive);
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Convert the HEX string to a 64 bit integer
+UINT64 HexToInt64(char *str)
+{
+ UINT len, i;
+ UINT64 ret = 0;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
+ {
+ str += 2;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
+ {
+ ret = ret * 16ULL + (UINT64)HexTo4Bit(c);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+// Convert the HEX string to a 32 bit integer
+UINT HexToInt(char *str)
+{
+ UINT len, i;
+ UINT ret = 0;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
+ {
+ str += 2;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
+ {
+ ret = ret * 16 + (UINT)HexTo4Bit(c);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+// Convert a 64 bit integer to a HEX
+void ToHex64(char *str, UINT64 value)
+{
+ char tmp[MAX_SIZE];
+ UINT wp = 0;
+ UINT len, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ // Set to empty character
+ StrCpy(tmp, 0, "");
+
+ // Append from the last digit
+ while (true)
+ {
+ UINT a = (UINT)(value % (UINT64)16);
+ value = value / (UINT)16;
+ tmp[wp++] = FourBitToHex(a);
+ if (value == 0)
+ {
+ tmp[wp++] = 0;
+ break;
+ }
+ }
+
+ // Reverse order
+ len = StrLen(tmp);
+ for (i = 0;i < len;i++)
+ {
+ str[len - i - 1] = tmp[i];
+ }
+ str[len] = 0;
+}
+
+// Convert a 32 bit integer into HEX
+void ToHex(char *str, UINT value)
+{
+ char tmp[MAX_SIZE];
+ UINT wp = 0;
+ UINT len, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ // Set to empty character
+ StrCpy(tmp, 0, "");
+
+ // Append from the last digit
+ while (true)
+ {
+ UINT a = (UINT)(value % (UINT)16);
+ value = value / (UINT)16;
+ tmp[wp++] = FourBitToHex(a);
+ if (value == 0)
+ {
+ tmp[wp++] = 0;
+ break;
+ }
+ }
+
+ // Reverse order
+ len = StrLen(tmp);
+ for (i = 0;i < len;i++)
+ {
+ str[len - i - 1] = tmp[i];
+ }
+ str[len] = 0;
+}
+
+// Converts a 4 bit value to hexadecimal string
+char FourBitToHex(UINT value)
+{
+ value = value % 16;
+
+ if (value <= 9)
+ {
+ return '0' + value;
+ }
+ else
+ {
+ return 'a' + (value - 10);
+ }
+}
+
+// Convert a hexadecimal string to a 4 bit integer
+UINT HexTo4Bit(char c)
+{
+ if ('0' <= c && c <= '9')
+ {
+ return c - '0';
+ }
+ else if ('a' <= c && c <= 'f')
+ {
+ return c - 'a' + 10;
+ }
+ else if ('A' <= c && c <= 'F')
+ {
+ return c - 'A' + 10;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// Get a standard token delimiter
+char *DefaultTokenSplitChars()
+{
+ return " ,\t\r\n";
+}
+
+// Check whether the specified character is in the string
+bool IsCharInStr(char *str, char c)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ if (str[i] == c)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Cut out the token from the string (not ignore the blanks between delimiters)
+TOKEN_LIST *ParseTokenWithNullStr(char *str, char *split_chars)
+{
+ LIST *o;
+ UINT i, len;
+ BUF *b;
+ char zero = 0;
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NullToken();
+ }
+ if (split_chars == NULL)
+ {
+ split_chars = DefaultTokenSplitChars();
+ }
+
+ b = NewBuf();
+ o = NewListFast(NULL);
+
+ len = StrLen(str);
+
+ for (i = 0;i < (len + 1);i++)
+ {
+ char c = str[i];
+ bool flag = IsCharInStr(split_chars, c);
+
+ if (c == '\0')
+ {
+ flag = true;
+ }
+
+ if (flag == false)
+ {
+ WriteBuf(b, &c, sizeof(char));
+ }
+ else
+ {
+ WriteBuf(b, &zero, sizeof(char));
+
+ Insert(o, CopyStr((char *)b->Buf));
+ ClearBuf(b);
+ }
+ }
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+ FreeBuf(b);
+
+ return t;
+}
+
+// Check whether the string contains at least one of the specified tokens
+bool InStrList(char *target_str, char *tokens, char *splitter, bool case_sensitive)
+{
+ TOKEN_LIST *t;
+ bool ret = false;
+ UINT i;
+ // Validate arguments
+ if (target_str == NULL || tokens == NULL || splitter == NULL)
+ {
+ return false;
+ }
+
+ t = ParseTokenWithoutNullStr(tokens, splitter);
+
+ if (t != NULL)
+ {
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ if (InStrEx(target_str, t->Token[i], case_sensitive))
+ {
+ ret = true;
+// printf("%s\n", t->Token[i]);
+ }
+
+ if (ret)
+ {
+ break;
+ }
+ }
+
+ FreeToken(t);
+ }
+
+ return ret;
+}
+
+// Confirm whether the specified string is in the token list
+bool IsStrInStrTokenList(char *str_list, char *str, char *split_chars, bool case_sensitive)
+{
+ TOKEN_LIST *t;
+ bool ret = false;
+ UINT i;
+ // Validate arguments
+ if (str_list == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ t = ParseTokenWithoutNullStr(str_list, split_chars);
+
+ if (t != NULL)
+ {
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ if ((case_sensitive == false) && (StrCmpi(t->Token[i], str) == 0))
+ {
+ ret = true;
+ }
+ if ((case_sensitive) && (StrCmp(t->Token[i], str) == 0))
+ {
+ ret = true;
+ }
+
+ if (ret)
+ {
+ break;
+ }
+ }
+
+ FreeToken(t);
+ }
+
+ return ret;
+}
+
+// Cut out the token from string (Ignore blanks between delimiters)
+TOKEN_LIST *ParseTokenWithoutNullStr(char *str, char *split_chars)
+{
+ LIST *o;
+ UINT i, len;
+ bool last_flag;
+ BUF *b;
+ char zero = 0;
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NullToken();
+ }
+ if (split_chars == NULL)
+ {
+ split_chars = DefaultTokenSplitChars();
+ }
+
+ b = NewBuf();
+ o = NewListFast(NULL);
+
+ len = StrLen(str);
+ last_flag = false;
+
+ for (i = 0;i < (len + 1);i++)
+ {
+ char c = str[i];
+ bool flag = IsCharInStr(split_chars, c);
+
+ if (c == '\0')
+ {
+ flag = true;
+ }
+
+ if (flag == false)
+ {
+ WriteBuf(b, &c, sizeof(char));
+ }
+ else
+ {
+ if (last_flag == false)
+ {
+ WriteBuf(b, &zero, sizeof(char));
+
+ if ((StrLen((char *)b->Buf)) != 0)
+ {
+ Insert(o, CopyStr((char *)b->Buf));
+ }
+ ClearBuf(b);
+ }
+ }
+
+ last_flag = flag;
+ }
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+ FreeBuf(b);
+
+ return t;
+}
+
+// Check whether the string is included
+bool InStr(char *str, char *keyword)
+{
+ return InStrEx(str, keyword, false);
+}
+bool InStrEx(char *str, char *keyword, bool case_sensitive)
+{
+ // Validate arguments
+ if (IsEmptyStr(str) || IsEmptyStr(keyword))
+ {
+ return false;
+ }
+
+ if (SearchStrEx(str, keyword, 0, case_sensitive) == INFINITE)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get a value from the INI
+UINT IniIntValue(LIST *o, char *key)
+{
+ INI_ENTRY *e;
+ // Validate arguments
+ if (o == NULL || key == NULL)
+ {
+ return 0;
+ }
+
+ e = GetIniEntry(o, key);
+ if (e == NULL)
+ {
+ return 0;
+ }
+
+ return ToInt(e->Value);
+}
+UINT64 IniInt64Value(LIST *o, char *key)
+{
+ INI_ENTRY *e;
+ // Validate arguments
+ if (o == NULL || key == NULL)
+ {
+ return 0;
+ }
+
+ e = GetIniEntry(o, key);
+ if (e == NULL)
+ {
+ return 0;
+ }
+
+ return ToInt64(e->Value);
+}
+char *IniStrValue(LIST *o, char *key)
+{
+ INI_ENTRY *e;
+ // Validate arguments
+ if (o == NULL || key == NULL)
+ {
+ return 0;
+ }
+
+ e = GetIniEntry(o, key);
+ if (e == NULL)
+ {
+ return "";
+ }
+
+ return e->Value;
+}
+wchar_t *IniUniStrValue(LIST *o, char *key)
+{
+ INI_ENTRY *e;
+ // Validate arguments
+ if (o == NULL || key == NULL)
+ {
+ return 0;
+ }
+
+ e = GetIniEntry(o, key);
+ if (e == NULL)
+ {
+ return L"";
+ }
+
+ return e->UnicodeValue;
+}
+
+// Check whether the specified value is in the INI
+bool IniHasValue(LIST *o, char *key)
+{
+ INI_ENTRY *e;
+ // Validate arguments
+ if (o == NULL || key == NULL)
+ {
+ return false;
+ }
+
+ e = GetIniEntry(o, key);
+
+ if (e == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Release the INI
+void FreeIni(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ INI_ENTRY *e = LIST_DATA(o, i);
+
+ Free(e->Key);
+ Free(e->Value);
+ Free(e->UnicodeValue);
+
+ Free(e);
+ }
+
+ ReleaseList(o);
+}
+
+// Get an entry in the INI file
+INI_ENTRY *GetIniEntry(LIST *o, char *key)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || key == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ INI_ENTRY *e = LIST_DATA(o, i);
+
+ if (StrCmpi(e->Key, key) == 0)
+ {
+ return e;
+ }
+ }
+
+ return NULL;
+}
+
+// Read an INI file
+LIST *ReadIni(BUF *b)
+{
+ LIST *o;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+
+ SeekBuf(b, 0, 0);
+
+ while (true)
+ {
+ char *line = CfgReadNextLine(b);
+
+ if (line == NULL)
+ {
+ break;
+ }
+
+ Trim(line);
+
+ if (IsEmptyStr(line) == false)
+ {
+ if (StartWith(line, "#") == false &&
+ StartWith(line, "//") == false &&
+ StartWith(line, ";") == false)
+ {
+ char *key, *value;
+ UINT size = StrLen(line) + 1;
+
+ key = ZeroMalloc(size);
+ value = ZeroMalloc(size);
+
+ if (GetKeyAndValue(line, key, size, value, size, NULL))
+ {
+ UINT uni_size;
+ INI_ENTRY *e = ZeroMalloc(sizeof(INI_ENTRY));
+ e->Key = CopyStr(key);
+ e->Value = CopyStr(value);
+
+ uni_size = CalcUtf8ToUni((BYTE *)value, StrLen(value));
+ e->UnicodeValue = ZeroMalloc(uni_size);
+ Utf8ToUni(e->UnicodeValue, uni_size, (BYTE *)value, StrLen(value));
+
+ Add(o, e);
+ }
+
+ Free(key);
+ Free(value);
+ }
+ }
+
+ Free(line);
+ }
+
+ return o;
+}
+
+// Check whether the specified character is a delimiter
+bool IsSplitChar(char c, char *split_str)
+{
+ UINT i, len;
+ char c_upper = ToUpper(c);
+ if (split_str == NULL)
+ {
+ split_str = default_spliter;
+ }
+
+ len = StrLen(split_str);
+
+ for (i = 0;i < len;i++)
+ {
+ if (ToUpper(split_str[i]) == c_upper)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Get the keys and the value from the string
+bool GetKeyAndValue(char *str, char *key, UINT key_size, char *value, UINT value_size, char *split_str)
+{
+ UINT mode = 0;
+ UINT wp1 = 0, wp2 = 0;
+ UINT i, len;
+ char *key_tmp, *value_tmp;
+ bool ret = false;
+ if (split_str == NULL)
+ {
+ split_str = default_spliter;
+ }
+
+ len = StrLen(str);
+
+ key_tmp = ZeroMalloc(len + 1);
+ value_tmp = ZeroMalloc(len + 1);
+
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ switch (mode)
+ {
+ case 0:
+ if (IsSplitChar(c, split_str) == false)
+ {
+ mode = 1;
+ key_tmp[wp1] = c;
+ wp1++;
+ }
+ break;
+
+ case 1:
+ if (IsSplitChar(c, split_str) == false)
+ {
+ key_tmp[wp1] = c;
+ wp1++;
+ }
+ else
+ {
+ mode = 2;
+ }
+ break;
+
+ case 2:
+ if (IsSplitChar(c, split_str) == false)
+ {
+ mode = 3;
+ value_tmp[wp2] = c;
+ wp2++;
+ }
+ break;
+
+ case 3:
+ value_tmp[wp2] = c;
+ wp2++;
+ break;
+ }
+ }
+
+ if (mode != 0)
+ {
+ ret = true;
+ StrCpy(key, key_size, key_tmp);
+ StrCpy(value, value_size, value_tmp);
+ }
+
+ Free(key_tmp);
+ Free(value_tmp);
+
+ return ret;
+}
+
+// Generate a sequence of specified character
+char *MakeCharArray(char c, UINT count)
+{
+ UINT i;
+ char *ret = Malloc(count + 1);
+
+ for (i = 0;i < count;i++)
+ {
+ ret[i] = c;
+ }
+
+ ret[count] = 0;
+
+ return ret;
+}
+void MakeCharArray2(char *str, char c, UINT count)
+{
+ UINT i;
+
+ for (i = 0;i < count;i++)
+ {
+ str[i] = c;
+ }
+
+ str[count] = 0;
+}
+
+// Get the width of the specified string
+UINT StrWidth(char *str)
+{
+ wchar_t *s;
+ UINT ret;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ s = CopyStrToUni(str);
+ ret = UniStrWidth(s);
+ Free(s);
+
+ return ret;
+}
+
+// Check whether the specified string is all uppercase
+bool IsAllUpperStr(char *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ len = StrLen(str);
+
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ if ((c >= '0' && c <= '9') ||
+ (c >= 'A' && c <= 'Z'))
+ {
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Normalize the line breaks
+char *NormalizeCrlf(char *str)
+{
+ char *ret;
+ UINT ret_size, i, len, wp;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = StrLen(str);
+ ret_size = sizeof(char) * (len + 32) * 2;
+ ret = Malloc(ret_size);
+
+ wp = 0;
+
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ switch (c)
+ {
+ case '\r':
+ if (str[i + 1] == '\n')
+ {
+ i++;
+ }
+ ret[wp++] = '\r';
+ ret[wp++] = '\n';
+ break;
+
+ case '\n':
+ ret[wp++] = '\r';
+ ret[wp++] = '\n';
+ break;
+
+ default:
+ ret[wp++] = c;
+ break;
+ }
+ }
+
+ ret[wp++] = 0;
+
+ return ret;
+}
+
+// Remove duplications from the token list
+TOKEN_LIST *UniqueToken(TOKEN_LIST *t)
+{
+ UINT i, num, j, n;
+ TOKEN_LIST *ret;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ num = 0;
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ bool exists = false;
+
+ for (j = 0;j < i;j++)
+ {
+ if (StrCmpi(t->Token[j], t->Token[i]) == 0)
+ {
+ exists = true;
+ break;
+ }
+ }
+
+ if (exists == false)
+ {
+ num++;
+ }
+ }
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->Token = ZeroMalloc(sizeof(char *) * num);
+ ret->NumTokens = num;
+
+ n = 0;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ bool exists = false;
+
+ for (j = 0;j < i;j++)
+ {
+ if (StrCmpi(t->Token[j], t->Token[i]) == 0)
+ {
+ exists = true;
+ break;
+ }
+ }
+
+ if (exists == false)
+ {
+ ret->Token[n++] = CopyStr(t->Token[i]);
+ }
+ }
+
+ return ret;
+}
+
+// Convert a value to a byte string (by 1,000)
+void ToStrByte1000(char *str, UINT size, UINT64 v)
+{
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ // Warning measures in gcc
+ bytestr[0].base_value = 1000000000UL;
+ bytestr[0].base_value *= 1000UL;
+ bytestr[0].base_value *= 1000UL;
+ bytestr[1].base_value = 1000000000UL;
+ bytestr[1].base_value *= 1000UL;
+ bytestr[2].base_value = 1000000000UL;
+ bytestr[3].base_value = 1000000UL;
+ bytestr[4].base_value = 1000UL;
+ bytestr[5].base_value = 0UL;
+
+ for (i = 0;i < sizeof(bytestr) / sizeof(bytestr[0]);i++)
+ {
+ BYTESTR *b = &bytestr[i];
+
+ if ((v * 11UL) / 10UL >= b->base_value)
+ {
+ if (b->base_value != 0)
+ {
+ double d = (double)v / (double)b->base_value;
+ Format(str, size, "%.2f %s", d, b->string);
+ }
+ else
+ {
+ Format(str, size, "%I64u %s", v, b->string);
+ }
+
+ break;
+ }
+ }
+}
+
+// Convert a value to a byte string
+void ToStrByte(char *str, UINT size, UINT64 v)
+{
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ // Warning measures in gcc
+ bytestr[0].base_value = 1073741824UL;
+ bytestr[0].base_value *= 1024UL;
+ bytestr[0].base_value *= 1024UL;
+ bytestr[1].base_value = 1073741824UL;
+ bytestr[1].base_value *= 1024UL;
+ bytestr[2].base_value = 1073741824UL;
+ bytestr[3].base_value = 1048576UL;
+ bytestr[4].base_value = 1024UL;
+ bytestr[5].base_value = 0UL;
+
+ for (i = 0;i < sizeof(bytestr) / sizeof(bytestr[0]);i++)
+ {
+ BYTESTR *b = &bytestr[i];
+
+ if ((v * 11UL) / 10UL >= b->base_value)
+ {
+ if (b->base_value != 0)
+ {
+ double d = (double)v / (double)b->base_value;
+ Format(str, size, "%.2f %s", d, b->string);
+ }
+ else
+ {
+ Format(str, size, "%I64u %s", v, b->string);
+ }
+
+ break;
+ }
+ }
+}
+
+// Convert the number to a string, and separate it with commas by three orders of magnitude
+void ToStr3(char *str, UINT size, UINT64 v)
+{
+ char tmp[128];
+ char tmp2[128];
+ UINT i, len, wp;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ ToStr64(tmp, v);
+
+ wp = 0;
+ len = StrLen(tmp);
+
+ for (i = len - 1;((int)i) >= 0;i--)
+ {
+ tmp2[wp++] = tmp[i];
+ }
+ tmp2[wp++] = 0;
+
+ wp = 0;
+
+ for (i = 0;i < len;i++)
+ {
+ if (i != 0 && (i % 3) == 0)
+ {
+ tmp[wp++] = ',';
+ }
+ tmp[wp++] = tmp2[i];
+ }
+ tmp[wp++] = 0;
+ wp = 0;
+ len = StrLen(tmp);
+
+ for (i = len - 1;((int)i) >= 0;i--)
+ {
+ tmp2[wp++] = tmp[i];
+ }
+ tmp2[wp++] = 0;
+
+ StrCpy(str, size, tmp2);
+}
+
+// Convert the MAC address to a string
+void MacToStr(char *str, UINT size, UCHAR *mac_address)
+{
+ // Validate arguments
+ if (str == NULL || mac_address == NULL)
+ {
+ return;
+ }
+
+ Format(str, size, "%02X-%02X-%02X-%02X-%02X-%02X",
+ mac_address[0],
+ mac_address[1],
+ mac_address[2],
+ mac_address[3],
+ mac_address[4],
+ mac_address[5]);
+}
+
+// Examine whether the string is empty
+bool IsEmptyStr(char *str)
+{
+ char *s;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return true;
+ }
+
+ s = CopyStr(str);
+ Trim(s);
+
+ if (StrLen(s) == 0)
+ {
+ Free(s);
+ return true;
+ }
+ else
+ {
+ Free(s);
+ return false;
+ }
+}
+
+// Convert the token list to a string list
+LIST *TokenListToList(TOKEN_LIST *t)
+{
+ UINT i;
+ LIST *o;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ Insert(o, CopyStr(t->Token[i]));
+ }
+
+ return o;
+}
+
+// Convert a string list to a token list
+TOKEN_LIST *ListToTokenList(LIST *o)
+{
+ UINT i;
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ t->Token[i] = CopyStr(LIST_DATA(o, i));
+ }
+
+ return t;
+}
+
+// Free the string list
+void FreeStrList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char *s = LIST_DATA(o, i);
+ Free(s);
+ }
+
+ ReleaseList(o);
+}
+
+// Convert the string list to a string
+BUF *StrListToStr(LIST *o)
+{
+ BUF *b;
+ UINT i;
+ char c;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+ b = NewBuf();
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ char *s = LIST_DATA(o, i);
+ WriteBuf(b, s, StrLen(s) + 1);
+ }
+
+ c = 0;
+ WriteBuf(b, &c, 1);
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Convert a (NULL delimited) string to a list
+LIST *StrToStrList(char *str, UINT size)
+{
+ LIST *o;
+ char *tmp;
+ UINT tmp_size;
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+
+ i = 0;
+ while (true)
+ {
+ if (i >= size)
+ {
+ break;
+ }
+ if (*str == 0)
+ {
+ break;
+ }
+
+ tmp_size = StrSize(str);
+ tmp = ZeroMalloc(tmp_size);
+ StrCpy(tmp, tmp_size, str);
+ Add(o, tmp);
+ str += StrLen(str) + 1;
+ i++;
+ }
+
+ return o;
+}
+
+// Check whether the specified string is a number
+bool IsNum(char *str)
+{
+ char c;
+ UINT i, len;
+ UINT n = 0;
+ char tmp[MAX_SIZE];
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(tmp, sizeof(tmp), str);
+ Trim(tmp);
+
+ if (StrLen(tmp) == 0)
+ {
+ return false;
+ }
+
+ t = ParseToken(tmp, " ");
+
+ if (t->NumTokens >= 1)
+ {
+ StrCpy(tmp, sizeof(tmp), t->Token[0]);
+ }
+
+ FreeToken(t);
+
+ len = StrLen(tmp);
+ for (i = 0;i < len;i++)
+ {
+ bool b = false;
+ c = tmp[i];
+ if (('0' <= c && c <= '9') || (c == '+') || (c == '-') || (c == ','))
+ {
+ b = true;
+ }
+
+ if (b == false)
+ {
+ return false;
+ }
+ }
+
+ for (i = 0;i < len;i++)
+ {
+ c = tmp[i];
+ if (c == '-')
+ {
+ n++;
+ }
+ }
+ if (n >= 2)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Empty token list
+TOKEN_LIST *NullToken()
+{
+ TOKEN_LIST *ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->Token = ZeroMalloc(0);
+
+ return ret;
+}
+
+// Copy the token list
+TOKEN_LIST *CopyToken(TOKEN_LIST *src)
+{
+ TOKEN_LIST *ret;
+ UINT i;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->NumTokens = src->NumTokens;
+ ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
+ for (i = 0;i < ret->NumTokens;i++)
+ {
+ ret->Token[i] = CopyStr(src->Token[i]);
+ }
+
+ return ret;
+}
+
+// Parse the command line
+TOKEN_LIST *ParseCmdLine(char *str)
+{
+ TOKEN_LIST *t;
+ LIST *o;
+ UINT i, len, wp, mode;
+ char c;
+ char *tmp;
+ bool ignore_space = false;
+ // Validate arguments
+ if (str == NULL)
+ {
+ // There is no token
+ return NullToken();
+ }
+
+ o = NewListFast(NULL);
+ tmp = Malloc(StrSize(str) + 32);
+
+ wp = 0;
+ mode = 0;
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ c = str[i];
+
+ switch (mode)
+ {
+ case 0:
+ // Mode to discover the next token
+ if (c == ' ' || c == '\t')
+ {
+ // Advance to the next character
+ }
+ else
+ {
+ // Start of the token
+ if (c == '\"')
+ {
+ if (str[i + 1] == '\"')
+ {
+ // Regard "" as a single "
+ tmp[wp++] = '\"';
+ i++;
+ }
+ else
+ {
+ // Enable the ignoring space flag for a single "
+ ignore_space = true;
+ }
+ }
+ else
+ {
+ tmp[wp++] = c;
+ }
+
+ mode = 1;
+ }
+ break;
+
+ case 1:
+ if (ignore_space == false && (c == ' ' || c == '\t'))
+ {
+ // End of the token
+ tmp[wp++] = 0;
+ wp = 0;
+
+ Insert(o, CopyStr(tmp));
+ mode = 0;
+ }
+ else
+ {
+ if (c == '\"')
+ {
+ if (str[i + 1] == '\"')
+ {
+ // Regard "" as a single "
+ tmp[wp++] = L'\"';
+ i++;
+ }
+ else
+ {
+ if (ignore_space == false)
+ {
+ // Enable the ignoring space flag for a single "
+ ignore_space = true;
+ }
+ else
+ {
+ // Disable the space ignore flag
+ ignore_space = false;
+ }
+ }
+ }
+ else
+ {
+ tmp[wp++] = c;
+ }
+ }
+ break;
+ }
+ }
+
+ if (wp != 0)
+ {
+ tmp[wp++] = 0;
+ Insert(o, CopyStr(tmp));
+ }
+
+ Free(tmp);
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+
+ return t;
+}
+
+// Convert a 64-bit integer to a string
+void ToStr64(char *str, UINT64 value)
+{
+ char tmp[MAX_SIZE];
+ UINT wp = 0;
+ UINT len, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ // Set to empty character
+ StrCpy(tmp, 0, "");
+
+ // Append from the last digit
+ while (true)
+ {
+ UINT a = (UINT)(value % (UINT64)10);
+ value = value / (UINT64)10;
+ tmp[wp++] = (char)('0' + a);
+ if (value == 0)
+ {
+ tmp[wp++] = 0;
+ break;
+ }
+ }
+
+ // Reverse order
+ len = StrLen(tmp);
+ for (i = 0;i < len;i++)
+ {
+ str[len - i - 1] = tmp[i];
+ }
+ str[len] = 0;
+}
+
+// Convert a string to a 64-bit integer
+UINT64 ToInt64(char *str)
+{
+ UINT len, i;
+ UINT64 ret = 0;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+ if (c != ',')
+ {
+ if ('0' <= c && c <= '9')
+ {
+ ret = ret * (UINT64)10 + (UINT64)(c - '0');
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Check whether the str ends with the key
+bool EndWith(char *str, char *key)
+{
+ UINT str_len;
+ UINT key_len;
+ // Validate arguments
+ if (str == NULL || key == NULL)
+ {
+ return false;
+ }
+
+ // Comparison
+ str_len = StrLen(str);
+ key_len = StrLen(key);
+ if (str_len < key_len)
+ {
+ return false;
+ }
+
+ if (StrCmpi(str + (str_len - key_len), key) == 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Check whether the str starts with the key
+bool StartWith(char *str, char *key)
+{
+ UINT str_len;
+ UINT key_len;
+ char *tmp;
+ bool ret;
+ // Validate arguments
+ if (str == NULL || key == NULL)
+ {
+ return false;
+ }
+
+ // Comparison
+ str_len = StrLen(str);
+ key_len = StrLen(key);
+ if (str_len < key_len)
+ {
+ return false;
+ }
+ if (str_len == 0 || key_len == 0)
+ {
+ return false;
+ }
+ tmp = CopyStr(str);
+ tmp[key_len] = 0;
+
+ if (StrCmpi(tmp, key) == 0)
+ {
+ ret = true;
+ }
+ else
+ {
+ ret = false;
+ }
+
+ Free(tmp);
+
+ return ret;
+}
+
+// Display the binary data
+void PrintBin(void *data, UINT size)
+{
+ char *tmp;
+ UINT i;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return;
+ }
+
+ i = size * 3 + 1;
+ tmp = Malloc(i);
+ BinToStrEx(tmp, i, data, size);
+ Print("%s\n", tmp);
+ Free(tmp);
+}
+
+// Convert the string to a MAC address
+bool StrToMac(UCHAR *mac_address, char *str)
+{
+ BUF *b;
+ // Validate arguments
+ if (mac_address == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ b = StrToBin(str);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ if (b->Size != 6)
+ {
+ FreeBuf(b);
+ return false;
+ }
+
+ Copy(mac_address, b->Buf, 6);
+
+ FreeBuf(b);
+
+ return true;
+}
+
+// Convert a hexadecimal string to a binary data
+BUF *StrToBin(char *str)
+{
+ BUF *b;
+ UINT len, i;
+ char tmp[3];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = StrLen(str);
+ tmp[0] = 0;
+ b = NewBuf();
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+ c = ToUpper(c);
+ if (('0' <= c && c <= '9') || ('A' <= c && c <= 'F'))
+ {
+ if (tmp[0] == 0)
+ {
+ tmp[0] = c;
+ tmp[1] = 0;
+ }
+ else if (tmp[1] == 0)
+ {
+ UCHAR data;
+ char tmp2[64];
+ tmp[1] = c;
+ tmp[2] = 0;
+ StrCpy(tmp2, sizeof(tmp2), "0x");
+ StrCat(tmp2, sizeof(tmp2), tmp);
+ data = (UCHAR)strtoul(tmp2, NULL, 0);
+ WriteBuf(b, &data, 1);
+ Zero(tmp, sizeof(tmp));
+ }
+ }
+ else if (c == ' ' || c == ',' || c == '-' || c == ':')
+ {
+ // Do Nothing
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return b;
+}
+
+// Convert the binary data to a hexadecimal string (with space)
+void BinToStrEx(char *str, UINT str_size, void *data, UINT data_size)
+{
+ char *tmp;
+ UCHAR *buf = (UCHAR *)data;
+ UINT size;
+ UINT i;
+ // Validate arguments
+ if (str == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Calculation of size
+ size = data_size * 3 + 1;
+ // Memory allocation
+ tmp = ZeroMalloc(size);
+ // Conversion
+ for (i = 0;i < data_size;i++)
+ {
+ Format(&tmp[i * 3], 0, "%02X ", buf[i]);
+ }
+ Trim(tmp);
+ // Copy
+ StrCpy(str, str_size, tmp);
+ // Memory release
+ Free(tmp);
+}
+void BinToStrEx2(char *str, UINT str_size, void *data, UINT data_size, char padding_char)
+{
+ char *tmp;
+ UCHAR *buf = (UCHAR *)data;
+ UINT size;
+ UINT i;
+ // Validate arguments
+ if (str == NULL || data == NULL)
+ {
+ return;
+ }
+
+ // Calculation of size
+ size = data_size * 3 + 1;
+ // Memory allocation
+ tmp = ZeroMalloc(size);
+ // Conversion
+ for (i = 0;i < data_size;i++)
+ {
+ Format(&tmp[i * 3], 0, "%02X%c", buf[i], padding_char);
+ }
+ if (StrLen(tmp) >= 1)
+ {
+ if (tmp[StrLen(tmp) - 1] == padding_char)
+ {
+ tmp[StrLen(tmp) - 1] = 0;
+ }
+ }
+ // Copy
+ StrCpy(str, str_size, tmp);
+ // Memory release
+ Free(tmp);
+}
+// Convert the binary data to a string, and copy it
+char *CopyBinToStrEx(void *data, UINT data_size)
+{
+ char *ret;
+ UINT size;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ size = data_size * 3 + 1;
+ ret = ZeroMalloc(size);
+
+ BinToStrEx(ret, size, data, data_size);
+
+ return ret;
+}
+char *CopyBinToStr(void *data, UINT data_size)
+{
+ char *ret;
+ UINT size;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ size = data_size * 2 + 1;
+ ret = ZeroMalloc(size);
+
+ BinToStr(ret, size, data, data_size);
+
+ return ret;
+}
+
+// Convert the binary data to a hexadecimal string
+void BinToStr(char *str, UINT str_size, void *data, UINT data_size)
+{
+ char *tmp;
+ UCHAR *buf = (UCHAR *)data;
+ UINT size;
+ UINT i;
+ // Validate arguments
+ if (str == NULL || data == NULL)
+ {
+ if (str != NULL)
+ {
+ str[0] = 0;
+ }
+ return;
+ }
+
+ // Calculation of size
+ size = data_size * 2 + 1;
+ // Memory allocation
+ tmp = ZeroMalloc(size);
+ // Conversion
+ for (i = 0;i < data_size;i++)
+ {
+ sprintf(&tmp[i * 2], "%02X", buf[i]);
+ }
+ // Copy
+ StrCpy(str, str_size, tmp);
+ // Memory release
+ Free(tmp);
+}
+void BinToStrW(wchar_t *str, UINT str_size, void *data, UINT data_size)
+{
+ char *tmp;
+ UINT tmp_size;
+ // Validate arguments
+ if (str == NULL || data == NULL)
+ {
+ if (str != NULL)
+ {
+ str[0] = 0;
+ }
+ return;
+ }
+
+ tmp_size = (data_size * 2 + 4) * sizeof(wchar_t);
+ tmp = ZeroMalloc(tmp_size);
+
+ BinToStr(tmp, tmp_size, data, data_size);
+
+ StrToUni(str, str_size, tmp);
+
+ Free(tmp);
+}
+
+// Convert a 160-bit sequence into a string
+void Bit160ToStr(char *str, UCHAR *data)
+{
+ // Validate arguments
+ if (str == NULL || data == NULL)
+ {
+ return;
+ }
+
+ Format(str, 0,
+ "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+ data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9],
+ data[10], data[11], data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19]);
+}
+
+// Make a string from a 128-bit sequence
+void Bit128ToStr(char *str, UCHAR *data)
+{
+ // Validate arguments
+ if (str == NULL || data == NULL)
+ {
+ return;
+ }
+
+ Format(str, 0,
+ "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+ data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9],
+ data[10], data[11], data[12], data[13], data[14], data[15]);
+}
+
+// Copy a string
+char *CopyStr(char *str)
+{
+ UINT len;
+ char *dst;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ len = StrLen(str);
+ dst = Malloc(len + 1);
+ StrCpy(dst, len + 1, str);
+ return dst;
+}
+
+// Check whether the string is safe
+bool IsSafeStr(char *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ if (IsSafeChar(str[i]) == false)
+ {
+ return false;
+ }
+ }
+ if (str[0] == ' ')
+ {
+ return false;
+ }
+ if (len != 0)
+ {
+ if (str[len - 1] == ' ')
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Check whether the character can be displayed
+bool IsPrintableAsciiChar(char c)
+{
+ UCHAR uc = (UCHAR)c;
+ if (uc <= 31)
+ {
+ return false;
+ }
+ if (uc >= 127)
+ {
+ return false;
+ }
+ return true;
+}
+
+// Check whether the string that can be displayed
+bool IsPrintableAsciiStr(char *str)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ if (IsPrintableAsciiChar(c) == false)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Convert a string to a displayable string
+void EnPrintableAsciiStr(char *str, char replace)
+{
+ UINT i, len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ len = StrLen(str);
+
+ for (i = 0;i < len;i++)
+ {
+ char c = str[i];
+
+ if (IsPrintableAsciiChar(c) == false)
+ {
+ str[i] = replace;
+ }
+ }
+}
+
+// Check whether the character is safe
+bool IsSafeChar(char c)
+{
+ UINT i, len;
+ char *check_str =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ " ()-_#%&.";
+
+ len = StrLen(check_str);
+ for (i = 0;i < len;i++)
+ {
+ if (c == check_str[i])
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Remove the specified character from a string
+void TruncateCharFromStr(char *str, char replace)
+{
+ char *src,*dst;
+
+ if (str == NULL)
+ {
+ return;
+ }
+
+ src = dst = str;
+
+ while(*src != '\0')
+ {
+ if(*src != replace)
+ {
+ *dst = *src;
+ dst++;
+ }
+ src++;
+ }
+ *dst = *src;
+
+ //BUF *b = NewBuf();
+ //UINT i, len;
+ //char zero = 0;
+
+ //len = StrLen(str);
+ //for (i = 0;i < len;i++)
+ //{
+ // char c = str[i];
+
+ // if (c != replace)
+ // {
+ // WriteBuf(b, &c, 1);
+ // }
+ //}
+
+ //if (b->Size == 0)
+ //{
+ // char c = '_';
+ // WriteBuf(b, &c, 1);
+ //}
+
+ //WriteBuf(b, &zero, 1);
+
+ //StrCpy(str, 0, b->Buf);
+
+ //FreeBuf(b);
+}
+
+// Replace the unsafe characters
+void EnSafeStr(char *str, char replace)
+{
+ if (str == NULL)
+ {
+ return;
+ }
+
+ while(*str != '\0')
+ {
+ if(IsSafeChar(*str) == false)
+ {
+ *str = replace;
+ }
+ str++;
+ }
+}
+
+// Operation check of string library
+bool CheckStringLibrary()
+{
+ wchar_t *compare_str = L"TEST_TEST_123_123456789012345";
+ char *teststr = "TEST";
+ wchar_t *testunistr = L"TEST";
+ wchar_t tmp[64];
+ UINT i1 = 123;
+ UINT64 i2 = 123456789012345ULL;
+
+ UniFormat(tmp, sizeof(tmp), L"%S_%s_%u_%I64u", teststr, testunistr,
+ i1, i2);
+
+ if (UniStrCmpi(tmp, compare_str) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Initialize the string library
+void InitStringLibrary()
+{
+ // Create a lock for token
+ token_lock = NewLock();
+
+ // Initialization of the International Library
+ InitInternational();
+
+ // Operation check
+ if (CheckStringLibrary() == false)
+ {
+#ifdef OS_WIN32
+ Alert("String Library Init Failed.\r\nPlease check your locale settings.", NULL);
+#else // OS_WIN32
+ Alert("String Library Init Failed.\r\nPlease check your locale settings and iconv() libraries.", NULL);
+#endif // OS_WIN32
+ exit(0);
+ }
+}
+
+// Release of the string library
+void FreeStringLibrary()
+{
+ // Release of the International Library
+ FreeInternational();
+
+ // Release of the lock for token
+ DeleteLock(token_lock);
+ token_lock = NULL;
+}
+
+// String replaceing (case insensitive)
+UINT ReplaceStri(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword)
+{
+ return ReplaceStrEx(dst, size, string, old_keyword, new_keyword, false);
+}
+
+// String replaceing (case sensitive)
+UINT ReplaceStr(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword)
+{
+ return ReplaceStrEx(dst, size, string, old_keyword, new_keyword, true);
+}
+
+// String replaceing
+UINT ReplaceStrEx(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword, bool case_sensitive)
+{
+ UINT i, j, num;
+ UINT len_string, len_old, len_new;
+ UINT len_ret;
+ UINT wp;
+ char *ret;
+ // Validate arguments
+ if (string == NULL || old_keyword == NULL || new_keyword == NULL)
+ {
+ return 0;
+ }
+
+ // Get the length of the string
+ len_string = StrLen(string);
+ len_old = StrLen(old_keyword);
+ len_new = StrLen(new_keyword);
+
+ // Calculate the final string length
+ len_ret = CalcReplaceStrEx(string, old_keyword, new_keyword, case_sensitive);
+ // Memory allocation
+ ret = Malloc(len_ret + 1);
+ ret[len_ret] = '\0';
+
+ // Search and Replace
+ i = 0;
+ j = 0;
+ num = 0;
+ wp = 0;
+ while (true)
+ {
+ i = SearchStrEx(string, old_keyword, i, case_sensitive);
+ if (i == INFINITE)
+ {
+ Copy(ret + wp, string + j, len_string - j);
+ wp += len_string - j;
+ break;
+ }
+ num++;
+ Copy(ret + wp, string + j, i - j);
+ wp += i - j;
+ Copy(ret + wp, new_keyword, len_new);
+ wp += len_new;
+ i += len_old;
+ j = i;
+ }
+
+ // Copy of the search results
+ StrCpy(dst, size, ret);
+
+ // Memory release
+ Free(ret);
+
+ return num;
+}
+
+// Calculate the length of the result of string replacement
+UINT CalcReplaceStrEx(char *string, char *old_keyword, char *new_keyword, bool case_sensitive)
+{
+ UINT i, num;
+ UINT len_string, len_old, len_new;
+ // Validate arguments
+ if (string == NULL || old_keyword == NULL || new_keyword == NULL)
+ {
+ return 0;
+ }
+
+ // Get the length of the string
+ len_string = StrLen(string);
+ len_old = StrLen(old_keyword);
+ len_new = StrLen(new_keyword);
+
+ if (len_old == len_new)
+ {
+ return len_string;
+ }
+
+ // Search
+ num = 0;
+ i = 0;
+ while (true)
+ {
+ i = SearchStrEx(string, old_keyword, i, case_sensitive);
+ if (i == INFINITE)
+ {
+ break;
+ }
+ i += len_old;
+ num++;
+ }
+
+ // Calculation
+ return len_string + len_new * num - len_old * num;
+}
+
+// Search for a string (distinguish between upper / lower case)
+UINT SearchStr(char *string, char *keyword, UINT start)
+{
+ return SearchStrEx(string, keyword, start, true);
+}
+
+// Search for a string (Don't distinguish between upper / lower case)
+UINT SearchStri(char *string, char *keyword, UINT start)
+{
+ return SearchStrEx(string, keyword, start, false);
+}
+
+// Examine whether the string contains the specified character
+bool InChar(char *string, char c)
+{
+ UINT i, len;
+ // Validate arguments
+ if (string == NULL)
+ {
+ return false;
+ }
+
+ len = StrLen(string);
+
+ for (i = 0;i < len;i++)
+ {
+ if (string[i] == c)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Return the position of the first found keyword in the string
+// (Found at first character: returns 0, Not found: returns INFINITE)
+UINT SearchStrEx(char *string, char *keyword, UINT start, bool case_sensitive)
+{
+ UINT len_string, len_keyword;
+ UINT i;
+ char *cmp_string, *cmp_keyword;
+ bool found;
+ // Validate arguments
+ if (string == NULL || keyword == NULL)
+ {
+ return INFINITE;
+ }
+
+ // Get the length of string
+ len_string = StrLen(string);
+ if (len_string <= start)
+ {
+ // Value of start is invalid
+ return INFINITE;
+ }
+
+ // Get the length of the keyword
+ len_keyword = StrLen(keyword);
+ if (len_keyword == 0)
+ {
+ // There is no keyword in the string
+ return INFINITE;
+ }
+
+ if ((len_string - start) < len_keyword)
+ {
+ // The keyword is longer than the string
+ return INFINITE;
+ }
+
+ if (case_sensitive)
+ {
+ cmp_string = string;
+ cmp_keyword = keyword;
+ }
+ else
+ {
+ cmp_string = Malloc(len_string + 1);
+ StrCpy(cmp_string, len_string + 1, string);
+ cmp_keyword = Malloc(len_keyword + 1);
+ StrCpy(cmp_keyword, len_keyword + 1, keyword);
+ StrUpper(cmp_string);
+ StrUpper(cmp_keyword);
+ }
+
+ // Search
+ found = false;
+ for (i = start;i < (len_string - len_keyword + 1);i++)
+ {
+ // Compare
+ if (!strncmp(&cmp_string[i], cmp_keyword, len_keyword))
+ {
+ // Found
+ found = true;
+ break;
+ }
+ }
+
+ if (case_sensitive == false)
+ {
+ // Memory release
+ Free(cmp_keyword);
+ Free(cmp_string);
+ }
+
+ if (found == false)
+ {
+ return INFINITE;
+ }
+ return i;
+}
+
+// Determine whether the specified character is in the token list
+bool IsInToken(TOKEN_LIST *t, char *str)
+{
+ UINT i;
+ // Validate arguments
+ if (t == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ if (StrCmpi(t->Token[i], str) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Release of the token list
+void FreeToken(TOKEN_LIST *tokens)
+{
+ UINT i;
+ if (tokens == NULL)
+ {
+ return;
+ }
+ for (i = 0;i < tokens->NumTokens;i++)
+ {
+ if (tokens->Token[i] != 0)
+ {
+ Free(tokens->Token[i]);
+ }
+ }
+ Free(tokens->Token);
+ Free(tokens);
+}
+
+// Parse the token
+TOKEN_LIST *ParseToken(char *src, char *separator)
+{
+ TOKEN_LIST *ret;
+ char *tmp;
+ char *str1, *str2;
+ UINT len;
+ UINT num;
+ if (src == NULL)
+ {
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->Token = ZeroMalloc(0);
+ return ret;
+ }
+ if (separator == NULL)
+ {
+ separator = " ,\t\r\n";
+ }
+ len = StrLen(src);
+ str1 = Malloc(len + 1);
+ str2 = Malloc(len + 1);
+ StrCpy(str1, 0, src);
+ StrCpy(str2, 0, src);
+
+ Lock(token_lock);
+ {
+ tmp = strtok(str1, separator);
+ num = 0;
+ while (tmp != NULL)
+ {
+ num++;
+ tmp = strtok(NULL, separator);
+ }
+ ret = Malloc(sizeof(TOKEN_LIST));
+ ret->NumTokens = num;
+ ret->Token = (char **)Malloc(sizeof(char *) * num);
+ num = 0;
+ tmp = strtok(str2, separator);
+ while (tmp != NULL)
+ {
+ ret->Token[num] = (char *)Malloc(StrLen(tmp) + 1);
+ StrCpy(ret->Token[num], 0, tmp);
+ num++;
+ tmp = strtok(NULL, separator);
+ }
+ }
+ Unlock(token_lock);
+
+ Free(str1);
+ Free(str2);
+ return ret;
+}
+
+// Get a line from standard input
+bool GetLine(char *str, UINT size)
+{
+ bool ret;
+ wchar_t *unistr;
+ UINT unistr_size = (size + 1) * sizeof(wchar_t);
+
+ unistr = Malloc(unistr_size);
+
+ ret = UniGetLine(unistr, unistr_size);
+
+ UniToStr(str, size, unistr);
+
+ Free(unistr);
+
+ return ret;
+}
+
+// Remove '\r' and '\n' at the end
+void TrimCrlf(char *str)
+{
+ UINT len;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ len = StrLen(str);
+ if (len == 0)
+ {
+ return;
+ }
+
+ if (str[len - 1] == '\n')
+ {
+ if (len >= 2 && str[len - 2] == '\r')
+ {
+ str[len - 2] = 0;
+ }
+ str[len - 1] = 0;
+ }
+ else if (str[len - 1] == '\r')
+ {
+ str[len - 1] = 0;
+ }
+}
+
+// Remove white spaces of the both side of the string
+void Trim(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ // Trim on the left side
+ TrimLeft(str);
+
+ // Trim on the right side
+ TrimRight(str);
+}
+
+// Remove white spaces on the right side of the string
+void TrimRight(char *str)
+{
+ char *buf, *tmp;
+ UINT len, i, wp, wp2;
+ BOOL flag;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ len = StrLen(str);
+ if (len == 0)
+ {
+ return;
+ }
+ if (str[len - 1] != ' ' && str[len - 1] != '\t')
+ {
+ return;
+ }
+
+ buf = Malloc(len + 1);
+ tmp = Malloc(len + 1);
+ flag = FALSE;
+ wp = 0;
+ wp2 = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (str[i] != ' ' && str[i] != '\t')
+ {
+ Copy(buf + wp, tmp, wp2);
+ wp += wp2;
+ wp2 = 0;
+ buf[wp++] = str[i];
+ }
+ else
+ {
+ tmp[wp2++] = str[i];
+ }
+ }
+ buf[wp] = 0;
+ StrCpy(str, 0, buf);
+ Free(buf);
+ Free(tmp);
+}
+
+// Remove white spaces from the left side of the string
+void TrimLeft(char *str)
+{
+ char *buf;
+ UINT len, i, wp;
+ BOOL flag;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+ len = StrLen(str);
+ if (len == 0)
+ {
+ return;
+ }
+ if (str[0] != ' ' && str[0] != '\t')
+ {
+ return;
+ }
+
+ buf = Malloc(len + 1);
+ flag = FALSE;
+ wp = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (str[i] != ' ' && str[i] != '\t')
+ {
+ flag = TRUE;
+ }
+ if (flag)
+ {
+ buf[wp++] = str[i];
+ }
+ }
+ buf[wp] = 0;
+ StrCpy(str, 0, buf);
+ Free(buf);
+}
+
+// Convert an integer to a hexadecimal string (8-digit fixed)
+void ToStrx8(char *str, UINT i)
+{
+ sprintf(str, "0x%08x", i);
+}
+
+// Convert an integer to a hexadecimal string
+void ToStrx(char *str, UINT i)
+{
+ sprintf(str, "0x%02x", i);
+}
+
+// Convert a signed integer to a string
+void ToStri(char *str, int i)
+{
+ sprintf(str, "%i", i);
+}
+
+// Convert an integer to a string
+void ToStr(char *str, UINT i)
+{
+ sprintf(str, "%u", i);
+}
+
+// Convert the string to a signed integer
+int ToInti(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ return (int)ToInt(str);
+}
+
+// Convert a string to a Boolean value
+bool ToBool(char *str)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(tmp, sizeof(tmp), str);
+ Trim(tmp);
+
+ if (IsEmptyStr(tmp))
+ {
+ return false;
+ }
+
+ if (ToInt(tmp) != 0)
+ {
+ return true;
+ }
+
+ if (StartWith("true", tmp))
+ {
+ return true;
+ }
+
+ if (StartWith("yes", tmp))
+ {
+ return true;
+ }
+
+ if (StartWith(tmp, "true"))
+ {
+ return true;
+ }
+
+ if (StartWith(tmp, "yes"))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Convert a string to an integer
+UINT ToInt(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ // Ignore the octal literal
+ while (true)
+ {
+ if (*str != '0')
+ {
+ break;
+ }
+ if ((*(str + 1) == 'x') || (*(str + 1) == 'X'))
+ {
+ break;
+ }
+ str++;
+ }
+
+ return (UINT)strtoul(str, NULL, 0);
+}
+
+// Replace a format string for 64-bit integer
+char *ReplaceFormatStringFor64(char *fmt)
+{
+ char *tmp;
+ char *ret;
+ UINT tmp_size;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return NULL;
+ }
+
+ tmp_size = StrSize(fmt) * 2;
+ tmp = ZeroMalloc(tmp_size);
+
+#ifdef OS_WIN32
+ ReplaceStrEx(tmp, tmp_size, fmt, "%ll", "%I64", false);
+#else // OS_WIN32
+ ReplaceStrEx(tmp, tmp_size, fmt, "%I64", "%ll", false);
+#endif // OS_WIN32
+
+ ret = CopyStr(tmp);
+ Free(tmp);
+
+ return ret;
+}
+
+// Display the string on the screen
+void PrintStr(char *str)
+{
+ wchar_t *unistr = NULL;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_UNIX
+ fputs(str, stdout);
+#else // OS_UNIX
+ unistr = CopyStrToUni(str);
+ UniPrintStr(unistr);
+ Free(unistr);
+#endif // OS_UNIX
+}
+
+// Display a string with arguments
+void PrintArgs(char *fmt, va_list args)
+{
+ wchar_t *ret;
+ wchar_t *fmt_wchar;
+ char *tmp;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+
+ fmt_wchar = CopyStrToUni(fmt);
+ ret = InternalFormatArgs(fmt_wchar, args, true);
+
+ tmp = CopyUniToStr(ret);
+ PrintStr(tmp);
+ Free(tmp);
+
+ Free(ret);
+ Free(fmt_wchar);
+}
+
+// Display a string
+void Print(char *fmt, ...)
+{
+ va_list args;
+ if (fmt == NULL)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+ PrintArgs(fmt, args);
+ va_end(args);
+}
+
+// Display a debug string with arguments
+void DebugArgs(char *fmt, va_list args)
+{
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+ if (g_debug == false)
+ {
+ return;
+ }
+
+ PrintArgs(fmt, args);
+}
+
+// Display a debug string
+void Debug(char *fmt, ...)
+{
+ va_list args;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return;
+ }
+ if (g_debug == false)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+
+ DebugArgs(fmt, args);
+
+ va_end(args);
+}
+
+// Format the string, and return the result
+char *CopyFormat(char *fmt, ...)
+{
+ char *buf;
+ char *ret;
+ UINT size;
+ va_list args;
+ // Validate arguments
+ if (fmt == NULL)
+ {
+ return NULL;
+ }
+
+ size = MAX(StrSize(fmt) * 10, MAX_SIZE * 10);
+ buf = Malloc(size);
+
+ va_start(args, fmt);
+ FormatArgs(buf, size, fmt, args);
+
+ ret = CopyStr(buf);
+ Free(buf);
+
+ va_end(args);
+ return ret;
+}
+
+// Format the string
+void Format(char *buf, UINT size, char *fmt, ...)
+{
+ va_list args;
+ // Validate arguments
+ if (buf == NULL || fmt == NULL)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+ FormatArgs(buf, size, fmt, args);
+ va_end(args);
+}
+
+// Format the string (argument list)
+void FormatArgs(char *buf, UINT size, char *fmt, va_list args)
+{
+ wchar_t *tag;
+ wchar_t *ret;
+ // Validate arguments
+ if (buf == NULL || fmt == NULL)
+ {
+ return;
+ }
+
+ tag = CopyStrToUni(fmt);
+ ret = InternalFormatArgs(tag, args, true);
+
+ UniToStr(buf, size, ret);
+ Free(ret);
+ Free(tag);
+}
+
+// Compare the strings in case-insensitive mode
+int StrCmpi(char *str1, char *str2)
+{
+ UINT i;
+ // Validate arguments
+ if (str1 == NULL && str2 == NULL)
+ {
+ return 0;
+ }
+ if (str1 == NULL)
+ {
+ return 1;
+ }
+ if (str2 == NULL)
+ {
+ return -1;
+ }
+
+ // String comparison
+ i = 0;
+ while (true)
+ {
+ char c1, c2;
+ c1 = ToUpper(str1[i]);
+ c2 = ToUpper(str2[i]);
+ if (c1 > c2)
+ {
+ return 1;
+ }
+ else if (c1 < c2)
+ {
+ return -1;
+ }
+ if (str1[i] == 0 || str2[i] == 0)
+ {
+ return 0;
+ }
+ i++;
+ }
+}
+
+// Compare the string
+int StrCmp(char *str1, char *str2)
+{
+ // Validate arguments
+ if (str1 == NULL && str2 == NULL)
+ {
+ return 0;
+ }
+ if (str1 == NULL)
+ {
+ return 1;
+ }
+ if (str2 == NULL)
+ {
+ return -1;
+ }
+
+ return strcmp(str1, str2);
+}
+
+// Uncapitalize the string
+void StrLower(char *str)
+{
+ UINT len, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ str[i] = ToLower(str[i]);
+ }
+}
+
+// Capitalize the string
+void StrUpper(char *str)
+{
+ UINT len, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ len = StrLen(str);
+ for (i = 0;i < len;i++)
+ {
+ str[i] = ToUpper(str[i]);
+ }
+}
+
+// Uncapitalize a character
+char ToLower(char c)
+{
+ if ('A' <= c && c <= 'Z')
+ {
+ c += 'z' - 'Z';
+ }
+ return c;
+}
+
+// Capitalize a character
+char ToUpper(char c)
+{
+ if ('a' <= c && c <= 'z')
+ {
+ c += 'Z' - 'z';
+ }
+ return c;
+}
+
+// Combine the string
+UINT StrCat(char *dst, UINT size, char *src)
+{
+ UINT len1, len2, len_test;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return 0;
+ }
+
+ // KS
+ KS_INC(KS_STRCAT_COUNT);
+
+ if (size == 0)
+ {
+ // Ignore the length
+ size = 0x7fffffff;
+ }
+
+ len1 = StrLen(dst);
+ len2 = StrLen(src);
+ len_test = len1 + len2 + 1;
+ if (len_test > size)
+ {
+ if (len2 <= (len_test - size))
+ {
+ return 0;
+ }
+ len2 -= len_test - size;
+ }
+ Copy(dst + len1, src, len2);
+ dst[len1 + len2] = 0;
+
+ return len1 + len2;
+}
+UINT StrCatLeft(char *dst, UINT size, char *src)
+{
+ char *s;
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return 0;
+ }
+
+ s = CopyStr(dst);
+ StrCpy(dst, size, src);
+ StrCat(dst, size, s);
+
+ Free(s);
+
+ return StrLen(dst);
+}
+
+// Copy a string
+UINT StrCpy(char *dst, UINT size, char *src)
+{
+ UINT len;
+ // Validate arguments
+ if (dst == src)
+ {
+ return StrLen(src);
+ }
+ if (dst == NULL || src == NULL)
+ {
+ if (src == NULL && dst != NULL)
+ {
+ if (size >= 1)
+ {
+ dst[0] = '\0';
+ }
+ }
+ return 0;
+ }
+ if (size == 1)
+ {
+ dst[0] = '\0';
+ return 0;
+ }
+ if (size == 0)
+ {
+ // Ignore the length
+ size = 0x7fffffff;
+ }
+
+ // Check the length
+ len = StrLen(src);
+ if (len <= (size - 1))
+ {
+ Copy(dst, src, len + 1);
+ }
+ else
+ {
+ len = size - 1;
+ Copy(dst, src, len);
+ dst[len] = '\0';
+ }
+
+ // KS
+ KS_INC(KS_STRCPY_COUNT);
+
+ return len;
+}
+
+// Check whether the string buffer is within the specified size
+bool StrCheckSize(char *str, UINT size)
+{
+ // Validate arguments
+ if (str == NULL || size == 0)
+ {
+ return false;
+ }
+
+ return StrCheckLen(str, size - 1);
+}
+
+// Make sure that the string is within the specified length
+bool StrCheckLen(char *str, UINT len)
+{
+ UINT count = 0;
+ UINT i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ // KS
+ KS_INC(KS_STRCHECK_COUNT);
+
+ for (i = 0;;i++)
+ {
+ if (str[i] == '\0')
+ {
+ return true;
+ }
+ count++;
+ if (count > len)
+ {
+ return false;
+ }
+ }
+}
+
+// Get the memory size needed to store the string
+UINT StrSize(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ return StrLen(str) + 1;
+}
+
+// Get the length of the string
+UINT StrLen(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ // KS
+ KS_INC(KS_STRLEN_COUNT);
+
+ return (UINT)strlen(str);
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Str.h b/src/Mayaqua/Str.h
new file mode 100644
index 00000000..bff89011
--- /dev/null
+++ b/src/Mayaqua/Str.h
@@ -0,0 +1,228 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Str.h
+// Header of Str.c
+
+#ifndef STR_H
+#define STR_H
+
+// String token
+struct TOKEN_LIST
+{
+ UINT NumTokens;
+ char **Token;
+};
+
+// INI_ENTRY
+struct INI_ENTRY
+{
+ char *Key;
+ char *Value;
+ wchar_t *UnicodeValue;
+};
+
+// Function prototype
+UINT StrLen(char *str);
+UINT StrSize(char *str);
+bool StrCheckLen(char *str, UINT len);
+bool StrCheckSize(char *str, UINT size);
+UINT StrCpy(char *dst, UINT size, char *src);
+UINT StrCat(char *dst, UINT size, char *src);
+UINT StrCatLeft(char *dst, UINT size, char *src);
+char ToLower(char c);
+char ToUpper(char c);
+void StrUpper(char *str);
+void StrLower(char *str);
+int StrCmp(char *str1, char *str2);
+int StrCmpi(char *str1, char *str2);
+void FormatArgs(char *buf, UINT size, char *fmt, va_list args);
+void Format(char *buf, UINT size, char *fmt, ...);
+char *CopyFormat(char *fmt, ...);
+void Print(char *fmt, ...);
+void PrintArgs(char *fmt, va_list args);
+void PrintStr(char *str);
+void Debug(char *fmt, ...);
+void DebugArgs(char *fmt, va_list args);
+UINT ToInt(char *str);
+bool ToBool(char *str);
+int ToInti(char *str);
+void ToStr(char *str, UINT i);
+void ToStri(char *str, int i);
+void ToStrx(char *str, UINT i);
+void ToStrx8(char *str, UINT i);
+void TrimCrlf(char *str);
+void Trim(char *str);
+void TrimRight(char *str);
+void TrimLeft(char *str);
+bool GetLine(char *str, UINT size);
+void FreeToken(TOKEN_LIST *tokens);
+bool IsInToken(TOKEN_LIST *t, char *str);
+TOKEN_LIST *ParseToken(char *src, char *separator);
+void InitStringLibrary();
+void FreeStringLibrary();
+bool CheckStringLibrary();
+bool InChar(char *string, char c);
+UINT SearchStrEx(char *string, char *keyword, UINT start, bool case_sensitive);
+UINT SearchStri(char *string, char *keyword, UINT start);
+UINT SearchStr(char *string, char *keyword, UINT start);
+UINT CalcReplaceStrEx(char *string, char *old_keyword, char *new_keyword, bool case_sensitive);
+UINT ReplaceStrEx(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword, bool case_sensitive);
+UINT ReplaceStr(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword);
+UINT ReplaceStri(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword);
+bool IsPrintableAsciiChar(char c);
+bool IsPrintableAsciiStr(char *str);
+void EnPrintableAsciiStr(char *str, char replace);
+bool IsSafeChar(char c);
+bool IsSafeStr(char *str);
+void EnSafeStr(char *str, char replace);
+void TruncateCharFromStr(char *str, char replace);
+char *CopyStr(char *str);
+void BinToStr(char *str, UINT str_size, void *data, UINT data_size);
+void BinToStrW(wchar_t *str, UINT str_size, void *data, UINT data_size);
+void PrintBin(void *data, UINT size);
+bool StartWith(char *str, char *key);
+bool EndWith(char *str, char *key);
+UINT64 ToInt64(char *str);
+void ToStr64(char *str, UINT64 value);
+char *ReplaceFormatStringFor64(char *fmt);
+TOKEN_LIST *ParseCmdLine(char *str);
+TOKEN_LIST *CopyToken(TOKEN_LIST *src);
+TOKEN_LIST *NullToken();
+bool IsNum(char *str);
+LIST *StrToStrList(char *str, UINT size);
+BUF *StrListToStr(LIST *o);
+void FreeStrList(LIST *o);
+TOKEN_LIST *ListToTokenList(LIST *o);
+LIST *TokenListToList(TOKEN_LIST *t);
+bool IsEmptyStr(char *str);
+void BinToStrEx(char *str, UINT str_size, void *data, UINT data_size);
+void BinToStrEx2(char *str, UINT str_size, void *data, UINT data_size, char padding_char);
+char *CopyBinToStrEx(void *data, UINT data_size);
+char *CopyBinToStr(void *data, UINT data_size);
+BUF *StrToBin(char *str);
+void MacToStr(char *str, UINT size, UCHAR *mac_address);
+void ToStr3(char *str, UINT size, UINT64 v);
+void ToStrByte(char *str, UINT size, UINT64 v);
+void ToStrByte1000(char *str, UINT size, UINT64 v);
+TOKEN_LIST *UniqueToken(TOKEN_LIST *t);
+char *NormalizeCrlf(char *str);
+bool IsAllUpperStr(char *str);
+UINT StrWidth(char *str);
+char *MakeCharArray(char c, UINT count);
+void MakeCharArray2(char *str, char c, UINT count);
+bool StrToMac(UCHAR *mac_address, char *str);
+bool IsSplitChar(char c, char *split_str);
+bool GetKeyAndValue(char *str, char *key, UINT key_size, char *value, UINT value_size, char *split_str);
+LIST *ReadIni(BUF *b);
+INI_ENTRY *GetIniEntry(LIST *o, char *key);
+void FreeIni(LIST *o);
+UINT IniIntValue(LIST *o, char *key);
+UINT64 IniInt64Value(LIST *o, char *key);
+char *IniStrValue(LIST *o, char *key);
+wchar_t *IniUniStrValue(LIST *o, char *key);
+bool IniHasValue(LIST *o, char *key);
+bool InStr(char *str, char *keyword);
+bool InStrEx(char *str, char *keyword, bool case_sensitive);
+bool InStrList(char *target_str, char *tokens, char *splitter, bool case_sensitive);
+TOKEN_LIST *ParseTokenWithoutNullStr(char *str, char *split_chars);
+TOKEN_LIST *ParseTokenWithNullStr(char *str, char *split_chars);
+char *DefaultTokenSplitChars();
+bool IsCharInStr(char *str, char c);
+UINT HexTo4Bit(char c);
+char FourBitToHex(UINT value);
+void ToHex(char *str, UINT value);
+void ToHex64(char *str, UINT64 value);
+UINT HexToInt(char *str);
+UINT64 HexToInt64(char *str);
+UINT SearchAsciiInBinary(void *data, UINT size, char *str, bool case_sensitive);
+bool IsStrInStrTokenList(char *str_list, char *str, char *split_chars, bool case_sensitive);
+void IntListToStr(char *str, UINT str_size, LIST *o, char *separate_str);
+LIST *StrToIntList(char *str, bool sorted);
+void NormalizeIntListStr(char *dst, UINT dst_size, char *src, bool sorted, char *separate_str);
+void ClearStr(char *str, UINT str_size);
+void SetStrCaseAccordingToBits(char *str, UINT bits);
+
+#endif // STR_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Table.c b/src/Mayaqua/Table.c
new file mode 100644
index 00000000..6cc3282b
--- /dev/null
+++ b/src/Mayaqua/Table.c
@@ -0,0 +1,1473 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Table.c
+// Read and management routines for string table
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// List of TABLE
+static LIST *TableList = NULL;
+static wchar_t old_table_name[MAX_SIZE] = {0}; // Old table name
+static LANGLIST current_lang = {0};
+static LANGLIST current_os_lang = {0};
+
+// Initialization of string table routine
+void InitTable()
+{
+ LIST *o;
+ char tmp[MAX_SIZE];
+ LANGLIST *e = NULL;
+ LANGLIST *os_lang = NULL;
+ char table_name[MAX_SIZE];
+ if (MayaquaIsMinimalMode())
+ {
+ // Not to load in case of minimum mode
+ return;
+ }
+
+ o = LoadLangList();
+ if (o == NULL)
+ {
+LABEL_FATAL_ERROR:
+ Alert("Fatal Error: The file \"hamcore.se2\" is missing or broken.\r\nPlease check hamcore.se2.\r\n\r\n(First, reboot the computer. If this problem occurs again, please reinstall VPN software files.)", NULL);
+ exit(-1);
+ return;
+ }
+
+ // Read the lang.config
+ if (LoadLangConfigCurrentDir(tmp, sizeof(tmp)))
+ {
+ e = GetBestLangByName(o, tmp);
+ }
+
+ os_lang = GetBestLangForCurrentEnvironment(o);
+
+ if (e == NULL)
+ {
+ e = os_lang;
+ }
+
+ if (e == NULL)
+ {
+ goto LABEL_FATAL_ERROR;
+ }
+
+ SaveLangConfigCurrentDir(e->Name);
+
+ Copy(&current_lang, e, sizeof(LANGLIST));
+ Copy(&current_os_lang, os_lang, sizeof(LANGLIST));
+
+ current_lang.LangList = current_lang.LcidList = NULL;
+ current_os_lang.LangList = current_os_lang.LcidList = NULL;
+
+ // Read the corresponding string table
+ Format(table_name, sizeof(table_name), "|strtable_%s.stb", current_lang.Name);
+ if (LoadTable(table_name) == false)
+ {
+ goto LABEL_FATAL_ERROR;
+ }
+
+ FreeLangList(o);
+}
+
+// Get the language of the current OS
+void GetCurrentOsLang(LANGLIST *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ Copy(e, &current_os_lang, sizeof(LANGLIST));
+}
+
+// Get the language ID of the current OS
+UINT GetCurrentOsLangId()
+{
+ LANGLIST e;
+
+ Zero(&e, sizeof(e));
+
+ GetCurrentOsLang(&e);
+
+ return e.Id;
+}
+
+// Get the current language
+void GetCurrentLang(LANGLIST *e)
+{
+ // Validate arguments
+ if (e == NULL)
+ {
+ return;
+ }
+
+ Copy(e, &current_lang, sizeof(LANGLIST));
+}
+
+// Get the current language ID
+UINT GetCurrentLangId()
+{
+ LANGLIST e;
+
+ Zero(&e, sizeof(e));
+
+ GetCurrentLang(&e);
+
+ return e.Id;
+}
+
+// Write to the lang.config file in the current directory
+bool SaveLangConfigCurrentDir(char *str)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ return SaveLangConfig(LANG_CONFIG_FILENAME, str);
+}
+
+// Write to the lang.config file
+bool SaveLangConfig(wchar_t *filename, char *str)
+{
+ BUF *b;
+ LIST *o;
+ UINT i;
+ bool ret;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return false;
+ }
+
+ // Read the template
+ b = ReadDump(LANG_CONFIG_TEMPLETE);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ SeekBuf(b, b->Size, 0);
+
+ o = LoadLangList();
+ if (o != NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ AppendBufStr(b, "# Available Language IDs are:\r\n");
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+
+ UniFormat(tmp, sizeof(tmp), L"# %S: %s (%s)\r\n",
+ e->Name, e->TitleEnglish, e->TitleLocal);
+
+ AppendBufUtf8(b, tmp);
+ }
+
+ AppendBufStr(b, "\r\n\r\n# Specify a Language ID here.\r\n");
+ AppendBufStr(b, str);
+ AppendBufStr(b, "\r\n\r\n");
+
+ FreeLangList(o);
+ }
+
+ ret = DumpBufW(b, filename);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Read the lang.config file in the current directory
+bool LoadLangConfigCurrentDir(char *str, UINT str_size)
+{
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+
+ return LoadLangConfig(LANG_CONFIG_FILENAME, str, str_size);
+}
+
+// Read the lang.config file
+bool LoadLangConfig(wchar_t *filename, char *str, UINT str_size)
+{
+ BUF *b;
+ bool ret = false;
+ // Validate arguments
+ if (filename == NULL || str == NULL)
+ {
+ return false;
+ }
+
+ b = ReadDumpW(filename);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ while (true)
+ {
+ char *line = CfgReadNextLine(b);
+
+ if (line == NULL)
+ {
+ break;
+ }
+
+ Trim(line);
+
+ if (IsEmptyStr(line) == false)
+ {
+ if (StartWith(line, "#") == false && StartWith(line, "//") == false && StartWith(line, ";") == false &&
+ InStr(line, "#") == false)
+ {
+ StrCpy(str, str_size, line);
+ ret = true;
+ }
+ }
+
+ Free(line);
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Choose the language from the ID
+LANGLIST *GetLangById(LIST *o, UINT id)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+
+ if (e->Id == id)
+ {
+ return e;
+ }
+ }
+
+ return NULL;
+}
+
+// Choice the best language for the current environment
+LANGLIST *GetBestLangForCurrentEnvironment(LIST *o)
+{
+ LANGLIST *ret = NULL;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+#ifdef OS_WIN32
+ ret = GetBestLangByLcid(o, MsGetUserLocaleId());
+#else // OS_WIN32
+ if (true)
+ {
+ char lang[MAX_SIZE];
+
+ if (GetEnv("LANG", lang, sizeof(lang)))
+ {
+ ret = GetBestLangByLangStr(o, lang);
+ }
+ else
+ {
+ ret = GetBestLangByLangStr(o, "C");
+ }
+ }
+#endif // OS_WIN32
+
+ return ret;
+}
+
+// Search for the best language from LANG string of UNIX
+LANGLIST *GetBestLangByLangStr(LIST *o, char *str)
+{
+ UINT i;
+ LANGLIST *ret;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+ UINT j;
+
+ for (j = 0;j < LIST_NUM(e->LangList);j++)
+ {
+ char *v = LIST_DATA(e->LangList, j);
+
+ if (StrCmpi(v, str) == 0)
+ {
+ return e;
+ }
+ }
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+ UINT j;
+
+ for (j = 0;j < LIST_NUM(e->LangList);j++)
+ {
+ char *v = LIST_DATA(e->LangList, j);
+
+ if (StartWith(str, v) || StartWith(v, str))
+ {
+ return e;
+ }
+ }
+ }
+
+ ret = GetBestLangByName(o, "en");
+
+ return ret;
+}
+
+// Search for the best language from LCID
+LANGLIST *GetBestLangByLcid(LIST *o, UINT lcid)
+{
+ LANGLIST *ret;
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+
+ if (IsIntInList(e->LcidList, lcid))
+ {
+ return e;
+ }
+ }
+
+ ret = GetBestLangByName(o, "en");
+
+ return ret;
+}
+
+// Search for the best language from the name
+LANGLIST *GetBestLangByName(LIST *o, char *name)
+{
+ UINT i;
+ LANGLIST *ret = NULL;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+
+ if (StrCmpi(e->Name, name) == 0)
+ {
+ ret = e;
+ break;
+ }
+ }
+
+ if (ret != NULL)
+ {
+ return ret;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+
+ if (StartWith(e->Name, name) || StartWith(name, e->Name))
+ {
+ ret = e;
+ break;
+ }
+ }
+
+ if (ret != NULL)
+ {
+ return ret;
+ }
+
+ return ret;
+}
+
+// Release the language list
+void FreeLangList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ LANGLIST *e = LIST_DATA(o, i);
+
+ FreeStrList(e->LangList);
+ ReleaseIntList(e->LcidList);
+
+ Free(e);
+ }
+
+ ReleaseList(o);
+}
+
+// Read the language list
+LIST *LoadLangList()
+{
+ LIST *o = NewListFast(NULL);
+ char *filename = LANGLIST_FILENAME;
+ BUF *b;
+
+ b = ReadDump(filename);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ while (true)
+ {
+ char *line = CfgReadNextLine(b);
+
+ if (line == NULL)
+ {
+ break;
+ }
+
+ Trim(line);
+
+ if (IsEmptyStr(line) == false && StartWith(line, "#") == false)
+ {
+ TOKEN_LIST *t = ParseToken(line, "\t ");
+ if (t != NULL)
+ {
+ if (t->NumTokens == 6)
+ {
+ LANGLIST *e = ZeroMalloc(sizeof(LANGLIST));
+ TOKEN_LIST *t2;
+
+ e->Id = ToInt(t->Token[0]);
+ StrCpy(e->Name, sizeof(e->Name), t->Token[1]);
+ Utf8ToUni(e->TitleEnglish, sizeof(e->TitleEnglish), t->Token[2], StrLen(t->Token[2]));
+ Utf8ToUni(e->TitleLocal, sizeof(e->TitleLocal), t->Token[3], StrLen(t->Token[3]));
+
+ UniReplaceStrEx(e->TitleEnglish, sizeof(e->TitleEnglish), e->TitleEnglish,
+ L"_", L" ", true);
+
+ UniReplaceStrEx(e->TitleLocal, sizeof(e->TitleLocal), e->TitleLocal,
+ L"_", L" ", true);
+
+ e->LcidList = NewIntList(false);
+
+ t2 = ParseToken(t->Token[4], ",");
+ if (t2 != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t2->NumTokens;i++)
+ {
+ UINT id = ToInt(t2->Token[i]);
+
+ AddIntDistinct(e->LcidList, id);
+ }
+
+ FreeToken(t2);
+ }
+
+ e->LangList = NewListFast(NULL);
+
+ t2 = ParseToken(t->Token[5], ",");
+ if (t2 != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < t2->NumTokens;i++)
+ {
+ Add(e->LangList, CopyStr(t2->Token[i]));
+ }
+
+ FreeToken(t2);
+ }
+
+ Add(o, e);
+ }
+
+ FreeToken(t);
+ }
+ }
+
+ Free(line);
+ }
+
+ FreeBuf(b);
+
+ return o;
+}
+
+// Get an error string in Unicode
+wchar_t *GetUniErrorStr(UINT err)
+{
+ wchar_t *ret;
+ char name[MAX_SIZE];
+ Format(name, sizeof(name), "ERR_%u", err);
+
+ ret = GetTableUniStr(name);
+ if (UniStrLen(ret) != 0)
+ {
+ return ret;
+ }
+ else
+ {
+ return _UU("ERR_UNKNOWN");
+ }
+}
+
+// Get an error string
+char *GetErrorStr(UINT err)
+{
+ char *ret;
+ char name[MAX_SIZE];
+ Format(name, sizeof(name), "ERR_%u", err);
+
+ ret = GetTableStr(name);
+ if (StrLen(ret) != 0)
+ {
+ return ret;
+ }
+ else
+ {
+ return _SS("ERR_UNKNOWN");
+ }
+}
+
+// Load the integer value from the table
+UINT GetTableInt(char *name)
+{
+ char *str;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return 0;
+ }
+
+ str = GetTableStr(name);
+ return ToInt(str);
+}
+
+// Load a Unicode string from the table
+wchar_t *GetTableUniStr(char *name)
+{
+ TABLE *t;
+ // Validate arguments
+ if (name == NULL)
+ {
+// Debug("%s: ************\n", name);
+ return L"";
+ }
+
+ // Search
+ t = FindTable(name);
+ if (t == NULL)
+ {
+ //Debug("%s: UNICODE STRING NOT FOUND\n", name);
+ return L"";
+ }
+
+ return t->unistr;
+}
+
+// Load the string from the table
+char *GetTableStr(char *name)
+{
+ TABLE *t;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return "";
+ }
+
+#ifdef OS_WIN32
+ if (StrCmpi(name, "DEFAULT_FONT") == 0)
+ {
+ if (_II("LANG") == 2)
+ {
+ UINT os_type = GetOsType();
+ if (OS_IS_WINDOWS_9X(os_type) ||
+ GET_KETA(os_type, 100) <= 4)
+ {
+ // Use the SimSun font in Windows 9x, Windows NT 4.0, Windows 2000, Windows XP, and Windows Server 2003
+ return "SimSun";
+ }
+ }
+ }
+#endif // OS_WIN32
+
+ // Search
+ t = FindTable(name);
+ if (t == NULL)
+ {
+ //Debug("%s: ANSI STRING NOT FOUND\n", name);
+ return "";
+ }
+
+ return t->str;
+}
+
+// Get the string name that begins with the specified name
+TOKEN_LIST *GetTableNameStartWith(char *str)
+{
+ UINT i;
+ UINT len;
+ LIST *o;
+ TOKEN_LIST *t;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NullToken();
+ }
+
+ StrCpy(tmp, sizeof(tmp), str);
+ StrUpper(tmp);
+
+ len = StrLen(tmp);
+
+ o = NewListFast(NULL);
+
+ for (i = 0;i < LIST_NUM(TableList);i++)
+ {
+ TABLE *t = LIST_DATA(TableList, i);
+ UINT len2 = StrLen(t->name);
+
+ if (len2 >= len)
+ {
+ if (Cmp(t->name, tmp, len) == 0)
+ {
+ Insert(o, CopyStr(t->name));
+ }
+ }
+ }
+
+ t = ZeroMalloc(sizeof(TOKEN_LIST));
+ t->NumTokens = LIST_NUM(o);
+ t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ t->Token[i] = LIST_DATA(o, i);
+ }
+
+ ReleaseList(o);
+
+ return t;
+}
+
+// Search the table
+TABLE *FindTable(char *name)
+{
+ TABLE *t, tt;
+ // Validate arguments
+ if (name == NULL || TableList == NULL)
+ {
+ return NULL;
+ }
+
+ tt.name = CopyStr(name);
+ t = Search(TableList, &tt);
+ Free(tt.name);
+
+ return t;
+}
+
+// A function that compares the table name
+int CmpTableName(void *p1, void *p2)
+{
+ TABLE *t1, *t2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ t1 = *(TABLE **)p1;
+ t2 = *(TABLE **)p2;
+ if (t1 == NULL || t2 == NULL)
+ {
+ return 0;
+ }
+
+ return StrCmpi(t1->name, t2->name);
+}
+
+// Interpret a line
+TABLE *ParseTableLine(char *line, char *prefix, UINT prefix_size, LIST *replace_list)
+{
+ UINT i, len;
+ UINT len_name;
+ UINT string_start;
+ char *name;
+ char *name2;
+ UINT name2_size;
+ wchar_t *unistr;
+ char *str;
+ UINT unistr_size, str_size;
+ TABLE *t;
+ // Validate arguments
+ if (line == NULL || prefix == NULL)
+ {
+ return NULL;
+ }
+ TrimLeft(line);
+
+ // No line
+ len = StrLen(line);
+ if (len == 0)
+ {
+ return NULL;
+ }
+
+ // Comment
+ if (line[0] == '#' || (line[0] == '/' && line[1] == '/'))
+ {
+ return NULL;
+ }
+
+ // Search to the end position of the name
+ len_name = 0;
+ for (i = 0;;i++)
+ {
+ if (line[i] == 0)
+ {
+ // There is only one token
+ return NULL;
+ }
+ if (line[i] == ' ' || line[i] == '\t')
+ {
+ break;
+ }
+ len_name++;
+ }
+
+ name = Malloc(len_name + 1);
+ StrCpy(name, len_name + 1, line);
+
+ string_start = len_name;
+ for (i = len_name;i < len;i++)
+ {
+ if (line[i] != ' ' && line[i] != '\t')
+ {
+ break;
+ }
+ string_start++;
+ }
+ if (i == len)
+ {
+ Free(name);
+ return NULL;
+ }
+
+ // Unescape
+ UnescapeStr(&line[string_start]);
+
+ // Convert to Unicode
+ unistr_size = CalcUtf8ToUni(&line[string_start], StrLen(&line[string_start]));
+ if (unistr_size == 0)
+ {
+ Free(name);
+ return NULL;
+ }
+ unistr = Malloc(unistr_size);
+ Utf8ToUni(unistr, unistr_size, &line[string_start], StrLen(&line[string_start]));
+
+ if (UniInChar(unistr, L'$'))
+ {
+ // Replace the replacement string
+ wchar_t *tmp;
+ UINT tmp_size = (UniStrSize(unistr) + 1024) * 2;
+ UINT i;
+
+ tmp = Malloc(tmp_size);
+
+ UniStrCpy(tmp, tmp_size, unistr);
+
+ for (i = 0; i < LIST_NUM(replace_list);i++)
+ {
+ TABLE *r = LIST_DATA(replace_list, i);
+
+ UniReplaceStrEx(tmp, tmp_size, tmp, (wchar_t *)r->name, r->unistr, false);
+ }
+
+ unistr = CopyUniStr(tmp);
+
+ Free(tmp);
+ }
+
+ // Convert to ANSI
+ str_size = CalcUniToStr(unistr);
+ if (str_size == 0)
+ {
+ str_size = 1;
+ str = Malloc(1);
+ str[0] = 0;
+ }
+ else
+ {
+ str = Malloc(str_size);
+ UniToStr(str, str_size, unistr);
+ }
+
+ if (StrCmpi(name, "PREFIX") == 0)
+ {
+ // Prefix is specified
+ StrCpy(prefix, prefix_size, str);
+ Trim(prefix);
+
+ if (StrCmpi(prefix, "$") == 0 || StrCmpi(prefix, "NULL") == 0)
+ {
+ prefix[0] = 0;
+ }
+
+ Free(name);
+ Free(str);
+ Free(unistr);
+
+ return NULL;
+ }
+
+ name2_size = StrLen(name) + StrLen(prefix) + 2;
+ name2 = ZeroMalloc(name2_size);
+
+ if (prefix[0] != 0)
+ {
+ StrCat(name2, name2_size, prefix);
+ StrCat(name2, name2_size, "@");
+ }
+
+ StrCat(name2, name2_size, name);
+
+ Free(name);
+
+ // Create a TABLE
+ t = Malloc(sizeof(TABLE));
+ StrUpper(name2);
+ t->name = name2;
+ t->str = str;
+ t->unistr = unistr;
+
+ return t;
+}
+
+// Unescape the string
+void UnescapeStr(char *src)
+{
+ UINT i, len, wp;
+ char *tmp;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return;
+ }
+
+ len = StrLen(src);
+ tmp = Malloc(len + 1);
+ wp = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (src[i] == '\\')
+ {
+ i++;
+ switch (src[i])
+ {
+ case 0:
+ goto FINISH;
+ case '\\':
+ tmp[wp++] = '\\';
+ break;
+ case ' ':
+ tmp[wp++] = ' ';
+ break;
+ case 'n':
+ case 'N':
+ tmp[wp++] = '\n';
+ break;
+ case 'r':
+ case 'R':
+ tmp[wp++] = '\r';
+ break;
+ case 't':
+ case 'T':
+ tmp[wp++] = '\t';
+ break;
+ }
+ }
+ else
+ {
+ tmp[wp++] = src[i];
+ }
+ }
+FINISH:
+ tmp[wp++] = 0;
+ StrCpy(src, 0, tmp);
+ Free(tmp);
+}
+
+// Release the table
+void FreeTable()
+{
+ UINT i, num;
+ TABLE **tables;
+ if (TableList == NULL)
+ {
+ return;
+ }
+
+ TrackingDisable();
+
+ num = LIST_NUM(TableList);
+ tables = ToArray(TableList);
+ for (i = 0;i < num;i++)
+ {
+ TABLE *t = tables[i];
+ Free(t->name);
+ Free(t->str);
+ Free(t->unistr);
+ Free(t);
+ }
+ ReleaseList(TableList);
+ TableList = NULL;
+ Free(tables);
+
+ Zero(old_table_name, sizeof(old_table_name));
+
+ TrackingEnable();
+}
+
+// Read a string table from the buffer
+bool LoadTableFromBuf(BUF *b)
+{
+ char *tmp;
+ char prefix[MAX_SIZE];
+ LIST *replace_list = NULL;
+ UINT i;
+ // Validate arguments
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ // If the table already exists, delete it
+ FreeTable();
+
+ // Create a list
+ TableList = NewList(CmpTableName);
+
+ Zero(prefix, sizeof(prefix));
+
+ replace_list = NewListFast(NULL);
+
+ // Read the contents of the buffer line by line
+ while (true)
+ {
+ TABLE *t;
+ bool ok = true;
+
+ tmp = CfgReadNextLine(b);
+ if (tmp == NULL)
+ {
+ break;
+ }
+
+ if (tmp[0] == '$')
+ {
+ char key[128];
+ char value[MAX_SIZE];
+ if (GetKeyAndValue(tmp, key, sizeof(key), value, sizeof(value), " \t"))
+ {
+ if (StartWith(key, "$") && EndWith(key, "$") && StrLen(key) >= 3)
+ {
+ TABLE *t;
+ wchar_t univalue[MAX_SIZE];
+ wchar_t uniname[MAX_SIZE];
+
+ t = ZeroMalloc(sizeof(TABLE));
+
+ Zero(univalue, sizeof(univalue));
+ Utf8ToUni(univalue, sizeof(univalue), value, StrLen(value));
+
+ StrToUni(uniname, sizeof(uniname), key);
+
+ t->name = (char *)CopyUniStr(uniname);
+ t->unistr = CopyUniStr(univalue);
+
+ Add(replace_list, t);
+
+ // Found a replacement definition
+ ok = false;
+ }
+ }
+ }
+
+ if (ok)
+ {
+ t = ParseTableLine(tmp, prefix, sizeof(prefix), replace_list);
+ if (t != NULL)
+ {
+ // Register
+ Insert(TableList, t);
+ }
+ }
+
+ Free(tmp);
+ }
+
+ for (i = 0;i < LIST_NUM(replace_list);i++)
+ {
+ TABLE *t = LIST_DATA(replace_list, i);
+
+ Free(t->name);
+ Free(t->str);
+ Free(t->unistr);
+
+ Free(t);
+ }
+
+ ReleaseList(replace_list);
+
+ return true;
+}
+
+// Generate the Unicode string cache file name
+void GenerateUnicodeCacheFileName(wchar_t *name, UINT size, wchar_t *strfilename, UINT strfilesize, UCHAR *filehash)
+{
+ wchar_t tmp[MAX_SIZE];
+ wchar_t hashstr[64];
+ wchar_t hashtemp[MAX_SIZE];
+ wchar_t exe[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ // Validate arguments
+ if (name == NULL || strfilename == NULL || filehash == NULL)
+ {
+ return;
+ }
+
+ GetExeDirW(exe, sizeof(exe));
+ UniStrCpy(hashtemp, sizeof(hashtemp), strfilename);
+ BinToStrW(tmp, sizeof(tmp), filehash, MD5_SIZE);
+ UniStrCat(hashtemp, sizeof(hashtemp), tmp);
+ UniStrCat(hashtemp, sizeof(hashtemp), exe);
+ UniStrLower(hashtemp);
+
+ Hash(hash, hashtemp, UniStrLen(hashtemp) * sizeof(wchar_t), true);
+ BinToStrW(hashstr, sizeof(hashstr), hash, 4);
+ UniFormat(tmp, sizeof(tmp), UNICODE_CACHE_FILE, hashstr);
+ UniStrLower(tmp);
+
+#ifndef OS_WIN32
+ UniStrCpy(exe, sizeof(exe), L"/tmp");
+#else // OS_WIN32
+ StrToUni(exe, sizeof(exe), MsGetTempDir());
+#endif // OS_WIN32
+
+ UniFormat(name, size, L"%s/%s", exe, tmp);
+ NormalizePathW(name, size, name);
+}
+
+// Save the Unicode cache
+void SaveUnicodeCache(wchar_t *strfilename, UINT strfilesize, UCHAR *hash)
+{
+ UNICODE_CACHE c;
+ BUF *b;
+ UINT i;
+ IO *io;
+ wchar_t name[MAX_PATH];
+ UCHAR binhash[MD5_SIZE];
+ // Validate arguments
+ if (strfilename == NULL || hash == NULL)
+ {
+ return;
+ }
+
+ Zero(&c, sizeof(c));
+ UniToStr(c.StrFileName, sizeof(c.StrFileName), strfilename);
+ c.StrFileSize = strfilesize;
+ GetMachineName(c.MachineName, sizeof(c.MachineName));
+ c.OsType = GetOsInfo()->OsType;
+ Copy(c.hash, hash, MD5_SIZE);
+
+#ifdef OS_UNIX
+ GetCurrentCharSet(c.CharSet, sizeof(c.CharSet));
+#else // OS_UNIX
+ {
+ UINT id = MsGetThreadLocale();
+ Copy(c.CharSet, &id, sizeof(id));
+ }
+#endif // OS_UNIX
+
+ b = NewBuf();
+ WriteBuf(b, &c, sizeof(c));
+
+ WriteBufInt(b, LIST_NUM(TableList));
+ for (i = 0;i < LIST_NUM(TableList);i++)
+ {
+ TABLE *t = LIST_DATA(TableList, i);
+ WriteBufInt(b, StrLen(t->name));
+ WriteBuf(b, t->name, StrLen(t->name));
+ WriteBufInt(b, StrLen(t->str));
+ WriteBuf(b, t->str, StrLen(t->str));
+ WriteBufInt(b, UniStrLen(t->unistr));
+ WriteBuf(b, t->unistr, UniStrLen(t->unistr) * sizeof(wchar_t));
+ }
+
+ Hash(binhash, b->Buf, b->Size, false);
+ WriteBuf(b, binhash, MD5_SIZE);
+
+ GenerateUnicodeCacheFileName(name, sizeof(name), strfilename, strfilesize, hash);
+
+ io = FileCreateW(name);
+ if (io != NULL)
+ {
+ SeekBuf(b, 0, 0);
+ BufToFile(io, b);
+ FileClose(io);
+ }
+
+ FreeBuf(b);
+}
+
+// Reading the Unicode cache
+bool LoadUnicodeCache(wchar_t *strfilename, UINT strfilesize, UCHAR *hash)
+{
+ UNICODE_CACHE c, t;
+ BUF *b;
+ UINT i, num;
+ IO *io;
+ wchar_t name[MAX_PATH];
+ UCHAR binhash[MD5_SIZE];
+ UCHAR binhash_2[MD5_SIZE];
+ // Validate arguments
+ if (strfilename == NULL || hash == NULL)
+ {
+ return false;
+ }
+
+ GenerateUnicodeCacheFileName(name, sizeof(name), strfilename, strfilesize, hash);
+
+ io = FileOpenW(name, false);
+ if (io == NULL)
+ {
+ return false;
+ }
+
+ b = FileToBuf(io);
+ if (b == NULL)
+ {
+ FileClose(io);
+ return false;
+ }
+
+ SeekBuf(b, 0, 0);
+ FileClose(io);
+
+ Hash(binhash, b->Buf, b->Size >= MD5_SIZE ? (b->Size - MD5_SIZE) : 0, false);
+ Copy(binhash_2, ((UCHAR *)b->Buf) + (b->Size >= MD5_SIZE ? (b->Size - MD5_SIZE) : 0), MD5_SIZE);
+ if (Cmp(binhash, binhash_2, MD5_SIZE) != 0)
+ {
+ FreeBuf(b);
+ return false;
+ }
+
+ Zero(&c, sizeof(c));
+ UniToStr(c.StrFileName, sizeof(c.StrFileName), strfilename);
+ c.StrFileSize = strfilesize;
+ DisableNetworkNameCache();
+ GetMachineName(c.MachineName, sizeof(c.MachineName));
+ EnableNetworkNameCache();
+ c.OsType = GetOsInfo()->OsType;
+ Copy(c.hash, hash, MD5_SIZE);
+
+#ifdef OS_UNIX
+ GetCurrentCharSet(c.CharSet, sizeof(c.CharSet));
+#else // OS_UNIX
+ {
+ UINT id = MsGetThreadLocale();
+ Copy(c.CharSet, &id, sizeof(id));
+ }
+#endif // OS_UNIX
+
+ Zero(&t, sizeof(t));
+ ReadBuf(b, &t, sizeof(t));
+
+ if (Cmp(&c, &t, sizeof(UNICODE_CACHE)) != 0)
+ {
+ FreeBuf(b);
+ return false;
+ }
+
+ num = ReadBufInt(b);
+
+ FreeTable();
+ TableList = NewList(CmpTableName);
+
+ for (i = 0;i < num;i++)
+ {
+ UINT len;
+ TABLE *t = ZeroMalloc(sizeof(TABLE));
+
+ len = ReadBufInt(b);
+ t->name = ZeroMalloc(len + 1);
+ ReadBuf(b, t->name, len);
+
+ len = ReadBufInt(b);
+ t->str = ZeroMalloc(len + 1);
+ ReadBuf(b, t->str, len);
+
+ len = ReadBufInt(b);
+ t->unistr = ZeroMalloc((len + 1) * sizeof(wchar_t));
+ ReadBuf(b, t->unistr, len * sizeof(wchar_t));
+
+ Add(TableList, t);
+ }
+
+ FreeBuf(b);
+
+ Sort(TableList);
+
+ return true;
+}
+
+// Read the string table
+bool LoadTableMain(wchar_t *filename)
+{
+ BUF *b;
+ UINT64 t1, t2;
+ UCHAR hash[MD5_SIZE];
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return false;
+ }
+
+ if (MayaquaIsMinimalMode())
+ {
+ return true;
+ }
+
+ if (UniStrCmpi(old_table_name, filename) == 0)
+ {
+ // Already loaded
+ return true;
+ }
+
+ t1 = Tick64();
+
+ // Open the file
+ b = ReadDumpW(filename);
+ if (b == NULL)
+ {
+ char tmp[MAX_SIZE];
+ StrCpy(tmp, sizeof(tmp), "Error: Can't read string tables (file not found).\r\nPlease check hamcore.se2.\r\n\r\n(First, reboot the computer. If this problem occurs again, please reinstall VPN software files.)");
+ Alert(tmp, NULL);
+ exit(-1);
+ return false;
+ }
+
+ Hash(hash, b->Buf, b->Size, false);
+
+ if (LoadUnicodeCache(filename, b->Size, hash) == false)
+ {
+ if (LoadTableFromBuf(b) == false)
+ {
+ FreeBuf(b);
+ return false;
+ }
+
+ SaveUnicodeCache(filename, b->Size, hash);
+
+ Debug("Unicode Source: strtable.stb\n");
+ }
+ else
+ {
+ Debug("Unicode Source: unicode_cache\n");
+ }
+
+ FreeBuf(b);
+
+ SetLocale(_UU("DEFAULE_LOCALE"));
+
+ UniStrCpy(old_table_name, sizeof(old_table_name), filename);
+
+ t2 = Tick64();
+
+ if (StrCmpi(_SS("STRTABLE_ID"), STRTABLE_ID) != 0)
+ {
+ char tmp[MAX_SIZE];
+ Format(tmp, sizeof(tmp), "Error: Can't read string tables (invalid version: '%s'!='%s').\r\nPlease check hamcore.se2.\r\n\r\n(First, reboot the computer. If this problem occurs again, please reinstall VPN software files.)",
+ _SS("STRTABLE_ID"), STRTABLE_ID);
+ Alert(tmp, NULL);
+ exit(-1);
+ return false;
+ }
+
+ Debug("Unicode File Read Cost: %u (%u Lines)\n", (UINT)(t2 - t1), LIST_NUM(TableList));
+
+ return true;
+}
+bool LoadTable(char *filename)
+{
+ wchar_t *filename_a = CopyStrToUni(filename);
+ bool ret = LoadTableW(filename_a);
+
+ Free(filename_a);
+
+ return ret;
+}
+bool LoadTableW(wchar_t *filename)
+{
+ bool ret;
+ BUF *b;
+ wchar_t replace_name[MAX_PATH];
+
+ Zero(replace_name, sizeof(replace_name));
+
+ TrackingDisable();
+
+ b = ReadDump("@table_name.txt");
+ if (b != NULL)
+ {
+ char *s = CfgReadNextLine(b);
+ if (s != NULL)
+ {
+ if (IsEmptyStr(s) == false)
+ {
+ StrToUni(replace_name, sizeof(replace_name), s);
+ filename = replace_name;
+ }
+
+ Free(s);
+ }
+ FreeBuf(b);
+ }
+
+ ret = LoadTableMain(filename);
+
+ TrackingEnable();
+
+ return ret;
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Table.h b/src/Mayaqua/Table.h
new file mode 100644
index 00000000..b7a0e64d
--- /dev/null
+++ b/src/Mayaqua/Table.h
@@ -0,0 +1,186 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Table.h
+// Header of Table.c
+
+#ifndef TABLE_H
+#define TABLE_H
+
+#define UNICODE_CACHE_FILE L".unicode_cache_%s.dat"
+
+#define LANGLIST_FILENAME "|languages.txt"
+#define LANG_CONFIG_FILENAME L"@lang.config"
+#define LANG_CONFIG_TEMPLETE "|lang.config"
+
+// Language constant
+#define SE_LANG_JAPANESE 0 // Japanese
+#define SE_LANG_ENGLISH 1 // English
+#define SE_LANG_CHINESE_ZH 2 // Simplified Chinese
+
+
+// String table
+struct TABLE
+{
+ char *name;
+ char *str;
+ wchar_t *unistr;
+};
+
+// Unicode cache structure
+typedef struct UNICODE_CACHE
+{
+ char StrFileName[256]; // String file name
+ UINT StrFileSize; // String file size
+ char MachineName[256]; // Machine name
+ UINT OsType; // OS type
+ UCHAR hash[MD5_SIZE]; // Hash
+ UCHAR CharSet[64]; // Type of character code
+} UNICODE_CACHE;
+
+// Macro
+#define _SS(name) (GetTableStr((char *)(name)))
+#define _UU(name) (GetTableUniStr((char *)(name)))
+#define _II(name) (GetTableInt((char *)(name)))
+#define _E(name) (GetUniErrorStr((UINT)(name)))
+#define _EA(name) (GetErrorStr((UINT)(name)))
+#define _GETLANG() (_II("LANG"))
+
+// Language list
+struct LANGLIST
+{
+ UINT Id; // Number
+ char Name[32]; // Identifier
+ wchar_t TitleEnglish[128]; // English notation
+ wchar_t TitleLocal[128]; // Local notation
+ LIST *LcidList; // Windows LCID list
+ LIST *LangList; // UNIX LANG environment variable list
+};
+
+
+// Function prototype
+bool LoadTable(char *filename);
+bool LoadTableW(wchar_t *filename);
+bool LoadTableMain(wchar_t *filename);
+bool LoadTableFromBuf(BUF *b);
+void FreeTable();
+TABLE *ParseTableLine(char *line, char *prefix, UINT prefix_size, LIST *replace_list);
+void UnescapeStr(char *src);
+int CmpTableName(void *p1, void *p2);
+TABLE *FindTable(char *name);
+TOKEN_LIST *GetTableNameStartWith(char *str);
+char *GetTableStr(char *name);
+wchar_t *GetTableUniStr(char *name);
+char *GetErrorStr(UINT err);
+wchar_t *GetUniErrorStr(UINT err);
+UINT GetTableInt(char *name);
+void GenerateUnicodeCacheFileName(wchar_t *name, UINT size, wchar_t *strfilename, UINT strfilesize, UCHAR *filehash);
+void SaveUnicodeCache(wchar_t *strfilename, UINT strfilesize, UCHAR *hash);
+bool LoadUnicodeCache(wchar_t *strfilename, UINT strfilesize, UCHAR *hash);
+void InitTable();
+
+LIST *LoadLangList();
+void FreeLangList(LIST *o);
+
+LANGLIST *GetBestLangByName(LIST *o, char *name);
+LANGLIST *GetBestLangByLcid(LIST *o, UINT lcid);
+LANGLIST *GetBestLangByLangStr(LIST *o, char *str);
+LANGLIST *GetBestLangForCurrentEnvironment(LIST *o);
+LANGLIST *GetLangById(LIST *o, UINT id);
+
+bool LoadLangConfig(wchar_t *filename, char *str, UINT str_size);
+bool LoadLangConfigCurrentDir(char *str, UINT str_size);
+bool SaveLangConfig(wchar_t *filename, char *str);
+bool SaveLangConfigCurrentDir(char *str);
+
+void GetCurrentLang(LANGLIST *e);
+UINT GetCurrentLangId();
+
+void GetCurrentOsLang(LANGLIST *e);
+UINT GetCurrentOsLangId();
+
+#endif // TABLE_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/TcpIp.c b/src/Mayaqua/TcpIp.c
new file mode 100644
index 00000000..4bb63c9b
--- /dev/null
+++ b/src/Mayaqua/TcpIp.c
@@ -0,0 +1,3802 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// TcpIp.c
+// Utility module for TCP/IP packet processing
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+
+// Send an ICMP Echo
+ICMP_RESULT *IcmpEchoSend(IP *dest_ip, UCHAR ttl, UCHAR *data, UINT size, UINT timeout)
+{
+ // Validate arguments
+ if (dest_ip == NULL || IsIP4(dest_ip) == false || (size != 0 && data == NULL))
+ {
+ return NULL;
+ }
+ if (ttl == 0)
+ {
+ ttl = 127;
+ }
+
+ if (IsIcmpApiSupported())
+ {
+ return IcmpApiEchoSend(dest_ip, ttl, data, size, timeout);
+ }
+ else
+ {
+ return IcmpEchoSendBySocket(dest_ip, ttl, data, size, timeout);
+ }
+}
+
+// Release the memory for the ICMP response
+void IcmpFreeResult(ICMP_RESULT *r)
+{
+ // Validate arguments
+ if (r == NULL)
+ {
+ return;
+ }
+
+ IcmpApiFreeResult(r);
+}
+
+// Parse the ICMP reply packet received from the socket
+ICMP_RESULT *IcmpParseResult(IP *dest_ip, USHORT src_id, USHORT src_seqno, UCHAR *recv_buffer, UINT recv_buffer_size)
+{
+ ICMP_RESULT *ret = NULL;
+ UINT i;
+ // Validate arguments
+ if (dest_ip == NULL || IsIP4(dest_ip) == false || recv_buffer == NULL || recv_buffer_size == 0)
+ {
+ return NULL;
+ }
+
+ i = recv_buffer_size;
+
+ if (true)
+ {
+ UINT ip_header_size = GetIpHeaderSize(recv_buffer, i);
+ if (ip_header_size >= sizeof(IPV4_HEADER))
+ {
+ IPV4_HEADER *ipv4 = (IPV4_HEADER *)recv_buffer;
+ if ((IPV4_GET_VERSION(ipv4) == 4) && (ipv4->Protocol == IP_PROTO_ICMPV4))
+ {
+ UINT ip_total_len = (UINT)Endian16(ipv4->TotalLength);
+
+ if ((ip_total_len >= sizeof(IPV4_HEADER)) && (ip_total_len <= i))
+ {
+ UINT icmp_packet_size = ip_total_len - ip_header_size;
+ ICMP_HEADER *icmp = (ICMP_HEADER *)(recv_buffer + ip_header_size);
+
+ if (icmp_packet_size >= sizeof(ICMP_HEADER))
+ {
+ USHORT chksum = icmp->Checksum;
+ USHORT chksum2;
+ icmp->Checksum = 0;
+
+ chksum2 = IpChecksum(icmp, icmp_packet_size);
+
+ if (chksum2 == chksum)
+ {
+ if (icmp->Type == ICMP_TYPE_ECHO_RESPONSE)
+ {
+ ICMP_ECHO *echo = (ICMP_ECHO *)(recv_buffer + ip_header_size + sizeof(ICMP_HEADER));
+ if (icmp_packet_size >= (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
+ {
+ if (Endian16(echo->Identifier) == src_id && (src_seqno == 0 || Endian16(echo->SeqNo) == src_seqno))
+ {
+ IP ip;
+
+ UINTToIP(&ip, ipv4->SrcIP);
+
+ // Received the correct Echo response
+ ret = ZeroMalloc(sizeof(ICMP_RESULT));
+
+ ret->Ok = true;
+ ret->Ttl = ipv4->TimeToLive;
+ ret->DataSize = icmp_packet_size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
+ ret->Data = Clone(recv_buffer + ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO),
+ ret->DataSize);
+ Copy(&ret->IpAddress, &ip, sizeof(IP));
+ }
+ }
+ }
+ else if (icmp->Type == ICMP_TYPE_ECHO_REQUEST)
+ {
+ // Ignore because an Echo request should not arrive
+ }
+ else
+ {
+ // If an error is returned, compare to the copy of
+ // the ICMP packet last sent
+ IPV4_HEADER *orig_ipv4 = (IPV4_HEADER *)(recv_buffer + ip_header_size + 4 + sizeof(ICMP_HEADER));
+ if (icmp_packet_size >= (sizeof(ICMP_HEADER) + 4 + sizeof(IPV4_HEADER)))
+ {
+ UINT orig_ipv4_header_size = GetIpHeaderSize((UCHAR *)orig_ipv4, icmp_packet_size - 4 - sizeof(ICMP_HEADER));
+ if (orig_ipv4_header_size >= sizeof(IPV4_HEADER))
+ {
+ if ((IPV4_GET_VERSION(orig_ipv4) == 4) && (orig_ipv4->Protocol == IP_PROTO_ICMPV4))
+ {
+ if (icmp_packet_size >= (sizeof(ICMP_HEADER) + 4 + orig_ipv4_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
+ {
+ ICMP_HEADER *orig_icmp = (ICMP_HEADER *)(recv_buffer + ip_header_size + sizeof(ICMP_HEADER) + 4 + orig_ipv4_header_size);
+ ICMP_ECHO *orig_echo = (ICMP_ECHO *)(recv_buffer + ip_header_size + sizeof(ICMP_HEADER) + 4 + orig_ipv4_header_size + sizeof(ICMP_HEADER));
+
+ if (orig_icmp->Type == ICMP_TYPE_ECHO_REQUEST && orig_echo->Identifier == Endian16(src_id) && (src_seqno == 0 || orig_echo->SeqNo == Endian16(src_seqno)))
+ {
+ IP ip;
+
+ UINTToIP(&ip, ipv4->SrcIP);
+
+ ret = ZeroMalloc(sizeof(ICMP_RESULT));
+
+ ret->Type = icmp->Type;
+ ret->Code = icmp->Code;
+ ret->Ttl = ipv4->TimeToLive;
+ ret->DataSize = icmp_packet_size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
+ ret->Data = Clone(recv_buffer + ip_header_size + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO),
+ ret->DataSize);
+ Copy(&ret->IpAddress, &ip, sizeof(IP));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Send the ICMP Echo (by a socket)
+ICMP_RESULT *IcmpEchoSendBySocket(IP *dest_ip, UCHAR ttl, UCHAR *data, UINT size, UINT timeout)
+{
+ SOCK *s;
+ ICMP_RESULT *ret = NULL;
+ USHORT id;
+ USHORT seq;
+ UINT64 sent_tick;
+ UINT64 recv_tick;
+ // Validate arguments
+ if (dest_ip == NULL || IsIP4(dest_ip) == false || (size != 0 && data == NULL))
+ {
+ return NULL;
+ }
+ if (ttl == 0)
+ {
+ ttl = 127;
+ }
+
+ s = NewUDP4(MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4), NULL);
+ if (s != NULL)
+ {
+ // Construction of the ICMP packet
+ UCHAR *send_buffer;
+ UINT send_buffer_size = sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + size;
+ ICMP_HEADER *send_icmp_header;
+ ICMP_ECHO *send_icmp_echo;
+ UINT i;
+
+ id = Rand16();
+ if (id == 0)
+ {
+ id = 1;
+ }
+
+ seq = Rand16();
+ if (seq == 0)
+ {
+ seq = 1;
+ }
+
+ send_buffer = ZeroMalloc(send_buffer_size);
+
+ send_icmp_header = (ICMP_HEADER *)send_buffer;
+ send_icmp_header->Type = ICMP_TYPE_ECHO_REQUEST;
+
+ send_icmp_echo = (ICMP_ECHO *)(send_buffer + sizeof(ICMP_HEADER));
+ send_icmp_echo->Identifier = Endian16(id);
+ send_icmp_echo->SeqNo = Endian16(seq);
+
+ Copy(send_buffer + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO), data, size);
+
+ send_icmp_header->Checksum = IpChecksum(send_buffer, send_buffer_size);
+
+ // Send an ICMP
+ SetTtl(s, ttl);
+ sent_tick = TickHighres64();
+ i = SendTo(s, dest_ip, MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4), send_buffer, send_buffer_size);
+
+ if (i != 0 && i != INFINITE)
+ {
+ // ICMP response received
+ INTERRUPT_MANAGER *interrupt = NewInterruptManager();
+ UINT64 giveup_time = Tick64() + (UINT64)timeout;
+ UINT recv_buffer_size = (sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + size + 64) * 2;
+ UCHAR *recv_buffer = Malloc(recv_buffer_size);
+
+ AddInterrupt(interrupt, giveup_time);
+
+ while (true)
+ {
+ UINT interval = GetNextIntervalForInterrupt(interrupt);
+ IP src_ip;
+ UINT src_port;
+ SOCKSET set;
+
+ InitSockSet(&set);
+ AddSockSet(&set, s);
+
+ Select(&set, interval, NULL, NULL);
+
+ while (true)
+ {
+ Zero(recv_buffer, recv_buffer_size);
+ i = RecvFrom(s, &src_ip, &src_port, recv_buffer, recv_buffer_size);
+ recv_tick = TickHighres64();
+
+ if (i != 0 && i != SOCK_LATER)
+ {
+ ret = IcmpParseResult(dest_ip, id, seq, recv_buffer, i);
+
+ if (ret != NULL)
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (interval == 0)
+ {
+ break;
+ }
+
+ if (ret != NULL)
+ {
+ break;
+ }
+ }
+
+ FreeInterruptManager(interrupt);
+
+ Free(recv_buffer);
+
+ if (ret == NULL)
+ {
+ ret = ZeroMalloc(sizeof(ICMP_RESULT));
+
+ ret->Timeout = true;
+ }
+ }
+
+ Free(send_buffer);
+ ReleaseSock(s);
+ }
+
+ return ret;
+}
+
+// Get whether the packet is a DHCP packet associated with the specified MAC address
+bool IsDhcpPacketForSpecificMac(UCHAR *data, UINT size, UCHAR *mac_address)
+{
+ USHORT *us;
+ IPV4_HEADER *ip;
+ UDP_HEADER *udp;
+ UINT ip_header_size;
+ bool is_send = false, is_recv = false;
+ // Validate arguments
+ if (data == NULL || mac_address == NULL || IsZero(mac_address, 6))
+ {
+ return false;
+ }
+
+ // Whether the src or the dest matches
+ if (size < 14)
+ {
+ return false;
+ }
+
+ // Destination MAC address
+ if (Cmp(data, mac_address, 6) == 0)
+ {
+ is_recv = true;
+ }
+ size -= 6;
+ data += 6;
+
+ // Source MAC address
+ if (Cmp(data, mac_address, 6) == 0)
+ {
+ is_send = true;
+ }
+ size -= 6;
+ data += 6;
+
+ if (is_send == false && is_recv == false)
+ {
+ return false;
+ }
+ if (is_send && is_recv)
+ {
+ return false;
+ }
+
+ // TPID
+ us = (USHORT *)data;
+ size -= 2;
+ data += 2;
+
+ if (READ_USHORT(us) != MAC_PROTO_IPV4)
+ {
+ // Other than IPv4
+ return false;
+ }
+
+ // IP header
+ ip_header_size = GetIpHeaderSize(data, size);
+ if (ip_header_size == 0)
+ {
+ // IPv4 header analysis failure
+ return false;
+ }
+
+ ip = (IPV4_HEADER *)data;
+ data += ip_header_size;
+ size -= ip_header_size;
+
+ if (ip->Protocol != IP_PROTO_UDP)
+ {
+ // Not an UDP packet
+ return false;
+ }
+
+ // UDP header
+ if (size < sizeof(UDP_HEADER))
+ {
+ return false;
+ }
+ udp = (UDP_HEADER *)data;
+ data += sizeof(UDP_HEADER);
+ size -= sizeof(UDP_HEADER);
+
+ if (is_send)
+ {
+ // Detect whether it's a DHCP Request packet
+ if (Endian16(udp->DstPort) == 67)
+ {
+ Debug("IsDhcpPacketForSpecificMac: DHCP Request Packet is Detected.\n");
+ return true;
+ }
+ }
+ else if (is_recv)
+ {
+ // Detect whether it's a DHCP Response packet
+ if (Endian16(udp->SrcPort) == 67)
+ {
+ Debug("IsDhcpPacketForSpecificMac: DHCP Response Packet is Detected.\n");
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Adjust the MSS of the TCP in the IP packet (L2)
+bool AdjustTcpMssL2(UCHAR *src, UINT src_size, UINT mss, USHORT tag_vlan_tpid)
+{
+ MAC_HEADER *mac;
+ USHORT proto;
+ // Validate arguments
+ if (src == NULL || src_size == 0 || mss == 0)
+ {
+ return false;
+ }
+ if (tag_vlan_tpid == 0)
+ {
+ tag_vlan_tpid = MAC_PROTO_TAGVLAN;
+ }
+
+ if (src_size < sizeof(MAC_HEADER))
+ {
+ return false;
+ }
+
+ mac = (MAC_HEADER *)src;
+
+ src += sizeof(MAC_HEADER);
+ src_size -= sizeof(MAC_HEADER);
+
+ proto = Endian16(mac->Protocol);
+
+ if (proto == MAC_PROTO_IPV4 || proto == MAC_PROTO_IPV6)
+ {
+ // Ordinary IPv4 / IPv6 packet
+ return AdjustTcpMssL3(src, src_size, mss);
+ }
+ else if (proto == tag_vlan_tpid)
+ {
+ // IPv4 / IPv6 packets in the VLAN tag
+ if (src_size < 4)
+ {
+ return false;
+ }
+
+ src += 2;
+ src_size -= 2;
+
+ proto = READ_USHORT(src);
+
+ if (proto == MAC_PROTO_IPV4 || proto == MAC_PROTO_IPV6)
+ {
+ if (mss >= 5)
+ {
+ mss -= 4;
+
+ src += 2;
+ src_size -= 2;
+
+ return AdjustTcpMssL3(src, src_size, mss);
+ }
+ }
+ }
+
+ return false;
+}
+
+// Get an IP header size
+UINT GetIpHeaderSize(UCHAR *src, UINT src_size)
+{
+ UCHAR ip_ver;
+ TCP_HEADER *tcp = NULL;
+ UINT tcp_size = 0;
+ IPV4_HEADER *ip = NULL;
+ IPV6_HEADER *ip6 = NULL;
+ // Validate arguments
+ if (src == NULL || src_size == 0)
+ {
+ return 0;
+ }
+
+ // Get the IP version number
+ ip_ver = (src[0] >> 4) & 0x0f;
+
+ if (ip_ver == 4)
+ {
+ // IPv4
+ UINT ip_header_size;
+ if (src_size < sizeof(IPV4_HEADER))
+ {
+ // No IPv4 header
+ return 0;
+ }
+
+ ip = (IPV4_HEADER *)src;
+
+ ip_header_size = IPV4_GET_HEADER_LEN(ip) * 4;
+ if (ip_header_size < sizeof(IPV4_HEADER))
+ {
+ // Header size is invalid
+ return 0;
+ }
+
+ if (src_size < ip_header_size)
+ {
+ // No IPv4 header
+ return 0;
+ }
+
+ return ip_header_size;
+ }
+ else if (ip_ver == 6)
+ {
+ // IPv6
+ IPV6_HEADER_PACKET_INFO v6;
+
+ if (ParsePacketIPv6Header(&v6, src, src_size) == false)
+ {
+ // IPv6 analysis failure
+ return 0;
+ }
+
+ ip6 = v6.IPv6Header;
+ if (ip6 == NULL)
+ {
+ return 0;
+ }
+
+ if (src_size < v6.TotalHeaderSize)
+ {
+ // No header data
+ return 0;
+ }
+
+ return v6.TotalHeaderSize;
+ }
+ else
+ {
+ // Invalid
+ return 0;
+ }
+}
+
+// Adjust the MSS of TCP in the IP packet (L3)
+bool AdjustTcpMssL3(UCHAR *src, UINT src_size, UINT mss)
+{
+ UCHAR ip_ver;
+ TCP_HEADER *tcp = NULL;
+ UINT tcp_size = 0;
+ UINT tcp_header_size;
+ UCHAR *options;
+ UINT options_size;
+ IPV4_HEADER *ip = NULL;
+ IPV6_HEADER *ip6 = NULL;
+ // Validate arguments
+ if (src == NULL || src_size == 0 || mss == 0)
+ {
+ return false;
+ }
+
+ // Get the IP version number
+ ip_ver = (src[0] >> 4) & 0x0f;
+
+ if (ip_ver == 4)
+ {
+ UINT ip_header_size;
+ // IPv4
+ if (src_size < sizeof(IPV4_HEADER))
+ {
+ // No IPv4 header
+ return false;
+ }
+
+ ip = (IPV4_HEADER *)src;
+
+ if (ip->Protocol != IP_PROTO_TCP)
+ {
+ // Non-TCP
+ return false;
+ }
+
+ if (IPV4_GET_OFFSET(ip) != 0)
+ {
+ // It is the second or later packet of fragmented packet
+ return false;
+ }
+
+ if (IPV4_GET_FLAGS(ip) & 0x01)
+ {
+ // Fragmented packet
+ return false;
+ }
+
+ ip_header_size = IPV4_GET_HEADER_LEN(ip) * 4;
+ if (ip_header_size < sizeof(IPV4_HEADER))
+ {
+ // Header size is invalid
+ return false;
+ }
+
+ if (src_size < ip_header_size)
+ {
+ // No IPv4 header
+ return false;
+ }
+
+ src += ip_header_size;
+ src_size -= ip_header_size;
+
+ if (src_size < sizeof(TCP_HEADER))
+ {
+ // No TCP header
+ return false;
+ }
+
+ tcp = (TCP_HEADER *)src;
+ tcp_size = src_size;
+ }
+ else if (ip_ver == 6)
+ {
+ // IPv6
+ IPV6_HEADER_PACKET_INFO v6;
+
+ if (ParsePacketIPv6Header(&v6, src, src_size) == false)
+ {
+ // IPv6 analysis failure
+ return false;
+ }
+
+ ip6 = v6.IPv6Header;
+ if (ip6 == NULL)
+ {
+ return false;
+ }
+
+ if (v6.Protocol != IP_PROTO_TCP)
+ {
+ // Non-TCP
+ return false;
+ }
+
+ if (v6.IsFragment)
+ {
+ // It is the second or later packet of fragmented packet
+ return false;
+ }
+
+ if (v6.FragmentHeader != NULL)
+ {
+ if (IPV6_GET_FLAGS(v6.FragmentHeader) & IPV6_FRAGMENT_HEADER_FLAG_MORE_FRAGMENTS)
+ {
+ // Fragmented packet
+ return false;
+ }
+ }
+
+ tcp = (TCP_HEADER *)v6.Payload;
+ tcp_size = v6.PayloadSize;
+ }
+ else
+ {
+ // This isn't either IPv4, IPv6
+ return false;
+ }
+
+ // Processing of the TCP header
+ if (tcp == NULL || tcp_size < sizeof(TCP_HEADER))
+ {
+ return false;
+ }
+
+ tcp_header_size = TCP_GET_HEADER_SIZE(tcp) * 4;
+ if (tcp_header_size < sizeof(TCP_HEADER))
+ {
+ // TCP header size is invalid
+ return false;
+ }
+
+ if (tcp_size < tcp_header_size)
+ {
+ // Packet length shortage
+ return false;
+ }
+
+ if (((tcp->Flag & TCP_SYN) == false) ||
+ ((tcp->Flag & TCP_RST) ||
+ (tcp->Flag & TCP_PSH) ||
+ (tcp->Flag & TCP_URG)))
+ {
+ // Not a SYN packet
+ return false;
+ }
+
+ // Get the option field
+ options = ((UCHAR *)tcp) + sizeof(TCP_HEADER);
+ options_size = tcp_header_size - sizeof(TCP_HEADER);
+
+ if (ip6 != NULL)
+ {
+ // Reduce MSS by 20 since an IP header for IPv6 is 20 bytes larger than IPv4
+ if (mss >= 20)
+ {
+ mss -= 20;
+ }
+ }
+
+ // MSS should be at least 64
+ mss = MAX(mss, 64);
+
+ if (options_size >= 4 && options[0] == 0x02 && options[1] == 0x04)
+ {
+ // MSS option of TCP is added
+ USHORT current_mss = READ_USHORT(((UCHAR *)options) + 2);
+
+ if (current_mss <= mss)
+ {
+ // if the value of the MSS is smaller than the specified size
+ // from the beginning, it doesn't need to be rewritten
+ return false;
+ }
+ else
+ {
+ WRITE_USHORT(((UCHAR *)options) + 2, mss);
+
+ // Clear the checksum
+ tcp->Checksum = 0;
+
+ if (ip != NULL)
+ {
+ // Calculate the TCPv4 checksum
+ tcp->Checksum = CalcChecksumForIPv4(ip->SrcIP, ip->DstIP, IP_PROTO_TCP, tcp, tcp_size, 0);
+ }
+ else
+ {
+ // Calculate the TCPv6 checksum
+ tcp->Checksum = CalcChecksumForIPv6(&ip6->SrcAddress, &ip6->DestAddress,
+ IP_PROTO_TCP, tcp, tcp_size, 0);
+ }
+
+ return true;
+ }
+ }
+ else
+ {
+ // MSS option of TCP is not added
+ return false;
+ }
+}
+
+
+// Parse the DHCPv4 packet
+DHCPV4_DATA *ParseDHCPv4Data(PKT *pkt)
+{
+ DHCPV4_DATA *d;
+ UCHAR *data;
+ UINT size;
+ UINT magic_cookie = Endian32(DHCP_MAGIC_COOKIE);
+ bool ok = false;
+ DHCP_OPTION *o;
+ // Validate arguments
+ if (pkt == NULL)
+ {
+ return NULL;
+ }
+ if (pkt->TypeL3 != L3_IPV4 || pkt->TypeL4 != L4_UDP || pkt->TypeL7 != L7_DHCPV4)
+ {
+ return NULL;
+ }
+
+ d = ZeroMalloc(sizeof(DHCPV4_DATA));
+ d->Size = (UINT)(pkt->PacketSize - (((UCHAR *)pkt->L7.PointerL7) - ((UCHAR *)pkt->PacketData)));
+ d->Data = Clone(pkt->L7.PointerL7, d->Size);
+
+ if (d->Size < sizeof(DHCPV4_HEADER))
+ {
+ goto LABEL_ERROR;
+ }
+
+ // Header
+ d->Header = (DHCPV4_HEADER *)d->Data;
+
+ data = d->Data;
+ size = d->Size;
+
+ // Search for the Magic Cookie
+ ok = false;
+ while (size >= 5)
+ {
+ if (Cmp(data, &magic_cookie, 4) == 0)
+ {
+ // Found
+ data += 4;
+ size -= 4;
+ ok = true;
+ break;
+ }
+
+ data++;
+ size--;
+ }
+
+ if (ok == false)
+ {
+ // Magic Cookie not found
+ goto LABEL_ERROR;
+ }
+
+ // Parse the DHCP Options
+ d->OptionData = data;
+ d->OptionSize = size;
+
+ d->OptionList = ParseDhcpOptions(data, size);
+ if (d->OptionList == NULL)
+ {
+ // Parsing failure
+ goto LABEL_ERROR;
+ }
+
+ UINTToIP(&d->SrcIP, pkt->L3.IPv4Header->SrcIP);
+ UINTToIP(&d->DestIP, pkt->L3.IPv4Header->DstIP);
+
+ d->SrcPort = Endian16(pkt->L4.UDPHeader->SrcPort);
+ d->DestPort = Endian16(pkt->L4.UDPHeader->DstPort);
+
+ o = GetDhcpOption(d->OptionList, DHCP_ID_MESSAGE_TYPE);
+ if (o == NULL || o->Size != 1)
+ {
+ goto LABEL_ERROR;
+ }
+
+ d->OpCode = *((UCHAR *)o->Data);
+
+ d->ParsedOptionList = ParseDhcpOptionList(d->OptionData, d->OptionSize);
+
+ if (d->ParsedOptionList == NULL)
+ {
+ goto LABEL_ERROR;
+ }
+
+ if (d->ParsedOptionList->ServerAddress == 0)
+ {
+ d->ParsedOptionList->ServerAddress = d->Header->ServerIP;
+ }
+
+ d->ParsedOptionList->ClientAddress = d->Header->YourIP;
+
+ return d;
+
+LABEL_ERROR:
+ FreeDHCPv4Data(d);
+ return NULL;
+}
+
+// Release the DHCPv4 packet
+void FreeDHCPv4Data(DHCPV4_DATA *d)
+{
+ // Validate arguments
+ if (d == NULL)
+ {
+ return;
+ }
+
+ FreeDhcpOptions(d->OptionList);
+ Free(d->Data);
+
+ Free(d->ParsedOptionList);
+
+ Free(d);
+}
+
+// Embed a VLAN tag to the packet
+void VLanInsertTag(void **packet_data, UINT *packet_size, UINT vlan_id, UINT vlan_tpid)
+{
+ UINT dest_size;
+ UCHAR *dest_data;
+ UINT src_size;
+ UCHAR *src_data;
+ USHORT vlan_ushort = Endian16(((USHORT)vlan_id) & 0xFFF);
+ USHORT vlan_tpid_ushort;
+ // Validate arguments
+ if (packet_data == NULL || *packet_data == NULL || packet_size == NULL ||
+ *packet_size < 14 || vlan_id == 0)
+ {
+ return;
+ }
+ if (vlan_tpid == 0)
+ {
+ vlan_tpid = MAC_PROTO_TAGVLAN;
+ }
+
+ vlan_tpid_ushort = Endian16((USHORT)vlan_tpid);
+
+ src_size = *packet_size;
+ src_data = (UCHAR *)(*packet_data);
+
+ dest_size = src_size + 4;
+ dest_data = Malloc(dest_size);
+
+ Copy(&dest_data[12], &vlan_tpid_ushort, sizeof(USHORT));
+ Copy(&dest_data[14], &vlan_ushort, sizeof(USHORT));
+
+ Copy(&dest_data[0], &src_data[0], 12);
+ Copy(&dest_data[16], &src_data[12], src_size - 12);
+
+ *packet_size = dest_size;
+ *packet_data = dest_data;
+
+ Free(src_data);
+}
+
+// Remove the VLAN tag from the packet
+bool VLanRemoveTag(void **packet_data, UINT *packet_size, UINT vlan_id, UINT vlan_tpid)
+{
+ bool has_vlan_tag = false;
+ UCHAR *src_data;
+ UINT src_size;
+ USHORT vlan_tpid_ushort;
+ UCHAR *vlan_tpid_uchar;
+ // Validate arguments
+ if (packet_data == NULL || *packet_data == NULL || packet_size == NULL ||
+ *packet_size < 14)
+ {
+ return false;
+ }
+
+ if (vlan_tpid == 0)
+ {
+ vlan_tpid = MAC_PROTO_TAGVLAN;
+ }
+
+ vlan_tpid_ushort = Endian16((USHORT)vlan_tpid);
+ vlan_tpid_uchar = (UCHAR *)(&vlan_tpid_ushort);
+
+ src_data = (UCHAR *)(*packet_data);
+ src_size = *packet_size;
+
+ if (src_data[12] == vlan_tpid_uchar[0] && src_data[13] == vlan_tpid_uchar[1])
+ {
+ if (src_size >= 18)
+ {
+ USHORT vlan_ushort;
+
+ vlan_ushort = READ_USHORT(&src_data[14]);
+ vlan_ushort = vlan_ushort & 0xFFF;
+
+ if (vlan_id == 0 || (vlan_ushort == vlan_id))
+ {
+ UINT dest_size = src_size - 4;
+ UINT i;
+
+ for (i = 12;i < dest_size;i++)
+ {
+ src_data[i] = src_data[i + 4];
+ }
+
+ *packet_size = dest_size;
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// Sending of an ICMPv6 packet
+BUF *BuildICMPv6(IPV6_ADDR *src_ip, IPV6_ADDR *dest_ip, UCHAR hop_limit, UCHAR type, UCHAR code, void *data, UINT size, UINT id)
+{
+ ICMP_HEADER *icmp;
+ void *data_buf;
+ BUF *ret;
+ // Validate arguments
+ if (src_ip == NULL || dest_ip == NULL || data == NULL)
+ {
+ return NULL;
+ }
+
+ // Assembe the header
+ icmp = ZeroMalloc(sizeof(ICMP_HEADER) + size);
+ data_buf = ((UCHAR *)icmp) + sizeof(ICMP_HEADER);
+ Copy(data_buf, data, size);
+
+ icmp->Type = type;
+ icmp->Code = code;
+ icmp->Checksum = CalcChecksumForIPv6(src_ip, dest_ip, IP_PROTO_ICMPV6, icmp,
+ sizeof(ICMP_HEADER) + size, 0);
+
+ ret = BuildIPv6(dest_ip, src_ip, id, IP_PROTO_ICMPV6, hop_limit, icmp,
+ sizeof(ICMP_HEADER) + size);
+
+ Free(icmp);
+
+ return ret;
+}
+
+// Build an ICMPv6 Neighbor Solicitation packet
+BUF *BuildICMPv6NeighborSoliciation(IPV6_ADDR *src_ip, IPV6_ADDR *target_ip, UCHAR *my_mac_address, UINT id)
+{
+ ICMPV6_OPTION_LIST opt;
+ ICMPV6_OPTION_LINK_LAYER link;
+ ICMPV6_NEIGHBOR_SOLICIATION_HEADER header;
+ BUF *b;
+ BUF *b2;
+ BUF *ret;
+ // Validate arguments
+ if (src_ip == NULL || target_ip == NULL || my_mac_address == NULL)
+ {
+ return NULL;
+ }
+
+ Zero(&link, sizeof(link));
+ Copy(link.Address, my_mac_address, 6);
+
+ Zero(&opt, sizeof(opt));
+ opt.SourceLinkLayer = &link;
+
+ b = BuildICMPv6Options(&opt);
+
+ Zero(&header, sizeof(header));
+ Copy(&header.TargetAddress, target_ip, sizeof(IPV6_ADDR));
+
+ b2 = NewBuf();
+
+ WriteBuf(b2, &header, sizeof(header));
+ WriteBufBuf(b2, b);
+
+ ret = BuildICMPv6(src_ip, target_ip, 255,
+ ICMPV6_TYPE_NEIGHBOR_SOLICIATION, 0, b2->Buf, b2->Size, id);
+
+ FreeBuf(b);
+ FreeBuf(b2);
+
+ return ret;
+}
+
+// Get the next header number from the queue
+UCHAR IPv6GetNextHeaderFromQueue(QUEUE *q)
+{
+ UINT *p;
+ UCHAR v;
+ // Validate arguments
+ if (q == NULL)
+ {
+ return IPV6_HEADER_NONE;
+ }
+
+ p = (UINT *)GetNext(q);
+ v = (UCHAR)(*p);
+ Free(p);
+
+ return v;
+}
+
+// Add an IPv6 extension header option (variable length)
+void BuildAndAddIPv6PacketOptionHeader(BUF *b, IPV6_OPTION_HEADER *opt, UCHAR next_header, UINT size)
+{
+ IPV6_OPTION_HEADER *h;
+ UINT total_size;
+ // Validate arguments
+ if (b == NULL || opt == NULL)
+ {
+ return;
+ }
+
+ total_size = size;
+ if ((total_size % 8) != 0)
+ {
+ total_size = ((total_size / 8) + 1) * 8;
+ }
+
+ h = ZeroMalloc(total_size);
+ Copy(h, opt, size);
+ h->Size = (total_size / 8) - 1;
+ h->NextHeader = next_header;
+
+ WriteBuf(b, h, total_size);
+
+ Free(h);
+}
+
+// Build an IPv6 packet
+BUF *BuildIPv6(IPV6_ADDR *dest_ip, IPV6_ADDR *src_ip, UINT id, UCHAR protocol, UCHAR hop_limit, void *data,
+ UINT size)
+{
+ IPV6_HEADER_PACKET_INFO info;
+ IPV6_HEADER ip_header;
+ BUF *buf;
+ UINT size_for_headers;
+ // Validate arguments
+ if (dest_ip == NULL || src_ip == NULL || data == NULL)
+ {
+ return NULL;
+ }
+ if (hop_limit == 0)
+ {
+ hop_limit = 255;
+ }
+
+ // IPv6 header
+ Zero(&ip_header, sizeof(ip_header));
+ IPV6_SET_VERSION(&ip_header, 6);
+ ip_header.HopLimit = hop_limit;
+ Copy(&ip_header.SrcAddress, src_ip, sizeof(IPV6_ADDR));
+ Copy(&ip_header.DestAddress, dest_ip, sizeof(IPV6_ADDR));
+
+ // Arrangement of the packet header information
+ Zero(&info, sizeof(info));
+ info.IPv6Header = &ip_header;
+ info.Protocol = protocol;
+ info.Payload = data;
+ info.PayloadSize = size;
+
+ buf = BuildIPv6PacketHeader(&info, &size_for_headers);
+ if (buf == NULL)
+ {
+ return NULL;
+ }
+
+ return buf;
+}
+
+// Build the IPv6 packet header section
+BUF *BuildIPv6PacketHeader(IPV6_HEADER_PACKET_INFO *info, UINT *bytes_before_payload)
+{
+ BUF *b;
+ QUEUE *q;
+ UINT bbp = 0;
+ // Validate arguments
+ if (info == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ q = NewQueueFast();
+
+ // Create the list of options headers
+ if (info->HopHeader != NULL)
+ {
+ InsertQueueInt(q, IPV6_HEADER_HOP);
+ }
+ if (info->EndPointHeader != NULL)
+ {
+ InsertQueueInt(q, IPV6_HEADER_ENDPOINT);
+ }
+ if (info->RoutingHeader != NULL)
+ {
+ InsertQueueInt(q, IPV6_HEADER_ROUTING);
+ }
+ if (info->FragmentHeader != NULL)
+ {
+ InsertQueueInt(q, IPV6_HEADER_FRAGMENT);
+ }
+ InsertQueueInt(q, info->Protocol);
+
+ // IPv6 header
+ info->IPv6Header->NextHeader = IPv6GetNextHeaderFromQueue(q);
+ WriteBuf(b, info->IPv6Header, sizeof(IPV6_HEADER));
+
+ // Hop-by-hop option header
+ if (info->HopHeader != NULL)
+ {
+ BuildAndAddIPv6PacketOptionHeader(b, info->HopHeader,
+ IPv6GetNextHeaderFromQueue(q), info->HopHeaderSize);
+ }
+
+ // End point option header
+ if (info->EndPointHeader != NULL)
+ {
+ BuildAndAddIPv6PacketOptionHeader(b, info->EndPointHeader,
+ IPv6GetNextHeaderFromQueue(q), info->EndPointHeaderSize);
+ }
+
+ // Routing header
+ if (info->RoutingHeader != NULL)
+ {
+ BuildAndAddIPv6PacketOptionHeader(b, info->RoutingHeader,
+ IPv6GetNextHeaderFromQueue(q), info->RoutingHeaderSize);
+ }
+
+ // Fragment header
+ if (info->FragmentHeader != NULL)
+ {
+ info->FragmentHeader->NextHeader = IPv6GetNextHeaderFromQueue(q);
+ WriteBuf(b, info->FragmentHeader, sizeof(IPV6_FRAGMENT_HEADER));
+ }
+
+ bbp = b->Size;
+ if (info->FragmentHeader == NULL)
+ {
+ bbp += sizeof(IPV6_FRAGMENT_HEADER);
+ }
+
+ // Payload
+ if (info->Protocol != IPV6_HEADER_NONE)
+ {
+ WriteBuf(b, info->Payload, info->PayloadSize);
+ }
+
+ ReleaseQueue(q);
+
+ SeekBuf(b, 0, 0);
+
+ // Payload length
+ ((IPV6_HEADER *)b->Buf)->PayloadLength = Endian16(b->Size - (USHORT)sizeof(IPV6_HEADER));
+
+ if (bytes_before_payload != NULL)
+ {
+ // Calculate the length just before the payload
+ // (by assuming fragment header is always included)
+ *bytes_before_payload = bbp;
+ }
+
+ return b;
+}
+
+// Build the option values of an ICMPv6 packet
+void BuildICMPv6OptionValue(BUF *b, UCHAR type, void *header_pointer, UINT total_size)
+{
+ UINT packet_size;
+ UCHAR *packet;
+ ICMPV6_OPTION *opt;
+ // Validate arguments
+ if (b == NULL || header_pointer == NULL)
+ {
+ return;
+ }
+
+ packet_size = ((total_size + 7) / 8) * 8;
+ packet = ZeroMalloc(packet_size);
+
+ Copy(packet, header_pointer, total_size);
+ opt = (ICMPV6_OPTION *)packet;
+ opt->Length = (UCHAR)(packet_size / 8);
+ opt->Type = type;
+
+ WriteBuf(b, packet, packet_size);
+
+ Free(packet);
+}
+
+// Build the options of the ICMPv6 packet
+BUF *BuildICMPv6Options(ICMPV6_OPTION_LIST *o)
+{
+ BUF *b;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+
+ if (o->SourceLinkLayer != NULL)
+ {
+ BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_SOURCE_LINK_LAYER, o->SourceLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER));
+ }
+ if (o->TargetLinkLayer != NULL)
+ {
+ BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_TARGET_LINK_LAYER, o->TargetLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER));
+ }
+ if (o->Prefix != NULL)
+ {
+ BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_PREFIX, o->Prefix, sizeof(ICMPV6_OPTION_PREFIX));
+ }
+ if (o->Mtu != NULL)
+ {
+ BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_MTU, o->Mtu, sizeof(ICMPV6_OPTION_MTU));
+ }
+
+ SeekBuf(b, 0, 0);
+
+ return b;
+}
+
+// Checksum calculation (IPv4)
+USHORT CalcChecksumForIPv4(UINT src_ip, UINT dst_ip, UCHAR protocol, void *data, UINT size, UINT real_size)
+{
+ UCHAR *tmp;
+ UINT tmp_size;
+ IPV4_PSEUDO_HEADER *ph;
+ USHORT ret;
+ bool use_free = false;
+ UCHAR tmp_buffer[1600];
+ // Validate arguments
+ if (data == NULL && size != 0)
+ {
+ return 0;
+ }
+
+ if (real_size == 0)
+ {
+ real_size = size;
+ }
+
+ if (real_size == INFINITE)
+ {
+ real_size = 0;
+ }
+
+ tmp_size = size + sizeof(IPV4_PSEUDO_HEADER);
+
+ if (tmp_size > sizeof(tmp_buffer))
+ {
+ tmp = Malloc(tmp_size);
+
+ use_free = true;
+ }
+ else
+ {
+ tmp = tmp_buffer;
+ }
+
+ ph = (IPV4_PSEUDO_HEADER *)tmp;
+ ph->SrcIP = src_ip;
+ ph->DstIP = dst_ip;
+ ph->PacketLength = Endian16(real_size);
+ ph->Protocol = protocol;
+ ph->Reserved = 0;
+
+ if (size >= 1)
+ {
+ Copy(((UCHAR *)tmp) + sizeof(IPV4_PSEUDO_HEADER), data, size);
+ }
+
+ ret = IpChecksum(tmp, tmp_size);
+
+ if (use_free)
+ {
+ Free(tmp);
+ }
+
+ return ret;
+}
+
+// Checksum calculation (IPv6)
+USHORT CalcChecksumForIPv6(IPV6_ADDR *src_ip, IPV6_ADDR *dest_ip, UCHAR protocol, void *data, UINT size, UINT real_size)
+{
+ UCHAR *tmp;
+ UINT tmp_size;
+ IPV6_PSEUDO_HEADER *ph;
+ USHORT ret;
+ bool use_free = false;
+ UCHAR tmp_buffer[256];
+ // Validate arguments
+ if (data == NULL && size != 0)
+ {
+ return 0;
+ }
+
+ if (real_size == 0)
+ {
+ real_size = size;
+ }
+
+ if (real_size == INFINITE)
+ {
+ real_size = 0;
+ }
+
+ tmp_size = size + sizeof(IPV6_PSEUDO_HEADER);
+
+ if (tmp_size > sizeof(tmp_buffer))
+ {
+ tmp = Malloc(tmp_size);
+
+ use_free = true;
+ }
+ else
+ {
+ tmp = tmp_buffer;
+ }
+
+ ph = (IPV6_PSEUDO_HEADER *)tmp;
+ Zero(ph, sizeof(IPV6_PSEUDO_HEADER));
+ Copy(&ph->SrcAddress, src_ip, sizeof(IPV6_ADDR));
+ Copy(&ph->DestAddress, dest_ip, sizeof(IPV6_ADDR));
+ ph->UpperLayerPacketSize = Endian32(real_size);
+ ph->NextHeader = protocol;
+
+ Copy(((UCHAR *)tmp) + sizeof(IPV6_PSEUDO_HEADER), data, size);
+
+ ret = IpChecksum(tmp, tmp_size);
+
+ if (use_free)
+ {
+ Free(tmp);
+ }
+
+ return ret;
+}
+
+// Release the cloned packet
+void FreeClonePacket(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ Free(p->IPv6HeaderPacketInfo.IPv6Header);
+ Free(p->IPv6HeaderPacketInfo.HopHeader);
+ Free(p->IPv6HeaderPacketInfo.EndPointHeader);
+ Free(p->IPv6HeaderPacketInfo.RoutingHeader);
+ Free(p->IPv6HeaderPacketInfo.FragmentHeader);
+ Free(p->IPv6HeaderPacketInfo.Payload);
+ Free(p->ICMPv6HeaderPacketInfo.Data);
+ Free(p->ICMPv6HeaderPacketInfo.EchoData);
+ Free(p->ICMPv6HeaderPacketInfo.Headers.HeaderPointer);
+ FreeCloneICMPv6Options(&p->ICMPv6HeaderPacketInfo.OptionList);
+ Free(p->L3.PointerL3);
+ Free(p->L4.PointerL4);
+ Free(p->L7.PointerL7);
+ Free(p->PacketData);
+ Free(p->MacHeader);
+ Free(p->HttpLog);
+ Free(p);
+}
+
+// Copy the packet header
+PKT *ClonePacket(PKT *p, bool copy_data)
+{
+ PKT *ret;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMallocFast(sizeof(PKT));
+ ret->PacketSize = p->PacketSize;
+
+ // Copy of the MAC header
+ ret->MacHeader = MallocFast(sizeof(MAC_HEADER));
+ Copy(ret->MacHeader, p->MacHeader, sizeof(MAC_HEADER));
+
+ // Copy of the MAC flag
+ ret->BroadcastPacket = p->BroadcastPacket;
+ ret->InvalidSourcePacket = p->InvalidSourcePacket;
+
+ // Copy of the IPv6 related structure
+ Copy(&ret->IPv6HeaderPacketInfo, &p->IPv6HeaderPacketInfo, sizeof(IPV6_HEADER_PACKET_INFO));
+ Copy(&ret->ICMPv6HeaderPacketInfo, &p->ICMPv6HeaderPacketInfo, sizeof(ICMPV6_HEADER_INFO));
+
+ // Layer 3
+ ret->TypeL3 = p->TypeL3;
+ switch (ret->TypeL3)
+ {
+ case L3_ARPV4:
+ // ARP packet
+ ret->L3.ARPv4Header = MallocFast(sizeof(ARPV4_HEADER));
+ Copy(ret->L3.ARPv4Header, p->L3.ARPv4Header, sizeof(ARPV4_HEADER));
+ break;
+
+ case L3_IPV4:
+ // IPv4 packet
+ ret->L3.IPv4Header = MallocFast(sizeof(IPV4_HEADER));
+ Copy(ret->L3.IPv4Header, p->L3.IPv4Header, sizeof(IPV4_HEADER));
+ break;
+
+ case L3_IPV6:
+ // IPv6 packet
+ ret->L3.IPv6Header = MallocFast(sizeof(IPV6_HEADER));
+ Copy(ret->L3.IPv6Header, p->L3.IPv6Header, sizeof(IPV6_HEADER));
+
+ ret->IPv6HeaderPacketInfo.IPv6Header = Clone(p->IPv6HeaderPacketInfo.IPv6Header,
+ sizeof(IPV6_HEADER));
+
+ ret->IPv6HeaderPacketInfo.HopHeader = Clone(p->IPv6HeaderPacketInfo.HopHeader,
+ sizeof(IPV6_OPTION_HEADER));
+
+ ret->IPv6HeaderPacketInfo.EndPointHeader = Clone(p->IPv6HeaderPacketInfo.EndPointHeader,
+ sizeof(IPV6_OPTION_HEADER));
+
+ ret->IPv6HeaderPacketInfo.RoutingHeader = Clone(p->IPv6HeaderPacketInfo.RoutingHeader,
+ sizeof(IPV6_OPTION_HEADER));
+
+ ret->IPv6HeaderPacketInfo.FragmentHeader = Clone(p->IPv6HeaderPacketInfo.FragmentHeader,
+ sizeof(IPV6_FRAGMENT_HEADER));
+
+ ret->IPv6HeaderPacketInfo.Payload = Clone(p->IPv6HeaderPacketInfo.Payload,
+ p->IPv6HeaderPacketInfo.PayloadSize);
+ break;
+ }
+
+ // Layer 4
+ ret->TypeL4 = p->TypeL4;
+ switch (ret->TypeL4)
+ {
+ case L4_ICMPV4:
+ // ICMPv4 packet
+ ret->L4.ICMPHeader = MallocFast(sizeof(ICMP_HEADER));
+ Copy(ret->L4.ICMPHeader, p->L4.ICMPHeader, sizeof(ICMP_HEADER));
+ break;
+
+ case L4_ICMPV6:
+ // ICMPv6 packet
+ ret->L4.ICMPHeader = MallocFast(sizeof(ICMP_HEADER));
+ Copy(ret->L4.ICMPHeader, p->L4.ICMPHeader, sizeof(ICMP_HEADER));
+
+ ret->ICMPv6HeaderPacketInfo.Data = Clone(p->ICMPv6HeaderPacketInfo.Data,
+ p->ICMPv6HeaderPacketInfo.DataSize);
+
+ ret->ICMPv6HeaderPacketInfo.EchoData = Clone(p->ICMPv6HeaderPacketInfo.EchoData,
+ p->ICMPv6HeaderPacketInfo.EchoDataSize);
+
+ switch (ret->ICMPv6HeaderPacketInfo.Type)
+ {
+ case ICMPV6_TYPE_ECHO_REQUEST:
+ case ICMPV6_TYPE_ECHO_RESPONSE:
+ break;
+
+ case ICMPV6_TYPE_ROUTER_SOLICIATION:
+ ret->ICMPv6HeaderPacketInfo.Headers.RouterSoliciationHeader =
+ Clone(p->ICMPv6HeaderPacketInfo.Headers.RouterSoliciationHeader,
+ sizeof(ICMPV6_ROUTER_SOLICIATION_HEADER));
+ break;
+
+ case ICMPV6_TYPE_ROUTER_ADVERTISEMENT:
+ ret->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader =
+ Clone(p->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader,
+ sizeof(ICMPV6_ROUTER_ADVERTISEMENT_HEADER));
+ break;
+
+ case ICMPV6_TYPE_NEIGHBOR_SOLICIATION:
+ ret->ICMPv6HeaderPacketInfo.Headers.NeighborSoliciationHeader =
+ Clone(p->ICMPv6HeaderPacketInfo.Headers.NeighborSoliciationHeader,
+ sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER));
+ break;
+
+ case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT:
+ ret->ICMPv6HeaderPacketInfo.Headers.NeighborAdvertisementHeader =
+ Clone(p->ICMPv6HeaderPacketInfo.Headers.NeighborAdvertisementHeader,
+ sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER));
+ break;
+ }
+
+ CloneICMPv6Options(&ret->ICMPv6HeaderPacketInfo.OptionList,
+ &p->ICMPv6HeaderPacketInfo.OptionList);
+ break;
+
+ case L4_TCP:
+ // TCP packet
+ ret->L4.TCPHeader = MallocFast(sizeof(TCP_HEADER));
+ Copy(ret->L4.TCPHeader, p->L4.TCPHeader, sizeof(TCP_HEADER));
+ break;
+
+ case L4_UDP:
+ // UDP packet
+ ret->L4.UDPHeader = MallocFast(sizeof(UDP_HEADER));
+ Copy(ret->L4.UDPHeader, p->L4.UDPHeader, sizeof(UDP_HEADER));
+ break;
+ }
+
+ // Layer 7
+ ret->TypeL7 = p->TypeL7;
+ switch (ret->TypeL7)
+ {
+ case L7_DHCPV4:
+ // DHCP packet
+ ret->L7.DHCPv4Header = MallocFast(sizeof(DHCPV4_HEADER));
+ Copy(ret->L7.DHCPv4Header, p->L7.DHCPv4Header, sizeof(DHCPV4_HEADER));
+ break;
+
+ case L7_IKECONN:
+ // IKE packet
+ ret->L7.IkeHeader = MallocFast(sizeof(IKE_HEADER));
+ Copy(ret->L7.IkeHeader, p->L7.IkeHeader, sizeof(IKE_HEADER));
+ break;
+ }
+
+ // Address data
+ ret->MacAddressSrc = ret->MacHeader->SrcAddress;
+ ret->MacAddressDest = ret->MacHeader->DestAddress;
+
+ if (copy_data)
+ {
+ // Copy also the packet body
+ ret->PacketData = MallocFast(p->PacketSize);
+ Copy(ret->PacketData, p->PacketData, p->PacketSize);
+ }
+
+ if (p->HttpLog != NULL)
+ {
+ ret->HttpLog = Clone(p->HttpLog, sizeof(HTTPLOG));
+ }
+
+ return ret;
+}
+
+// Parse the contents of the packet
+PKT *ParsePacket(UCHAR *buf, UINT size)
+{
+ return ParsePacketEx(buf, size, false);
+}
+PKT *ParsePacketEx(UCHAR *buf, UINT size, bool no_l3)
+{
+ return ParsePacketEx2(buf, size, no_l3, 0);
+}
+PKT *ParsePacketEx2(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id)
+{
+ return ParsePacketEx3(buf, size, no_l3, vlan_type_id, true);
+}
+PKT *ParsePacketEx3(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address)
+{
+ return ParsePacketEx4(buf, size, no_l3, vlan_type_id, bridge_id_as_mac_address, false, false);
+}
+PKT *ParsePacketEx4(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address, bool no_http, bool correct_checksum)
+{
+ PKT *p;
+ USHORT vlan_type_id_16;
+ // Validate arguments
+ if (buf == NULL || size == 0)
+ {
+ return NULL;
+ }
+
+ if (vlan_type_id == 0)
+ {
+ vlan_type_id = MAC_PROTO_TAGVLAN;
+ }
+
+ vlan_type_id_16 = Endian16((USHORT)vlan_type_id);
+
+ p = ZeroMallocFast(sizeof(PKT));
+
+ p->VlanTypeID = vlan_type_id;
+
+ // If there is garbage after the payload in IPv4 and IPv6 packets, eliminate it
+ if (size >= 24)
+ {
+ if (buf[12] == 0x08 && buf[13] == 0x00)
+ {
+ USHORT ip_total_size2 = READ_USHORT(&buf[16]);
+ UINT mac_packet_size;
+
+ if (ip_total_size2 >= 1)
+ {
+ mac_packet_size = (UINT)ip_total_size2 + 14;
+
+ if (size > mac_packet_size)
+ {
+ size = mac_packet_size;
+ }
+ }
+ }
+ else if (buf[12] == 0x86 && buf[13] == 0xdd)
+ {
+ USHORT ip_payload_size_2 = READ_USHORT(&buf[18]);
+ UINT mac_packet_size;
+
+ if (ip_payload_size_2 >= 1)
+ {
+ mac_packet_size = (UINT)ip_payload_size_2 + 14 + 40;
+
+ if (size > mac_packet_size)
+ {
+ size = mac_packet_size;
+ }
+ }
+ }
+ else if (buf[12] == ((UCHAR *)&vlan_type_id_16)[0] && buf[13] == ((UCHAR *)&vlan_type_id_16)[1])
+ {
+ if (buf[16] == 0x08 && buf[17] == 0x00)
+ {
+ USHORT ip_total_size2 = READ_USHORT(&buf[20]);
+ UINT mac_packet_size;
+
+ if (ip_total_size2 >= 1)
+ {
+ mac_packet_size = (UINT)ip_total_size2 + 14 + 4;
+
+ if (size > mac_packet_size)
+ {
+ size = mac_packet_size;
+ }
+ }
+ }
+ else if (buf[16] == 0x86 && buf[17] == 0xdd)
+ {
+ USHORT ip_payload_size_2 = READ_USHORT(&buf[22]);
+ UINT mac_packet_size;
+
+ if (ip_payload_size_2 >= 1)
+ {
+ mac_packet_size = (UINT)ip_payload_size_2 + 14 + 40 + 4;
+
+ if (size > mac_packet_size)
+ {
+ size = mac_packet_size;
+ }
+ }
+ }
+ }
+ }
+
+ // Do parse
+ if (ParsePacketL2Ex(p, buf, size, no_l3) == false)
+ {
+ // Parsing failure
+ FreePacket(p);
+ return NULL;
+ }
+
+ p->PacketData = buf;
+ p->PacketSize = size;
+
+ p->MacAddressSrc = p->MacHeader->SrcAddress;
+ p->MacAddressDest = p->MacHeader->DestAddress;
+
+ if (bridge_id_as_mac_address)
+ {
+ if (p->TypeL3 == L3_BPDU)
+ {
+ if (p->L3.BpduHeader != NULL)
+ {
+ p->MacAddressSrc = p->L3.BpduHeader->BridgeMacAddress;
+ }
+ }
+ }
+
+ if (no_http == false)
+ {
+ USHORT port_raw = Endian16(80);
+
+ // Analyze if the packet is a part of HTTP
+ if ((p->TypeL3 == L3_IPV4 || p->TypeL3 == L3_IPV6) && p->TypeL4 == L4_TCP)
+ {
+ TCP_HEADER *tcp = p->L4.TCPHeader;
+ if (tcp->DstPort == port_raw)
+ {
+ if (tcp != NULL && (!((tcp->Flag & TCP_SYN) || (tcp->Flag & TCP_RST) || (tcp->Flag & TCP_FIN))))
+ {
+ if (p->PayloadSize >= 1)
+ {
+ p->HttpLog = ParseHttpAccessLog(p);
+ }
+ }
+ }
+ }
+ }
+
+ if (p->TypeL3 == L3_IPV4 && p->TypeL4 == L4_UDP && p->TypeL7 == L7_DHCPV4)
+ {
+ // Get the DHCP opcode
+ DHCPV4_DATA *d = ParseDHCPv4Data(p);
+
+ if (d != NULL)
+ {
+ p->DhcpOpCode = d->OpCode;
+
+ FreeDHCPv4Data(d);
+ }
+ }
+
+ if (correct_checksum)
+ {
+ // Correct the checksum of the UDP, IP and TCP
+ CorrectChecksum(p);
+ }
+
+ // Parsing success
+ return p;
+}
+
+// Correct the checksum (store the correct value in the header by recalculating the checksum which is by off-load processing)
+void CorrectChecksum(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (p->TypeL3 == L3_IPV4)
+ {
+ IPV4_HEADER *v4 = p->L3.IPv4Header;
+
+ if (v4 != NULL)
+ {
+ if (v4->Checksum == 0x0000)
+ {
+ v4->Checksum = IpChecksum(v4, IPV4_GET_HEADER_LEN(v4) * 4);
+ }
+
+ if (p->TypeL4 == L4_TCP)
+ {
+ // Recalculate the TCP checksum
+ if (IPV4_GET_OFFSET(v4) == 0 && (IPV4_GET_FLAGS(v4) & 0x01) == 0)
+ {
+ // TCP checksuming doesn't target fragmented IP packets
+ TCP_HEADER *tcp = p->L4.TCPHeader;
+
+ if (tcp != NULL)
+ {
+ USHORT tcp_offloading_checksum1 = CalcChecksumForIPv4(v4->SrcIP, v4->DstIP, IP_PROTO_TCP, NULL, 0, p->IPv4PayloadSize);
+ USHORT tcp_offloading_checksum2 = ~tcp_offloading_checksum1;
+
+ if (tcp->Checksum == 0 || tcp->Checksum == tcp_offloading_checksum1 || tcp->Checksum == tcp_offloading_checksum2)
+ {
+ tcp->Checksum = 0;
+ tcp->Checksum = CalcChecksumForIPv4(v4->SrcIP, v4->DstIP, IP_PROTO_TCP, tcp, p->IPv4PayloadSize, 0);
+ }
+ }
+ }
+ }
+
+ if (p->TypeL4 == L4_UDP)
+ {
+ // Recalculation of the UDP checksum
+ if (IPV4_GET_OFFSET(v4) == 0 || (IPV4_GET_FLAGS(v4) & 0x01) == 0)
+ {
+ // If it is not divided, or it is divided but it is the first fragment of the UDP packet
+ UDP_HEADER *udp = p->L4.UDPHeader;
+
+ if (udp != NULL && udp->Checksum != 0)
+ {
+ USHORT udp_len = Endian16(udp->PacketLength);
+ USHORT udp_offloading_checksum1 = CalcChecksumForIPv4(v4->SrcIP, v4->DstIP, IP_PROTO_UDP, NULL, 0, udp_len);
+ USHORT udp_offloading_checksum2 = ~udp_offloading_checksum1;
+
+ if (udp->Checksum == udp_offloading_checksum1 || udp->Checksum == udp_offloading_checksum2)
+ {
+ udp->Checksum = 0;
+
+ if ((IPV4_GET_FLAGS(v4) & 0x01) == 0)
+ {
+ // Calculate the checksum correctly based on the data in case of a non-fragmented packet
+ udp->Checksum = CalcChecksumForIPv4(v4->SrcIP, v4->DstIP, IP_PROTO_UDP, udp, udp_len, 0);
+ }
+ else
+ {
+ // In case of the first fragment of the packet, set the checksum to 0
+ // because there isn't entire data of the packet
+ udp->Checksum = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (p->TypeL3 == L3_IPV6)
+ {
+ IPV6_HEADER *v6 = p->L3.IPv6Header;
+ IPV6_HEADER_PACKET_INFO *v6info = &p->IPv6HeaderPacketInfo;
+
+ if (v6 != NULL)
+ {
+ if (p->TypeL4 == L4_TCP)
+ {
+ // Recalculate the TCP checksum
+ if (v6info->IsFragment == false)
+ {
+ if (v6info->FragmentHeader == NULL || ((IPV6_GET_FLAGS(v6info->FragmentHeader) & IPV6_FRAGMENT_HEADER_FLAG_MORE_FRAGMENTS) == 0))
+ {
+ // TCP checksuming doesn't target fragmented packets
+ TCP_HEADER *tcp = p->L4.TCPHeader;
+
+ if (tcp != NULL)
+ {
+ UINT tcp_header_size = TCP_GET_HEADER_SIZE(tcp) * 4;
+ USHORT tcp_offloading_checksum1 = CalcChecksumForIPv6(&v6->SrcAddress, &v6->DestAddress, IP_PROTO_TCP, NULL, 0, v6info->PayloadSize);
+ USHORT tcp_offloading_checksum2 = ~tcp_offloading_checksum1;
+
+ if (tcp->Checksum == 0 || tcp->Checksum == tcp_offloading_checksum1 || tcp->Checksum == tcp_offloading_checksum2)
+ {
+ tcp->Checksum = 0;
+ tcp->Checksum = CalcChecksumForIPv6(&v6->SrcAddress, &v6->DestAddress, IP_PROTO_TCP, tcp, v6info->PayloadSize, 0);
+ }
+ }
+ }
+ }
+ }
+ else if (p->TypeL4 == L4_UDP)
+ {
+ // Recalculation of the UDP checksum
+ if (v6info->IsFragment == false)
+ {
+ UDP_HEADER *udp = p->L4.UDPHeader;
+
+ if (udp != NULL && udp->Checksum != 0)
+ {
+ USHORT udp_len = Endian16(udp->PacketLength);
+ USHORT udp_offloading_checksum1 = CalcChecksumForIPv6(&v6->SrcAddress, &v6->DestAddress, IP_PROTO_UDP, NULL, 0, udp_len);
+ USHORT udp_offloading_checksum2 = ~udp_offloading_checksum1;
+
+ if (udp->Checksum == 0 || udp->Checksum == udp_offloading_checksum1 || udp->Checksum == udp_offloading_checksum2)
+ {
+ udp->Checksum = 0;
+
+ if (v6info->FragmentHeader == NULL || ((IPV6_GET_FLAGS(v6info->FragmentHeader) & IPV6_FRAGMENT_HEADER_FLAG_MORE_FRAGMENTS) == 0))
+ {
+ // If the packet is not fragmented, recalculate the checksum
+ udp->Checksum = CalcChecksumForIPv6(&v6->SrcAddress, &v6->DestAddress, IP_PROTO_UDP, udp, udp_len, 0);
+ }
+ else
+ {
+ // Don't do (can't do) anything in the case of fragmented packet
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+// Parse the HTTP access log
+HTTPLOG *ParseHttpAccessLog(PKT *pkt)
+{
+ HTTPLOG h;
+ UCHAR *buf;
+ UINT size;
+ BUF *b;
+ char *line1;
+ bool ok = false;
+ // Validate arguments
+ if (pkt == NULL)
+ {
+ return NULL;
+ }
+
+ buf = pkt->Payload;
+ size = pkt->PayloadSize;
+
+ if (size <= 5)
+ {
+ return NULL;
+ }
+
+ // Check whether it starts with the HTTP-specific string
+ if (CmpCaseIgnore(buf, "GET ", 4) != 0 &&
+ CmpCaseIgnore(buf, "HEAD ", 5) != 0 &&
+ CmpCaseIgnore(buf, "POST ", 5) != 0)
+ {
+ return NULL;
+ }
+
+ Zero(&h, sizeof(h));
+
+ h.Port = Endian16(pkt->L4.TCPHeader->DstPort);
+
+ b = NewBuf();
+ WriteBuf(b, buf, size);
+ SeekBuf(b, 0, 0);
+
+ line1 = CfgReadNextLine(b);
+
+ if (line1 != NULL)
+ {
+ TOKEN_LIST *tokens = ParseToken(line1, " \t");
+ if (tokens != NULL)
+ {
+ if (tokens->NumTokens == 3)
+ {
+ StrCpy(h.Method, sizeof(h.Hostname), tokens->Token[0]);
+ Trim(h.Method);
+
+ StrCpy(h.Path, sizeof(h.Path), tokens->Token[1]);
+ Trim(h.Path);
+
+ StrCpy(h.Protocol, sizeof(h.Protocol), tokens->Token[2]);
+ Trim(h.Protocol);
+
+ StrUpper(h.Method);
+
+ while (true)
+ {
+ char *line = CfgReadNextLine(b);
+ UINT i;
+
+ if (line == NULL)
+ {
+ break;
+ }
+
+ i = SearchStr(line, ":", 0);
+ if (i != INFINITE && i < (MAX_SIZE / 2))
+ {
+ char name[MAX_SIZE];
+ char value[MAX_SIZE];
+
+ StrCpy(name, sizeof(name), line);
+ name[i] = 0;
+ Trim(name);
+
+ StrCpy(value, sizeof(value), line + i + 1);
+ Trim(value);
+
+ if (StrCmpi(name, "host") == 0)
+ {
+ StrCpy(h.Hostname, sizeof(h.Hostname), value);
+ }
+ else if (StrCmpi(name, "referer") == 0)
+ {
+ StrCpy(h.Referer, sizeof(h.Referer), value);
+ }
+ else if (StrCmpi(name, "user-agent") == 0)
+ {
+ StrCpy(h.UserAgent, sizeof(h.UserAgent), value);
+ }
+ }
+
+ Free(line);
+ }
+
+ if (IsEmptyStr(h.Hostname) == false)
+ {
+ ok = true;
+ }
+ }
+ FreeToken(tokens);
+ }
+ }
+
+ Free(line1);
+ FreeBuf(b);
+
+ if (ok)
+ {
+ return Clone(&h, sizeof(h));
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+
+// Layer-2 parsing
+bool ParsePacketL2(PKT *p, UCHAR *buf, UINT size)
+{
+ return ParsePacketL2Ex(p, buf, size, false);
+}
+bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3)
+{
+ UINT i;
+ bool b1, b2;
+ USHORT type_id_16;
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(MAC_HEADER))
+ {
+ return false;
+ }
+
+ // MAC header
+ p->MacHeader = (MAC_HEADER *)buf;
+
+ buf += sizeof(MAC_HEADER);
+ size -= sizeof(MAC_HEADER);
+
+ // Analysis of the MAC header
+ p->BroadcastPacket = true;
+ b1 = true;
+ b2 = true;
+ for (i = 0;i < 6;i++)
+ {
+ if (p->MacHeader->DestAddress[i] != 0xff)
+ {
+ p->BroadcastPacket = false;
+ }
+ if (p->MacHeader->SrcAddress[i] != 0xff)
+ {
+ b1 = false;
+ }
+ if (p->MacHeader->SrcAddress[i] != 0x00)
+ {
+ b2 = false;
+ }
+ }
+ if (b1 || b2 || (Cmp(p->MacHeader->SrcAddress, p->MacHeader->DestAddress, 6) == 0))
+ {
+ p->InvalidSourcePacket = true;
+ }
+ else
+ {
+ p->InvalidSourcePacket = false;
+ }
+
+ if (p->MacHeader->DestAddress[0] & 0x01)
+ {
+ p->BroadcastPacket = true;
+ }
+
+ // Parse L3 packet
+ type_id_16 = Endian16(p->MacHeader->Protocol);
+
+ if (type_id_16 > 1500)
+ {
+ // Ordinary Ethernet frame
+ switch (type_id_16)
+ {
+ case MAC_PROTO_ARPV4: // ARPv4
+ if (no_l3)
+ {
+ return true;
+ }
+
+ return ParsePacketARPv4(p, buf, size);
+
+ case MAC_PROTO_IPV4: // IPv4
+ if (no_l3)
+ {
+ return true;
+ }
+
+ return ParsePacketIPv4(p, buf, size);
+
+ case MAC_PROTO_IPV6: // IPv6
+ if (no_l3)
+ {
+ return true;
+ }
+
+ return ParsePacketIPv6(p, buf, size);
+
+ default: // Unknown
+ if (type_id_16 == p->VlanTypeID)
+ {
+ // VLAN
+ return ParsePacketTAGVLAN(p, buf, size);
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+ else
+ {
+ // Old IEEE 802.3 frame (payload length of the packet is written in the header)
+ // (It has been used in the BPDU, etc.)
+ UINT length = (UINT)type_id_16;
+ LLC_HEADER *llc;
+
+ // Check whether the length is remaining
+ if (size < length || size < sizeof(LLC_HEADER))
+ {
+ return true;
+ }
+
+ // Read an LLC header
+ llc = (LLC_HEADER *)buf;
+ buf += sizeof(LLC_HEADER);
+ size -= sizeof(LLC_HEADER);
+
+ // Determine the protocol by the value of DSAP and SSAP
+ if (llc->Dsap == LLC_DSAP_BPDU && llc->Ssap == LLC_SSAP_BPDU)
+ {
+ // This is a BPDU (Spanning Tree)
+ return ParsePacketBPDU(p, buf, size);
+ }
+ else
+ {
+ // Unknown protocol
+ return true;
+ }
+ }
+}
+
+// TAG VLAN parsing
+bool ParsePacketTAGVLAN(PKT *p, UCHAR *buf, UINT size)
+{
+ USHORT vlan_ushort;
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(TAGVLAN_HEADER))
+ {
+ return false;
+ }
+
+ // TAG VLAN header
+ p->L3.TagVlanHeader = (TAGVLAN_HEADER *)buf;
+ p->TypeL3 = L3_TAGVLAN;
+
+ buf += sizeof(TAGVLAN_HEADER);
+ size -= sizeof(TAGVLAN_HEADER);
+
+ vlan_ushort = READ_USHORT(p->L3.TagVlanHeader->Data);
+ vlan_ushort = vlan_ushort & 0xFFF;
+
+ p->VlanId = vlan_ushort;
+
+ return true;
+}
+
+// BPDU Parsing
+bool ParsePacketBPDU(PKT *p, UCHAR *buf, UINT size)
+{
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(BPDU_HEADER))
+ {
+ return true;
+ }
+
+ // BPDU header
+ p->L3.BpduHeader = (BPDU_HEADER *)buf;
+ p->TypeL3 = L3_BPDU;
+
+ buf += sizeof(BPDU_HEADER);
+ size -= sizeof(BPDU_HEADER);
+
+ return true;
+}
+
+// ARPv4 Parsing
+bool ParsePacketARPv4(PKT *p, UCHAR *buf, UINT size)
+{
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(ARPV4_HEADER))
+ {
+ return false;
+ }
+
+ // ARPv4 header
+ p->L3.ARPv4Header = (ARPV4_HEADER *)buf;
+ p->TypeL3 = L3_ARPV4;
+
+ buf += sizeof(ARPV4_HEADER);
+ size -= sizeof(ARPV4_HEADER);
+
+ return true;
+}
+
+// Analysis of the IPv6 extension header
+bool ParseIPv6ExtHeader(IPV6_HEADER_PACKET_INFO *info, UCHAR next_header, UCHAR *buf, UINT size)
+{
+ bool ret = false;
+ IPV6_OPTION_HEADER *option_header;
+ UINT option_header_size;
+ UCHAR next_header_2 = IPV6_HEADER_NONE;
+ // Validate arguments
+ if (info == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ info->IsFragment = false;
+
+ while (true)
+ {
+ if (size > 8)
+ {
+ next_header_2 = *((UCHAR *)buf);
+ }
+
+ switch (next_header)
+ {
+ case IPV6_HEADER_HOP:
+ case IPV6_HEADER_ENDPOINT:
+ case IPV6_HEADER_ROUTING:
+ // Variable-length header
+ if (size < 8)
+ {
+ return false;
+ }
+
+ option_header = (IPV6_OPTION_HEADER *)buf;
+ option_header_size = (option_header->Size + 1) * 8;
+ if (size < option_header_size)
+ {
+ return false;
+ }
+
+ switch (next_header)
+ {
+ case IPV6_HEADER_HOP:
+ info->HopHeader = (IPV6_OPTION_HEADER *)buf;
+ info->HopHeaderSize = option_header_size;
+ break;
+
+ case IPV6_HEADER_ENDPOINT:
+ info->EndPointHeader = (IPV6_OPTION_HEADER *)buf;
+ info->EndPointHeaderSize = option_header_size;
+ break;
+
+ case IPV6_HEADER_ROUTING:
+ info->RoutingHeader = (IPV6_OPTION_HEADER *)buf;
+ info->RoutingHeaderSize = option_header_size;
+ break;
+ }
+
+ buf += option_header_size;
+ size -= option_header_size;
+ break;
+
+ case IPV6_HEADER_FRAGMENT:
+ // Fragment header (fixed length)
+ if (size < sizeof(IPV6_FRAGMENT_HEADER))
+ {
+ return false;
+ }
+
+ info->FragmentHeader = (IPV6_FRAGMENT_HEADER *)buf;
+
+ if (IPV6_GET_FRAGMENT_OFFSET(info->FragmentHeader) != 0)
+ {
+ info->IsFragment = true;
+ }
+
+ buf += sizeof(IPV6_FRAGMENT_HEADER);
+ size -= sizeof(IPV6_FRAGMENT_HEADER);
+ break;
+
+ default:
+ // Considered that the payload follows
+ if (next_header != IPV6_HEADER_NONE)
+ {
+ info->Payload = buf;
+ info->PayloadSize = size;
+ }
+ else
+ {
+ info->Payload = NULL;
+ info->PayloadSize = 0;
+ }
+ info->Protocol = next_header;
+ return true;
+ }
+
+ next_header = next_header_2;
+ }
+}
+
+// Analysis of the IPv6 header
+bool ParsePacketIPv6Header(IPV6_HEADER_PACKET_INFO *info, UCHAR *buf, UINT size)
+{
+ // Validate arguments
+ if (info == NULL || buf == NULL)
+ {
+ Zero(info, sizeof(IPV6_HEADER_PACKET_INFO));
+ return false;
+ }
+
+ Zero(info, sizeof(IPV6_HEADER_PACKET_INFO));
+
+ // IPv6 header
+ if (size < sizeof(IPV6_HEADER))
+ {
+ // Invalid size
+ return false;
+ }
+
+ info->IPv6Header = (IPV6_HEADER *)buf;
+ buf += sizeof(IPV6_HEADER);
+ size -= sizeof(IPV6_HEADER);
+
+ if (IPV6_GET_VERSION(info->IPv6Header) != 6)
+ {
+ // Invalid version
+ return false;
+ }
+
+ // Analysis of the extension header
+ if (ParseIPv6ExtHeader(info, info->IPv6Header->NextHeader, buf, size) == false)
+ {
+ return false;
+ }
+
+ // Record the header size
+ if (info->Payload != NULL)
+ {
+ info->TotalHeaderSize = (UINT)((UINT64)(info->Payload) - (UINT64)(info->IPv6Header));
+ }
+
+ return true;
+}
+
+// Analyse the options of ICMPv6 packet
+bool ParseICMPv6Options(ICMPV6_OPTION_LIST *o, UCHAR *buf, UINT size)
+{
+ // Validate arguments
+ if (o == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ Zero(o, sizeof(ICMPV6_OPTION_LIST));
+
+ // Read the header part
+ while (true)
+ {
+ ICMPV6_OPTION *option_header;
+ UINT header_total_size;
+ UCHAR *header_pointer;
+ if (size < sizeof(ICMPV6_OPTION))
+ {
+ // Size shortage
+ return true;
+ }
+
+ option_header = (ICMPV6_OPTION *)buf;
+ // Calculate the entire header size
+ header_total_size = option_header->Length * 8;
+ if (header_total_size == 0)
+ {
+ // The size is zero
+ return true;
+ }
+ if (size < header_total_size)
+ {
+ // Size shortage
+ return true;
+ }
+
+ header_pointer = buf;
+ buf += header_total_size;
+ size -= header_total_size;
+
+ switch (option_header->Type)
+ {
+ case ICMPV6_OPTION_TYPE_SOURCE_LINK_LAYER:
+ case ICMPV6_OPTION_TYPE_TARGET_LINK_LAYER:
+ // Source or target link-layer option
+ if (header_total_size >= sizeof(ICMPV6_OPTION_LINK_LAYER))
+ {
+ if (option_header->Type == ICMPV6_OPTION_TYPE_SOURCE_LINK_LAYER)
+ {
+ o->SourceLinkLayer = (ICMPV6_OPTION_LINK_LAYER *)header_pointer;
+ }
+ else
+ {
+ o->TargetLinkLayer = (ICMPV6_OPTION_LINK_LAYER *)header_pointer;
+ }
+ }
+ else
+ {
+ // ICMPv6 packet corruption?
+ return false;
+ }
+ break;
+
+ case ICMPV6_OPTION_TYPE_PREFIX:
+ // Prefix Information
+ if (header_total_size >= sizeof(ICMPV6_OPTION_PREFIX))
+ {
+ o->Prefix = (ICMPV6_OPTION_PREFIX *)header_pointer;
+ }
+ else
+ {
+ // ICMPv6 packet corruption?
+ }
+ break;
+
+ case ICMPV6_OPTION_TYPE_MTU:
+ // MTU
+ if (header_total_size >= sizeof(ICMPV6_OPTION_MTU))
+ {
+ o->Mtu = (ICMPV6_OPTION_MTU *)header_pointer;
+ }
+ else
+ {
+ // ICMPv6 packet corruption?
+ }
+ break;
+ }
+ }
+}
+
+// ICMPv6 parsing
+bool ParseICMPv6(PKT *p, UCHAR *buf, UINT size)
+{
+ ICMPV6_HEADER_INFO icmp_info;
+ ICMP_HEADER *icmp;
+ ICMP_ECHO *echo;
+ UINT msg_size;
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ Zero(&icmp_info, sizeof(icmp_info));
+
+ if (size < sizeof(ICMP_HEADER))
+ {
+ return false;
+ }
+
+ icmp = (ICMP_HEADER *)buf;
+ p->L4.ICMPHeader = icmp;
+
+ msg_size = size - sizeof(ICMP_HEADER);
+
+ icmp_info.Type = icmp->Type;
+ icmp_info.Code = icmp->Code;
+ icmp_info.Data = ((UCHAR *)buf) + sizeof(ICMP_HEADER);
+ icmp_info.DataSize = msg_size;
+
+ switch (icmp_info.Type)
+ {
+ case ICMPV6_TYPE_ECHO_REQUEST:
+ case ICMPV6_TYPE_ECHO_RESPONSE:
+ // ICMP Echo Request / Response
+ if (icmp_info.DataSize < sizeof(ICMP_ECHO))
+ {
+ return false;
+ }
+
+ echo = (ICMP_ECHO *)icmp_info.Data;
+
+ icmp_info.EchoHeader.Identifier = Endian16(echo->Identifier);
+ icmp_info.EchoHeader.SeqNo = Endian16(echo->SeqNo);
+ icmp_info.EchoData = (UCHAR *)echo + sizeof(ICMP_ECHO);
+ icmp_info.EchoDataSize = icmp_info.DataSize - sizeof(ICMP_ECHO);
+
+ break;
+
+ case ICMPV6_TYPE_ROUTER_SOLICIATION:
+ // Router Solicitation
+ if (icmp_info.DataSize < sizeof(ICMPV6_ROUTER_SOLICIATION_HEADER))
+ {
+ return false;
+ }
+
+ icmp_info.Headers.RouterSoliciationHeader =
+ (ICMPV6_ROUTER_SOLICIATION_HEADER *)(((UCHAR *)icmp_info.Data));
+
+ if (ParseICMPv6Options(&icmp_info.OptionList, ((UCHAR *)icmp_info.Headers.HeaderPointer) + sizeof(ICMPV6_ROUTER_SOLICIATION_HEADER),
+ icmp_info.DataSize - sizeof(ICMPV6_ROUTER_SOLICIATION_HEADER)) == false)
+ {
+ return false;
+ }
+
+ break;
+
+ case ICMPV6_TYPE_ROUTER_ADVERTISEMENT:
+ // Router Advertisement
+ if (icmp_info.DataSize < sizeof(ICMPV6_ROUTER_ADVERTISEMENT_HEADER))
+ {
+ return false;
+ }
+
+ icmp_info.Headers.RouterAdvertisementHeader =
+ (ICMPV6_ROUTER_ADVERTISEMENT_HEADER *)(((UCHAR *)icmp_info.Data));
+
+ if (ParseICMPv6Options(&icmp_info.OptionList, ((UCHAR *)icmp_info.Headers.HeaderPointer) + sizeof(ICMPV6_ROUTER_ADVERTISEMENT_HEADER),
+ icmp_info.DataSize - sizeof(ICMPV6_ROUTER_ADVERTISEMENT_HEADER)) == false)
+ {
+ return false;
+ }
+
+ break;
+
+ case ICMPV6_TYPE_NEIGHBOR_SOLICIATION:
+ // Neighbor Solicitation
+ if (icmp_info.DataSize < sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER))
+ {
+ return false;
+ }
+
+ icmp_info.Headers.NeighborSoliciationHeader =
+ (ICMPV6_NEIGHBOR_SOLICIATION_HEADER *)(((UCHAR *)icmp_info.Data));
+
+ if (ParseICMPv6Options(&icmp_info.OptionList, ((UCHAR *)icmp_info.Headers.HeaderPointer) + sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER),
+ icmp_info.DataSize - sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER)) == false)
+ {
+ return false;
+ }
+
+ break;
+
+ case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT:
+ // Neighbor Advertisement
+ if (icmp_info.DataSize < sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER))
+ {
+ return false;
+ }
+
+ icmp_info.Headers.NeighborAdvertisementHeader =
+ (ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER *)(((UCHAR *)icmp_info.Data));
+
+ if (ParseICMPv6Options(&icmp_info.OptionList, ((UCHAR *)icmp_info.Headers.HeaderPointer) + sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER),
+ icmp_info.DataSize - sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER)) == false)
+ {
+ return false;
+ }
+
+ break;
+ }
+
+ p->TypeL4 = L4_ICMPV6;
+ Copy(&p->ICMPv6HeaderPacketInfo, &icmp_info, sizeof(ICMPV6_HEADER_INFO));
+
+ return true;
+}
+
+// Release of the ICMPv6 options
+void FreeCloneICMPv6Options(ICMPV6_OPTION_LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ Free(o->SourceLinkLayer);
+ Free(o->TargetLinkLayer);
+ Free(o->Prefix);
+ Free(o->Mtu);
+}
+
+// Clone of the ICMPv6 options
+void CloneICMPv6Options(ICMPV6_OPTION_LIST *dst, ICMPV6_OPTION_LIST *src)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL)
+ {
+ return;
+ }
+
+ Zero(dst, sizeof(ICMPV6_OPTION_LIST));
+
+ dst->SourceLinkLayer = Clone(src->SourceLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER));
+ dst->TargetLinkLayer = Clone(src->TargetLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER));
+ dst->Prefix = Clone(src->Prefix, sizeof(ICMPV6_OPTION_PREFIX));
+ dst->Mtu = Clone(src->Mtu, sizeof(ICMPV6_OPTION_MTU));
+}
+
+// IPv6 parsing
+bool ParsePacketIPv6(PKT *p, UCHAR *buf, UINT size)
+{
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ if (ParsePacketIPv6Header(&p->IPv6HeaderPacketInfo, buf, size) == false)
+ {
+ return false;
+ }
+
+ p->TypeL3 = L3_IPV6;
+ p->L3.IPv6Header = p->IPv6HeaderPacketInfo.IPv6Header;
+
+ if (p->IPv6HeaderPacketInfo.Payload == NULL)
+ {
+ // No payload
+ return true;
+ }
+
+ buf = p->IPv6HeaderPacketInfo.Payload;
+ size = p->IPv6HeaderPacketInfo.PayloadSize;
+
+ if (p->IPv6HeaderPacketInfo.IsFragment)
+ {
+ // This is a fragmented packet. Quit interpreting
+ p->TypeL4 = L4_FRAGMENT;
+ return true;
+ }
+
+ // Parse a L4 packet
+ switch (p->IPv6HeaderPacketInfo.Protocol)
+ {
+ case IP_PROTO_ICMPV6: // ICMPv6
+ if (ParseICMPv6(p, buf, size) == false)
+ {
+ // Returns true also if it fails to parse ICMPv6
+ return true;
+ }
+ else
+ {
+ return true;
+ }
+
+ case IP_PROTO_TCP: // TCP
+ return ParseTCP(p, buf, size);
+
+ case IP_PROTO_UDP: // UDP
+ return ParseUDP(p, buf, size);
+
+ default: // Unknown
+ return true;
+ }
+
+ return true;
+}
+
+// Parse the IPv4 by adding a dummy MAC header
+PKT *ParsePacketIPv4WithDummyMacHeader(UCHAR *buf, UINT size)
+{
+ UCHAR *tmp;
+ UINT tmp_size;
+ // Validate arguments
+ if (buf == NULL)
+ {
+ return NULL;
+ }
+
+ tmp_size = size + 14;
+ tmp = Malloc(tmp_size);
+ Zero(tmp, 12);
+ WRITE_USHORT(tmp + 12, MAC_PROTO_IPV4);
+ Copy(tmp + 14, buf, size);
+
+ return ParsePacket(tmp, tmp_size);
+}
+
+// IPv4 parsing
+bool ParsePacketIPv4(PKT *p, UCHAR *buf, UINT size)
+{
+ UINT header_size;
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(IPV4_HEADER))
+ {
+ return false;
+ }
+
+ // IPv4 header
+ p->L3.IPv4Header = (IPV4_HEADER *)buf;
+ p->TypeL3 = L3_IPV4;
+
+ // Check the header
+ header_size = IPV4_GET_HEADER_LEN(p->L3.IPv4Header) * 4;
+ if (header_size < sizeof(IPV4_HEADER) || size < header_size)
+ {
+ // Header size is invalid
+ p->L3.IPv4Header = NULL;
+ p->TypeL3= L3_UNKNOWN;
+ return true;
+ }
+
+ buf += header_size;
+ size -= header_size;
+
+ p->IPv4PayloadSize = MIN(size, Endian16(p->L3.IPv4Header->TotalLength) - header_size);
+ if (Endian16(p->L3.IPv4Header->TotalLength) < header_size)
+ {
+ p->IPv4PayloadSize = 0;
+ }
+
+ p->IPv4PayloadData = buf;
+
+ if (IPV4_GET_OFFSET(p->L3.IPv4Header) != 0)
+ {
+ // Quit analysing since this is fragmented
+ p->TypeL4 = L4_FRAGMENT;
+ return true;
+ }
+
+ // Parse a L4 packet
+ switch (p->L3.IPv4Header->Protocol)
+ {
+ case IP_PROTO_ICMPV4: // ICMPv4
+ return ParseICMPv4(p, buf, size);
+
+ case IP_PROTO_UDP: // UDP
+ return ParseUDP(p, buf, size);
+
+ case IP_PROTO_TCP: // TCP
+ return ParseTCP(p, buf, size);
+
+ default: // Unknown
+ return true;
+ }
+}
+
+// ICMPv4 parsing
+bool ParseICMPv4(PKT *p, UCHAR *buf, UINT size)
+{
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(ICMP_HEADER))
+ {
+ // Size is invalid
+ return false;
+ }
+
+ // ICMPv4 header
+ p->L4.ICMPHeader = (ICMP_HEADER *)buf;
+ p->TypeL4 = L4_ICMPV4;
+
+ buf += sizeof(ICMP_HEADER);
+ size -= sizeof(ICMP_HEADER);
+
+ return true;
+}
+
+// TCP parsing
+bool ParseTCP(PKT *p, UCHAR *buf, UINT size)
+{
+ UINT header_size;
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(TCP_HEADER))
+ {
+ // Size is invalid
+ return false;
+ }
+
+ // TCP header
+ p->L4.TCPHeader = (TCP_HEADER *)buf;
+ p->TypeL4 = L4_TCP;
+
+ // Check the header size
+ header_size = TCP_GET_HEADER_SIZE(p->L4.TCPHeader) * 4;
+ if (header_size < sizeof(TCP_HEADER) || size < header_size)
+ {
+ // Header size is invalid
+ p->L4.TCPHeader = NULL;
+ p->TypeL4 = L4_UNKNOWN;
+ return true;
+ }
+
+ buf += header_size;
+ size -= header_size;
+
+ p->Payload = buf;
+ p->PayloadSize = size;
+
+ return true;
+}
+
+// UDP parsing
+bool ParseUDP(PKT *p, UCHAR *buf, UINT size)
+{
+ USHORT src_port, dst_port;
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return false;
+ }
+
+ // Check the size
+ if (size < sizeof(UDP_HEADER))
+ {
+ // Size is invalid
+ return false;
+ }
+
+ // UDP header
+ p->L4.UDPHeader = (UDP_HEADER *)buf;
+ p->TypeL4 = L4_UDP;
+
+ buf += sizeof(UDP_HEADER);
+ size -= sizeof(UDP_HEADER);
+
+ p->Payload = buf;
+ p->PayloadSize = size;
+
+ // Check the port number
+ src_port = Endian16(p->L4.UDPHeader->SrcPort);
+ dst_port = Endian16(p->L4.UDPHeader->DstPort);
+
+ if ((src_port == 67 && dst_port == 68) ||
+ (src_port == 68 && dst_port == 67))
+ {
+ if (p->TypeL3 == L3_IPV4)
+ {
+ // A DHCP packet is found
+ ParseDHCPv4(p, buf, size);
+
+ return true;
+ }
+ }
+
+ if (src_port == 500 || dst_port == 500 || src_port == 4500 || dst_port == 4500)
+ {
+ if (p->PayloadSize >= sizeof(IKE_HEADER))
+ {
+ IKE_HEADER *ike_header = (IKE_HEADER *)p->Payload;
+
+ if (ike_header->InitiatorCookie != 0 && ike_header->ResponderCookie == 0 &&
+ (ike_header->ExchangeType == IKE_EXCHANGE_TYPE_MAIN ||
+ ike_header->ExchangeType == IKE_EXCHANGE_TYPE_AGGRESSIVE))
+ {
+ // the IKE connection request packet is found
+ p->TypeL7 = L7_IKECONN;
+ p->L7.IkeHeader = ike_header;
+ return true;
+ }
+ }
+ }
+
+ // Determine whether it's an OpenVPN UDP packet
+ if (size == 14)
+ {
+ if (buf[0] == 0x38)
+ {
+ if (IsZero(buf + 9, 5))
+ {
+ if (IsZero(buf + 1, 8) == false)
+ {
+ // An OpenVPN connection request packet is found
+ p->TypeL7 = L7_OPENVPNCONN;
+ return true;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+// DHCPv4 parsing
+void ParseDHCPv4(PKT *p, UCHAR *buf, UINT size)
+{
+ // Validate arguments
+ if (p == NULL || buf == NULL)
+ {
+ return;
+ }
+
+ // Check the size
+ if (size < sizeof(DHCPV4_HEADER))
+ {
+ // Size is invalid
+ return;
+ }
+
+ // DHCPv4 header
+ p->L7.DHCPv4Header = (DHCPV4_HEADER *)buf;
+ p->TypeL7 = L7_DHCPV4;
+}
+
+// Release the memory of the packet
+void FreePacket(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (p->MacHeader != NULL)
+ {
+ switch (p->TypeL3)
+ {
+ case L3_IPV4:
+ FreePacketIPv4(p);
+ break;
+
+ case L3_ARPV4:
+ FreePacketARPv4(p);
+ break;
+
+ case L3_TAGVLAN:
+ FreePacketTagVlan(p);
+ break;
+ }
+ }
+
+ if (p->HttpLog != NULL)
+ {
+ Free(p->HttpLog);
+ }
+
+ Free(p);
+}
+
+// Release the memory of the packet with data
+void FreePacketWithData(PKT *p)
+{
+ void *data;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ data = p->PacketData;
+
+ FreePacket(p);
+
+ Free(data);
+}
+
+// Release the memory for the IPv4 packet
+void FreePacketIPv4(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ switch (p->TypeL4)
+ {
+ case L4_ICMPV4:
+ FreePacketICMPv4(p);
+ break;
+
+ case L4_TCP:
+ FreePacketTCPv4(p);
+ break;
+
+ case L4_UDP:
+ FreePacketUDPv4(p);
+ break;
+ }
+
+ p->L3.IPv4Header = NULL;
+ p->TypeL3 = L3_UNKNOWN;
+}
+
+// Release the memory for the tagged VLAN packet
+void FreePacketTagVlan(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p->L3.TagVlanHeader = NULL;
+ p->TypeL3 = L3_UNKNOWN;
+}
+
+// Release the memory for the ARPv4 packet
+void FreePacketARPv4(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p->L3.ARPv4Header = NULL;
+ p->TypeL3 = L3_UNKNOWN;
+}
+
+// Release the memory of the UDPv4 packet
+void FreePacketUDPv4(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ switch (p->TypeL7)
+ {
+ case L7_DHCPV4:
+ FreePacketDHCPv4(p);
+ break;
+ }
+
+ p->L4.UDPHeader = NULL;
+ p->TypeL4 = L4_UNKNOWN;
+}
+
+// Release the memory for the TCPv4 packet
+void FreePacketTCPv4(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p->L4.TCPHeader = NULL;
+ p->TypeL4 = L4_UNKNOWN;
+}
+
+// Release the memory for the ICMPv4 packet
+void FreePacketICMPv4(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p->L4.ICMPHeader = NULL;
+ p->TypeL4 = L4_UNKNOWN;
+}
+
+// Release the memory for the DHCPv4 packet
+void FreePacketDHCPv4(PKT *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p->L7.DHCPv4Header = NULL;
+ p->TypeL7 = L7_UNKNOWN;
+}
+
+
+// Confirm the checksum of the IP header
+bool IpCheckChecksum(IPV4_HEADER *ip)
+{
+ UINT header_size;
+ USHORT checksum_original, checksum_calc;
+ // Validate arguments
+ if (ip == NULL)
+ {
+ return false;
+ }
+
+ header_size = IPV4_GET_HEADER_LEN(ip) * 4;
+ checksum_original = ip->Checksum;
+ ip->Checksum = 0;
+ checksum_calc = IpChecksum(ip, header_size);
+ ip->Checksum = checksum_original;
+
+ if (checksum_original == checksum_calc)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Calculate the checksum
+USHORT IpChecksum(void *buf, UINT size)
+{
+ int sum = 0;
+ USHORT *addr = (USHORT *)buf;
+ int len = (int)size;
+ USHORT *w = addr;
+ int nleft = len;
+ USHORT answer = 0;
+
+ while (nleft > 1)
+ {
+ USHORT ww = 0;
+ Copy(&ww, w++, sizeof(USHORT));
+ sum += ww;
+ nleft -= 2;
+ }
+
+ if (nleft == 1)
+ {
+ *(UCHAR *)(&answer) = *(UCHAR *)w;
+ sum += answer;
+ }
+
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+
+ answer = ~sum;
+
+ return answer;
+}
+
+// Convert a DHCP option list into a buffer
+BUF *BuildDhcpOptionsBuf(LIST *o)
+{
+ BUF *b;
+ UINT i;
+ UCHAR id;
+ UCHAR sz;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ DHCP_OPTION *d = LIST_DATA(o, i);
+ id = (UCHAR)d->Id;
+ sz = (UCHAR)d->Size;
+ WriteBuf(b, &id, 1);
+ WriteBuf(b, &sz, 1);
+ WriteBuf(b, d->Data, d->Size);
+ }
+
+ id = 0xff;
+ WriteBuf(b, &id, 1);
+
+ return b;
+}
+
+// Convert a DHCP option list to the DHCP option
+LIST *BuildDhcpOption(DHCP_OPTION_LIST *opt)
+{
+ LIST *o;
+ UCHAR opcode;
+ BUF *dns_buf;
+ // Validate arguments
+ if (opt == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(NULL);
+
+ // Op-code
+ opcode = (UCHAR)opt->Opcode;
+ Add(o, NewDhcpOption(DHCP_ID_MESSAGE_TYPE, &opcode, sizeof(opcode)));
+ Add(o, NewDhcpOption(DHCP_ID_SERVER_ADDRESS, &opt->ServerAddress, sizeof(opt->ServerAddress)));
+
+ if (opt->LeaseTime != 0)
+ {
+ Add(o, NewDhcpOption(DHCP_ID_LEASE_TIME, &opt->LeaseTime, sizeof(opt->LeaseTime)));
+ }
+
+ if (StrLen(opt->DomainName) != 0 && opt->DnsServer != 0)
+ {
+ Add(o, NewDhcpOption(DHCP_ID_DOMAIN_NAME, opt->DomainName, StrLen(opt->DomainName)));
+ }
+ if (opt->SubnetMask != 0)
+ {
+ Add(o, NewDhcpOption(DHCP_ID_SUBNET_MASK, &opt->SubnetMask, sizeof(opt->SubnetMask)));
+ }
+ if (opt->Gateway != 0)
+ {
+ Add(o, NewDhcpOption(DHCP_ID_GATEWAY_ADDR, &opt->Gateway, sizeof(opt->Gateway)));
+ }
+
+ dns_buf = NewBuf();
+
+ if (opt->DnsServer != 0)
+ {
+ WriteBuf(dns_buf, &opt->DnsServer, sizeof(opt->DnsServer));
+ }
+ if (opt->DnsServer2 != 0)
+ {
+ WriteBuf(dns_buf, &opt->DnsServer2, sizeof(opt->DnsServer2));
+ }
+
+ if (dns_buf->Size >= 1)
+ {
+ Add(o, NewDhcpOption(DHCP_ID_DNS_ADDR, dns_buf->Buf, dns_buf->Size));
+ }
+
+ FreeBuf(dns_buf);
+
+ return o;
+}
+
+// Create a new DHCP option item
+DHCP_OPTION *NewDhcpOption(UINT id, void *data, UINT size)
+{
+ DHCP_OPTION *ret;
+ if (size != 0 && data == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(DHCP_OPTION));
+ ret->Data = ZeroMalloc(size);
+ Copy(ret->Data, data, size);
+ ret->Size = (UCHAR)size;
+ ret->Id = (UCHAR)id;
+
+ return ret;
+}
+
+// Parse a DHCP options list
+DHCP_OPTION_LIST *ParseDhcpOptionList(void *data, UINT size)
+{
+ DHCP_OPTION_LIST *ret;
+ LIST *o;
+ DHCP_OPTION *a;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ // Parse the list
+ o = ParseDhcpOptions(data, size);
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ ret = ZeroMalloc(sizeof(DHCP_OPTION_LIST));
+
+ // Get the opcode
+ a = GetDhcpOption(o, DHCP_ID_MESSAGE_TYPE);
+ if (a != NULL)
+ {
+ if (a->Size == 1)
+ {
+ ret->Opcode = *((UCHAR *)a->Data);
+ }
+ }
+
+ switch (ret->Opcode)
+ {
+ case DHCP_DISCOVER:
+ case DHCP_REQUEST:
+ // Parse this more finely because this is client requests
+ // Requested IP address
+ a = GetDhcpOption(o, DHCP_ID_REQUEST_IP_ADDRESS);
+ if (a != NULL && a->Size == 4)
+ {
+ Copy(&ret->RequestedIp, a->Data, 4);
+ }
+ // Host name
+ a = GetDhcpOption(o, DHCP_ID_HOST_NAME);
+ if (a != NULL)
+ {
+ if (a->Size > 1)
+ {
+ Copy(ret->Hostname, a->Data, MIN(a->Size, sizeof(ret->Hostname) - 1));
+ }
+ }
+ break;
+
+ case DHCP_OFFER:
+ case DHCP_ACK:
+ // Subnet mask
+ a = GetDhcpOption(o, DHCP_ID_SUBNET_MASK);
+ if (a != NULL && a->Size >= 4)
+ {
+ Copy(&ret->SubnetMask, a->Data, 4);
+ }
+
+ // Lease time
+ a = GetDhcpOption(o, DHCP_ID_LEASE_TIME);
+ if (a != NULL && a->Size == 4)
+ {
+ ret->LeaseTime = READ_UINT(a->Data);
+ }
+
+ // Server IP address
+ a = GetDhcpOption(o, DHCP_ID_SERVER_ADDRESS);
+ if (a != NULL && a->Size >= 4)
+ {
+ Copy(&ret->ServerAddress, a->Data, 4);
+ }
+
+ // Domain name
+ a = GetDhcpOption(o, DHCP_ID_DOMAIN_NAME);
+ if (a != NULL && a->Size >= 1)
+ {
+ Zero(ret->DomainName, sizeof(ret->DomainName));
+ Copy(ret->DomainName, a->Data, MIN(a->Size, sizeof(ret->DomainName) - 1));
+ }
+
+ // Gateway
+ a = GetDhcpOption(o, DHCP_ID_GATEWAY_ADDR);
+ if (a != NULL && a->Size >= 4)
+ {
+ Copy(&ret->Gateway, a->Data, 4);
+ }
+
+ // DNS server
+ a = GetDhcpOption(o, DHCP_ID_DNS_ADDR);
+ if (a != NULL && a->Size >= 4)
+ {
+ Copy(&ret->DnsServer, a->Data, 4);
+
+ if (a->Size >= 8)
+ {
+ Copy(&ret->DnsServer2, ((UCHAR *)a->Data) + 4, 4);
+ }
+ }
+
+ // WINS server
+ a = GetDhcpOption(o, DHCP_ID_WINS_ADDR);
+ if (a != NULL && a->Size >= 4)
+ {
+ Copy(&ret->WinsServer, a->Data, 4);
+
+ if (a->Size >= 8)
+ {
+ Copy(&ret->WinsServer2, ((UCHAR *)a->Data) + 4, 4);
+ }
+ }
+
+ break;
+ }
+
+ // Release the list
+ FreeDhcpOptions(o);
+
+ return ret;
+}
+
+// Finding a DHCP option
+DHCP_OPTION *GetDhcpOption(LIST *o, UINT id)
+{
+ UINT i;
+ DHCP_OPTION *ret = NULL;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ DHCP_OPTION *opt = LIST_DATA(o, i);
+ if (opt->Id == id)
+ {
+ ret = opt;
+ }
+ }
+
+ return ret;
+}
+
+// Release the DHCP option
+void FreeDhcpOptions(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ DHCP_OPTION *opt = LIST_DATA(o, i);
+ Free(opt->Data);
+ Free(opt);
+ }
+
+ ReleaseList(o);
+}
+
+// Parse the DHCP Options
+LIST *ParseDhcpOptions(void *data, UINT size)
+{
+ BUF *b;
+ LIST *o;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, data, size);
+ SeekBuf(b, 0, 0);
+
+ o = NewListFast(NULL);
+
+ while (true)
+ {
+ UCHAR c = 0;
+ UCHAR sz = 0;
+ DHCP_OPTION *opt;
+ if (ReadBuf(b, &c, 1) != 1)
+ {
+ break;
+ }
+ if (c == 0xff)
+ {
+ break;
+ }
+ if (ReadBuf(b, &sz, 1) != 1)
+ {
+ break;
+ }
+
+ opt = ZeroMalloc(sizeof(DHCP_OPTION));
+ opt->Id = (UINT)c;
+ opt->Size = (UINT)sz;
+ opt->Data = ZeroMalloc((UINT)sz);
+ ReadBuf(b, opt->Data, sz);
+ Add(o, opt);
+ }
+
+ FreeBuf(b);
+
+ return o;
+}
+
+// Rewrite the DHCP message data in the requested IPv4 packet appropriately
+BUF *DhcpModifyIPv4(DHCP_MODIFY_OPTION *m, void *data, UINT size)
+{
+ PKT *p;
+ BUF *ret = NULL;
+ // Validate arguments
+ if (m == NULL || data == NULL || size == 0)
+ {
+ return NULL;
+ }
+
+ p = ParsePacketEx4(data, size, false, 0, false, false, false);
+
+ if (p != NULL && p->TypeL3 == L3_IPV4 && p->TypeL4 == L4_UDP && p->TypeL7 == L7_DHCPV4)
+ {
+ BUF *new_buf = DhcpModify(m, p->Payload, p->PayloadSize);
+
+ if (new_buf != NULL)
+ {
+ ret = NewBuf();
+
+ WriteBuf(ret, p->PacketData, p->PacketSize - p->PayloadSize);
+ WriteBuf(ret, new_buf->Buf, new_buf->Size);
+
+ FreeBuf(new_buf);
+ }
+ }
+
+ FreePacket(p);
+
+ if (ret != NULL)
+ {
+ PKT *p = ParsePacketEx4(ret->Buf, ret->Size, false, 0, false, false, false);
+
+ if (p != NULL)
+ {
+ // Recalculation of the UDP checksum
+ if (p->TypeL3 == L3_IPV4 && p->TypeL4 == L4_UDP)
+ {
+ UDP_HEADER *udp = p->L4.UDPHeader;
+
+ udp->Checksum = 0;
+ udp->Checksum = CalcChecksumForIPv4(p->L3.IPv4Header->SrcIP,
+ p->L3.IPv4Header->DstIP,
+ IP_PROTO_UDP,
+ udp,
+ p->PacketSize - (UINT)(((UCHAR *)udp) - ((UCHAR *)p->PacketData)), 0);
+ }
+
+ FreePacket(p);
+ }
+ }
+
+ return ret;
+}
+
+// Rewrite the DHCP packet appropriately
+BUF *DhcpModify(DHCP_MODIFY_OPTION *m, void *data, UINT size)
+{
+ DHCPV4_HEADER *dhcp_header;
+ UCHAR *data_ptr;
+ bool ret_ok = false;
+ BUF *ret = NULL;
+ BUF *opt_buf = NULL;
+ UINT magic_cookie = Endian32(DHCP_MAGIC_COOKIE);
+ bool ok = false;
+ DHCP_OPTION_LIST *opt = NULL;
+ LIST *opt_list = NULL;
+ LIST *opt_list2 = NULL;
+ UINT src_size = size;
+ UINT i;
+ // Validate arguments
+ if (m == NULL || data == NULL || size == 0)
+ {
+ return NULL;
+ }
+
+ data_ptr = (UCHAR *)data;
+
+ if (size < sizeof(DHCPV4_HEADER))
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ dhcp_header = (DHCPV4_HEADER *)data_ptr;
+ data_ptr += sizeof(DHCPV4_HEADER);
+
+ // Search for a Magic Cookie
+ while (size >= 5)
+ {
+ if (Cmp(data_ptr, &magic_cookie, sizeof(UINT)) == 0)
+ {
+ // Found
+ data_ptr += sizeof(UINT);
+ size -= sizeof(UINT);
+ ok = true;
+ break;
+ }
+
+ data_ptr++;
+ size--;
+ }
+
+ if (ok == false)
+ {
+ // The packet is invalid
+ goto LABEL_CLEANUP;
+ }
+
+ ret = NewBuf();
+ WriteBuf(ret, data, (UINT)(data_ptr - ((UCHAR *)data)));
+
+ // Parse the DHCP options list
+ opt = ParseDhcpOptionList(data_ptr, size);
+ if (opt == NULL)
+ {
+ // The packet is invalid
+ goto LABEL_CLEANUP;
+ }
+
+ opt_list = ParseDhcpOptions(data_ptr, size);
+ if (opt_list == NULL)
+ {
+ // The packet is invalid
+ goto LABEL_CLEANUP;
+ }
+
+ // Rebuilding the options list
+ opt_list2 = NewListFast(NULL);
+
+ for (i = 0;i < LIST_NUM(opt_list);i++)
+ {
+ DHCP_OPTION *o = LIST_DATA(opt_list, i);
+ DHCP_OPTION *o2 = NULL;
+ bool ok = true;
+
+ if (m->RemoveDefaultGatewayOnReply)
+ {
+ if (opt->Opcode == DHCP_OFFER || opt->Opcode == DHCP_ACK)
+ {
+ // Remove the default gateway from the DHCP Reply
+ if (o->Id == DHCP_ID_GATEWAY_ADDR)
+ {
+ ok = false;
+ }
+ if (o->Id == DHCP_ID_DNS_ADDR || o->Id == DHCP_ID_WINS_ADDR || o->Id == DHCP_ID_DOMAIN_NAME)
+ {
+ ok = false;
+ }
+ }
+ }
+
+ if (ok && o2 == NULL)
+ {
+ o2 = NewDhcpOption(o->Id, o->Data, o->Size);
+ }
+
+ if (o2 != NULL)
+ {
+ Add(opt_list2, o2);
+ }
+ }
+
+ opt_buf = BuildDhcpOptionsBuf(opt_list2);
+
+ WriteBuf(ret, opt_buf->Buf, opt_buf->Size);
+
+ if (src_size != ret->Size || Cmp(data, ret->Buf, ret->Size) != 0)
+ {
+ // Rewrite if anything changes. Do not rewrite if there is no change
+ ret_ok = true;
+
+ if (ret->Size < DHCP_MIN_SIZE)
+ {
+ // Padding
+ UCHAR *pad_buf;
+ UINT pad_size = DHCP_MIN_SIZE - ret->Size;
+
+ pad_buf = ZeroMalloc(pad_size);
+
+ WriteBuf(ret, pad_buf, pad_size);
+
+ Free(pad_buf);
+ }
+ }
+
+LABEL_CLEANUP:
+ // Memory release
+ if (opt_buf != NULL)
+ {
+ FreeBuf(opt_buf);
+ }
+
+ if (opt != NULL)
+ {
+ Free(opt);
+ }
+
+ if (opt_list != NULL)
+ {
+ FreeDhcpOptions(opt_list);
+ }
+
+ if (opt_list2 != NULL)
+ {
+ FreeDhcpOptions(opt_list2);
+ }
+
+ // Return a value
+ if (ret_ok)
+ {
+ return ret;
+ }
+ else
+ {
+ FreeBuf(ret);
+ return NULL;
+ }
+}
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/TcpIp.h b/src/Mayaqua/TcpIp.h
new file mode 100644
index 00000000..0740460a
--- /dev/null
+++ b/src/Mayaqua/TcpIp.h
@@ -0,0 +1,876 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// TcpIp.h
+// Header of TcpIp.c
+
+#ifndef TCPIP_H
+#define TCPIP_H
+
+#ifdef OS_WIN32
+#pragma pack(push, 1)
+#endif // OS_WIN32
+
+// MTU when using of the PPPoE
+#define MTU_FOR_PPPOE (1500 - 46)
+
+// MAC header
+struct MAC_HEADER
+{
+ UCHAR DestAddress[6]; // Source MAC address
+ UCHAR SrcAddress[6]; // Destination MAC address
+ USHORT Protocol; // Protocol
+} GCC_PACKED;
+
+// MAC protocol
+#define MAC_PROTO_ARPV4 0x0806 // ARPv4 packet
+#define MAC_PROTO_IPV4 0x0800 // IPv4 packets
+#define MAC_PROTO_IPV6 0x86dd // IPv6 packets
+#define MAC_PROTO_TAGVLAN 0x8100 // Tagged VLAN packets
+
+// LLC header
+struct LLC_HEADER
+{
+ UCHAR Dsap;
+ UCHAR Ssap;
+ UCHAR Ctl;
+} GCC_PACKED;
+
+// The value of the SSAP and the DSAP of the LLC header
+#define LLC_DSAP_BPDU 0x42
+#define LLC_SSAP_BPDU 0x42
+
+// BPDU header
+struct BPDU_HEADER
+{
+ USHORT ProtocolId; // Protocol ID (STP == 0x0000)
+ UCHAR Version; // Version
+ UCHAR Type; // Type
+ UCHAR Flags; // Flag
+ USHORT RootPriority; // Priority of the root bridge
+ UCHAR RootMacAddress[6]; // MAC address of the root bridge
+ UINT RootPathCost; // Path cost to the root bridge
+ USHORT BridgePriority; // Priority of the outgoing bridge
+ UCHAR BridgeMacAddress[6]; // MAC address of the outgoing bridge
+ USHORT BridgePortId; // Port ID of the outgoing bridge
+ USHORT MessageAge; // Expiration date
+ USHORT MaxAge; // Maximum expiration date
+ USHORT HelloTime; // Hello Time
+ USHORT ForwardDelay; // Forward Delay
+} GCC_PACKED;
+
+// ARPv4 header
+struct ARPV4_HEADER
+{
+ USHORT HardwareType; // Hardware type
+ USHORT ProtocolType; // Protocol type
+ UCHAR HardwareSize; // Hardware size
+ UCHAR ProtocolSize; // Protocol size
+ USHORT Operation; // Operation
+ UCHAR SrcAddress[6]; // Source MAC address
+ UINT SrcIP; // Source IP address
+ UCHAR TargetAddress[6]; // Target MAC address
+ UINT TargetIP; // Target IP address
+} GCC_PACKED;
+
+// ARP hardware type
+#define ARP_HARDWARE_TYPE_ETHERNET 0x0001
+
+// ARP operation type
+#define ARP_OPERATION_REQUEST 1
+#define ARP_OPERATION_RESPONSE 2
+
+// Tagged VLAN header
+struct TAGVLAN_HEADER
+{
+ UCHAR Data[2]; // Data
+} GCC_PACKED;
+
+// IPv4 header
+struct IPV4_HEADER
+{
+ UCHAR VersionAndHeaderLength; // Version and header size
+ UCHAR TypeOfService; // Service Type
+ USHORT TotalLength; // Total size
+ USHORT Identification; // Identifier
+ UCHAR FlagsAndFlagmentOffset[2]; // Flag and Fragment offset
+ UCHAR TimeToLive; // TTL
+ UCHAR Protocol; // Protocol
+ USHORT Checksum; // Checksum
+ UINT SrcIP; // Source IP address
+ UINT DstIP; // Destination IP address
+} GCC_PACKED;
+
+// Macro for IPv4 header operation
+#define IPV4_GET_VERSION(h) (((h)->VersionAndHeaderLength >> 4 & 0x0f))
+#define IPV4_SET_VERSION(h, v) ((h)->VersionAndHeaderLength |= (((v) & 0x0f) << 4))
+#define IPV4_GET_HEADER_LEN(h) ((h)->VersionAndHeaderLength & 0x0f)
+#define IPV4_SET_HEADER_LEN(h, v) ((h)->VersionAndHeaderLength |= ((v) & 0x0f))
+
+// Macro for IPv4 fragment related operation
+#define IPV4_GET_FLAGS(h) (((h)->FlagsAndFlagmentOffset[0] >> 5) & 0x07)
+#define IPV4_SET_FLAGS(h, v) ((h)->FlagsAndFlagmentOffset[0] |= (((v) & 0x07) << 5))
+#define IPV4_GET_OFFSET(h) (((h)->FlagsAndFlagmentOffset[0] & 0x1f) * 256 + ((h)->FlagsAndFlagmentOffset[1]))
+#define IPV4_SET_OFFSET(h, v) {(h)->FlagsAndFlagmentOffset[0] |= (UCHAR)((v) / 256); (h)->FlagsAndFlagmentOffset[1] = (UCHAR)((v) % 256);}
+
+// IPv4 / IPv6 common protocol
+#define IP_PROTO_TCP 0x06 // TCP protocol
+#define IP_PROTO_UDP 0x11 // UDP protocol
+#define IP_PROTO_ESP 50 // ESP protocol
+#define IP_PROTO_ETHERIP 97 // EtherIP protocol
+#define IP_PROTO_L2TPV3 115 // L2TPv3 protocol
+
+
+// UDP header
+struct UDP_HEADER
+{
+ USHORT SrcPort; // Source port number
+ USHORT DstPort; // Destination port number
+ USHORT PacketLength; // Data length
+ USHORT Checksum; // Checksum
+} GCC_PACKED;
+
+// UDPv4 pseudo header
+struct UDPV4_PSEUDO_HEADER
+{
+ UINT SrcIP; // Source IP address
+ UINT DstIP; // Destination IP address
+ UCHAR Reserved; // Unused
+ UCHAR Protocol; // Protocol number
+ USHORT PacketLength1; // UDP data length 1
+ USHORT SrcPort; // Source port number
+ USHORT DstPort; // Destination port number
+ USHORT PacketLength2; // UDP data length 2
+ USHORT Checksum; // Checksum
+} GCC_PACKED;
+
+// IPv4 pseudo header
+struct IPV4_PSEUDO_HEADER
+{
+ UINT SrcIP; // Source IP address
+ UINT DstIP; // Destination IP address
+ UCHAR Reserved; // Unused
+ UCHAR Protocol; // Protocol number
+ USHORT PacketLength; // Packet size
+} GCC_PACKED;
+
+// TCP header
+struct TCP_HEADER
+{
+ USHORT SrcPort; // Source port number
+ USHORT DstPort; // Destination port number
+ UINT SeqNumber; // Sequence number
+ UINT AckNumber; // Acknowledgment number
+ UCHAR HeaderSizeAndReserved; // Header size and Reserved area
+ UCHAR Flag; // Flag
+ USHORT WindowSize; // Window size
+ USHORT Checksum; // Checksum
+ USHORT UrgentPointer; // Urgent Pointer
+} GCC_PACKED;
+
+// TCP macro
+#define TCP_GET_HEADER_SIZE(h) (((h)->HeaderSizeAndReserved >> 4) & 0x0f)
+#define TCP_SET_HEADER_SIZE(h, v) ((h)->HeaderSizeAndReserved = (((v) & 0x0f) << 4))
+
+// TCP flags
+#define TCP_FIN 1
+#define TCP_SYN 2
+#define TCP_RST 4
+#define TCP_PSH 8
+#define TCP_ACK 16
+#define TCP_URG 32
+
+// ICMP header
+struct ICMP_HEADER
+{
+ UCHAR Type; // Type
+ UCHAR Code; // Code
+ USHORT Checksum; // Checksum
+} GCC_PACKED;
+
+// ICMP Echo
+struct ICMP_ECHO
+{
+ USHORT Identifier; // ID
+ USHORT SeqNo; // Sequence number
+} GCC_PACKED;
+
+// ICMP message type
+#define ICMP_TYPE_ECHO_REQUEST 8
+#define ICMP_TYPE_ECHO_RESPONSE 0
+#define ICMP_TYPE_DESTINATION_UNREACHABLE 3
+#define ICMP_TYPE_TIME_EXCEEDED 11
+#define ICMP_TYPE_INFORMATION_REQUEST 15
+#define ICMP_TYPE_INFORMATION_REPLY 16
+
+// ICMP message code
+// In case of ICMP_TYPE_DESTINATION_UNREACHABLE
+#define ICMP_CODE_NET_UNREACHABLE 0
+#define ICMP_CODE_HOST_UNREACHABLE 1
+#define ICMP_CODE_PROTOCOL_UNREACHABLE 2
+#define ICMP_CODE_PORT_UNREACHABLE 3
+#define ICMP_CODE_FRAGMENTATION_NEEDED_DF_SET 4
+#define ICMP_CODE_SOURCE_ROUTE_FAILED 5
+
+// In case of TIME_EXCEEDED
+#define ICMP_CODE_TTL_EXCEEDED_IN_TRANSIT 0
+#define ICMP_CODE_FRAGMENT_REASSEMBLY_TIME_EXCEEDED 1
+
+// DHCPv4 Header
+struct DHCPV4_HEADER
+{
+ UCHAR OpCode; // Op-code
+ UCHAR HardwareType; // Hardware type
+ UCHAR HardwareAddressSize; // Hardware address size
+ UCHAR Hops; // Number of hops
+ UINT TransactionId; // Transaction ID
+ USHORT Seconds; // Seconds
+ USHORT Flags; // Flag
+ UINT ClientIP; // Client IP address
+ UINT YourIP; // Assigned IP address
+ UINT ServerIP; // Server IP address
+ UINT RelayIP; // Relay IP address
+ UCHAR ClientMacAddress[6]; // Client MAC address
+ UCHAR Padding[10]; // Padding for non-Ethernet
+} GCC_PACKED;
+
+// DNSv4 header
+struct DNSV4_HEADER
+{
+ USHORT TransactionId; // Transaction ID
+ UCHAR Flag1; // Flag 1
+ UCHAR Flag2; // Flag 2
+ USHORT NumQuery; // Number of queries
+ USHORT AnswerRRs; // Answer RR number
+ USHORT AuthorityRRs; // Authority RR number
+ USHORT AdditionalRRs; // Additional RR number
+} GCC_PACKED;
+
+#define DHCP_MAGIC_COOKIE 0x63825363 // Magic Cookie (fixed)
+
+// NetBIOS Datagram header
+struct NBTDG_HEADER
+{
+ UCHAR MessageType;
+ UCHAR MoreFlagments;
+ USHORT DatagramId;
+ UINT SrcIP;
+ USHORT SrcPort;
+ USHORT DatagramLen;
+ USHORT PacketOffset;
+} GCC_PACKED;
+
+// IPv6 packet header information
+struct IPV6_HEADER_PACKET_INFO
+{
+ IPV6_HEADER *IPv6Header; // IPv6 header
+ IPV6_OPTION_HEADER *HopHeader; // Hop-by-hop option header
+ UINT HopHeaderSize; // Hop-by-hop option header size
+ IPV6_OPTION_HEADER *EndPointHeader; // End point option header
+ UINT EndPointHeaderSize; // End point option header size
+ IPV6_OPTION_HEADER *RoutingHeader; // Routing header
+ UINT RoutingHeaderSize; // Routing header size
+ IPV6_FRAGMENT_HEADER *FragmentHeader; // Fragment header
+ void *Payload; // Payload
+ UINT PayloadSize; // Payload size
+ UCHAR Protocol; // Payload protocol
+ bool IsFragment; // Whether it's a fragmented packet
+ UINT TotalHeaderSize; // Total header size
+};
+
+// IPv6 header
+struct IPV6_HEADER
+{
+ UCHAR VersionAndTrafficClass1; // Version Number (4 bit) and Traffic Class 1 (4 bit)
+ UCHAR TrafficClass2AndFlowLabel1; // Traffic Class 2 (4 bit) and Flow Label 1 (4 bit)
+ UCHAR FlowLabel2; // Flow Label 2 (8 bit)
+ UCHAR FlowLabel3; // Flow Label 3 (8 bit)
+ USHORT PayloadLength; // Length of the payload (including extension header)
+ UCHAR NextHeader; // Next header
+ UCHAR HopLimit; // Hop limit
+ IPV6_ADDR SrcAddress; // Source address
+ IPV6_ADDR DestAddress; // Destination address
+} GCC_PACKED;
+
+
+// Macro for IPv6 header operation
+#define IPV6_GET_VERSION(h) (((h)->VersionAndTrafficClass1 >> 4) & 0x0f)
+#define IPV6_SET_VERSION(h, v) ((h)->VersionAndTrafficClass1 = ((h)->VersionAndTrafficClass1 & 0x0f) | ((v) << 4) & 0xf0)
+#define IPV6_GET_TRAFFIC_CLASS(h) ((((h)->VersionAndTrafficClass1 << 4) & 0xf0) | ((h)->TrafficClass2AndFlowLabel1 >> 4) & 0x0f)
+#define IPV6_SET_TRAFFIC_CLASS(h, v) ((h)->VersionAndTrafficClass1 = ((h)->VersionAndTrafficClass1 & 0xf0) | (((v) >> 4) & 0x0f),\
+ (h)->TrafficClass2AndFlowLabel1 = (h)->TrafficClass2AndFlowLabel1 & 0x0f | ((v) << 4) & 0xf0)
+#define IPV6_GET_FLOW_LABEL(h) ((((h)->TrafficClass2AndFlowLabel1 << 16) & 0xf0000) | (((h)->FlowLabel2 << 8) & 0xff00) |\
+ (((h)->FlowLabel3) & 0xff))
+#define IPV6_SET_FLOW_LABEL(h, v) ((h)->TrafficClass2AndFlowLabel1 = ((h)->TrafficClass2AndFlowLabel1 & 0xf0 | ((v) >> 16) & 0x0f),\
+ (h)->FlowLabel2 = ((v) >> 8) & 0xff,\
+ (h)->FlowLabel3 = (v) & 0xff)
+
+
+// Maximum hops of IPv6 (not routing)
+#define IPV6_HOP_MAX 255
+
+// Standard hops of IPv6
+#define IPV6_HOP_DEFAULT 127
+
+// IPv6 header number
+#define IPV6_HEADER_HOP 0 // Hop-by-hop option header
+#define IPV6_HEADER_ENDPOINT 60 // End point option header
+#define IPV6_HEADER_ROUTING 43 // Routing header
+#define IPV6_HEADER_FRAGMENT 44 // Fragment header
+#define IPV6_HEADER_NONE 59 // No Next Header
+
+// IPv6 option header
+// (Used on hop option header, end point option header, routing header)
+struct IPV6_OPTION_HEADER
+{
+ UCHAR NextHeader; // Next header
+ UCHAR Size; // Header size (/8)
+} GCC_PACKED;
+
+// IPv6 fragment header
+// (fragment impossible part is until just before the routing header
+// or hop-by-hop option header or first extended header or payload)
+struct IPV6_FRAGMENT_HEADER
+{
+ UCHAR NextHeader; // Next header
+ UCHAR Reserved; // Reserved
+ UCHAR FlagmentOffset1; // Fragment offset 1 (/8, 8 bit)
+ UCHAR FlagmentOffset2AndFlags; // Fragment offset 2 (/8, 5 bit) + Reserved (2 bit) + More flag (1 bit)
+ UINT Identification; // ID
+} GCC_PACKED;
+
+// Macro for IPv6 fragment header operation
+#define IPV6_GET_FRAGMENT_OFFSET(h) (((((h)->FlagmentOffset1) << 5) & 0x1fe0) | (((h)->FlagmentOffset2AndFlags >> 3) & 0x1f))
+#define IPV6_SET_FRAGMENT_OFFSET(h, v) ((h)->FlagmentOffset1 = (v / 32) & 0xff, \
+ ((h)->FlagmentOffset2AndFlags = ((v % 256) << 3) & 0xf8) | ((h)->FlagmentOffset2AndFlags & 0x07))
+#define IPV6_GET_FLAGS(h) ((h)->FlagmentOffset2AndFlags & 0x0f)
+#define IPV6_SET_FLAGS(h, v) ((h)->FlagmentOffset2AndFlags = (((h)->FlagmentOffset2AndFlags & 0xf8) | (v & 0x07)))
+
+// Flag
+#define IPV6_FRAGMENT_HEADER_FLAG_MORE_FRAGMENTS 0x01 // There are more fragments
+
+// Virtual IPv6 header
+struct IPV6_PSEUDO_HEADER
+{
+ IPV6_ADDR SrcAddress; // Source address
+ IPV6_ADDR DestAddress; // Destination address
+ UINT UpperLayerPacketSize; // Upper layer packet size
+ UCHAR Padding[3]; // Padding
+ UCHAR NextHeader; // Next Header (TCP / UDP)
+} GCC_PACKED;
+
+// ICMPv6 Router Solicitation header
+struct ICMPV6_ROUTER_SOLICIATION_HEADER
+{
+ UINT Reserved; // Reserved
+ // + Option (source link-layer address [optional])
+} GCC_PACKED;
+
+// ICMPv6 Router Advertisement header
+struct ICMPV6_ROUTER_ADVERTISEMENT_HEADER
+{
+ UCHAR CurHopLimit; // Hop limit of the default
+ UCHAR Flags; // Flag (0)
+ USHORT Lifetime; // Lifetime
+ UINT ReachableTime; // 0
+ UINT RetransTimer; // 0
+ // + Option (prefix information [required], MTU [optional])
+} GCC_PACKED;
+
+// ICMPv6 Neighbor Solicitation header
+struct ICMPV6_NEIGHBOR_SOLICIATION_HEADER
+{
+ UINT Reserved; // Reserved
+ IPV6_ADDR TargetAddress; // Target address
+ // + Option (source link-layer address [required])
+} GCC_PACKED;
+
+// ICMPv6 Neighbor Advertisement header
+struct ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER
+{
+ UCHAR Flags; // Flag
+ UCHAR Reserved[3]; // Reserved
+ IPV6_ADDR TargetAddress; // Target address
+ // + Option (target link-layer address)
+} GCC_PACKED;
+
+#define ICMPV6_NEIGHBOR_ADVERTISEMENT_FLAG_ROUTER 0x80 // Router
+#define ICMPV6_NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED 0x40 // Solicited flag
+#define ICMPV6_NEIGHBOR_ADVERTISEMENT_FLAG_OVERWRITE 0x20 // Overwrite flag
+
+// ICMPv6 option list
+struct ICMPV6_OPTION_LIST
+{
+ ICMPV6_OPTION_LINK_LAYER *SourceLinkLayer; // Source link-layer address
+ ICMPV6_OPTION_LINK_LAYER *TargetLinkLayer; // Target link-layer address
+ ICMPV6_OPTION_PREFIX *Prefix; // Prefix Information
+ ICMPV6_OPTION_MTU *Mtu; // MTU
+} GCC_PACKED;
+
+// ICMPv6 option
+struct ICMPV6_OPTION
+{
+ UCHAR Type; // Type
+ UCHAR Length; // Length (/8, include type and length)
+} GCC_PACKED;
+
+#define ICMPV6_OPTION_TYPE_SOURCE_LINK_LAYER 1 // Source link-layer address
+#define ICMPV6_OPTION_TYPE_TARGET_LINK_LAYER 2 // Target link-layer address
+#define ICMPV6_OPTION_TYPE_PREFIX 3 // Prefix Information
+#define ICMPV6_OPTION_TYPE_MTU 5 // MTU
+
+// ICMPv6 link layer options
+struct ICMPV6_OPTION_LINK_LAYER
+{
+ ICMPV6_OPTION IcmpOptionHeader; // Option header
+ UCHAR Address[6]; // MAC address
+} GCC_PACKED;
+
+// ICMPv6 prefix information option
+struct ICMPV6_OPTION_PREFIX
+{
+ ICMPV6_OPTION IcmpOptionHeader; // Option header
+ UCHAR SubnetLength; // Subnet length
+ UCHAR Flags; // Flag
+ UINT ValidLifetime; // Formal lifetime
+ UINT PreferredLifetime; // Preferred lifetime
+ UINT Reserved; // Reserved
+ IPV6_ADDR Prefix; // Prefix address
+} GCC_PACKED;
+
+#define ICMPV6_OPTION_PREFIX_FLAG_ONLINK 0x80 // On link
+#define ICMPV6_OPTION_PREFIX_FLAG_AUTO 0x40 // Automatic
+
+// ICMPv6 MTU option
+struct ICMPV6_OPTION_MTU
+{
+ ICMPV6_OPTION IcmpOptionHeader; // Option header
+ USHORT Reserved; // Reserved
+ UINT Mtu; // MTU value
+} GCC_PACKED;
+
+
+// IPv6 header information
+struct IPV6_HEADER_INFO
+{
+ bool IsRawIpPacket;
+ USHORT Size;
+ UINT Id;
+ UCHAR Protocol;
+ UCHAR HopLimit;
+ IPV6_ADDR SrcIpAddress;
+ IPV6_ADDR DestIpAddress;
+ bool UnicastForMe;
+ bool UnicastForRouting;
+ bool UnicastForRoutingWithProxyNdp;
+ bool IsBroadcast;
+ UINT TypeL4;
+};
+
+// ICMPv6 header information
+struct ICMPV6_HEADER_INFO
+{
+ UCHAR Type;
+ UCHAR Code;
+ USHORT DataSize;
+ void *Data;
+ ICMP_ECHO EchoHeader;
+ void *EchoData;
+ UINT EchoDataSize;
+
+ union
+ {
+ // Meaning is determined by the value of the Type
+ ICMPV6_ROUTER_SOLICIATION_HEADER *RouterSoliciationHeader;
+ ICMPV6_ROUTER_ADVERTISEMENT_HEADER *RouterAdvertisementHeader;
+ ICMPV6_NEIGHBOR_SOLICIATION_HEADER *NeighborSoliciationHeader;
+ ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER *NeighborAdvertisementHeader;
+ void *HeaderPointer;
+ } Headers;
+
+ ICMPV6_OPTION_LIST OptionList;
+};
+
+// The Type value of ICMPv6
+#define ICMPV6_TYPE_ECHO_REQUEST 128 // ICMPv6 Echo request
+#define ICMPV6_TYPE_ECHO_RESPONSE 129 // ICMPv6 Echo response
+#define ICMPV6_TYPE_ROUTER_SOLICIATION 133 // Router Solicitation
+#define ICMPV6_TYPE_ROUTER_ADVERTISEMENT 134 // Router Advertisement
+#define ICMPV6_TYPE_NEIGHBOR_SOLICIATION 135 // Neighbor Solicitation
+#define ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT 136 // Neighbor Advertisement
+
+// Minimum DHCP packet size
+#define DHCP_MIN_SIZE 300
+
+// Constants about DHCP
+#define DHCP_ID_MESSAGE_TYPE 0x35
+#define DHCP_ID_REQUEST_IP_ADDRESS 0x32
+#define DHCP_ID_HOST_NAME 0x0c
+#define DHCP_ID_SERVER_ADDRESS 0x36
+#define DHCP_ID_LEASE_TIME 0x33
+#define DHCP_ID_DOMAIN_NAME 0x0f
+#define DHCP_ID_SUBNET_MASK 0x01
+#define DHCP_ID_GATEWAY_ADDR 0x03
+#define DHCP_ID_DNS_ADDR 0x06
+#define DHCP_ID_WINS_ADDR 0x2C
+#define DHCP_ID_CLIENT_ID 0x3d
+#define DHCP_ID_VENDOR_ID 0x3c
+#define DHCP_ID_REQ_PARAM_LIST 0x37
+
+// DHCP client action
+#define DHCP_DISCOVER 1
+#define DHCP_REQUEST 3
+#define DHCP_RELEASE 7
+#define DHCP_INFORM 8
+
+// DHCP server action
+#define DHCP_OFFER 2
+#define DHCP_DECLINE 4
+#define DHCP_ACK 5
+#define DHCP_NACK 6
+
+// HTTPLOG data structure
+struct HTTPLOG
+{
+ char Method[32]; // Method
+ char Hostname[MAX_HOST_NAME_LEN + 1]; // Host name
+ UINT Port; // Port number
+ char Path[MAX_SIZE]; // Path
+ char Protocol[64]; // Protocol
+ char UserAgent[MAX_SIZE]; // User Agent value
+ char Referer[MAX_SIZE]; // Referer
+};
+
+// Packet
+struct PKT
+{
+ UCHAR *PacketData; // Packet data body
+ UINT PacketSize; // Packet size
+ MAC_HEADER *MacHeader; // MAC header
+ UCHAR *MacAddressSrc; // Source MAC address
+ UCHAR *MacAddressDest; // Destination MAC address
+ bool BroadcastPacket; // Broadcast packet
+ bool InvalidSourcePacket; // Packet with an invalid source address
+ bool AccessChecked; // Packets that pass was confirmed by the access list
+ UINT VlanTypeID; // TypeID of the tagged VLAN (usually 0x8100)
+ UINT VlanId; // VLAN ID
+ UINT Delay; // Delay
+ UINT Jitter; // Jitter
+ UINT Loss; // Packet loss
+ UINT64 DelayedForwardTick; // Sending time in case of delayed
+ struct SESSION *DelayedSrcSession; // Source session
+ UINT TypeL3; // Layer-3 packet classification
+ IPV6_HEADER_PACKET_INFO IPv6HeaderPacketInfo; // IPv6 packet header information (only for TypeL3 == L3_IPV6)
+ ICMPV6_HEADER_INFO ICMPv6HeaderPacketInfo; // ICMPv6 header information (Only for TypeL4 == L4_ICMPV6)
+ UINT DhcpOpCode; // DHCP opcode
+ union
+ {
+ IPV4_HEADER *IPv4Header; // IPv4 header
+ ARPV4_HEADER *ARPv4Header; // ARPv4 header
+ IPV6_HEADER *IPv6Header; // IPv6 header
+ TAGVLAN_HEADER *TagVlanHeader; // Tag header
+ BPDU_HEADER *BpduHeader; // BPDU header
+ void *PointerL3;
+ } L3;
+ UINT TypeL4; // Layer-4 packet classification
+ UINT IPv4PayloadSize; // IPv4 payload size
+ void *IPv4PayloadData; // IPv4 payload data
+ union
+ {
+ UDP_HEADER *UDPHeader; // UDP header
+ TCP_HEADER *TCPHeader; // TCP header
+ ICMP_HEADER *ICMPHeader; // ICMP header
+ void *PointerL4;
+ } L4;
+ UINT TypeL7; // Layer-7 packet classification
+ union
+ {
+ DHCPV4_HEADER *DHCPv4Header; // DHCPv4 header
+ IKE_HEADER *IkeHeader; // IKE header
+ void *PointerL7;
+ } L7;
+ UCHAR *Payload; // Pointer to the payload of TCP or UDP
+ UINT PayloadSize; // Payload size
+ struct HTTPLOG *HttpLog; // HTTP log
+} GCC_PACKED;
+
+// Layer-3 packet classification
+#define L3_UNKNOWN 0 // Unknown
+#define L3_ARPV4 1 // ARPv4 packet
+#define L3_IPV4 2 // IPv4 packet
+#define L3_TAGVLAN 3 // Tagged VLAN packet
+#define L3_BPDU 4 // BPDU packet
+#define L3_IPV6 5 // IPv6 packet
+
+// Layer-4 packet classification
+#define L4_UNKNOWN 0 // Unknown
+#define L4_UDP 1 // UDPv4 packet
+#define L4_TCP 2 // TCPv4 packet
+#define L4_ICMPV4 3 // ICMPv4 packet
+#define L4_ICMPV6 4 // ICMPv6 packet
+#define L4_FRAGMENT 5 // Fragment packet
+
+// Layer-7 packet classification
+#define L7_UNKNOWN 0 // Unknown
+#define L7_DHCPV4 1 // DHCPv4 packet
+#define L7_IKECONN 2 // IKE connection request packet
+#define L7_OPENVPNCONN 3 // OpenVPN connection request packet
+
+
+// IKE header
+struct IKE_HEADER
+{
+ UINT64 InitiatorCookie; // Initiator cookie
+ UINT64 ResponderCookie; // Responder cookie
+ UCHAR NextPayload; // Next payload
+ UCHAR Version; // Version
+ UCHAR ExchangeType; // Exchange type
+ UCHAR Flag; // Flag
+ UINT MessageId; // Message ID
+ UINT MessageSize; // Message size
+} GCC_PACKED;
+
+// IKE exchange type
+#define IKE_EXCHANGE_TYPE_MAIN 2 // Main mode
+#define IKE_EXCHANGE_TYPE_AGGRESSIVE 4 // Aggressive mode
+#define IKE_EXCHANGE_TYPE_INFORMATION 5 // Information exchange
+#define IKE_EXCHANGE_TYPE_QUICK 32 // Quick mode
+
+// DHCPv4 data
+struct DHCPV4_DATA
+{
+ UCHAR *Data;
+ UINT Size;
+ IP SrcIP;
+ UINT SrcPort;
+ IP DestIP;
+ UINT DestPort;
+ UINT OpCode;
+
+ UCHAR *OptionData;
+ UINT OptionSize;
+
+ DHCPV4_HEADER *Header;
+ LIST *OptionList;
+
+ struct DHCP_OPTION_LIST *ParsedOptionList;
+};
+// DHCP Option
+struct DHCP_OPTION
+{
+ UINT Id; // ID
+ UINT Size; // Size
+ void *Data; // Data
+};
+
+// DHCP option list
+struct DHCP_OPTION_LIST
+{
+ // Common Item
+ UINT Opcode; // DHCP opcode
+
+ // Client request
+ UINT RequestedIp; // Requested IP address
+ char Hostname[MAX_HOST_NAME_LEN + 1]; // Host name
+
+ // Server response
+ UINT ClientAddress; // Client address
+ UINT ServerAddress; // DHCP server address
+ UINT LeaseTime; // Lease time
+ char DomainName[MAX_HOST_NAME_LEN + 1]; // Domain name
+ UINT SubnetMask; // Subnet mask
+ UINT Gateway; // Gateway address
+ UINT DnsServer; // DNS server address 1
+ UINT DnsServer2; // DNS server address 2
+ UINT WinsServer; // WINS server address 1
+ UINT WinsServer2; // WINS server address 2
+};
+
+// Modification option in the DHCP packet
+struct DHCP_MODIFY_OPTION
+{
+ bool RemoveDefaultGatewayOnReply; // Remove the default gateway from the DHCP Reply
+};
+
+// Special IP address
+#define SPECIAL_IPV4_ADDR_LLMNR_DEST 0xE00000FC // 224.0.0.252
+
+// Special port
+#define SPECIAL_UDP_PORT_LLMNR 5355 // LLMNR
+#define SPECIAL_UDP_PORT_NBTNS 137 // NetBIOS Name Service
+#define SPECIAL_UDP_PORT_NBTDGM 138 // NetBIOS Datagram
+#define SPECIAL_UDP_PORT_WSD 3702 // WS-Discovery
+#define SPECIAL_UDP_PORT_SSDP 1900 // SSDP
+
+
+PKT *ParsePacketIPv4WithDummyMacHeader(UCHAR *buf, UINT size);
+PKT *ParsePacket(UCHAR *buf, UINT size);
+PKT *ParsePacketEx(UCHAR *buf, UINT size, bool no_l3);
+PKT *ParsePacketEx2(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id);
+PKT *ParsePacketEx3(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address);
+PKT *ParsePacketEx4(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address, bool no_http, bool correct_checksum);
+void FreePacket(PKT *p);
+void FreePacketWithData(PKT *p);
+void FreePacketIPv4(PKT *p);
+void FreePacketTagVlan(PKT *p);
+void FreePacketARPv4(PKT *p);
+void FreePacketUDPv4(PKT *p);
+void FreePacketTCPv4(PKT *p);
+void FreePacketICMPv4(PKT *p);
+void FreePacketDHCPv4(PKT *p);
+bool ParsePacketL2(PKT *p, UCHAR *buf, UINT size);
+bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3);
+bool ParsePacketARPv4(PKT *p, UCHAR *buf, UINT size);
+bool ParsePacketIPv4(PKT *p, UCHAR *buf, UINT size);
+bool ParsePacketBPDU(PKT *p, UCHAR *buf, UINT size);
+bool ParsePacketTAGVLAN(PKT *p, UCHAR *buf, UINT size);
+bool ParseICMPv4(PKT *p, UCHAR *buf, UINT size);
+bool ParseICMPv6(PKT *p, UCHAR *buf, UINT size);
+bool ParseTCP(PKT *p, UCHAR *buf, UINT size);
+bool ParseUDP(PKT *p, UCHAR *buf, UINT size);
+void ParseDHCPv4(PKT *p, UCHAR *buf, UINT size);
+PKT *ClonePacket(PKT *p, bool copy_data);
+void FreeClonePacket(PKT *p);
+
+void CorrectChecksum(PKT *p);
+
+bool ParsePacketIPv6(PKT *p, UCHAR *buf, UINT size);
+bool ParsePacketIPv6Header(IPV6_HEADER_PACKET_INFO *info, UCHAR *buf, UINT size);
+bool ParseIPv6ExtHeader(IPV6_HEADER_PACKET_INFO *info, UCHAR next_header, UCHAR *buf, UINT size);
+bool ParseICMPv6Options(ICMPV6_OPTION_LIST *o, UCHAR *buf, UINT size);
+void CloneICMPv6Options(ICMPV6_OPTION_LIST *dst, ICMPV6_OPTION_LIST *src);
+void FreeCloneICMPv6Options(ICMPV6_OPTION_LIST *o);
+USHORT CalcChecksumForIPv4(UINT src_ip, UINT dst_ip, UCHAR protocol, void *data, UINT size, UINT real_size);
+USHORT CalcChecksumForIPv6(IPV6_ADDR *src_ip, IPV6_ADDR *dest_ip, UCHAR protocol, void *data, UINT size, UINT real_size);
+BUF *BuildICMPv6Options(ICMPV6_OPTION_LIST *o);
+void BuildICMPv6OptionValue(BUF *b, UCHAR type, void *header_pointer, UINT total_size);
+BUF *BuildIPv6(IPV6_ADDR *dest_ip, IPV6_ADDR *src_ip, UINT id, UCHAR protocol, UCHAR hop_limit, void *data,
+ UINT size);
+BUF *BuildIPv6PacketHeader(IPV6_HEADER_PACKET_INFO *info, UINT *bytes_before_payload);
+UCHAR IPv6GetNextHeaderFromQueue(QUEUE *q);
+void BuildAndAddIPv6PacketOptionHeader(BUF *b, IPV6_OPTION_HEADER *opt, UCHAR next_header, UINT size);
+BUF *BuildICMPv6NeighborSoliciation(IPV6_ADDR *src_ip, IPV6_ADDR *target_ip, UCHAR *my_mac_address, UINT id);
+BUF *BuildICMPv6(IPV6_ADDR *src_ip, IPV6_ADDR *dest_ip, UCHAR hop_limit, UCHAR type, UCHAR code, void *data, UINT size, UINT id);
+
+bool VLanRemoveTag(void **packet_data, UINT *packet_size, UINT vlan_id, UINT vlan_tpid);
+void VLanInsertTag(void **packet_data, UINT *packet_size, UINT vlan_id, UINT vlan_tpid);
+
+DHCPV4_DATA *ParseDHCPv4Data(PKT *pkt);
+void FreeDHCPv4Data(DHCPV4_DATA *d);
+
+bool AdjustTcpMssL3(UCHAR *src, UINT src_size, UINT mss);
+bool AdjustTcpMssL2(UCHAR *src, UINT src_size, UINT mss, USHORT tag_vlan_tpid);
+UINT GetIpHeaderSize(UCHAR *src, UINT src_size);
+
+bool IsDhcpPacketForSpecificMac(UCHAR *data, UINT size, UCHAR *mac_address);
+
+ICMP_RESULT *IcmpEchoSendBySocket(IP *dest_ip, UCHAR ttl, UCHAR *data, UINT size, UINT timeout);
+ICMP_RESULT *IcmpEchoSend(IP *dest_ip, UCHAR ttl, UCHAR *data, UINT size, UINT timeout);
+ICMP_RESULT *IcmpParseResult(IP *dest_ip, USHORT src_id, USHORT src_seqno, UCHAR *recv_buffer, UINT recv_buffer_size);
+void IcmpFreeResult(ICMP_RESULT *r);
+
+USHORT IpChecksum(void *buf, UINT size);
+bool IpCheckChecksum(IPV4_HEADER *ip);
+
+LIST *BuildDhcpOption(DHCP_OPTION_LIST *opt);
+DHCP_OPTION *NewDhcpOption(UINT id, void *data, UINT size);
+DHCP_OPTION_LIST *ParseDhcpOptionList(void *data, UINT size);
+DHCP_OPTION *GetDhcpOption(LIST *o, UINT id);
+void FreeDhcpOptions(LIST *o);
+LIST *ParseDhcpOptions(void *data, UINT size);
+BUF *BuildDhcpOptionsBuf(LIST *o);
+HTTPLOG *ParseHttpAccessLog(PKT *pkt);
+
+BUF *DhcpModify(DHCP_MODIFY_OPTION *m, void *data, UINT size);
+BUF *DhcpModifyIPv4(DHCP_MODIFY_OPTION *m, void *data, UINT size);
+
+
+
+#ifdef OS_WIN32
+#pragma pack(pop)
+#endif // OS_WIN32
+
+#endif // TCPIP_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Tick64.c b/src/Mayaqua/Tick64.c
new file mode 100644
index 00000000..91224cdf
--- /dev/null
+++ b/src/Mayaqua/Tick64.c
@@ -0,0 +1,378 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Tick64.c
+// 64-bit real-time clock program
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+#include <windows.h>
+#endif // WIN32
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <locale.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+static TICK64 *tk64 = NULL;
+static EVENT *halt_tick_event = NULL;
+
+// Get the high-resolution time
+UINT64 TickHighres64()
+{
+ UINT64 ret = 0;
+
+#ifdef OS_WIN32
+
+ ret = (UINT64)(MsGetHiResTimeSpan(MsGetHiResCounter()) * 1000.0f);
+
+#else // OS_WIN32
+
+ return Tick64();
+
+#endif // OS_WIN32
+
+ return ret;
+}
+
+// Convert the Tick value to time
+UINT64 Tick64ToTime64(UINT64 tick)
+{
+ UINT64 ret = 0;
+ if (tick == 0)
+ {
+ return 0;
+ }
+ LockList(tk64->AdjustTime);
+ {
+ UINT i;
+ for (i = 0;i < LIST_NUM(tk64->AdjustTime);i++)
+ {
+ ADJUST_TIME *t = LIST_DATA(tk64->AdjustTime, i);
+ if (t->Tick <= tick)
+ {
+ ret = t->Time + (tick - t->Tick);
+ }
+ }
+ }
+ UnlockList(tk64->AdjustTime);
+ if (ret == 0)
+ {
+ ret++;
+ }
+ return ret;
+}
+
+// Convert the Tick value to time
+UINT64 TickToTime(UINT64 tick)
+{
+ return Tick64ToTime64(tick);
+}
+
+// Get the Tick value
+UINT64 Tick64()
+{
+#ifdef OS_WIN32
+ return Win32FastTick64();
+#else // OS_WIN32
+ UINT64 tick64;
+ if (tk64 == NULL)
+ {
+ return 0;
+ }
+ Lock(tk64->TickLock);
+ {
+ tick64 = tk64->Tick;
+ }
+ Unlock(tk64->TickLock);
+ return tick64;
+#endif // OS_WIN32
+}
+
+// Real-time clock measuring thread
+void Tick64Thread(THREAD *thread, void *param)
+{
+ UINT n = 0;
+ bool first = false;
+ bool create_first_entry = true;
+ UINT tick_span;
+ // Validate arguments
+ if (thread == NULL)
+ {
+ return;
+ }
+
+#ifdef OS_WIN32
+
+ // Raise the priority of the Win32 thread
+ MsSetThreadPriorityRealtime();
+
+ tick_span = TICK64_SPAN_WIN32;
+
+#else // OS_WIN32
+
+ // Raise the priority of a POSIX threads
+ UnixSetThreadPriorityRealtime();
+
+ tick_span = TICK64_SPAN;
+
+#endif // OS_WIN32
+
+ while (true)
+ {
+ UINT tick;
+ UINT64 tick64;
+
+#ifndef OS_WIN32
+ tick = TickRealtime(); // Get the current system clock
+
+ if (tk64->LastTick > tick)
+ {
+ if ((tk64->LastTick - tick) >= (UINT64)0x0fffffff)
+ {
+ // The Tick has gone lap around
+ tk64->RoundCount++;
+ }
+ else
+ {
+ // tick skewed (System administrator might change hardware clock)
+ // Normally, the clock skew appears as sub-seconds error
+ tick = tk64->LastTick;
+ }
+ }
+ tk64->LastTick = tick;
+
+ tick64 = (UINT64)tk64->RoundCount * (UINT64)4294967296LL + (UINT64)tick;
+
+ Lock(tk64->TickLock);
+ {
+ if (tk64->TickStart == 0)
+ {
+ tk64->TickStart = tick64;
+ }
+ tick64 = tk64->Tick = tick64 - tk64->TickStart + (UINT64)1;
+ }
+ Unlock(tk64->TickLock);
+#else // OS_WIN32
+ tick64 = Win32FastTick64();
+ tick = (UINT)tick64;
+#endif // OS_WIN32
+
+ if (create_first_entry)
+ {
+ ADJUST_TIME *t = ZeroMalloc(sizeof(ADJUST_TIME));
+ t->Tick = tick64;
+ t->Time = SystemTime64();
+ tk64->Tick64WithTime64 = tick64;
+ tk64->Time64 = t->Time;
+ Add(tk64->AdjustTime, t);
+
+ // Notify the completion of the initialization
+ NoticeThreadInit(thread);
+ create_first_entry = false;
+ }
+
+ // Time correction
+ n += tick_span;
+ if (n >= 1000 || first == false)
+ {
+ UINT64 now = SystemTime64();
+
+ if (now < tk64->Time64 ||
+ Diff64((now - tk64->Time64) + tk64->Tick64WithTime64, tick64) >= tick_span)
+ {
+ ADJUST_TIME *t = ZeroMalloc(sizeof(ADJUST_TIME));
+ LockList(tk64->AdjustTime);
+ {
+ t->Tick = tick64;
+ t->Time = now;
+ Add(tk64->AdjustTime, t);
+ Debug("Adjust Time: Tick = %I64u, Time = %I64u\n",
+ t->Tick, t->Time);
+
+ // To prevent consuming memory infinite on a system that clock is skewd
+ if (LIST_NUM(tk64->AdjustTime) > MAX_ADJUST_TIME)
+ {
+ // Remove the second
+ ADJUST_TIME *t2 = LIST_DATA(tk64->AdjustTime, 1);
+
+ Delete(tk64->AdjustTime, t2);
+
+ Debug("NUM_ADJUST TIME: %u\n", LIST_NUM(tk64->AdjustTime));
+
+ Free(t2);
+ }
+ }
+ UnlockList(tk64->AdjustTime);
+ tk64->Time64 = now;
+ tk64->Tick64WithTime64 = tick64;
+ }
+ first = true;
+ n = 0;
+ }
+
+ if (tk64->Halt)
+ {
+ break;
+ }
+
+#ifdef OS_WIN32
+ Wait(halt_tick_event, tick_span);
+#else // OS_WIN32
+ SleepThread(tick_span);
+#endif // OS_WIN32
+ }
+}
+
+// Get the absolute value of the difference between the two 64 bit integers
+UINT64 Diff64(UINT64 a, UINT64 b)
+{
+ if (a > b)
+ {
+ return a - b;
+ }
+ else
+ {
+ return b - a;
+ }
+}
+
+// Initialization of the Tick64
+void InitTick64()
+{
+ if (tk64 != NULL)
+ {
+ // Already initialized
+ return;
+ }
+
+ halt_tick_event = NewEvent();
+
+ // Initialize the structure
+ tk64 = ZeroMalloc(sizeof(TICK64));
+ tk64->TickLock = NewLock();
+ tk64->AdjustTime = NewList(NULL);
+
+ // Creating a thread
+ tk64->Thread = NewThread(Tick64Thread, NULL);
+ WaitThreadInit(tk64->Thread);
+}
+
+// Release of the Tick64
+void FreeTick64()
+{
+ UINT i;
+ if (tk64 == NULL)
+ {
+ // Uninitialized
+ return;
+ }
+
+ // Termination process
+ tk64->Halt = true;
+ Set(halt_tick_event);
+ WaitThread(tk64->Thread, INFINITE);
+ ReleaseThread(tk64->Thread);
+
+ // Releasing process
+ for (i = 0;i < LIST_NUM(tk64->AdjustTime);i++)
+ {
+ ADJUST_TIME *t = LIST_DATA(tk64->AdjustTime, i);
+ Free(t);
+ }
+ ReleaseList(tk64->AdjustTime);
+ DeleteLock(tk64->TickLock);
+ Free(tk64);
+ tk64 = NULL;
+
+ ReleaseEvent(halt_tick_event);
+ halt_tick_event = NULL;
+}
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Tick64.h b/src/Mayaqua/Tick64.h
new file mode 100644
index 00000000..8d5b5eed
--- /dev/null
+++ b/src/Mayaqua/Tick64.h
@@ -0,0 +1,134 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Tick64.h
+// Header of Tick64.c
+
+#ifndef TICK64_H
+#define TICK64_H
+
+// Maximum number of correction list entries
+#define MAX_ADJUST_TIME 5000
+
+// Correction list entry
+struct ADJUST_TIME
+{
+ UINT64 Tick;
+ UINT64 Time;
+};
+
+// TICK64 structure
+struct TICK64
+{
+ THREAD *Thread;
+ UINT64 Tick;
+ UINT64 TickStart;
+ UINT64 Time64;
+ UINT64 Tick64WithTime64;
+ UINT LastTick;
+ UINT RoundCount;
+ LOCK *TickLock;
+ volatile bool Halt;
+ LIST *AdjustTime;
+};
+
+// Constant
+#define TICK64_SPAN 10 // Measurement interval (Usually less than 10ms)
+#define TICK64_SPAN_WIN32 1000 // Interval of measurement on Win32
+#define TICK64_ADJUST_SPAN 5000 // Correct the clock if it shifts more than this value
+
+// Function prototype
+void InitTick64();
+void FreeTick64();
+void Tick64Thread(THREAD *thread, void *param);
+UINT64 Tick64();
+UINT64 Diff64(UINT64 a, UINT64 b);
+UINT64 Tick64ToTime64(UINT64 tick);
+UINT64 TickToTime(UINT64 tick);
+UINT64 TickHighres64();
+
+#endif // TICK64_H
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Tracking.c b/src/Mayaqua/Tracking.c
new file mode 100644
index 00000000..55bb9284
--- /dev/null
+++ b/src/Mayaqua/Tracking.c
@@ -0,0 +1,975 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Tracking.c
+// Object tracking module
+
+#include <GlobalConst.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// Global variables
+static LOCK *obj_lock;
+static LOCK *obj_id_lock;
+static UINT obj_id;
+static LOCK *cs_lock;
+static bool disable_tracking = false;
+static TRACKING_LIST **hashlist;
+
+static bool do_not_get_callstack;
+
+// Enable the tracking
+void TrackingEnable()
+{
+ disable_tracking = false;
+}
+
+// Disable the tracking
+void TrackingDisable()
+{
+ disable_tracking = true;
+}
+
+// Get whether the tracking is enabled
+bool IsTrackingEnabled()
+{
+ return !disable_tracking;
+}
+
+// Memory debug menu
+void MemoryDebugMenu()
+{
+ char tmp[MAX_SIZE];
+ TOKEN_LIST *t;
+ char *cmd;
+ Print("Mayaqua Kernel Memory Debug Tools\n"
+ "Copyright (c) SoftEther Corporation. All Rights Reserved.\n\n");
+ g_memcheck = false;
+ while (true)
+ {
+ Print("debug>");
+ GetLine(tmp, sizeof(tmp));
+ t = ParseToken(tmp, " \t");
+ if (t->NumTokens == 0)
+ {
+ FreeToken(t);
+ DebugPrintAllObjects();
+ continue;
+ }
+ cmd = t->Token[0];
+ if (!StrCmpi(cmd, "?"))
+ {
+ DebugPrintCommandList();
+ }
+ else if (!StrCmpi(cmd, "a"))
+ {
+ DebugPrintAllObjects();
+ }
+ else if (!StrCmpi(cmd, "i"))
+ {
+ if (t->NumTokens == 1)
+ {
+ Print("Usage: i <obj_id>\n\n");
+ }
+ else
+ {
+ DebugPrintObjectInfo(ToInt(t->Token[1]));
+ }
+ }
+ else if (!StrCmpi(cmd, "q"))
+ {
+ break;
+ }
+ else if (ToInt(cmd) != 0)
+ {
+ DebugPrintObjectInfo(ToInt(t->Token[0]));
+ }
+ else
+ {
+ Print("Command Not Found,\n\n");
+ }
+ FreeToken(t);
+ }
+ FreeToken(t);
+ g_memcheck = true;
+}
+
+// Sort the objects by chronological order
+int SortObjectView(void *p1, void *p2)
+{
+ TRACKING_OBJECT *o1, *o2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ o1 = *(TRACKING_OBJECT **)p1;
+ o2 = *(TRACKING_OBJECT **)p2;
+ if (o1 == NULL || o2 == NULL)
+ {
+ return 0;
+ }
+
+ if (o1->Id > o2->Id)
+ {
+ return 1;
+ }
+ else if (o1->Id == o2->Id)
+ {
+ return 0;
+ }
+ return -1;
+}
+
+// Display the information of the object
+void PrintObjectInfo(TRACKING_OBJECT *o)
+{
+ SYSTEMTIME t;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ UINT64ToSystem(&t, o->CreatedDate);
+ GetDateTimeStrMilli(tmp, sizeof(tmp), &t);
+
+ Print(" TRACKING_OBJECT ID: %u\n"
+ " TRACKING_OBJECT TYPE: %s\n"
+ " ADDRESS: 0x%p\n"
+ " TRACKING_OBJECT SIZE: %u bytes\n"
+ " CREATED DATE: %s\n",
+ o->Id, o->Name, UINT64_TO_POINTER(o->Address), o->Size, tmp);
+
+ PrintCallStack(o->CallStack);
+}
+
+// Display the object information
+void DebugPrintObjectInfo(UINT id)
+{
+ UINT i;
+ TRACKING_OBJECT *o;
+
+ // Search
+ o = NULL;
+ LockTrackingList();
+ {
+ for (i = 0;i < TRACKING_NUM_ARRAY;i++)
+ {
+ if (hashlist[i] != NULL)
+ {
+ TRACKING_LIST *t = hashlist[i];
+
+ while (true)
+ {
+ if (t->Object->Id == id)
+ {
+ o = t->Object;
+ break;
+ }
+
+ if (t->Next == NULL)
+ {
+ break;
+ }
+
+ t = t->Next;
+ }
+
+ if (o != NULL)
+ {
+ break;
+ }
+ }
+ }
+ }
+ UnlockTrackingList();
+
+ if (o == NULL)
+ {
+ // The ID could not be found
+ Print("obj_id %u Not Found.\n\n", id);
+ return;
+ }
+
+ PrintObjectInfo(o);
+ Print("\n");
+}
+
+// Show a Summary of the object
+void PrintObjectList(TRACKING_OBJECT *o)
+{
+ char tmp[MAX_SIZE];
+ SYSTEMTIME t;
+ UINT64ToSystem(&t, o->CreatedDate);
+ GetTimeStrMilli(tmp, sizeof(tmp), &t);
+ TrackGetObjSymbolInfo(o);
+ Print("%-4u - [%-6s] %s 0x%p size=%-5u %11s %u\n",
+ o->Id, o->Name, tmp, UINT64_TO_POINTER(o->Address), o->Size, o->FileName, o->LineNumber);
+}
+
+// Display all the objects
+void DebugPrintAllObjects()
+{
+ UINT i;
+ LIST *view;
+
+ // Creating a List
+ view = NewListFast(SortObjectView);
+ LockTrackingList();
+ {
+ for (i = 0;i < TRACKING_NUM_ARRAY;i++)
+ {
+ if (hashlist[i] != NULL)
+ {
+ TRACKING_LIST *t = hashlist[i];
+
+ while (true)
+ {
+ Add(view, t->Object);
+
+ if (t->Next == NULL)
+ {
+ break;
+ }
+
+ t = t->Next;
+ }
+ }
+ }
+ }
+ UnlockTrackingList();
+
+ // Sort
+ Sort(view);
+
+ // Drawing
+ for (i = 0;i < LIST_NUM(view);i++)
+ {
+ TRACKING_OBJECT *o = (TRACKING_OBJECT *)LIST_DATA(view, i);
+ PrintObjectList(o);
+ }
+
+ // Release the list
+ ReleaseList(view);
+
+ Print("\n");
+}
+
+// List of the commands
+void DebugPrintCommandList()
+{
+ Print(
+ "a - All Objects\n"
+ "i - Object Information\n"
+ "? - Help\n"
+ "q - Quit\n\n"
+ );
+}
+
+// Display the usage of the memory
+void PrintMemoryStatus()
+{
+ MEMORY_STATUS s;
+ GetMemoryStatus(&s);
+ Print("MEMORY STATUS:\n"
+ " NUM_OF_MEMORY_BLOCKS: %u\n"
+ " SIZE_OF_TOTAL_MEMORY: %u bytes\n",
+ s.MemoryBlocksNum, s.MemorySize);
+}
+
+// Get the using state of the memory
+void GetMemoryStatus(MEMORY_STATUS *status)
+{
+ UINT i, num, size;
+ // Validate arguments
+ if (status == NULL)
+ {
+ return;
+ }
+
+ LockTrackingList();
+ {
+ size = num = 0;
+
+ for (i = 0;i < TRACKING_NUM_ARRAY;i++)
+ {
+ if (hashlist[i] != NULL)
+ {
+ TRACKING_LIST *t = hashlist[i];
+
+ while (true)
+ {
+ TRACKING_OBJECT *o = t->Object;
+
+ if (StrCmpi(o->Name, "MEM") == 0)
+ {
+ num++;
+ size += o->Size;
+ }
+
+ if (t->Next == NULL)
+ {
+ break;
+ }
+
+ t = t->Next;
+ }
+ }
+ }
+ }
+ UnlockTrackingList();
+
+ status->MemoryBlocksNum = num;
+ status->MemorySize = size;
+}
+
+// Get the symbol information by the object
+void TrackGetObjSymbolInfo(TRACKING_OBJECT *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ if (!(o->LineNumber == 0 && o->FileName[0] == 0))
+ {
+ return;
+ }
+
+ if (o->CallStack != NULL)
+ {
+ GetCallStackSymbolInfo(o->CallStack);
+ if (StrLen(o->CallStack->filename) != 0 && o->CallStack->line != 0)
+ {
+ StrCpy(o->FileName, sizeof(o->FileName), o->CallStack->filename);
+ o->LineNumber = o->CallStack->line;
+ }
+ }
+}
+
+// Put a new object into the tracking list
+void TrackNewObj(UINT64 addr, char *name, UINT size)
+{
+ TRACKING_OBJECT *o;
+ UINT new_id;
+ // Validate arguments
+ if (addr == 0 || name == NULL)
+ {
+ return;
+ }
+
+ if (IsMemCheck() == false)
+ {
+ // Don't track in the release mode
+ return;
+ }
+
+ if (disable_tracking)
+ {
+ return;
+ }
+
+ // Generate a new ID
+ OSLock(obj_id_lock);
+ {
+ new_id = ++obj_id;
+ }
+ OSUnlock(obj_id_lock);
+
+ o = OSMemoryAlloc(sizeof(TRACKING_OBJECT));
+ o->Id = new_id;
+ o->Address = addr;
+ o->Name = name;
+ o->Size = size;
+ o->CreatedDate = LocalTime64();
+ o->CallStack = WalkDownCallStack(GetCallStack(), 2);
+
+ o->FileName[0] = 0;
+ o->LineNumber = 0;
+
+ LockTrackingList();
+ {
+ InsertTrackingList(o);
+ }
+ UnlockTrackingList();
+}
+
+// Remove the object from the tracking list
+void TrackDeleteObj(UINT64 addr)
+{
+ TRACKING_OBJECT *o;
+ // Validate arguments
+ if (addr == 0)
+ {
+ return;
+ }
+
+ if (IsMemCheck() == false)
+ {
+ // Don't track in the release mode
+ return;
+ }
+
+ if (disable_tracking)
+ {
+ return;
+ }
+
+ LockTrackingList();
+ {
+ o = SearchTrackingList(addr);
+ if (o == NULL)
+ {
+ UnlockTrackingList();
+
+ if (IsDebug())
+ {
+ printf("TrackDeleteObj: 0x%x is not Object!!\n", (void *)addr);
+ }
+ return;
+ }
+ DeleteTrackingList(o, true);
+ }
+ UnlockTrackingList();
+}
+
+// Change the size of the object being tracked
+void TrackChangeObjSize(UINT64 addr, UINT size, UINT64 new_addr)
+{
+ TRACKING_OBJECT *o;
+ // Validate arguments
+ if (addr == 0)
+ {
+ return;
+ }
+
+ if (IsMemCheck() == false)
+ {
+ // Don't track in the release mode
+ return;
+ }
+
+ if (disable_tracking)
+ {
+ return;
+ }
+
+ LockTrackingList();
+ {
+ o = SearchTrackingList(addr);
+ if (o == NULL)
+ {
+ UnlockTrackingList();
+ return;
+ }
+
+ DeleteTrackingList(o, false);
+
+ o->Size = size;
+ o->Address = new_addr;
+
+ InsertTrackingList(o);
+ }
+ UnlockTrackingList();
+}
+
+// Memory address comparison function
+int CompareTrackingObject(const void *p1, const void *p2)
+{
+ TRACKING_OBJECT *o1, *o2;
+ // Validate arguments
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ o1 = *(TRACKING_OBJECT **)p1;
+ o2 = *(TRACKING_OBJECT **)p2;
+ if (o1 == NULL || o2 == NULL)
+ {
+ return 0;
+ }
+
+ if (o1->Address > o2->Address)
+ {
+ return 1;
+ }
+ if (o1->Address == o2->Address)
+ {
+ return 0;
+ }
+ return -1;
+}
+
+// Search an object in the tracking list
+TRACKING_OBJECT *SearchTrackingList(UINT64 Address)
+{
+ UINT i;
+ // Validate arguments
+ if (Address == 0)
+ {
+ return NULL;
+ }
+
+ i = TRACKING_HASH(Address);
+
+ if (hashlist[i] != NULL)
+ {
+ TRACKING_LIST *tt = hashlist[i];
+
+ while (true)
+ {
+ if (tt->Object->Address == Address)
+ {
+ return tt->Object;
+ }
+
+ tt = tt->Next;
+
+ if (tt == NULL)
+ {
+ break;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// Remove an object from a tracking list
+void DeleteTrackingList(TRACKING_OBJECT *o, bool free_object_memory)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ i = TRACKING_HASH(o->Address);
+
+ if (hashlist[i] != NULL)
+ {
+ TRACKING_LIST *ft = NULL;
+
+ if (hashlist[i]->Object == o)
+ {
+ ft = hashlist[i];
+ hashlist[i] = hashlist[i]->Next;
+ }
+ else
+ {
+ TRACKING_LIST *tt = hashlist[i];
+ TRACKING_LIST *prev = NULL;
+
+ while (true)
+ {
+ if (tt->Object == o)
+ {
+ prev->Next = tt->Next;
+ ft = tt;
+ break;
+ }
+
+ if (tt->Next == NULL)
+ {
+ break;
+ }
+
+ prev = tt;
+ tt = tt->Next;
+ }
+ }
+
+ if (ft != NULL)
+ {
+ OSMemoryFree(ft);
+
+ if (free_object_memory)
+ {
+ FreeCallStack(o->CallStack);
+ OSMemoryFree(o);
+ }
+ }
+ }
+}
+
+// Insert an object into the tracking list
+void InsertTrackingList(TRACKING_OBJECT *o)
+{
+ UINT i;
+ TRACKING_LIST *t;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ t = OSMemoryAlloc(sizeof(TRACKING_LIST));
+ t->Object = o;
+ t->Next = NULL;
+
+ i = TRACKING_HASH(o->Address);
+
+ if (hashlist[i] == NULL)
+ {
+ hashlist[i] = t;
+ }
+ else
+ {
+ TRACKING_LIST *tt = hashlist[i];
+ while (true)
+ {
+ if (tt->Next == NULL)
+ {
+ tt->Next = t;
+ break;
+ }
+
+ tt = tt->Next;
+ }
+ }
+}
+
+// Lock the tracking list
+void LockTrackingList()
+{
+ OSLock(obj_lock);
+}
+
+// Unlock the tracking list
+void UnlockTrackingList()
+{
+ OSUnlock(obj_lock);
+}
+
+// Initialize the tracking
+void InitTracking()
+{
+ UINT i;
+ CALLSTACK_DATA *s;
+
+ // Hash list initialization
+ hashlist = (TRACKING_LIST **)OSMemoryAlloc(sizeof(TRACKING_LIST *) * TRACKING_NUM_ARRAY);
+
+ for (i = 0;i < TRACKING_NUM_ARRAY;i++)
+ {
+ hashlist[i] = NULL;
+ }
+
+ obj_id = 0;
+
+ // Create a lock
+ obj_lock = OSNewLock();
+ obj_id_lock = OSNewLock();
+ cs_lock = OSNewLock();
+
+ s = GetCallStack();
+ if (s == NULL)
+ {
+ do_not_get_callstack = true;
+ }
+ else
+ {
+ do_not_get_callstack = false;
+ FreeCallStack(s);
+ }
+}
+
+// Release the tracking
+void FreeTracking()
+{
+ UINT i;
+ // Delete the lock
+ OSDeleteLock(obj_lock);
+ OSDeleteLock(obj_id_lock);
+ OSDeleteLock(cs_lock);
+ cs_lock = NULL;
+ obj_id_lock = NULL;
+ obj_lock = NULL;
+
+ // Release all of the elements
+ for (i = 0;i < TRACKING_NUM_ARRAY;i++)
+ {
+ if (hashlist[i] != NULL)
+ {
+ TRACKING_LIST *t = hashlist[i];
+
+ while (true)
+ {
+ TRACKING_LIST *t2 = t;
+ TRACKING_OBJECT *o = t->Object;
+
+ FreeCallStack(o->CallStack);
+ OSMemoryFree(o);
+
+ t = t->Next;
+
+ OSMemoryFree(t2);
+
+ if (t == NULL)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ // Release the list
+ OSMemoryFree(hashlist);
+}
+
+// Show the call stack
+void PrintCallStack(CALLSTACK_DATA *s)
+{
+ char tmp[MAX_SIZE * 2];
+
+ GetCallStackStr(tmp, sizeof(tmp), s);
+ Print("%s", tmp);
+}
+
+// Convert the call stack to a string
+void GetCallStackStr(char *str, UINT size, CALLSTACK_DATA *s)
+{
+ char tmp[MAX_SIZE];
+ char tmp2[MAX_SIZE];
+ char tmp3[MAX_SIZE];
+ UINT num, i;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ if (s == NULL)
+ {
+ StrCpy(str, size, "(Unknown)\n");
+ }
+ else
+ {
+ num = 0;
+ str[0] = 0;
+ while (true)
+ {
+ if (s == NULL)
+ {
+ break;
+ }
+
+ GetCallStackSymbolInfo(s);
+
+ if (s->name == NULL)
+ {
+ Format(tmp, sizeof(tmp), "0x%p ---", UINT64_TO_POINTER(s->offset));
+ }
+ else
+ {
+ Format(tmp, sizeof(tmp), "0x%p %s() + 0x%02x",
+ (void *)s->offset, s->name, UINT64_TO_POINTER(s->disp));
+ }
+ for (i = 0;i < num;i++)
+ {
+ tmp2[i] = ' ';
+ }
+ tmp2[i] = '\0';
+ StrCpy(tmp3, sizeof(tmp3), tmp2);
+ StrCat(tmp3, sizeof(tmp3), tmp);
+ Format(tmp, sizeof(tmp), "%-55s %11s %u\n", tmp3, s->filename, s->line);
+ StrCat(str, size, tmp);
+ num++;
+ s = s->next;
+ }
+ }
+}
+
+// Get the current call stack
+CALLSTACK_DATA *GetCallStack()
+{
+ CALLSTACK_DATA *s;
+ if (do_not_get_callstack)
+ {
+ // Not to get the call stack
+ return NULL;
+ }
+
+ OSLock(cs_lock);
+ {
+ // Get the call stack
+ s = OSGetCallStack();
+ }
+ OSUnlock(cs_lock);
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ // Descend in the call stack for 3 steps
+ s = WalkDownCallStack(s, 3);
+
+ return s;
+}
+
+// Get the symbol information of the call stack
+bool GetCallStackSymbolInfo(CALLSTACK_DATA *s)
+{
+ bool ret;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ OSLock(cs_lock);
+ {
+ ret = OSGetCallStackSymbolInfo(s);
+ }
+ OSUnlock(cs_lock);
+
+ return ret;
+}
+
+// Descend in the call stack by a specified number
+CALLSTACK_DATA *WalkDownCallStack(CALLSTACK_DATA *s, UINT num)
+{
+ CALLSTACK_DATA *cs, *tmp;
+ UINT i;
+ // Validate arguments
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ cs = s;
+ i = 0;
+
+ while (true)
+ {
+ if (i >= num)
+ {
+ return cs;
+ }
+ i++;
+ tmp = cs;
+ cs = tmp->next;
+ OSMemoryFree(tmp->name);
+ OSMemoryFree(tmp);
+
+ if (cs == NULL)
+ {
+ return NULL;
+ }
+ }
+}
+
+// Release the call stack
+void FreeCallStack(CALLSTACK_DATA *s)
+{
+ // Validate arguments
+ if (s == NULL)
+ {
+ return;
+ }
+
+ while (true)
+ {
+ CALLSTACK_DATA *next = s->next;
+ OSMemoryFree(s->name);
+ OSMemoryFree(s);
+ if (next == NULL)
+ {
+ break;
+ }
+ s = next;
+ }
+}
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Tracking.h b/src/Mayaqua/Tracking.h
new file mode 100644
index 00000000..54cd6d6b
--- /dev/null
+++ b/src/Mayaqua/Tracking.h
@@ -0,0 +1,171 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Tracking.h
+// Header of Tracking.c
+
+#ifndef TRACKING_H
+#define TRACKING_H
+
+// The number of array
+#define TRACKING_NUM_ARRAY 1048576
+
+// Hash from an pointer to an array index
+#define TRACKING_HASH(p) (UINT)(((((UINT64)(p)) / (UINT64)(sizeof(void *))) % ((UINT64)TRACKING_NUM_ARRAY)))
+
+// Call stack
+struct CALLSTACK_DATA
+{
+ bool symbol_cache;
+ UINT64 offset, disp;
+ char *name;
+ struct CALLSTACK_DATA *next;
+ char filename[MAX_PATH];
+ UINT line;
+};
+
+// Object
+struct TRACKING_OBJECT
+{
+ UINT Id;
+ char *Name;
+ UINT64 Address;
+ UINT Size;
+ UINT64 CreatedDate;
+ CALLSTACK_DATA *CallStack;
+ char FileName[MAX_PATH];
+ UINT LineNumber;
+};
+
+// Usage of the memory
+struct MEMORY_STATUS
+{
+ UINT MemoryBlocksNum;
+ UINT MemorySize;
+};
+
+// Tracking list
+struct TRACKING_LIST
+{
+ struct TRACKING_LIST *Next;
+ struct TRACKING_OBJECT *Object;
+};
+
+CALLSTACK_DATA *GetCallStack();
+bool GetCallStackSymbolInfo(CALLSTACK_DATA *s);
+void FreeCallStack(CALLSTACK_DATA *s);
+CALLSTACK_DATA *WalkDownCallStack(CALLSTACK_DATA *s, UINT num);
+void GetCallStackStr(char *str, UINT size, CALLSTACK_DATA *s);
+void PrintCallStack(CALLSTACK_DATA *s);
+void InitTracking();
+void FreeTracking();
+int CompareTrackingObject(const void *p1, const void *p2);
+void LockTrackingList();
+void UnlockTrackingList();
+void InsertTrackingList(TRACKING_OBJECT *o);
+void DeleteTrackingList(TRACKING_OBJECT *o, bool free_object_memory);
+TRACKING_OBJECT *SearchTrackingList(UINT64 Address);
+
+void TrackNewObj(UINT64 addr, char *name, UINT size);
+void TrackGetObjSymbolInfo(TRACKING_OBJECT *o);
+void TrackDeleteObj(UINT64 addr);
+void TrackChangeObjSize(UINT64 addr, UINT size, UINT64 new_addr);
+
+void GetMemoryStatus(MEMORY_STATUS *status);
+void PrintMemoryStatus();
+void MemoryDebugMenu();
+int SortObjectView(void *p1, void *p2);
+void DebugPrintAllObjects();
+void DebugPrintCommandList();
+void PrintObjectList(TRACKING_OBJECT *o);
+void PrintObjectInfo(TRACKING_OBJECT *o);
+void DebugPrintObjectInfo(UINT id);
+
+void TrackingEnable();
+void TrackingDisable();
+bool IsTrackingEnabled();
+
+#endif // TRACKING_H
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/TunTap.h b/src/Mayaqua/TunTap.h
new file mode 100644
index 00000000..5db02c06
--- /dev/null
+++ b/src/Mayaqua/TunTap.h
@@ -0,0 +1,306 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// TunTap.h
+// Header file of the TUN / TAP device driver
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+#ifndef TUNTAP_H
+#define TUNTAP_H
+
+#ifdef UNIX_LINUX
+
+// -----------------------------------------------------------------
+// Tap header for Linux
+// -----------------------------------------------------------------
+/*
+ * Universal TUN/TAP device driver.
+ * Copyright (C) 1999-2000 Maxim Krasnyansky <max_mk@yahoo.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * $Id: if_tun.h,v 1.2 2001/10/31 15:27:57 arjanv Exp $
+ */
+
+#ifndef __IF_TUN_H
+#define __IF_TUN_H
+
+/* Uncomment to enable debugging */
+/* #define TUN_DEBUG 1 */
+
+
+
+/* Read queue size */
+#define TUN_READQ_SIZE 10
+
+/* TUN device flags */
+#define TUN_TUN_DEV 0x0001
+#define TUN_TAP_DEV 0x0002
+#define TUN_TYPE_MASK 0x000f
+
+#define TUN_FASYNC 0x0010
+#define TUN_NOCHECKSUM 0x0020
+#define TUN_NO_PI 0x0040
+#define TUN_ONE_QUEUE 0x0080
+#define TUN_PERSIST 0x0100
+
+/* Ioctl defines */
+#define TUNSETNOCSUM _IOW('T', 200, int)
+#define TUNSETDEBUG _IOW('T', 201, int)
+#define TUNSETIFF _IOW('T', 202, int)
+#define TUNSETPERSIST _IOW('T', 203, int)
+#define TUNSETOWNER _IOW('T', 204, int)
+
+/* TUNSETIFF ifr flags */
+#define IFF_TUN 0x0001
+#define IFF_TAP 0x0002
+#define IFF_NO_PI 0x1000
+#define IFF_ONE_QUEUE 0x2000
+
+struct tun_pi {
+ unsigned short flags;
+ unsigned short proto;
+};
+#define TUN_PKT_STRIP 0x0001
+
+#endif /* __IF_TUN_H */
+#else // UNIX_LINUX
+
+#ifdef UNIX_SOLARIS
+
+// -----------------------------------------------------------------
+// Tap header for Solaris
+// -----------------------------------------------------------------
+/*
+ * Universal TUN/TAP device driver.
+ *
+ * Multithreaded STREAMS tun pseudo device driver.
+ *
+ * Copyright (C) 1999-2000 Maxim Krasnyansky <max_mk@yahoo.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * $Id: if_tun.h,v 1.4 2000/05/01 12:23:27 maxk Exp $
+ */
+
+#ifndef _SYS_IF_TUN_H
+#define _SYS_IF_TUN_H
+
+#ifdef _KERNEL
+/* Uncomment to enable debuging */
+/* #define TUN_DEBUG 1 */
+
+#ifdef TUN_DEBUG
+#define DBG cmn_err
+#else
+#define DBG( a... )
+#endif
+
+/* PPA structure, one per TUN iface */
+struct tunppa {
+ unsigned int id; /* Iface number */
+ queue_t *rq; /* Control Stream RQ */
+ struct tunstr * p_str; /* Protocol Streams */
+};
+#define TUNMAXPPA 20
+
+/* Stream structure, one per Stream */
+struct tunstr {
+ struct tunstr *s_next; /* next in streams list */
+ struct tunstr *p_next; /* next in ppa list */
+ queue_t *rq; /* pointer to rq */
+
+ struct tunppa *ppa; /* assigned PPA */
+ u_long flags; /* flags */
+ u_long state; /* DL state */
+ u_long sap; /* bound sap */
+ u_long minor; /* minor device number */
+};
+
+/* Flags */
+#define TUN_CONTROL 0x0001
+
+#define TUN_RAW 0x0100
+#define TUN_FAST 0x0200
+
+#define TUN_ALL_PHY 0x0010
+#define TUN_ALL_SAP 0x0020
+#define TUN_ALL_MUL 0x0040
+
+#define SNIFFER(a) ( (a & TUN_ALL_SAP) || (a & TUN_ALL_PHY) )
+
+struct tundladdr {
+ u_short sap;
+};
+#define TUN_ADDR_LEN (sizeof(struct tundladdr))
+
+#define TUN_QUEUE 0
+#define TUN_DROP 1
+
+#endif /* _KERNEL */
+
+/* IOCTL defines */
+#define TUNNEWPPA (('T'<<16) | 0x0001)
+#define TUNSETPPA (('T'<<16) | 0x0002)
+
+#endif /* _SYS_IF_TUN_H */
+
+#else // UNIX_SOLARIS
+
+#ifdef UNIX_BSD
+
+// -----------------------------------------------------------------
+// Tap header for FreeBSD
+// -----------------------------------------------------------------
+/* $NetBSD: if_tun.h,v 1.5 1994/06/29 06:36:27 cgd Exp $ */
+
+/*
+ * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
+ * Nottingham University 1987.
+ *
+ * This source may be freely distributed, however I would be interested
+ * in any changes that are made.
+ *
+ * This driver takes packets off the IP i/f and hands them up to a
+ * user process to have its wicked way with. This driver has it's
+ * roots in a similar driver written by Phil Cockcroft (formerly) at
+ * UCL. This driver is based much more on read/write/select mode of
+ * operation though.
+ *
+ * $FreeBSD: src/sys/net/if_tun.h,v 1.17 2000/01/23 01:47:12 brian Exp $
+ */
+
+#ifndef _NET_IF_TUN_H_
+#define _NET_IF_TUN_H_
+
+/* Refer to if_tunvar.h for the softc stuff */
+
+/* Maximum transmit packet size (default) */
+#define TUNMTU 1500
+
+/* Maximum receive packet size (hard limit) */
+#define TUNMRU 16384
+
+struct tuninfo {
+ int baudrate; /* linespeed */
+ short mtu; /* maximum transmission unit */
+ u_char type; /* ethernet, tokenring, etc. */
+ u_char dummy; /* place holder */
+};
+
+/* ioctl's for get/set debug */
+#define TUNSDEBUG _IOW('t', 90, int)
+#define TUNGDEBUG _IOR('t', 89, int)
+#define TUNSIFINFO _IOW('t', 91, struct tuninfo)
+#define TUNGIFINFO _IOR('t', 92, struct tuninfo)
+#define TUNSLMODE _IOW('t', 93, int)
+#define TUNSIFMODE _IOW('t', 94, int)
+#define TUNSIFPID _IO('t', 95)
+#define TUNSIFHEAD _IOW('t', 96, int)
+#define TUNGIFHEAD _IOR('t', 97, int)
+
+#endif /* !_NET_IF_TUN_H_ */
+
+#else // UNIX_BSD
+
+#ifdef UNIX_MACOS
+
+// -----------------------------------------------------------------
+// Tap header For MacOS
+// -----------------------------------------------------------------
+
+#else // UNIX_MACOS
+
+#endif // UNIX_MACOS
+
+#endif // UNIX_BSD
+
+#endif // UNIX_SOLARIS
+
+#endif // UNIX_LINUX
+
+#endif // TUNTAP_H
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Unix.c b/src/Mayaqua/Unix.c
new file mode 100644
index 00000000..8ee0b9c3
--- /dev/null
+++ b/src/Mayaqua/Unix.c
@@ -0,0 +1,2741 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Unix.c
+// UNIX dependent code
+
+#include <GlobalConst.h>
+
+#ifdef UNIX
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+// Struct statfs for MacOS X
+#ifdef UNIX_MACOS
+typedef struct fsid { int32_t val[2]; } fsid_t;
+struct statfs {
+ short f_otype; /* TEMPORARY SHADOW COPY OF f_type */
+ short f_oflags; /* TEMPORARY SHADOW COPY OF f_flags */
+ long f_bsize; /* fundamental file system block size */
+ long f_iosize; /* optimal transfer block size */
+ long f_blocks; /* total data blocks in file system */
+ long f_bfree; /* free blocks in fs */
+ long f_bavail; /* free blocks avail to non-superuser */
+ long f_files; /* total file nodes in file system */
+ long f_ffree; /* free file nodes in fs */
+ fsid_t f_fsid; /* file system id */
+ uid_t f_owner; /* user that mounted the filesystem */
+ short f_reserved1; /* spare for later */
+ short f_type; /* type of filesystem */
+ long f_flags; /* copy of mount exported flags */
+ long f_reserved2[2]; /* reserved for future use */
+ char f_fstypename[15]; /* fs type name */
+ char f_mntonname[90]; /* directory on which mounted */
+ char f_mntfromname[90];/* mounted filesystem */
+};
+#endif // UNIX_MACOS
+
+// Scandir() function for Solaris
+#ifdef UNIX_SOLARIS
+#define scandir local_scandir
+#define alphasort local_alphasort
+
+int local_scandir(const char *dir, struct dirent ***namelist,
+ int (*select)(const struct dirent *),
+ int (*compar)(const struct dirent **, const struct dirent **))
+{
+ DIR *d;
+ struct dirent *entry;
+ register int i=0;
+ size_t entrysize;
+
+ if ((d=opendir(dir)) == NULL)
+ return(-1);
+
+ *namelist=NULL;
+ while ((entry=readdir(d)) != NULL)
+ {
+ if (select == NULL || (select != NULL && (*select)(entry)))
+ {
+ *namelist=(struct dirent **)realloc((void *)(*namelist),
+ (size_t)((i+1)*sizeof(struct dirent *)));
+ if (*namelist == NULL) return(-1);
+ entrysize=sizeof(struct dirent)-sizeof(entry->d_name)+strlen(entry->d_name)+1;
+ (*namelist)[i]=(struct dirent *)malloc(entrysize);
+ if ((*namelist)[i] == NULL) return(-1);
+ memcpy((*namelist)[i], entry, entrysize);
+ i++;
+ }
+ }
+ if (closedir(d)) return(-1);
+ if (i == 0) return(-1);
+ if (compar != NULL)
+ qsort((void *)(*namelist), (size_t)i, sizeof(struct dirent *), compar);
+
+ return(i);
+}
+
+int local_alphasort(const struct dirent **a, const struct dirent **b)
+{
+ return(strcmp((*a)->d_name, (*b)->d_name));
+}
+
+
+#endif // UNIX_SOLARIS
+
+// Thread data for UNIX
+typedef struct UNIXTHREAD
+{
+ pthread_t thread;
+ bool finished;
+} UNIXTHREAD;
+
+// Thread startup information for UNIX
+typedef struct UNIXTHREADSTARTUPINFO
+{
+ THREAD_PROC *thread_proc;
+ void *param;
+ THREAD *thread;
+} UNIXTHREADSTARTUPINFO;
+
+// Thread function prototype for UNIX
+void *UnixDefaultThreadProc(void *param);
+
+// Current process ID
+static pid_t current_process_id = 0;
+
+// File I/O data for UNIX
+typedef struct UNIXIO
+{
+ int fd;
+ bool write_mode;
+} UNIXIO;
+
+// Lock file data for UNIX
+typedef struct UNIXLOCKFILE
+{
+ char FileName[MAX_SIZE];
+ int fd;
+} UNIXLOCKFILE;
+
+// Event data for UNIX
+typedef struct UNIXEVENT
+{
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ bool signal;
+} UNIXEVENT;
+
+static pthread_mutex_t get_time_lock;
+static pthread_mutex_t malloc_lock;
+static bool high_process = false;
+
+static bool unix_svc_terminate = false;
+static int solaris_sleep_p1 = -1, solaris_sleep_p2 = -1;
+
+// Create a dispatch table
+OS_DISPATCH_TABLE *UnixGetDispatchTable()
+{
+ static OS_DISPATCH_TABLE t =
+ {
+ UnixInit,
+ UnixFree,
+ UnixMemoryAlloc,
+ UnixMemoryReAlloc,
+ UnixMemoryFree,
+ UnixGetTick,
+ UnixGetSystemTime,
+ UnixInc32,
+ UnixDec32,
+ UnixSleep,
+ UnixNewLock,
+ UnixLock,
+ UnixUnlock,
+ UnixDeleteLock,
+ UnixInitEvent,
+ UnixSetEvent,
+ UnixResetEvent,
+ UnixWaitEvent,
+ UnixFreeEvent,
+ UnixWaitThread,
+ UnixFreeThread,
+ UnixInitThread,
+ UnixThreadId,
+ UnixFileOpen,
+ UnixFileOpenW,
+ UnixFileCreate,
+ UnixFileCreateW,
+ UnixFileWrite,
+ UnixFileRead,
+ UnixFileClose,
+ UnixFileFlush,
+ UnixFileSize,
+ UnixFileSeek,
+ UnixFileDelete,
+ UnixFileDeleteW,
+ UnixMakeDir,
+ UnixMakeDirW,
+ UnixDeleteDir,
+ UnixDeleteDirW,
+ UnixGetCallStack,
+ UnixGetCallStackSymbolInfo,
+ UnixFileRename,
+ UnixFileRenameW,
+ UnixRun,
+ UnixRunW,
+ UnixIsSupportedOs,
+ UnixGetOsInfo,
+ UnixAlert,
+ UnixAlertW,
+ UnixGetProductId,
+ UnixSetHighPriority,
+ UnixRestorePriority,
+ UnixNewSingleInstance,
+ UnixFreeSingleInstance,
+ UnixGetMemInfo,
+ UnixYield,
+ };
+
+ return &t;
+}
+
+static void *signal_received_for_ignore(int sig, siginfo_t *info, void *ucontext)
+{
+ return NULL;
+}
+
+// Ignore the signal flew to the thread
+void UnixIgnoreSignalForThread(int sig)
+{
+ struct sigaction sa;
+
+ Zero(&sa, sizeof(sa));
+ sa.sa_handler = NULL;
+ sa.sa_sigaction = signal_received_for_ignore;
+ sa.sa_flags = SA_SIGINFO;
+
+ sigemptyset(&sa.sa_mask);
+
+ sigaction(SIGUSR1, &sa, NULL);
+}
+
+// Disable the off-loading function of the specific Ethernet device
+void UnixDisableInterfaceOffload(char *name)
+{
+#ifdef UNIX_LINUX
+ char tmp[MAX_SIZE];
+ TOKEN_LIST *t;
+ char *names = "rx tx sg tso ufo gso gro lro rxvlan txvlan ntuple rxhash";
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ t = ParseToken(names, " ");
+
+ if (t != NULL)
+ {
+ UINT i;
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *a = t->Token[i];
+
+ Format(tmp, sizeof(tmp), "/sbin/ethtool -K %s %s off 2>/dev/null", name, a);
+ FreeToken(UnixExec(tmp));
+ }
+ }
+
+ FreeToken(t);
+#endif // UNIX_LINUX
+}
+
+// Validate whether the UNIX is running in a VM
+bool UnixIsInVmMain()
+{
+ TOKEN_LIST *t = NULL;
+ bool ret = false;
+ char *vm_str_list = "Hypervisor detected,VMware Virtual Platform,VMware Virtual USB,qemu,xen,paravirtualized,virtual hd,virtualhd,virtual pc,virtualpc,kvm,oracle vm,oraclevm,parallels,xvm,bochs";
+
+#ifdef UNIX_LINUX
+ t = UnixExec("/bin/dmesg");
+
+ if (t != NULL)
+ {
+ BUF *b = NewBuf();
+ UINT i;
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *line = t->Token[i];
+
+ AddBufStr(b, line);
+ AddBufStr(b, " ");
+ }
+
+ WriteBufInt(b, 0);
+
+// printf("%s\n", b->Buf);
+
+ ret = InStrList(b->Buf, vm_str_list, ",", false);
+
+ FreeBuf(b);
+ FreeToken(t);
+ }
+#endif // UNIX_LINUX
+
+ return ret;
+}
+bool UnixIsInVm()
+{
+ static bool is_in_vm_flag = false;
+ static bool is_in_vm_ret = false;
+
+ if (is_in_vm_flag == false)
+ {
+ is_in_vm_ret = UnixIsInVmMain();
+ is_in_vm_flag = true;
+ }
+
+ return is_in_vm_ret;
+}
+
+// Run quietly in the UNIX
+void UnixExecSilent(char *cmd)
+{
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (cmd == NULL)
+ {
+ return;
+ }
+
+ Format(tmp, sizeof(tmp), "%s 2>/dev/null", cmd);
+
+ FreeToken(UnixExec(tmp));
+}
+
+// Enable / disable the ESP processing in the kernel
+void UnixSetEnableKernelEspProcessing(bool b)
+{
+ if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
+ {
+ // Mac OS X
+ if (b)
+ {
+ UnixExecSilent("/usr/sbin/sysctl -w net.inet.ipsec.esp_port=4500");
+ }
+ else
+ {
+ UnixExecSilent("/usr/sbin/sysctl -w net.inet.ipsec.esp_port=4501");
+ }
+ }
+}
+
+// Run a command and return its result
+TOKEN_LIST *UnixExec(char *cmd)
+{
+ FILE *fp;
+ char tmp[MAX_SIZE];
+ char *ptr;
+ LIST *o;
+ UINT i;
+ TOKEN_LIST *ret;
+ // Validate arguments
+ if (cmd == NULL)
+ {
+ return NULL;
+ }
+
+ fp = popen(cmd, "r");
+ if (fp == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewList(NULL);
+
+ while (true)
+ {
+ fgets(tmp, sizeof(tmp), fp);
+ if (feof(fp))
+ {
+ break;
+ }
+
+ ptr = strchr(tmp, '\n');
+ if (ptr != NULL)
+ {
+ *ptr = 0;
+ }
+
+ ptr = strchr(tmp, '\r');
+ if (ptr != NULL)
+ {
+ *ptr = 0;
+ }
+
+ Add(o, CopyStr(tmp));
+ }
+
+ pclose(fp);
+
+ ret = ListToTokenList(o);
+
+ FreeStrList(o);
+
+ return ret;
+}
+
+// Initialize the Sleep for Solaris
+void UnixInitSolarisSleep()
+{
+ char tmp[MAX_SIZE];
+
+ UnixNewPipe(&solaris_sleep_p1, &solaris_sleep_p2);
+ read(solaris_sleep_p1, tmp, sizeof(tmp));
+}
+
+// Release the Sleep for Solaris
+void UnixFreeSolarisSleep()
+{
+ UnixDeletePipe(solaris_sleep_p1, solaris_sleep_p2);
+ solaris_sleep_p1 = -1;
+ solaris_sleep_p2 = -1;
+}
+
+// Sleep for Solaris
+void UnixSolarisSleep(UINT msec)
+{
+ struct pollfd p;
+
+ memset(&p, 0, sizeof(p));
+ p.fd = solaris_sleep_p1;
+ p.events = POLLIN;
+
+ poll(&p, 1, msec == INFINITE ? -1 : (int)msec);
+}
+
+// Get the free space of the disk
+bool UnixGetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
+{
+ char *path_a = CopyUniToStr(path);
+ bool ret;
+
+ ret = UnixGetDiskFree(path_a, free_size, used_size, total_size);
+
+ Free(path_a);
+
+ return ret;
+}
+bool UnixGetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
+{
+ char tmp[MAX_PATH];
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ NormalizePath(tmp, sizeof(tmp), path);
+
+ while ((ret = UnixGetDiskFreeMain(tmp, free_size, used_size, total_size)) == false)
+ {
+ if (StrCmpi(tmp, "/") == 0)
+ {
+ break;
+ }
+
+ GetDirNameFromFilePath(tmp, sizeof(tmp), tmp);
+ }
+
+ return ret;
+}
+bool UnixGetDiskFreeMain(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
+{
+#ifndef USE_STATVFS
+ struct statfs st;
+ char tmp[MAX_PATH];
+ UINT64 v1 = 0, v2 = 0;
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ NormalizePath(tmp, sizeof(tmp), path);
+
+ Zero(&st, sizeof(st));
+ if (statfs(tmp, &st) == 0)
+ {
+ v1 = (UINT64)st.f_bsize * (UINT64)st.f_bavail;
+ v2 = (UINT64)st.f_bsize * (UINT64)st.f_blocks;
+ ret = true;
+ }
+
+ if (free_size != NULL)
+ {
+ *free_size = v1;
+ }
+
+ if (total_size != NULL)
+ {
+ *total_size = v2;
+ }
+
+ if (used_size != NULL)
+ {
+ *used_size = v2 - v1;
+ }
+
+ return ret;
+#else // USE_STATVFS
+ struct statvfs st;
+ char tmp[MAX_PATH];
+ UINT64 v1 = 0, v2 = 0;
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ NormalizePath(tmp, sizeof(tmp), path);
+
+ Zero(&st, sizeof(st));
+
+ if (statvfs(tmp, &st) == 0)
+ {
+ v1 = (UINT64)st.f_bsize * (UINT64)st.f_bavail;
+ v2 = (UINT64)st.f_bsize * (UINT64)st.f_blocks;
+ ret = true;
+ }
+
+ if (free_size != NULL)
+ {
+ *free_size = v1;
+ }
+
+ if (total_size != NULL)
+ {
+ *total_size = v2;
+ }
+
+ if (used_size != NULL)
+ {
+ *used_size = v2 - v1;
+ }
+
+ return ret;
+#endif // USE_STATVFS
+}
+
+// Directory enumeration
+DIRLIST *UnixEnumDirEx(char *dirname, COMPARE *compare)
+{
+ char tmp[MAX_PATH];
+ DIRLIST *d;
+ int n;
+ struct dirent **e;
+ LIST *o;
+ // Validate arguments
+ if (dirname == NULL)
+ {
+ return NULL;
+ }
+
+ o = NewListFast(compare);
+
+ NormalizePath(tmp, sizeof(tmp), dirname);
+
+ if (StrLen(tmp) >= 1 && tmp[StrLen(tmp) - 1] != '/')
+ {
+ StrCat(tmp, sizeof(tmp), "/");
+ }
+
+ e = NULL;
+ n = scandir(tmp, &e, 0, alphasort);
+
+ if (StrLen(tmp) >= 1 && tmp[StrLen(tmp) - 1] == '/')
+ {
+ tmp[StrLen(tmp) - 1] = 0;
+ }
+
+ if (n >= 0 && e != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < (UINT)n;i++)
+ {
+ char *filename = e[i]->d_name;
+
+ if (filename != NULL)
+ {
+ if (StrCmpi(filename, "..") != 0 && StrCmpi(filename, ".") != 0)
+ {
+ char fullpath[MAX_PATH];
+ struct stat st;
+ Format(fullpath, sizeof(fullpath), "%s/%s", tmp, filename);
+
+ Zero(&st, sizeof(st));
+
+ if (stat(fullpath, &st) == 0)
+ {
+ DIRENT *f = ZeroMalloc(sizeof(DIRENT));
+ SYSTEMTIME t;
+
+ f->Folder = S_ISDIR(st.st_mode) ? true : false;
+ f->FileName = CopyStr(filename);
+ f->FileNameW = CopyUtfToUni(f->FileName);
+
+ Zero(&t, sizeof(t));
+ TimeToSystem(&t, st.st_ctime);
+ f->CreateDate = SystemToUINT64(&t);
+
+ Zero(&t, sizeof(t));
+ TimeToSystem(&t, st.st_mtime);
+ f->UpdateDate = SystemToUINT64(&t);
+
+ if (f->Folder == false)
+ {
+ f->FileSize = st.st_size;
+ }
+
+ Add(o, f);
+ }
+ }
+ }
+
+ free(e[i]);
+ }
+
+ free(e);
+ }
+
+ Sort(o);
+
+ d = ZeroMalloc(sizeof(DIRLIST));
+ d->NumFiles = LIST_NUM(o);
+ d->File = ToArray(o);
+
+ ReleaseList(o);
+
+ return d;
+}
+DIRLIST *UnixEnumDirExW(wchar_t *dirname, COMPARE *compare)
+{
+ char *dirname_a = CopyUniToUtf(dirname);
+ DIRLIST *ret;
+
+ ret = UnixEnumDirEx(dirname_a, compare);
+
+ Free(dirname_a);
+
+ return ret;
+}
+
+// Check the execute permissions of the specified file
+bool UnixCheckExecAccess(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (access(name, X_OK) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+bool UnixCheckExecAccessW(wchar_t *name)
+{
+ char *name_a;
+ bool ret;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ name_a = CopyUniToUtf(name);
+
+ ret = UnixCheckExecAccess(name_a);
+
+ Free(name_a);
+
+ return ret;
+}
+
+// Raise the priority of the thread to highest
+void UnixSetThreadPriorityRealtime()
+{
+ struct sched_param p;
+ Zero(&p, sizeof(p));
+ p.sched_priority = 255;
+ pthread_setschedparam(pthread_self(), SCHED_RR, &p);
+}
+
+// Lower the priority of the thread
+void UnixSetThreadPriorityLow()
+{
+ struct sched_param p;
+ Zero(&p, sizeof(p));
+ p.sched_priority = 32;
+ pthread_setschedparam(pthread_self(), SCHED_OTHER, &p);
+}
+
+// Raise the priority of the thread
+void UnixSetThreadPriorityHigh()
+{
+ struct sched_param p;
+ Zero(&p, sizeof(p));
+ p.sched_priority = 127;
+ pthread_setschedparam(pthread_self(), SCHED_RR, &p);
+}
+
+// Set the priority of the thread to idle
+void UnixSetThreadPriorityIdle()
+{
+ struct sched_param p;
+ Zero(&p, sizeof(p));
+ p.sched_priority = 1;
+ pthread_setschedparam(pthread_self(), SCHED_OTHER, &p);
+}
+
+// Restore the priority of the thread to normal
+void UnixRestoreThreadPriority()
+{
+ struct sched_param p;
+ Zero(&p, sizeof(p));
+ p.sched_priority = 64;
+ pthread_setschedparam(pthread_self(), SCHED_OTHER, &p);
+}
+
+// Get the current directory
+void UnixGetCurrentDir(char *dir, UINT size)
+{
+ // Validate arguments
+ if (dir == NULL)
+ {
+ return;
+ }
+
+ getcwd(dir, size);
+}
+void UnixGetCurrentDirW(wchar_t *dir, UINT size)
+{
+ char dir_a[MAX_PATH];
+
+ UnixGetCurrentDir(dir_a, sizeof(dir_a));
+
+ UtfToUni(dir, size, dir_a);
+}
+
+// Yield
+void UnixYield()
+{
+#ifdef UNIX_SOLARIS
+ UnixSolarisSleep(1);
+#else
+ usleep(1000);
+#endif
+}
+
+// Get the memory information
+void UnixGetMemInfo(MEMINFO *info)
+{
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ // I don't know!!
+ Zero(info, sizeof(MEMINFO));
+}
+
+// Release of the single instance
+void UnixFreeSingleInstance(void *data)
+{
+ UNIXLOCKFILE *o;
+ struct flock lock;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return;
+ }
+
+ o = (UNIXLOCKFILE *)data;
+
+ Zero(&lock, sizeof(lock));
+ lock.l_type = F_UNLCK;
+ lock.l_whence = SEEK_SET;
+
+ fcntl(o->fd, F_SETLK, &lock);
+ close(o->fd);
+
+ remove(o->FileName);
+
+ Free(data);
+}
+
+// Creating a single instance
+void *UnixNewSingleInstance(char *instance_name)
+{
+ UNIXLOCKFILE *ret;
+ char tmp[MAX_SIZE];
+ char name[MAX_SIZE];
+ char dir[MAX_PATH];
+ int fd;
+ struct flock lock;
+ int mode = S_IRUSR | S_IWUSR;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ GetExeName(tmp, sizeof(tmp));
+ HashInstanceName(tmp, sizeof(tmp), tmp);
+ }
+ else
+ {
+ StrCpy(tmp, sizeof(tmp), instance_name);
+ }
+
+ GetExeDir(dir, sizeof(dir));
+
+ // File name generation
+ Format(name, sizeof(name), "%s/.%s", dir, tmp);
+
+ fd = open(name, O_WRONLY);
+ if (fd == -1)
+ {
+ fd = creat(name, mode);
+ }
+ if (fd == -1)
+ {
+ Format(tmp, sizeof(tmp), "Unable to create %s.", name);
+ Alert(tmp, NULL);
+ exit(0);
+ return NULL;
+ }
+
+ fchmod(fd, mode);
+ chmod(name, mode);
+
+ Zero(&lock, sizeof(lock));
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+
+ if (fcntl(fd, F_SETLK, &lock) == -1)
+ {
+ return NULL;
+ }
+ else
+ {
+ ret = ZeroMalloc(sizeof(UNIXLOCKFILE));
+ ret->fd = fd;
+ StrCpy(ret->FileName, sizeof(ret->FileName), name);
+ return (void *)ret;
+ }
+}
+
+// Raise the priority of the process
+void UnixSetHighPriority()
+{
+ if (high_process == false)
+ {
+ UINT pid = getpid();
+ UINT pgid = getpgid(pid);
+
+ high_process = true;
+ nice(-20);
+
+ setpriority(PRIO_PROCESS, pid, -20);
+ setpriority(PRIO_PGRP, pgid, -20);
+ }
+}
+
+// Restore the priority of the process
+void UnixRestorePriority()
+{
+ if (high_process != false)
+ {
+ high_process = false;
+ nice(20);
+ }
+}
+
+// Get the product ID
+char *UnixGetProductId()
+{
+ return CopyStr("--");
+}
+
+// Display an alert
+void UnixAlertW(wchar_t *msg, wchar_t *caption)
+{
+ char *msg8 = CopyUniToUtf(msg);
+ char *caption8 = CopyUniToUtf(caption);
+
+ UnixAlert(msg8, caption8);
+
+ Free(msg8);
+ Free(caption8);
+}
+void UnixAlert(char *msg, char *caption)
+{
+ char *tag =
+ "-- Alert: %s --\n%s\n";
+ // Validate arguments
+ if (msg == NULL)
+ {
+ msg = "Alert";
+ }
+ if (caption == NULL)
+ {
+ caption = CEDAR_PRODUCT_STR " VPN Kernel";
+ }
+
+ printf(tag, caption, msg);
+}
+
+// Get the information of the current OS
+void UnixGetOsInfo(OS_INFO *info)
+{
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ Zero(info, sizeof(OS_INFO));
+ info->OsType = OSTYPE_UNIX_UNKNOWN;
+
+#ifdef UNIX_SOLARIS
+ info->OsType = OSTYPE_SOLARIS;
+#endif // UNIX_SOLARIS
+
+#ifdef UNIX_CYGWIN
+ info->OsType = OSTYPE_CYGWIN;
+#endif // UNIX_CYGWIN
+
+#ifdef UNIX_MACOS
+ info->OsType = OSTYPE_MACOS_X;
+#endif // UNIX_MACOS
+
+#ifdef UNIX_BSD
+ info->OsType = OSTYPE_BSD;
+#endif // UNIX_BSD
+
+#ifdef UNIX_LINUX
+ info->OsType = OSTYPE_LINUX;
+#endif // UNIX_LINUX
+
+ info->OsServicePack = 0;
+
+ if (info->OsType != OSTYPE_LINUX)
+ {
+ info->OsSystemName = CopyStr("UNIX");
+ info->OsProductName = CopyStr("UNIX");
+ }
+ else
+ {
+ info->OsSystemName = CopyStr("Linux");
+ info->OsProductName = CopyStr("Linux");
+ }
+
+ if (info->OsType == OSTYPE_LINUX)
+ {
+ // Get the distribution name on Linux
+ BUF *b;
+ b = ReadDump("/etc/redhat-release");
+ if (b != NULL)
+ {
+ info->OsVersion = CfgReadNextLine(b);
+ info->OsVendorName = CopyStr("Red Hat, Inc.");
+ FreeBuf(b);
+ }
+ else
+ {
+ b = ReadDump("/etc/turbolinux-release");
+ if (b != NULL)
+ {
+ info->OsVersion = CfgReadNextLine(b);
+ info->OsVendorName = CopyStr("Turbolinux, Inc.");
+ FreeBuf(b);
+ }
+ else
+ {
+ info->OsVersion = CopyStr("Unknown Liunx Version");
+ info->OsVendorName = CopyStr("Unknown Vendor");
+ }
+ }
+
+ info->KernelName = CopyStr("Linux Kernel");
+
+ b = ReadDump("/proc/sys/kernel/osrelease");
+ if (b != NULL)
+ {
+ info->KernelVersion = CfgReadNextLine(b);
+ FreeBuf(b);
+ }
+ else
+ {
+ info->KernelVersion = CopyStr("Unknown Version");
+ }
+ }
+ else
+ {
+ // In other cases
+ Free(info->OsProductName);
+ info->OsProductName = CopyStr(OsTypeToStr(info->OsType));
+ info->OsVersion = CopyStr("Unknown Version");
+ info->KernelName = CopyStr(OsTypeToStr(info->OsType));
+ info->KernelVersion = CopyStr("Unknown Version");
+ }
+}
+
+// Examine whether the current OS is supported by the PacketiX VPN Kernel
+bool UnixIsSupportedOs()
+{
+ // Support all UNIX OS which can run PacketiX VPN
+ return true;
+}
+
+// Run a specified command
+bool UnixRunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
+{
+ char *filename8 = CopyUniToUtf(filename);
+ char *arg8 = CopyUniToUtf(arg);
+ bool ret = UnixRun(filename8, arg8, hide, wait);
+
+ Free(filename8);
+ Free(arg8);
+
+ return ret;
+}
+bool UnixRun(char *filename, char *arg, bool hide, bool wait)
+{
+ TOKEN_LIST *t;
+ UINT ret;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return false;
+ }
+ if (arg == NULL)
+ {
+ arg = "";
+ }
+
+ // Create a child process
+ ret = fork();
+ if (ret == -1)
+ {
+ // Child process creation failure
+ return false;
+ }
+
+ if (ret == 0)
+ {
+ Print("", filename, arg);
+ // Child process
+ if (hide)
+ {
+ // Close the standard I/O
+ UnixCloseIO();
+ }
+
+ t = ParseToken(arg, " ");
+ if (t == NULL)
+ {
+ AbortExit();
+ }
+ else
+ {
+ char **args;
+ UINT num_args;
+ UINT i;
+ num_args = t->NumTokens + 2;
+ args = ZeroMalloc(sizeof(char *) * num_args);
+ args[0] = filename;
+ for (i = 1;i < num_args - 1;i++)
+ {
+ args[i] = t->Token[i - 1];
+ }
+ execvp(filename, args);
+ AbortExit();
+ }
+ }
+ else
+ {
+ // Parent process
+ pid_t pid = (pid_t)ret;
+
+ if (wait)
+ {
+ int status = 0;
+ // Wait for the termination of the child process
+ if (waitpid(pid, &status, 0) == -1)
+ {
+ return false;
+ }
+
+ if (WEXITSTATUS(status) == 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
+
+// Initialize the daemon
+void UnixDaemon(bool debug_mode)
+{
+ UINT ret;
+
+ if (debug_mode)
+ {
+ // Debug mode
+ signal(SIGHUP, SIG_IGN);
+ return;
+ }
+
+ ret = fork();
+
+ if (ret == -1)
+ {
+ // Error
+ return;
+ }
+ else if (ret == 0)
+ {
+ // Create a new session for the child process
+ setsid();
+
+ // Close the standard I/O
+ UnixCloseIO();
+
+ // Mute the unwanted signal
+ signal(SIGHUP, SIG_IGN);
+ }
+ else
+ {
+ // Terminate the parent process
+ exit(0);
+ }
+}
+
+// Close the standard I/O
+void UnixCloseIO()
+{
+ static bool close_io_first = false;
+
+ // Execute only once
+ if (close_io_first)
+ {
+ return;
+ }
+ else
+ {
+ close(0);
+ close(1);
+ close(2);
+ open("/dev/null", O_RDWR);
+ dup2(0, 1);
+ dup2(0, 2);
+ close_io_first = false;
+ }
+}
+
+// Change the file name
+bool UnixFileRenameW(wchar_t *old_name, wchar_t *new_name)
+{
+ char *old_name8 = CopyUniToUtf(old_name);
+ char *new_name8 = CopyUniToUtf(new_name);
+ bool ret = UnixFileRename(old_name8, new_name8);
+
+ Free(old_name8);
+ Free(new_name8);
+
+ return ret;
+}
+bool UnixFileRename(char *old_name, char *new_name)
+{
+ // Validate arguments
+ if (old_name == NULL || new_name == NULL)
+ {
+ return false;
+ }
+
+ if (rename(old_name, new_name) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the call stack
+CALLSTACK_DATA *UnixGetCallStack()
+{
+ // This is not supported on non-Win32
+ return NULL;
+}
+
+// Get the symbol information from the call stack
+bool UnixGetCallStackSymbolInfo(CALLSTACK_DATA *s)
+{
+ // This is not supported on non-Win32
+ return false;
+}
+
+// Delete the directory
+bool UnixDeleteDirW(wchar_t *name)
+{
+ char *name8 = CopyUniToUtf(name);
+ bool ret = UnixDeleteDir(name8);
+
+ Free(name8);
+
+ return ret;
+}
+bool UnixDeleteDir(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (rmdir(name) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Create a directory
+bool UnixMakeDirW(wchar_t *name)
+{
+ char *name8 = CopyUniToUtf(name);
+ bool ret = UnixMakeDir(name8);
+
+ Free(name8);
+
+ return ret;
+}
+bool UnixMakeDir(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (mkdir(name, 0700) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Delete the file
+bool UnixFileDeleteW(wchar_t *name)
+{
+ bool ret;
+ char *name8 = CopyUniToUtf(name);
+
+ ret = UnixFileDelete(name8);
+
+ Free(name8);
+
+ return ret;
+}
+bool UnixFileDelete(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (remove(name) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Seek the file
+bool UnixFileSeek(void *pData, UINT mode, int offset)
+{
+ UNIXIO *p;
+ UINT ret;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return 0;
+ }
+ if (mode != FILE_BEGIN && mode != FILE_END && mode != FILE_CURRENT)
+ {
+ return false;
+ }
+
+ p = (UNIXIO *)pData;
+
+ ret = lseek(p->fd, offset, mode);
+
+ if (ret == -1)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Get the file size
+UINT64 UnixFileSize(void *pData)
+{
+ struct stat st;
+ UNIXIO *p;
+ int r;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return 0;
+ }
+
+ p = (UNIXIO *)pData;
+
+ Zero(&st, sizeof(st));
+ r = fstat(p->fd, &st);
+ if (r != 0)
+ {
+ return 0;
+ }
+
+ return (UINT64)st.st_size;
+}
+
+// Write to the file
+bool UnixFileWrite(void *pData, void *buf, UINT size)
+{
+ UNIXIO *p;
+ UINT ret;
+ // Validate arguments
+ if (pData == NULL || buf == NULL || size == 0)
+ {
+ return false;
+ }
+
+ p = (UNIXIO *)pData;
+
+ ret = write(p->fd, buf, size);
+ if (ret != size)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Read from the file
+bool UnixFileRead(void *pData, void *buf, UINT size)
+{
+ UNIXIO *p;
+ UINT ret;
+ // Validate arguments
+ if (pData == NULL || buf == NULL || size == 0)
+ {
+ return false;
+ }
+
+ p = (UNIXIO *)pData;
+
+ ret = read(p->fd, buf, size);
+ if (ret != size)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Flush to the file
+void UnixFileFlush(void *pData)
+{
+ UNIXIO *p;
+ bool write_mode;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return;
+ }
+
+ p = (UNIXIO *)pData;
+
+ write_mode = p->write_mode;
+
+ if (write_mode)
+ {
+ fsync(p->fd);
+ }
+}
+
+// Close the file
+void UnixFileClose(void *pData, bool no_flush)
+{
+ UNIXIO *p;
+ bool write_mode;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return;
+ }
+
+ p = (UNIXIO *)pData;
+
+ write_mode = p->write_mode;
+
+ if (write_mode && no_flush == false)
+ {
+ fsync(p->fd);
+ }
+
+ close(p->fd);
+
+ UnixMemoryFree(p);
+
+ if (write_mode)
+ {
+ //sync();
+ }
+}
+
+// Create a file
+void *UnixFileCreateW(wchar_t *name)
+{
+ void *ret;
+ char *name8 = CopyUniToUtf(name);
+
+ ret = UnixFileCreate(name8);
+
+ Free(name8);
+
+ return ret;
+}
+void *UnixFileCreate(char *name)
+{
+ UNIXIO *p;
+ int fd;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ fd = creat(name, 0600);
+ if (fd == -1)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ p = UnixMemoryAlloc(sizeof(UNIXIO));
+ p->fd = fd;
+ p->write_mode = true;
+
+ return (void *)p;
+}
+
+// Open the file
+void *UnixFileOpenW(wchar_t *name, bool write_mode, bool read_lock)
+{
+ char *name8 = CopyUniToUtf(name);
+ void *ret;
+
+ ret = UnixFileOpen(name8, write_mode, read_lock);
+
+ Free(name8);
+
+ return ret;
+}
+void *UnixFileOpen(char *name, bool write_mode, bool read_lock)
+{
+ UNIXIO *p;
+ int fd;
+ int mode;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (write_mode == false)
+ {
+ mode = O_RDONLY;
+ }
+ else
+ {
+ mode = O_RDWR;
+ }
+
+ // Open the file
+ fd = open(name, mode);
+ if (fd == -1)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ p = UnixMemoryAlloc(sizeof(UNIXIO));
+ p->fd = fd;
+ p->write_mode = write_mode;
+
+ return (void *)p;
+}
+
+// Return the current thread ID
+UINT UnixThreadId()
+{
+ UINT ret;
+
+ ret = (UINT)pthread_self();
+
+ return ret;
+}
+
+// Thread function
+void *UnixDefaultThreadProc(void *param)
+{
+ UNIXTHREAD *ut;
+ UNIXTHREADSTARTUPINFO *info = (UNIXTHREADSTARTUPINFO *)param;
+ if (info == NULL)
+ {
+ return 0;
+ }
+
+ ut = (UNIXTHREAD *)info->thread->pData;
+
+ // Call the thread function
+ info->thread_proc(info->thread, info->param);
+
+ // Set a termination flag
+ ut->finished = true;
+
+ // Release of reference
+ ReleaseThread(info->thread);
+
+ UnixMemoryFree(info);
+
+ FreeOpenSSLThreadState();
+
+ return 0;
+}
+
+// Release of thread
+void UnixFreeThread(THREAD *t)
+{
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+
+ // Free memory
+ UnixMemoryFree(t->pData);
+}
+
+// Wait for the termination of the thread
+bool UnixWaitThread(THREAD *t)
+{
+ UNIXTHREAD *ut;
+ void *retcode = NULL;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+ ut = (UNIXTHREAD *)t->pData;
+ if (ut == NULL)
+ {
+ return false;
+ }
+
+ pthread_join(ut->thread, &retcode);
+
+ return true;
+}
+
+// Thread initialization
+bool UnixInitThread(THREAD *t)
+{
+ UNIXTHREAD *ut;
+ UNIXTHREADSTARTUPINFO *info;
+ pthread_attr_t attr;
+ // Validate arguments
+ if (t == NULL || t->thread_proc == NULL)
+ {
+ return false;
+ }
+
+ // Thread data creation
+ ut = UnixMemoryAlloc(sizeof(UNIXTHREAD));
+ Zero(ut, sizeof(UNIXTHREAD));
+
+ // Creating the startup information
+ info = UnixMemoryAlloc(sizeof(UNIXTHREADSTARTUPINFO));
+ Zero(info, sizeof(UNIXTHREADSTARTUPINFO));
+ info->param = t->param;
+ info->thread_proc = t->thread_proc;
+ info->thread = t;
+ AddRef(t->ref);
+
+ // Thread creation
+ pthread_attr_init(&attr);
+ pthread_attr_setstacksize(&attr, UNIX_THREAD_STACK_SIZE);
+
+ t->pData = (void *)ut;
+
+ if (pthread_create(&ut->thread, &attr, UnixDefaultThreadProc, info) != 0)
+ {
+ // An error has occured
+ t->pData = NULL;
+ Release(t->ref);
+ UnixMemoryFree(ut);
+ UnixMemoryFree(info);
+ pthread_attr_destroy(&attr);
+ return false;
+ }
+
+ pthread_attr_destroy(&attr);
+
+ return true;
+}
+
+// Release the event
+void UnixFreeEvent(EVENT *event)
+{
+ UNIXEVENT *ue = (UNIXEVENT *)event->pData;
+ if (ue == NULL)
+ {
+ return;
+ }
+
+ pthread_cond_destroy(&ue->cond);
+ pthread_mutex_destroy(&ue->mutex);
+
+ UnixMemoryFree(ue);
+}
+
+// Wait for a event
+bool UnixWaitEvent(EVENT *event, UINT timeout)
+{
+ UNIXEVENT *ue = (UNIXEVENT *)event->pData;
+ struct timeval now;
+ struct timespec to;
+ bool ret;
+ if (ue == NULL)
+ {
+ return false;
+ }
+
+ pthread_mutex_lock(&ue->mutex);
+ gettimeofday(&now, NULL);
+ to.tv_sec = now.tv_sec + timeout / 1000;
+ to.tv_nsec = now.tv_usec * 1000 + (timeout % 1000) * 1000 * 1000;
+ if ((to.tv_nsec / 1000000000) >= 1)
+ {
+ to.tv_sec += to.tv_nsec / 1000000000;
+ to.tv_nsec = to.tv_nsec % 1000000000;
+ }
+
+ ret = true;
+
+ while (ue->signal == false)
+ {
+ if (timeout != INFINITE)
+ {
+ if (pthread_cond_timedwait(&ue->cond, &ue->mutex, &to))
+ {
+ ret = false;
+ break;
+ }
+ }
+ else
+ {
+ pthread_cond_wait(&ue->cond, &ue->mutex);
+ }
+ }
+ ue->signal = false;
+
+ pthread_mutex_unlock(&ue->mutex);
+
+ return ret;
+}
+
+// Reset the event
+void UnixResetEvent(EVENT *event)
+{
+ UNIXEVENT *ue = (UNIXEVENT *)event->pData;
+ if (ue == NULL)
+ {
+ return;
+ }
+
+ pthread_mutex_lock(&ue->mutex);
+ ue->signal = false;
+ pthread_cond_signal(&ue->cond);
+ pthread_mutex_unlock(&ue->mutex);
+}
+
+// Set the event
+void UnixSetEvent(EVENT *event)
+{
+ UNIXEVENT *ue = (UNIXEVENT *)event->pData;
+ if (ue == NULL)
+ {
+ return;
+ }
+
+ pthread_mutex_lock(&ue->mutex);
+ ue->signal = true;
+ pthread_cond_signal(&ue->cond);
+ pthread_mutex_unlock(&ue->mutex);
+}
+
+// Initialize the event
+void UnixInitEvent(EVENT *event)
+{
+ UNIXEVENT *ue = UnixMemoryAlloc(sizeof(UNIXEVENT));
+
+ Zero(ue, sizeof(UNIXEVENT));
+
+ pthread_cond_init(&ue->cond, NULL);
+ pthread_mutex_init(&ue->mutex, NULL);
+ ue->signal = false;
+
+ event->pData = (void *)ue;
+}
+
+// Delete the lock
+void UnixDeleteLock(LOCK *lock)
+{
+ pthread_mutex_t *mutex;
+ // Reset Ready flag safely
+ UnixLock(lock);
+ lock->Ready = false;
+ UnixUnlockEx(lock, true);
+
+ // Delete the mutex
+ mutex = (pthread_mutex_t *)lock->pData;
+ pthread_mutex_destroy(mutex);
+
+ // Memory release
+ UnixMemoryFree(mutex);
+ UnixMemoryFree(lock);
+}
+
+// Unlock
+void UnixUnlock(LOCK *lock)
+{
+ UnixUnlockEx(lock, false);
+}
+void UnixUnlockEx(LOCK *lock, bool inner)
+{
+ pthread_mutex_t *mutex;
+ if (lock->Ready == false && inner == false)
+ {
+ // State is invalid
+ return;
+ }
+ mutex = (pthread_mutex_t *)lock->pData;
+
+ if ((--lock->locked_count) > 0)
+ {
+ return;
+ }
+
+ lock->thread_id = INFINITE;
+
+ pthread_mutex_unlock(mutex);
+
+ return;
+}
+
+// Lock
+bool UnixLock(LOCK *lock)
+{
+ pthread_mutex_t *mutex;
+ UINT thread_id = UnixThreadId();
+ if (lock->Ready == false)
+ {
+ // State is invalid
+ return false;
+ }
+
+ if (lock->thread_id == thread_id)
+ {
+ lock->locked_count++;
+ return true;
+ }
+
+ mutex = (pthread_mutex_t *)lock->pData;
+
+ pthread_mutex_lock(mutex);
+
+ lock->thread_id = thread_id;
+ lock->locked_count++;
+
+ return true;
+}
+
+// Creating a new lock
+LOCK *UnixNewLock()
+{
+ pthread_mutex_t *mutex;
+ // Memory allocation
+ LOCK *lock = UnixMemoryAlloc(sizeof(LOCK));
+
+ // Create a mutex
+ mutex = UnixMemoryAlloc(sizeof(pthread_mutex_t));
+
+ // Initialization of the mutex
+ pthread_mutex_init(mutex, NULL);
+
+ lock->pData = (void *)mutex;
+ lock->Ready = true;
+
+ lock->thread_id = INFINITE;
+ lock->locked_count = 0;
+
+ return lock;
+}
+
+// Sleep
+void UnixSleep(UINT time)
+{
+ UINT sec = 0, millisec = 0;
+ // Validate arguments
+ if (time == 0)
+ {
+ return;
+ }
+
+ if (time == INFINITE)
+ {
+ // Wait forever
+ while (true)
+ {
+#ifdef UNIX_SOLARIS
+ UnixSolarisSleep(time);
+#else
+ sleep(1000000);
+#endif
+ }
+ }
+
+#ifdef UNIX_SOLARIS
+ UnixSolarisSleep(time);
+#else
+
+ // Prevent overflow
+ sec = time / 1000;
+ millisec = time % 1000;
+
+ if (sec != 0)
+ {
+ sleep(sec);
+ }
+ if (millisec != 0)
+ {
+ usleep(millisec * 1000);
+ }
+#endif
+}
+
+// Decrement
+void UnixDec32(UINT *value)
+{
+ if (value != NULL)
+ {
+ (*value)--;
+ }
+}
+
+// Increment
+void UnixInc32(UINT *value)
+{
+ if (value != NULL)
+ {
+ (*value)++;
+ }
+}
+
+// Get the System Time
+void UnixGetSystemTime(SYSTEMTIME *system_time)
+{
+ time_t now = 0;
+ struct tm tm;
+ struct timeval tv;
+ struct timezone tz;
+ // Validate arguments
+ if (system_time == NULL)
+ {
+ return;
+ }
+
+ pthread_mutex_lock(&get_time_lock);
+
+ Zero(system_time, sizeof(SYSTEMTIME));
+ Zero(&tv, sizeof(tv));
+ Zero(&tz, sizeof(tz));
+
+ time(&now);
+
+ gmtime_r(&now, &tm);
+
+ TmToSystem(system_time, &tm);
+
+ gettimeofday(&tv, &tz);
+
+ system_time->wMilliseconds = tv.tv_usec / 1000;
+
+ pthread_mutex_unlock(&get_time_lock);
+}
+
+// Get the system timer (64bit)
+UINT64 UnixGetTick64()
+{
+#if defined(OS_WIN32) || defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC) || defined(CLOCK_HIGHRES)
+
+ struct timespec t;
+ UINT64 ret;
+ static bool akirame = false;
+
+ if (akirame)
+ {
+ return TickRealtimeManual();
+ }
+
+ Zero(&t, sizeof(t));
+
+ // Function to get the boot time of the system
+ // Be careful. The Implementation is depend on the system.
+#ifdef CLOCK_HIGHRES
+ clock_gettime(CLOCK_HIGHRES, &t);
+#else // CLOCK_HIGHRES
+#ifdef CLOCK_MONOTONIC
+ clock_gettime(CLOCK_MONOTONIC, &t);
+#else // CLOCK_MONOTONIC
+ clock_gettime(CLOCK_REALTIME, &t);
+#endif // CLOCK_MONOTONIC
+#endif // CLOCK_HIGHRES
+
+ ret = (UINT64)t.tv_sec * 1000LL + (UINT64)t.tv_nsec / 1000000LL;
+
+ if (akirame == false && ret == 0)
+ {
+ ret = TickRealtimeManual();
+ akirame = true;
+ }
+
+ return ret;
+
+#else
+
+ return TickRealtimeManual();
+
+#endif
+}
+
+// Get the system timer
+UINT UnixGetTick()
+{
+ return (UINT)UnixGetTick64();
+}
+
+// Memory allocation
+void *UnixMemoryAlloc(UINT size)
+{
+ void *r;
+ pthread_mutex_lock(&malloc_lock);
+ r = malloc(size);
+ pthread_mutex_unlock(&malloc_lock);
+ return r;
+}
+
+// Reallocation of the memory
+void *UnixMemoryReAlloc(void *addr, UINT size)
+{
+ void *r;
+ pthread_mutex_lock(&malloc_lock);
+ r = realloc(addr, size);
+ pthread_mutex_unlock(&malloc_lock);
+ return r;
+}
+
+// Free the memory
+void UnixMemoryFree(void *addr)
+{
+ pthread_mutex_lock(&malloc_lock);
+ free(addr);
+ pthread_mutex_unlock(&malloc_lock);
+}
+
+// SIGCHLD handler
+void UnixSigChldHandler(int sig)
+{
+ // Recall the zombie processes
+ while (waitpid(-1, NULL, WNOHANG) > 0);
+ signal(SIGCHLD, UnixSigChldHandler);
+}
+
+// Initialize the library for UNIX
+void UnixInit()
+{
+ UNIXIO *o;
+
+ UnixInitSolarisSleep();
+
+ // Global lock
+ pthread_mutex_init(&get_time_lock, NULL);
+ pthread_mutex_init(&malloc_lock, NULL);
+
+ // Get the Process ID
+ current_process_id = getpid();
+
+#ifdef RLIMIT_CORE
+ UnixSetResourceLimit(RLIMIT_CORE, UNIX_MAX_MEMORY);
+#endif // RLIMIT_CORE
+
+#ifdef RLIMIT_DATA
+ UnixSetResourceLimit(RLIMIT_DATA, UNIX_MAX_MEMORY);
+#endif // RLIMIT_DATA
+
+#ifdef RLIMIT_NOFILE
+#ifndef UNIX_MACOS
+ UnixSetResourceLimit(RLIMIT_NOFILE, UNIX_MAX_FD);
+#else // UNIX_MACOS
+ UnixSetResourceLimit(RLIMIT_NOFILE, UNIX_MAX_FD_MACOS);
+#endif // UNIX_MACOS
+#endif // RLIMIT_NOFILE
+
+#ifdef RLIMIT_STACK
+// UnixSetResourceLimit(RLIMIT_STACK, UNIX_MAX_MEMORY);
+#endif // RLIMIT_STACK
+
+#ifdef RLIMIT_RSS
+ UnixSetResourceLimit(RLIMIT_RSS, UNIX_MAX_MEMORY);
+#endif // RLIMIT_RSS
+
+#ifdef RLIMIT_LOCKS
+ UnixSetResourceLimit(RLIMIT_LOCKS, UNIX_MAX_LOCKS);
+#endif // RLIMIT_LOCKS
+
+#ifdef RLIMIT_MEMLOCK
+ UnixSetResourceLimit(RLIMIT_MEMLOCK, UNIX_MAX_MEMORY);
+#endif // RLIMIT_MEMLOCK
+
+#ifdef RLIMIT_NPROC
+ UnixSetResourceLimit(RLIMIT_NPROC, UNIX_MAX_CHILD_PROCESSES);
+#endif // RLIMIT_NPROC
+
+ // Write a value to the threads-max of the proc file system
+ o = UnixFileCreate("/proc/sys/kernel/threads-max");
+ if (o != NULL)
+ {
+ char tmp[128];
+ sprintf(tmp, "%u\n", UNIX_LINUX_MAX_THREADS);
+ UnixFileWrite(o, tmp, strlen(tmp));
+ UnixFileClose(o, false);
+ }
+
+ // Set the signals that is to be ignored
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGALRM, SIG_IGN);
+
+#ifdef UNIX_BSD
+ signal(64, SIG_IGN);
+#endif // UNIX_BSD
+
+#ifdef SIGXFSZ
+ signal(SIGXFSZ, SIG_IGN);
+#endif // SIGXFSZ
+
+ // Set a signal handler to salvage the child processes
+ signal(SIGCHLD, UnixSigChldHandler);
+}
+
+// Release the library for UNIX
+void UnixFree()
+{
+ UnixFreeSolarisSleep();
+
+ current_process_id = 0;
+
+ pthread_mutex_destroy(&get_time_lock);
+}
+
+// Adjust the upper limit of resources that may be occupied
+void UnixSetResourceLimit(UINT id, UINT value)
+{
+ struct rlimit t;
+ UINT hard_limit;
+
+ Zero(&t, sizeof(t));
+ getrlimit(id, &t);
+
+ hard_limit = t.rlim_max;
+
+ Zero(&t, sizeof(t));
+ t.rlim_cur = MIN(value, hard_limit);
+ t.rlim_max = hard_limit;
+ setrlimit(id, &t);
+
+ Zero(&t, sizeof(t));
+ t.rlim_cur = value;
+ t.rlim_max = value;
+ setrlimit(id, &t);
+}
+
+// Generate the PID file name
+void UnixGenPidFileName(char *name, UINT size)
+{
+ char exe_name[MAX_PATH];
+ UCHAR hash[MD5_SIZE];
+ char tmp1[64];
+ char dir[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ GetExeDir(dir, sizeof(dir));
+
+ GetExeName(exe_name, sizeof(exe_name));
+ StrCat(exe_name, sizeof(exe_name), ":pid_hash");
+ StrUpper(exe_name);
+
+ Hash(hash, exe_name, StrLen(exe_name), false);
+ BinToStr(tmp1, sizeof(tmp1), hash, sizeof(hash));
+
+ Format(name, size, "%s/.pid_%s", dir, tmp1);
+}
+
+// Delete the PID file
+void UnixDeletePidFile()
+{
+ char tmp[MAX_PATH];
+
+ UnixGenPidFileName(tmp, sizeof(tmp));
+
+ UnixFileDelete(tmp);
+}
+
+// Delete the CTL file
+void UnixDeleteCtlFile()
+{
+ char tmp[MAX_PATH];
+
+ UnixGenCtlFileName(tmp, sizeof(tmp));
+
+ UnixFileDelete(tmp);
+}
+
+// Generate the CTL file name
+void UnixGenCtlFileName(char *name, UINT size)
+{
+ char exe_name[MAX_PATH];
+ UCHAR hash[MD5_SIZE];
+ char tmp1[64];
+ char dir[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ GetExeDir(dir, sizeof(dir));
+
+ GetExeName(exe_name, sizeof(exe_name));
+ StrCat(exe_name, sizeof(exe_name), ":pid_hash");
+ StrUpper(exe_name);
+
+ Hash(hash, exe_name, StrLen(exe_name), false);
+ BinToStr(tmp1, sizeof(tmp1), hash, sizeof(hash));
+
+ Format(name, size, "%s/.ctl_%s", dir, tmp1);
+}
+
+// Write the CTL file
+void UnixWriteCtlFile(UINT i)
+{
+ char tmp[MAX_PATH];
+ char tmp2[64];
+ IO *o;
+
+ UnixGenCtlFileName(tmp, sizeof(tmp));
+ Format(tmp2, sizeof(tmp2), "%u\n", i);
+
+ o = FileCreate(tmp);
+ if (o != NULL)
+ {
+ FileWrite(o, tmp2, StrLen(tmp2));
+ FileClose(o);
+ }
+}
+
+// Write to the PID file
+void UnixWritePidFile(UINT pid)
+{
+ char tmp[MAX_PATH];
+ char tmp2[64];
+ IO *o;
+
+ UnixGenPidFileName(tmp, sizeof(tmp));
+ Format(tmp2, sizeof(tmp2), "%u\n", pid);
+
+ o = FileCreate(tmp);
+ if (o != NULL)
+ {
+ FileWrite(o, tmp2, StrLen(tmp2));
+ FileClose(o);
+ }
+}
+
+// Read the PID file
+UINT UnixReadPidFile()
+{
+ char tmp[MAX_PATH];
+ BUF *buf;
+
+ UnixGenPidFileName(tmp, sizeof(tmp));
+
+ buf = ReadDump(tmp);
+ if (buf == NULL)
+ {
+ return 0;
+ }
+
+ Zero(tmp, sizeof(tmp));
+ Copy(tmp, buf->Buf, MIN(buf->Size, sizeof(tmp)));
+ FreeBuf(buf);
+
+ return ToInt(tmp);
+}
+
+// Read the CTL file
+UINT UnixReadCtlFile()
+{
+ char tmp[MAX_PATH];
+ BUF *buf;
+
+ UnixGenCtlFileName(tmp, sizeof(tmp));
+
+ buf = ReadDump(tmp);
+ if (buf == NULL)
+ {
+ return 0;
+ }
+
+ Zero(tmp, sizeof(tmp));
+ Copy(tmp, buf->Buf, MIN(buf->Size, sizeof(tmp)));
+ FreeBuf(buf);
+
+ return ToInt(tmp);
+}
+
+// Get the UID
+UINT UnixGetUID()
+{
+ return (UINT)getuid();
+}
+
+// Start the service
+void UnixStartService(char *name)
+{
+ char *svc_name, *svc_title;
+ char tmp[128];
+ INSTANCE *inst;
+ char exe[MAX_PATH];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ GetExeName(exe, sizeof(exe));
+
+ Format(tmp, sizeof(tmp), SVC_NAME, name);
+ svc_name = _SS(tmp);
+ Format(tmp, sizeof(tmp), SVC_TITLE, name);
+ svc_title = _SS(tmp);
+
+ // Examine whether the service has not been started already
+ inst = NewSingleInstance(NULL);
+ if (inst == NULL)
+ {
+ // Service is already running
+ UniPrint(_UU("UNIX_SVC_ALREADY_START"), svc_title, svc_name);
+ }
+ else
+ {
+ int pid;
+ // Begin to start the service
+ UniPrint(_UU("UNIX_SVC_STARTED"), svc_title);
+ FreeSingleInstance(inst);
+
+ // Create a child process
+ pid = fork();
+ if (pid == -1)
+ {
+ UniPrint(_UU("UNIX_SVC_ERROR_FORK"), svc_title);
+ }
+ else
+ {
+ if (pid == 0)
+ {
+ // Child process
+ char *param = UNIX_SVC_ARG_EXEC_SVC;
+ char **args;
+
+ // Daemonize
+ setsid();
+ UnixCloseIO();
+ signal(SIGHUP, SIG_IGN);
+
+ // Prepare arguments
+ args = ZeroMalloc(sizeof(char *) * 3);
+ args[0] = exe;
+ args[1] = param;
+ args[2] = NULL;
+
+ execvp(exe, args);
+ AbortExit();
+ }
+ else
+ {
+ // Don't write the child process number to the file
+// UnixWritePidFile(pid);
+ }
+ }
+ }
+}
+
+// Stop the Service
+void UnixStopService(char *name)
+{
+ char *svc_name, *svc_title;
+ char tmp[128];
+ INSTANCE *inst;
+ char exe[MAX_PATH];
+ UINT pid;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ GetExeName(exe, sizeof(exe));
+
+ Format(tmp, sizeof(tmp), SVC_NAME, name);
+ svc_name = _SS(tmp);
+ Format(tmp, sizeof(tmp), SVC_TITLE, name);
+ svc_title = _SS(tmp);
+
+ inst = NewSingleInstance(NULL);
+ pid = UnixReadPidFile();
+ if (inst != NULL || pid == 0)
+ {
+ // Service is not running yet
+ UniPrint(_UU("UNIX_SVC_NOT_STARTED"), svc_title, svc_name);
+ }
+ else
+ {
+ int status;
+
+ // Stop the service
+ UniPrint(_UU("UNIX_SVC_STOPPING"), svc_title);
+
+ // Terminate the process
+ kill(pid, SIGTERM);
+#ifdef UNIX_BSD
+ UnixWriteCtlFile(Rand32());
+#endif // UNIX_BSD
+ if (UnixWaitProcessEx(pid, UNIX_SERVICE_STOP_TIMEOUT_2))
+ {
+ UniPrint(_UU("UNIX_SVC_STOPPED"), svc_title);
+ }
+ else
+ {
+ UniPrint(_UU("UNIX_SVC_STOP_FAILED"), svc_title);
+ }
+ }
+
+ FreeSingleInstance(inst);
+}
+
+// Handler of the stop signal to the process
+void UnixSigTermHandler(int signum)
+{
+ if (signum == SIGTERM)
+ {
+ unix_svc_terminate = true;
+ }
+}
+
+// The thread for stop service
+void UnixStopThread(THREAD *t, void *param)
+{
+ SERVICE_FUNCTION *stop = (SERVICE_FUNCTION *)param;
+ // Validate arguments
+ if (t == NULL || param == NULL)
+ {
+ return;
+ }
+
+ stop();
+}
+
+// Execute the main body of the service
+void UnixExecService(char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
+{
+ char *svc_name, *svc_title;
+ char tmp[128];
+ INSTANCE *inst;
+ UINT yobi_size = 1024 * 128;
+ void *yobi1, *yobi2;
+ UINT saved_ctl;
+ // Validate arguments
+ if (start == NULL || stop == NULL || name == NULL)
+ {
+ return;
+ }
+
+ Format(tmp, sizeof(tmp), SVC_NAME, name);
+ svc_name = _SS(tmp);
+ Format(tmp, sizeof(tmp), SVC_TITLE, name);
+ svc_title = _SS(tmp);
+
+ UnixWriteCtlFile(Rand32());
+ saved_ctl = UnixReadCtlFile();
+
+ inst = NewSingleInstance(NULL);
+ if (inst != NULL)
+ {
+ THREAD *t;
+
+ yobi1 = ZeroMalloc(yobi_size);
+ yobi2 = ZeroMalloc(yobi_size);
+
+ // Start
+ UnixWritePidFile(getpid());
+
+ start();
+
+ // Starting complete. wait for arriving SIGTERM from another process
+ signal(SIGTERM, &UnixSigTermHandler);
+ while (unix_svc_terminate == false)
+ {
+#ifndef UNIX_BSD
+ pause();
+#else // UNIX_BSD
+ if (UnixReadCtlFile() != saved_ctl)
+ {
+ break;
+ }
+
+ SleepThread(1394);
+#endif // UNIX_BSD
+ }
+
+ // Stop
+ Free(yobi1);
+ t = NewThread(UnixStopThread, stop);
+ if (t == NULL || (WaitThread(t, UNIX_SERVICE_STOP_TIMEOUT_1) == false))
+ {
+ // Terminate forcibly if creation of a halting thread have
+ // failed or timed out
+ Free(yobi2);
+ FreeSingleInstance(inst);
+ UnixDeletePidFile();
+ _exit(0);
+ }
+ ReleaseThread(t);
+
+ // Delete the PID file
+ UnixDeletePidFile();
+
+ // Delete the CTL file
+ UnixDeleteCtlFile();
+
+ FreeSingleInstance(inst);
+
+ Free(yobi2);
+ }
+}
+
+// Get whether the process with the specified pid exists
+bool UnixIsProcess(UINT pid)
+{
+ if (getsid((pid_t)pid) == -1)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Wait for the termination of the specified process
+bool UnixWaitProcessEx(UINT pid, UINT timeout)
+{
+ UINT64 start_tick = Tick64();
+ UINT64 end_tick = start_tick + (UINT64)timeout;
+ if (timeout == INFINITE)
+ {
+ end_tick = 0;
+ }
+ while (UnixIsProcess(pid))
+ {
+ if (end_tick != 0)
+ {
+ if (end_tick < Tick64())
+ {
+ return false;
+ }
+ }
+ SleepThread(100);
+ }
+ return true;
+}
+void UnixWaitProcess(UINT pid)
+{
+ UnixWaitProcessEx(pid, INFINITE);
+}
+
+// Description of how to start
+void UnixUsage(char *name)
+{
+ char *svc_name, *svc_title;
+ char tmp[128];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ Format(tmp, sizeof(tmp), SVC_NAME, name);
+ svc_name = _SS(tmp);
+ Format(tmp, sizeof(tmp), SVC_TITLE, name);
+ svc_title = _SS(tmp);
+
+ UniPrint(_UU("UNIX_SVC_HELP"), svc_title, svc_name, svc_name, svc_title, svc_name, svc_title);
+}
+
+// Main function of the UNIX service
+UINT UnixService(int argc, char *argv[], char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
+{
+ // Validate arguments
+ if (name == NULL || start == NULL || stop == NULL)
+ {
+ return 0;
+ }
+
+ if (argc >= 2 && StrCmpi(argv[1], UNIX_SVC_ARG_EXEC_SVC) == 0)
+ {
+ UINT pid;
+ // Start a child process
+ // Restart if the child process didn't exit properly
+
+RESTART_PROCESS:
+ pid = fork();
+ if ((int)pid != -1)
+ {
+ if (pid == 0)
+ {
+ // Run the main process
+ UnixServiceMain(argc, argv, name, start, stop);
+ }
+ else
+ {
+ int status = 0, ret;
+
+ // Wait for the termination of the child process
+ ret = waitpid(pid, &status, 0);
+
+ if (WIFEXITED(status) == 0)
+ {
+ // Aborted
+ UnixSleep(100);
+ goto RESTART_PROCESS;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Start normally
+ UnixServiceMain(argc, argv, name, start, stop);
+ }
+
+ return 0;
+}
+void UnixServiceMain(int argc, char *argv[], char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
+{
+ UINT mode = 0;
+ // Start of the Mayaqua
+ InitMayaqua(false, false, argc, argv);
+
+ if (argc >= 2)
+ {
+ if (StrCmpi(argv[1], UNIX_SVC_ARG_START) == 0)
+ {
+ mode = UNIX_SVC_MODE_START;
+ }
+ if (StrCmpi(argv[1], UNIX_SVC_ARG_STOP) == 0)
+ {
+ mode = UNIX_SVC_MODE_STOP;
+ }
+ if (StrCmpi(argv[1], UNIX_SVC_ARG_EXEC_SVC) == 0)
+ {
+ mode = UNIX_SVC_MODE_EXEC_SVC;
+ }
+ if (StrCmpi(argv[1], UNIX_ARG_EXIT) == 0)
+ {
+ mode = UNIX_SVC_MODE_EXIT;
+ }
+ }
+
+ switch (mode)
+ {
+ case UNIX_SVC_MODE_EXIT:
+ break;
+
+ case UNIX_SVC_MODE_START:
+ UnixStartService(name);
+ break;
+
+ case UNIX_SVC_MODE_STOP:
+ UnixStopService(name);
+ break;
+
+ case UNIX_SVC_MODE_EXEC_SVC:
+ UnixExecService(name, start, stop);
+ break;
+
+ default:
+ UnixUsage(name);
+ break;
+ }
+
+ // End of the Mayaqua
+ FreeMayaqua();
+
+ return;
+}
+
+#endif // UNIX
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Unix.h b/src/Mayaqua/Unix.h
new file mode 100644
index 00000000..1f881a15
--- /dev/null
+++ b/src/Mayaqua/Unix.h
@@ -0,0 +1,239 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Unix.h
+// Header of Unix.c
+
+#ifdef OS_UNIX
+
+#ifndef UNIX_H
+#define UNIX_H
+
+// Constants
+#define UNIX_THREAD_STACK_SIZE (200 * 1000) // Stack size
+#define UNIX_MAX_CHILD_PROCESSES 2000000 // Maximum number of child processes
+#define UNIX_LINUX_MAX_THREADS 200000000 // Maximum number of threads
+#define UNIX_MAX_LOCKS 65536 // Maximum number of locks
+#define UNIX_MAX_MEMORY (2147483648UL) // Maximum memory capacity
+#define UNIX_MAX_FD (655360) // Maximum number of FDs
+#define UNIX_MAX_FD_MACOS (10000) // Maximum number of FDs (Mac OS X)
+#define MAXIMUM_WAIT_OBJECTS 64 // Maximum number of select
+
+#define UNIX_SERVICE_STOP_TIMEOUT_1 (600 * 1000) // Timeout to stop the service
+#define UNIX_SERVICE_STOP_TIMEOUT_2 (900 * 1000) // Timeout to stop the service (parent process)
+
+
+// Service related
+typedef void (SERVICE_FUNCTION)();
+
+#define SVC_NAME "SVC_%s_NAME"
+#define SVC_TITLE "SVC_%s_TITLE"
+
+#define UNIX_SVC_ARG_START "start"
+#define UNIX_SVC_ARG_STOP "stop"
+#define UNIX_SVC_ARG_EXEC_SVC "execsvc"
+#define UNIX_ARG_EXIT "exit"
+
+#define UNIX_SVC_MODE_START 1
+#define UNIX_SVC_MODE_STOP 2
+#define UNIX_SVC_MODE_EXEC_SVC 3
+#define UNIX_SVC_MODE_EXIT 4
+
+
+// Function prototype
+OS_DISPATCH_TABLE *UnixGetDispatchTable();
+void UnixInit();
+void UnixFree();
+void *UnixMemoryAlloc(UINT size);
+void *UnixMemoryReAlloc(void *addr, UINT size);
+void UnixMemoryFree(void *addr);
+UINT UnixGetTick();
+void UnixGetSystemTime(SYSTEMTIME *system_time);
+void UnixInc32(UINT *value);
+void UnixDec32(UINT *value);
+void UnixSleep(UINT time);
+LOCK *UnixNewLock();
+bool UnixLock(LOCK *lock);
+void UnixUnlock(LOCK *lock);
+void UnixUnlockEx(LOCK *lock, bool inner);
+void UnixDeleteLock(LOCK *lock);
+void UnixInitEvent(EVENT *event);
+void UnixSetEvent(EVENT *event);
+void UnixResetEvent(EVENT *event);
+bool UnixWaitEvent(EVENT *event, UINT timeout);
+void UnixFreeEvent(EVENT *event);
+bool UnixWaitThread(THREAD *t);
+void UnixFreeThread(THREAD *t);
+bool UnixInitThread(THREAD *t);
+UINT UnixThreadId();
+void *UnixFileOpen(char *name, bool write_mode, bool read_lock);
+void *UnixFileOpenW(wchar_t *name, bool write_mode, bool read_lock);
+void *UnixFileCreate(char *name);
+void *UnixFileCreateW(wchar_t *name);
+bool UnixFileWrite(void *pData, void *buf, UINT size);
+bool UnixFileRead(void *pData, void *buf, UINT size);
+void UnixFileClose(void *pData, bool no_flush);
+void UnixFileFlush(void *pData);
+UINT64 UnixFileSize(void *pData);
+bool UnixFileSeek(void *pData, UINT mode, int offset);
+bool UnixFileDelete(char *name);
+bool UnixFileDeleteW(wchar_t *name);
+bool UnixMakeDir(char *name);
+bool UnixMakeDirW(wchar_t *name);
+bool UnixDeleteDir(char *name);
+bool UnixDeleteDirW(wchar_t *name);
+CALLSTACK_DATA *UnixGetCallStack();
+bool UnixGetCallStackSymbolInfo(CALLSTACK_DATA *s);
+bool UnixFileRename(char *old_name, char *new_name);
+bool UnixFileRenameW(wchar_t *old_name, wchar_t *new_name);
+bool UnixRun(char *filename, char *arg, bool hide, bool wait);
+bool UnixRunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait);
+bool UnixIsSupportedOs();
+void UnixGetOsInfo(OS_INFO *info);
+void UnixAlert(char *msg, char *caption);
+void UnixAlertW(wchar_t *msg, wchar_t *caption);
+char *UnixGetProductId();
+void UnixSetHighPriority();
+void UnixRestorePriority();
+void *UnixNewSingleInstance(char *instance_name);
+void UnixFreeSingleInstance(void *data);
+void UnixGetMemInfo(MEMINFO *info);
+void UnixYield();
+TOKEN_LIST *UnixExec(char *cmd);
+void UnixExecSilent(char *cmd);
+void UnixDisableInterfaceOffload(char *name);
+void UnixSetEnableKernelEspProcessing(bool b);
+
+void UnixSetThreadPriorityRealtime();
+void UnixSetThreadPriorityLow();
+void UnixSetThreadPriorityHigh();
+void UnixSetThreadPriorityIdle();
+void UnixRestoreThreadPriority();
+void UnixSetResourceLimit(UINT id, UINT value);
+UINT64 UnixGetTick64();
+void UnixSigChldHandler(int sig);
+void UnixCloseIO();
+void UnixDaemon(bool debug_mode);
+void UnixGetCurrentDir(char *dir, UINT size);
+void UnixGetCurrentDirW(wchar_t *dir, UINT size);
+bool UnixCheckExecAccess(char *name);
+bool UnixCheckExecAccessW(wchar_t *name);
+DIRLIST *UnixEnumDirEx(char *dirname, COMPARE *compare);
+DIRLIST *UnixEnumDirExW(wchar_t *dirname, COMPARE *compare);
+bool UnixGetDiskFreeMain(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
+bool UnixGetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
+bool UnixGetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
+void UnixInitSolarisSleep();
+void UnixFreeSolarisSleep();
+void UnixSolarisSleep(UINT msec);
+
+UINT UnixService(int argc, char *argv[], char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop);
+void UnixServiceMain(int argc, char *argv[], char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop);
+void UnixGenPidFileName(char *name, UINT size);
+void UnixGenCtlFileName(char *name, UINT size);
+void UnixStartService(char *name);
+void UnixStopService(char *name);
+void UnixExecService(char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop);
+void UnixUsage(char *name);
+void UnixWritePidFile(UINT pid);
+void UnixWriteCtlFile(UINT i);
+UINT UnixReadPidFile();
+UINT UnixReadCtlFile();
+bool UnixIsProcess(UINT pid);
+bool UnixWaitProcessEx(UINT pid, UINT timeout);
+void UnixWaitProcess(UINT pid);
+void UnixDeletePidFile();
+void UnixDeleteCtlFile();
+void UnixStopThread(THREAD *t, void *param);
+UINT UnixGetUID();
+void UnixIgnoreSignalForThread(int sig);
+
+bool UnixIsInVmMain();
+bool UnixIsInVm();
+
+
+#endif // UNIX_H
+
+#endif // OS_UNIX
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Win32.c b/src/Mayaqua/Win32.c
new file mode 100644
index 00000000..7e1cc778
--- /dev/null
+++ b/src/Mayaqua/Win32.c
@@ -0,0 +1,3463 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Win32.c
+// Microsoft Windows dependent code
+
+#include <GlobalConst.h>
+
+#ifdef WIN32
+
+#define _WIN32_WINNT 0x0502
+#define WINVER 0x0502
+#include <winsock2.h>
+#include <windows.h>
+#include <Dbghelp.h>
+#include <commctrl.h>
+#include <process.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+
+static HANDLE heap_handle = NULL;
+static HANDLE hstdout = INVALID_HANDLE_VALUE;
+static HANDLE hstdin = INVALID_HANDLE_VALUE;
+
+// Thread data for Win32
+typedef struct WIN32THREAD
+{
+ HANDLE hThread;
+ DWORD thread_id;
+} WIN32THREAD;
+
+// Thread startup information for Win32
+typedef struct WIN32THREADSTARTUPINFO
+{
+ THREAD_PROC *thread_proc;
+ void *param;
+ THREAD *thread;
+} WIN32THREADSTARTUPINFO;
+
+// Function prototype for Win32
+DWORD CALLBACK Win32DefaultThreadProc(void *param);
+
+// Current process handle
+static HANDLE hCurrentProcessHandle = NULL;
+static CRITICAL_SECTION fasttick_lock;
+static UINT64 start_tick = 0;
+static bool use_heap_api = false;
+static bool win32_is_nt = false;
+
+// File I/O data for Win32
+typedef struct WIN32IO
+{
+ HANDLE hFile;
+ bool WriteMode;
+} WIN32IO;
+
+// Mutex data for Win32
+typedef struct WIN32MUTEX
+{
+ HANDLE hMutex;
+} WIN32MUTEX;
+
+// Set the Thread name
+#pragma pack(push,8)
+typedef struct tagTHREADNAME_INFO
+{
+ DWORD dwType; // Must be 0x1000.
+ LPCSTR szName; // Pointer to name (in user addr space).
+ DWORD dwThreadID; // Thread ID (-1=caller thread).
+ DWORD dwFlags; // Reserved for future use, must be zero.
+} THREADNAME_INFO;
+#pragma pack(pop)
+
+// Create a dispatch table
+OS_DISPATCH_TABLE *Win32GetDispatchTable()
+{
+ static OS_DISPATCH_TABLE t =
+ {
+ Win32Init,
+ Win32Free,
+ Win32MemoryAlloc,
+ Win32MemoryReAlloc,
+ Win32MemoryFree,
+ Win32GetTick,
+ Win32GetSystemTime,
+ Win32Inc32,
+ Win32Dec32,
+ Win32Sleep,
+ Win32NewLock,
+ Win32Lock,
+ Win32Unlock,
+ Win32DeleteLock,
+ Win32InitEvent,
+ Win32SetEvent,
+ Win32ResetEvent,
+ Win32WaitEvent,
+ Win32FreeEvent,
+ Win32WaitThread,
+ Win32FreeThread,
+ Win32InitThread,
+ Win32ThreadId,
+ Win32FileOpen,
+ Win32FileOpenW,
+ Win32FileCreate,
+ Win32FileCreateW,
+ Win32FileWrite,
+ Win32FileRead,
+ Win32FileClose,
+ Win32FileFlush,
+ Win32FileSize,
+ Win32FileSeek,
+ Win32FileDelete,
+ Win32FileDeleteW,
+ Win32MakeDir,
+ Win32MakeDirW,
+ Win32DeleteDir,
+ Win32DeleteDirW,
+ Win32GetCallStack,
+ Win32GetCallStackSymbolInfo,
+ Win32FileRename,
+ Win32FileRenameW,
+ Win32Run,
+ Win32RunW,
+ Win32IsSupportedOs,
+ Win32GetOsInfo,
+ Win32Alert,
+ Win32AlertW,
+ Win32GetProductId,
+ Win32SetHighPriority,
+ Win32RestorePriority,
+ Win32NewSingleInstance,
+ Win32FreeSingleInstance,
+ Win32GetMemInfo,
+ Win32Yield,
+ };
+
+ return &t;
+}
+
+// Set the thread name
+void Win32SetThreadName(UINT thread_id, char *name)
+{
+ DWORD ms_vc_exception = 0x406D1388;
+ THREADNAME_INFO t;
+ // Validate arguments
+ if (thread_id == 0 || name == NULL)
+ {
+ return;
+ }
+
+ Zero(&t, sizeof(t));
+ t.dwType = 0x1000;
+ t.szName = name;
+ t.dwThreadID = thread_id;
+ t.dwFlags = 0;
+
+ __try
+ {
+ RaiseException(ms_vc_exception, 0, sizeof(t) / sizeof(ULONG_PTR), (ULONG_PTR *)&t);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ }
+}
+
+// Initialization function of the new thread
+void Win32InitNewThread()
+{
+ static HINSTANCE hDll = NULL;
+ static bool (WINAPI *_SetThreadLocale)(LCID) = NULL;
+
+ if (hDll == NULL)
+ {
+ hDll = LoadLibrary("kernel32.dll");
+
+ _SetThreadLocale =
+ (bool (__stdcall *)(LCID))
+ GetProcAddress(hDll, "SetThreadLocale");
+ }
+
+ if (_SetThreadLocale != NULL)
+ {
+ _SetThreadLocale(LOCALE_USER_DEFAULT);
+ }
+}
+
+// Set the compression flag of the folder
+bool Win32SetFolderCompressW(wchar_t *path, bool compressed)
+{
+ HANDLE h;
+ UINT retsize = 0;
+ USHORT flag;
+ wchar_t tmp[MAX_PATH];
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char *path_a = CopyUniToStr(path);
+ bool ret = Win32SetFolderCompress(path_a, compressed);
+
+ Free(path_a);
+
+ return ret;
+ }
+
+ InnerFilePathW(tmp, sizeof(tmp), path);
+
+ // Open the folder
+ h = CreateFileW(tmp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return false;
+ }
+
+ flag = compressed ? COMPRESSION_FORMAT_DEFAULT : COMPRESSION_FORMAT_NONE;
+
+ if (DeviceIoControl(h, FSCTL_SET_COMPRESSION, &flag, sizeof(USHORT),
+ NULL, 0, &retsize, NULL) == false)
+ {
+ return false;
+ }
+
+ CloseHandle(h);
+
+ return true;
+}
+bool Win32SetFolderCompress(char *path, bool compressed)
+{
+ HANDLE h;
+ UINT retsize = 0;
+ USHORT flag;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ InnerFilePath(tmp, sizeof(tmp), path);
+
+ // Open the folder
+ h = CreateFile(tmp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return false;
+ }
+
+ flag = compressed ? COMPRESSION_FORMAT_DEFAULT : COMPRESSION_FORMAT_NONE;
+
+ if (DeviceIoControl(h, FSCTL_SET_COMPRESSION, &flag, sizeof(USHORT),
+ NULL, 0, &retsize, NULL) == false)
+ {
+ return false;
+ }
+
+ CloseHandle(h);
+
+ return true;
+}
+
+// Get the free space of the disk
+bool Win32GetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
+{
+ wchar_t tmp[MAX_SIZE];
+ UINT count = 0;
+ UINT i, n, len;
+ ULARGE_INTEGER v1, v2, v3;
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ bool ret;
+ char *path_a = CopyUniToStr(path);
+
+ ret = Win32GetDiskFree(path_a, free_size, used_size, total_size);
+
+ Free(path_a);
+
+ return ret;
+ }
+
+ Zero(&v1, sizeof(v1));
+ Zero(&v2, sizeof(v2));
+ Zero(&v3, sizeof(v3));
+
+ NormalizePathW(tmp, sizeof(tmp), path);
+
+ // Get the directory name
+ if (UniStartWith(path, L"\\\\"))
+ {
+ count = 4;
+ }
+ else
+ {
+ count = 1;
+ }
+
+ len = UniStrLen(tmp);
+ n = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (tmp[i] == L'\\')
+ {
+ n++;
+ if (n >= count)
+ {
+ tmp[i + 1] = 0;
+ break;
+ }
+ }
+ }
+
+ if (GetDiskFreeSpaceExW(tmp, &v1, &v2, &v3))
+ {
+ ret = true;
+ }
+
+ if (free_size != NULL)
+ {
+ *free_size = v1.QuadPart;
+ }
+
+ if (total_size != NULL)
+ {
+ *total_size = v2.QuadPart;
+ }
+
+ if (used_size != NULL)
+ {
+ *used_size = v2.QuadPart - v1.QuadPart;
+ }
+
+ return ret;
+}
+bool Win32GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
+{
+ char tmp[MAX_SIZE];
+ UINT count = 0;
+ UINT i, n, len;
+ ULARGE_INTEGER v1, v2, v3;
+ bool ret = false;
+ // Validate arguments
+ if (path == NULL)
+ {
+ return false;
+ }
+
+ Zero(&v1, sizeof(v1));
+ Zero(&v2, sizeof(v2));
+ Zero(&v3, sizeof(v3));
+
+ NormalizePath(tmp, sizeof(tmp), path);
+
+ // Get the directory name
+ if (StartWith(path, "\\\\"))
+ {
+ count = 4;
+ }
+ else
+ {
+ count = 1;
+ }
+
+ len = StrLen(tmp);
+ n = 0;
+ for (i = 0;i < len;i++)
+ {
+ if (tmp[i] == '\\')
+ {
+ n++;
+ if (n >= count)
+ {
+ tmp[i + 1] = 0;
+ break;
+ }
+ }
+ }
+
+ if (GetDiskFreeSpaceEx(tmp, &v1, &v2, &v3))
+ {
+ ret = true;
+ }
+
+ if (free_size != NULL)
+ {
+ *free_size = v1.QuadPart;
+ }
+
+ if (total_size != NULL)
+ {
+ *total_size = v2.QuadPart;
+ }
+
+ if (used_size != NULL)
+ {
+ *used_size = v2.QuadPart - v1.QuadPart;
+ }
+
+ return ret;
+}
+
+// Enumeration of directory
+DIRLIST *Win32EnumDirEx(char *dirname, COMPARE *compare)
+{
+ DIRLIST *ret;
+ wchar_t *dirname_w = CopyStrToUni(dirname);
+
+ ret = Win32EnumDirExW(dirname_w, compare);
+
+ Free(dirname_w);
+
+ return ret;
+}
+DIRLIST *Win32EnumDirExW(wchar_t *dirname, COMPARE *compare)
+{
+ WIN32_FIND_DATAA data_a;
+ WIN32_FIND_DATAW data_w;
+ HANDLE h;
+ wchar_t tmp[MAX_PATH];
+ wchar_t tmp2[MAX_PATH];
+ wchar_t dirname2[MAX_PATH];
+ LIST *o;
+ DIRLIST *d;
+
+ UniStrCpy(tmp2, sizeof(tmp2), dirname);
+
+ if (UniStrLen(tmp2) >= 1 && tmp[UniStrLen(tmp2) - 1] == L'\\')
+ {
+ tmp2[UniStrLen(tmp2) - 1] = 0;
+ }
+
+ UniFormat(tmp, sizeof(tmp), L"%s\\*.*", tmp2);
+ NormalizePathW(tmp, sizeof(tmp), tmp);
+ NormalizePathW(dirname2, sizeof(dirname2), tmp2);
+
+ o = NewListFast(compare);
+
+ Zero(&data_a, sizeof(data_a));
+ Zero(&data_w, sizeof(data_w));
+
+ if (IsNt())
+ {
+ h = FindFirstFileW(tmp, &data_w);
+ }
+ else
+ {
+ char *tmp_a = CopyUniToStr(tmp);
+
+ h = FindFirstFileA(tmp_a, &data_a);
+
+ Free(tmp_a);
+ }
+
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ bool b = true;
+
+ do
+ {
+ if (IsNt() == false)
+ {
+ Zero(&data_w, sizeof(data_w));
+ StrToUni(data_w.cFileName, sizeof(data_w.cFileName), data_a.cFileName);
+ data_w.dwFileAttributes = data_a.dwFileAttributes;
+ data_w.ftCreationTime = data_a.ftCreationTime;
+ data_w.ftLastWriteTime = data_a.ftLastWriteTime;
+ data_w.nFileSizeHigh = data_a.nFileSizeHigh;
+ data_w.nFileSizeLow = data_a.nFileSizeLow;
+ }
+
+ if (UniStrCmpi(data_w.cFileName, L"..") != 0 &&
+ UniStrCmpi(data_w.cFileName, L".") != 0)
+ {
+ DIRENT *f = ZeroMalloc(sizeof(DIRENT));
+ SYSTEMTIME t1, t2;
+ wchar_t fullpath[MAX_SIZE];
+ bool ok = false;
+
+ f->FileNameW = UniCopyStr(data_w.cFileName);
+ f->FileName = CopyUniToStr(f->FileNameW);
+ f->Folder = (data_w.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false;
+
+ CombinePathW(fullpath, sizeof(fullpath), dirname2, f->FileNameW);
+
+ // Attempt to get the file information
+ if (MsIsNt())
+ {
+ HANDLE h = CreateFileW(fullpath, 0,
+ FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, 0, NULL);
+
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ BY_HANDLE_FILE_INFORMATION info;
+
+ Zero(&info, sizeof(info));
+
+ if (MsGetFileInformation(h, &info))
+ {
+ Zero(&t1, sizeof(t1));
+ Zero(&t2, sizeof(t2));
+ FileTimeToSystemTime(&info.ftCreationTime, &t1);
+ FileTimeToSystemTime(&info.ftLastWriteTime, &t2);
+ f->CreateDate = SystemToUINT64(&t1);
+ f->UpdateDate = SystemToUINT64(&t2);
+
+ if (f->Folder == false)
+ {
+ f->FileSize = ((UINT64)info.nFileSizeHigh * (UINT64)((UINT64)MAXDWORD + (UINT64)1)) + (UINT64)info.nFileSizeLow;
+ }
+
+ ok = true;
+ }
+
+ CloseHandle(h);
+ }
+ }
+
+ if (ok == false)
+ {
+ Zero(&t1, sizeof(t1));
+ Zero(&t2, sizeof(t2));
+ FileTimeToSystemTime(&data_w.ftCreationTime, &t1);
+ FileTimeToSystemTime(&data_w.ftLastWriteTime, &t2);
+ f->CreateDate = SystemToUINT64(&t1);
+ f->UpdateDate = SystemToUINT64(&t2);
+
+ if (f->Folder == false)
+ {
+ f->FileSize = ((UINT64)data_w.nFileSizeHigh * (UINT64)((UINT64)MAXDWORD + (UINT64)1)) + (UINT64)data_w.nFileSizeLow;
+ }
+ }
+
+ Add(o, f);
+ }
+
+ Zero(&data_w, sizeof(data_w));
+ Zero(&data_a, sizeof(data_a));
+
+ if (IsNt())
+ {
+ b = FindNextFileW(h, &data_w);
+ }
+ else
+ {
+ b = FindNextFileA(h, &data_a);
+ }
+ }
+ while (b);
+
+ FindClose(h);
+ }
+
+ Sort(o);
+
+ d = ZeroMalloc(sizeof(DIRLIST));
+ d->NumFiles = LIST_NUM(o);
+ d->File = ToArray(o);
+
+ ReleaseList(o);
+
+ return d;
+}
+
+// Get the EXE file name
+void Win32GetExeNameW(wchar_t *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ if (IsNt() == false)
+ {
+ char name_a[MAX_PATH];
+
+ Win32GetExeName(name_a, sizeof(name_a));
+
+ StrToUni(name, size, name_a);
+
+ return;
+ }
+
+ UniStrCpy(name, size, L"");
+
+ GetModuleFileNameW(NULL, name, size);
+}
+void Win32GetExeName(char *name, UINT size)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ StrCpy(name, size, "");
+
+ GetModuleFileName(NULL, name, size);
+}
+
+// Get the current directory
+void Win32GetCurrentDirW(wchar_t *dir, UINT size)
+{
+ // Validate arguments
+ if (dir == NULL)
+ {
+ return;
+ }
+
+ if (IsNt() == false)
+ {
+ char dir_a[MAX_PATH];
+
+ Win32GetCurrentDir(dir_a, sizeof(dir_a));
+
+ StrToUni(dir, size, dir_a);
+
+ return;
+ }
+
+ GetCurrentDirectoryW(size, dir);
+}
+void Win32GetCurrentDir(char *dir, UINT size)
+{
+ // Validate arguments
+ if (dir == NULL)
+ {
+ return;
+ }
+
+ GetCurrentDirectory(size, dir);
+}
+
+// Yield
+void Win32Yield()
+{
+ Sleep(0);
+}
+
+// Get the memory information
+void Win32GetMemInfo(MEMINFO *info)
+{
+ static HINSTANCE hDll = NULL;
+ static bool (WINAPI *_GlobalMemoryStatusEx)(LPMEMORYSTATUSEX) = NULL;
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ Zero(info, sizeof(MEMINFO));
+
+ if (hDll == NULL)
+ {
+ hDll = LoadLibrary("kernel32.dll");
+ }
+ if (hDll != NULL)
+ {
+ if (_GlobalMemoryStatusEx == NULL)
+ {
+ _GlobalMemoryStatusEx =
+ (bool (__stdcall *)(LPMEMORYSTATUSEX))GetProcAddress(hDll, "GlobalMemoryStatusEx");
+ }
+ }
+
+
+ if (_GlobalMemoryStatusEx == NULL)
+ {
+ // Old API
+ MEMORYSTATUS st;
+ Zero(&st, sizeof(st));
+ st.dwLength = sizeof(st);
+
+ GlobalMemoryStatus(&st);
+
+ // Amount of the logical memory
+ info->TotalMemory = (UINT64)st.dwTotalPageFile;
+ info->FreeMemory = (UINT64)st.dwAvailPageFile;
+ info->UsedMemory = info->TotalMemory - info->FreeMemory;
+
+ // Amount of the physical memory
+ info->TotalPhys = (UINT64)st.dwTotalPhys;
+ info->FreePhys = (UINT64)st.dwAvailPhys;
+ info->UsedPhys = info->TotalPhys - info->FreePhys;
+ }
+ else
+ {
+ // New API
+ MEMORYSTATUSEX st;
+ Zero(&st, sizeof(st));
+ st.dwLength = sizeof(st);
+
+ _GlobalMemoryStatusEx(&st);
+
+ // Amount of the logical memory
+ info->TotalMemory = st.ullTotalPageFile;
+ info->FreeMemory = st.ullAvailPageFile;
+ info->UsedMemory = info->TotalMemory - info->FreeMemory;
+
+ // Amount of the physical memory
+ info->TotalPhys = st.ullTotalPhys;
+ info->FreePhys = st.ullAvailPhys;
+ info->UsedPhys = info->TotalPhys - info->FreePhys;
+ }
+}
+
+// Creating a single instance
+void *Win32NewSingleInstance(char *instance_name)
+{
+ WIN32MUTEX *ret;
+ char tmp[MAX_SIZE];
+ HANDLE hMutex;
+ // Validate arguments
+ if (instance_name == NULL)
+ {
+ char exe_path[MAX_PATH];
+ GetModuleFileName(NULL, exe_path, sizeof(exe_path));
+ HashInstanceName(tmp, sizeof(tmp), exe_path);
+ instance_name = tmp;
+ }
+
+ hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, instance_name);
+ if (hMutex != NULL)
+ {
+ CloseHandle(hMutex);
+ return NULL;
+ }
+
+ hMutex = CreateMutex(NULL, FALSE, instance_name);
+ if (hMutex == NULL)
+ {
+ CloseHandle(hMutex);
+ return NULL;
+ }
+
+ ret = Win32MemoryAlloc(sizeof(WIN32MUTEX));
+ ret->hMutex = hMutex;
+
+ return (void *)ret;
+}
+
+// Release the single instance
+void Win32FreeSingleInstance(void *data)
+{
+ WIN32MUTEX *m;
+ // Validate arguments
+ if (data == NULL)
+ {
+ return;
+ }
+
+ m = (WIN32MUTEX *)data;
+ ReleaseMutex(m->hMutex);
+ CloseHandle(m->hMutex);
+
+ Win32MemoryFree(m);
+}
+
+// Raise the priority
+void Win32SetHighPriority()
+{
+ SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
+}
+
+// Restore the priority
+void Win32RestorePriority()
+{
+ SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
+}
+
+// Get the node information
+char* Win32GetProductId()
+{
+ char *product_id;
+
+ return CopyStr("--");
+
+ // Product ID
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductId");
+ if (product_id == NULL)
+ {
+ product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductId");
+ }
+
+ return product_id;
+}
+
+// Acquisition whether the OS is currently supported
+bool Win32IsSupportedOs()
+{
+ if (Win32GetOsType() == 0)
+ {
+ Win32Alert(
+ CEDAR_PRODUCT_STR " VPN doesn't support this Windows Operating System.\n"
+ CEDAR_PRODUCT_STR " VPN requires " SUPPORTED_WINDOWS_LIST ".\n\n"
+ "Please contact your system administrator.", NULL);
+ return false;
+ }
+
+ return true;
+}
+
+// Show an alert
+void Win32AlertW(wchar_t *msg, wchar_t *caption)
+{
+ char *s;
+ // Validate arguments
+ if (msg == NULL)
+ {
+ msg = L"Alert";
+ }
+ if (caption == NULL)
+ {
+ caption = CEDAR_PRODUCT_STR_W L" VPN Kernel";
+ }
+
+ s = GetCommandLineStr();
+
+ if (SearchStr(s, "win9x_uninstall", 0) == INFINITE && SearchStr(s, "win9x_install", 0) == INFINITE)
+ {
+ // Hide during the uninstallation in Win9x service mode
+ MessageBoxW(NULL, msg, caption, MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION);
+ }
+
+ Free(s);
+}
+void Win32Alert(char *msg, char *caption)
+{
+ char *s;
+ // Validate arguments
+ if (msg == NULL)
+ {
+ msg = "Alert";
+ }
+ if (caption == NULL)
+ {
+ caption = CEDAR_PRODUCT_STR " VPN Kernel";
+ }
+
+ s = GetCommandLineStr();
+
+ if (SearchStr(s, "win9x_uninstall", 0) == INFINITE && SearchStr(s, "win9x_install", 0) == INFINITE)
+ {
+ // Hide during the uninstallation in Win9x service mode
+ MessageBox(NULL, msg, caption, MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION);
+ }
+
+ Free(s);
+}
+void Win32DebugAlert(char *msg)
+{
+ // Validate arguments
+ if (msg == NULL)
+ {
+ msg = "Alert";
+ }
+
+ MessageBox(NULL, msg, "Debug", MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION);
+}
+
+// Get the OS information
+void Win32GetOsInfo(OS_INFO *info)
+{
+ UINT type = Win32GetOsType();
+ OSVERSIONINFOEX os;
+ char tmp[MAX_SIZE];
+ // Validate arguments
+ if (info == NULL)
+ {
+ return;
+ }
+
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+ Win32GetVersionExInternal((LPOSVERSIONINFOA)&os);
+
+ info->OsType = Win32GetOsType();
+ info->OsServicePack = os.wServicePackMajor;
+ if (OS_IS_WINDOWS_NT(info->OsType))
+ {
+ char *s;
+ char *keyname = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
+ info->OsSystemName = CopyStr("Windows NT");
+ Format(tmp, sizeof(tmp), "Build %u", os.dwBuildNumber);
+ if (s = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "CurrentType"))
+ {
+ char str[MAX_SIZE];
+ Format(str, sizeof(str), ", %s", s);
+ StrCat(tmp, sizeof(tmp), str);
+ Free(s);
+ }
+ if (os.wServicePackMajor != 0)
+ {
+ char str[MAX_SIZE];
+ Format(str, sizeof(str), ", Service Pack %u", os.wServicePackMajor);
+ StrCat(tmp, sizeof(tmp), str);
+ }
+ if (s = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "BuildLab"))
+ {
+ char str[MAX_SIZE];
+ Format(str, sizeof(str), " (%s)", s);
+ StrCat(tmp, sizeof(tmp), str);
+ Free(s);
+ }
+ info->OsVersion = CopyStr(tmp);
+ info->KernelName = CopyStr("NTOS Kernel");
+ Format(tmp, sizeof(tmp), "Build %u", os.dwBuildNumber);
+ if (s = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "CurrentType"))
+ {
+ char str[MAX_SIZE];
+ Format(str, sizeof(str), " %s", s);
+ StrCat(tmp, sizeof(tmp), str);
+ Free(s);
+ }
+ info->KernelVersion = CopyStr(tmp);
+ }
+ else
+ {
+ OSVERSIONINFO os;
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+ GetVersionEx(&os);
+ Format(tmp, sizeof(tmp), "Build %u %s", LOWORD(os.dwBuildNumber), os.szCSDVersion);
+ Trim(tmp);
+ info->OsVersion = CopyStr(tmp);
+ info->OsSystemName = CopyStr("Windows");
+ info->KernelName = CopyStr("Windows 9x Kernel");
+ info->KernelVersion = CopyStr(tmp);
+ }
+
+ info->OsProductName = CopyStr(OsTypeToStr(info->OsType));
+ info->OsVendorName = CopyStr("Microsoft Corporation");
+}
+
+// GetVersionEx API (Ignore the tricky features that have been added to the Windows 8.2 or later)
+bool Win32GetVersionExInternal(void *info)
+{
+ OSVERSIONINFOA os;
+ // Validate arguments
+ if (info == NULL)
+ {
+ return false;
+ }
+
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+
+ if (GetVersionExA(&os))
+ {
+ if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ if ((os.dwMajorVersion == 6 && os.dwMinorVersion >= 2) ||
+ (os.dwMajorVersion == 7))
+ {
+ // Windows 8 later
+ return Win32GetVersionExInternalForWindows81orLater(info);
+ }
+ }
+ }
+
+ return GetVersionExA(info);
+}
+
+// GetVersionEx for Windows 8.1 and later
+bool Win32GetVersionExInternalForWindows81orLater(void *info)
+{
+ OSVERSIONINFOEXA *ex = (OSVERSIONINFOEXA *)info;
+ char *str;
+ // Validate arguments
+ if (info == NULL)
+ {
+ return false;
+ }
+
+ if (ex->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXA) &&
+ ex->dwOSVersionInfoSize != sizeof(OSVERSIONINFOA))
+ {
+ return GetVersionExA(info);
+ }
+
+ if (GetVersionExA(info) == false)
+ {
+ return false;
+ }
+
+ str = MsRegReadStrEx2(REG_LOCAL_MACHINE,
+ "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
+ "CurrentVersion",
+ false, true);
+
+ if (IsEmptyStr(str) == false)
+ {
+ // Is the version string formed as x.y?
+ TOKEN_LIST *t = ParseToken(str, ".");
+
+ if (t != NULL && t->NumTokens == 2)
+ {
+ UINT major = ToInt(t->Token[0]);
+ UINT minor = ToInt(t->Token[1]);
+
+ if (major >= 6)
+ {
+ // Version number acquisition success
+ ex->dwMajorVersion = major;
+ ex->dwMinorVersion = minor;
+ }
+ }
+
+ FreeToken(t);
+ }
+
+ Free(str);
+
+ return true;
+}
+
+// Acquisition whether it's a Windows NT
+bool Win32IsNt()
+{
+ OSVERSIONINFO os;
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+
+ if (GetVersionEx(&os) == FALSE)
+ {
+ // Failure?
+ return false;
+ }
+
+ if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ // NT
+ return true;
+ }
+
+ // 9x
+ return false;
+}
+
+// Get the OS type
+UINT Win32GetOsType()
+{
+ OSVERSIONINFO os;
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+
+ if (Win32GetVersionExInternal(&os) == FALSE)
+ {
+ // Failure?
+ return 0;
+ }
+
+ if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
+ {
+ // Windows 9x system
+ if (os.dwMajorVersion == 4)
+ {
+ if (os.dwMinorVersion == 0)
+ {
+ return OSTYPE_WINDOWS_95;
+ }
+ else if (os.dwMinorVersion == 10)
+ {
+ return OSTYPE_WINDOWS_98;
+ }
+ else if (os.dwMinorVersion == 90)
+ {
+ return OSTYPE_WINDOWS_ME;
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_UNKNOWN;
+ }
+ }
+ else if (os.dwMajorVersion >= 5)
+ {
+ return OSTYPE_WINDOWS_UNKNOWN;
+ }
+ }
+ else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ UINT sp = Win32GetSpVer(os.szCSDVersion);
+ if (os.dwMajorVersion == 4)
+ {
+ if (sp < 6)
+ {
+ // SP6 or earlier
+ return 0;
+ }
+ }
+ if (os.dwMajorVersion < 4)
+ {
+ // NT 3.51 or earlier
+ return 0;
+ }
+ else
+ {
+ OSVERSIONINFOEX os;
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+ Win32GetVersionExInternal((LPOSVERSIONINFOA)&os);
+
+ if (os.dwMajorVersion == 4)
+ {
+ // Windows NT 4.0
+ if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER)
+ {
+ if ((os.wSuiteMask & VER_SUITE_TERMINAL) || (os.wSuiteMask & VER_SUITE_SINGLEUSERTS))
+ {
+ return OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER;
+ }
+ if (os.wSuiteMask & VER_SUITE_ENTERPRISE)
+ {
+ return OSTYPE_WINDOWS_NT_4_SERVER_ENTERPRISE;
+ }
+ if (os.wSuiteMask & VER_SUITE_BACKOFFICE)
+ {
+ return OSTYPE_WINDOWS_NT_4_BACKOFFICE;
+ }
+ if ((os.wSuiteMask & VER_SUITE_SMALLBUSINESS) || (os.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED))
+ {
+ return OSTYPE_WINDOWS_NT_4_SMS;
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_NT_4_SERVER;
+ }
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_NT_4_WORKSTATION;
+ }
+ }
+ else if (os.dwMajorVersion == 5)
+ {
+ // Windows 2000, XP, Server 2003
+ if (os.dwMinorVersion == 0)
+ {
+ // Windows 2000
+ if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER)
+ {
+ // Server
+ if (os.wSuiteMask & VER_SUITE_DATACENTER)
+ {
+ return OSTYPE_WINDOWS_2000_DATACENTER_SERVER;
+ }
+ else if ((os.wSuiteMask & VER_SUITE_SMALLBUSINESS) || (os.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED))
+ {
+ return OSTYPE_WINDOWS_2000_SBS;
+ }
+ else if (os.wSuiteMask & VER_SUITE_BACKOFFICE)
+ {
+ return OSTYPE_WINDOWS_2000_BACKOFFICE;
+ }
+ else if (os.wSuiteMask & VER_SUITE_ENTERPRISE)
+ {
+ return OSTYPE_WINDOWS_2000_ADVANCED_SERVER;
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_2000_SERVER;
+ }
+ }
+ else
+ {
+ // Client
+ return OSTYPE_WINDOWS_2000_PROFESSIONAL;
+ }
+ }
+ else if (os.dwMinorVersion == 1)
+ {
+ // Windows XP
+ if (os.wSuiteMask & VER_SUITE_PERSONAL)
+ {
+ return OSTYPE_WINDOWS_XP_HOME;
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_XP_PROFESSIONAL;
+ }
+ }
+ else if (os.dwMinorVersion == 2)
+ {
+ // Windows Server 2003
+ if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER)
+ {
+ // Server
+ if (os.wSuiteMask & VER_SUITE_DATACENTER)
+ {
+ return OSTYPE_WINDOWS_2003_DATACENTER;
+ }
+ else if ((os.wSuiteMask & VER_SUITE_SMALLBUSINESS) || (os.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED))
+ {
+ return OSTYPE_WINDOWS_2003_SBS;
+ }
+ else if (os.wSuiteMask & VER_SUITE_BACKOFFICE)
+ {
+ return OSTYPE_WINDOWS_2003_BACKOFFICE;
+ }
+ else if (os.wSuiteMask & VER_SUITE_ENTERPRISE)
+ {
+ return OSTYPE_WINDOWS_2003_ENTERPRISE;
+ }
+ else if (os.wSuiteMask & VER_SUITE_BLADE)
+ {
+ return OSTYPE_WINDOWS_2003_WEB;
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_2003_STANDARD;
+ }
+ }
+ else
+ {
+ // Client (Unknown XP?)
+ return OSTYPE_WINDOWS_XP_PROFESSIONAL;
+ }
+ }
+ else
+ {
+ // Windows Longhorn
+ if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER)
+ {
+ return OSTYPE_WINDOWS_LONGHORN_SERVER;
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_LONGHORN_PROFESSIONAL;
+ }
+ }
+ }
+ else
+ {
+ if (os.dwMajorVersion == 6 && os.dwMinorVersion == 0)
+ {
+ // Windows Vista, Server 2008
+ if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER)
+ {
+ return OSTYPE_WINDOWS_LONGHORN_SERVER;
+ }
+ else
+ {
+ return OSTYPE_WINDOWS_LONGHORN_PROFESSIONAL;
+ }
+ }
+ else if (os.dwMajorVersion == 6 && os.dwMinorVersion == 1)
+ {
+ if (os.wProductType == VER_NT_WORKSTATION)
+ {
+ // Windows 7
+ return OSTYPE_WINDOWS_7;
+ }
+ else
+ {
+ // Windows Server 2008 R2
+ return OSTYPE_WINDOWS_SERVER_2008_R2;
+ }
+ }
+ else if (os.dwMajorVersion == 6 && os.dwMinorVersion == 2)
+ {
+ if (os.wProductType == VER_NT_WORKSTATION)
+ {
+ // Windows 8
+ return OSTYPE_WINDOWS_8;
+ }
+ else
+ {
+ // Windows Server 2012
+ return OSTYPE_WINDOWS_SERVER_8;
+ }
+ }
+ else if (os.dwMajorVersion == 6 && os.dwMinorVersion == 3)
+ {
+ if (os.wProductType == VER_NT_WORKSTATION)
+ {
+ // Windows 8.1
+ return OSTYPE_WINDOWS_81;
+ }
+ else
+ {
+ // Windows Server 2012 R2
+ return OSTYPE_WINDOWS_SERVER_81;
+ }
+ }
+ else
+ {
+ if (os.wProductType == VER_NT_WORKSTATION)
+ {
+ // Windows 9?
+ return OSTYPE_WINDOWS_9;
+ }
+ else
+ {
+ // Windows Server 9?
+ return OSTYPE_WINDOWS_SERVER_9;
+ }
+ }
+ }
+ }
+ }
+
+ // Can not be determined
+ return 0;
+}
+
+// Get the SP version from the string
+UINT Win32GetSpVer(char *str)
+{
+ UINT ret, i;
+ TOKEN_LIST *t;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return 0;
+ }
+
+ t = ParseToken(str, NULL);
+ if (t == NULL)
+ {
+ return 0;
+ }
+
+ ret = 0;
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ ret = ToInt(t->Token[i]);
+ if (ret != 0)
+ {
+ break;
+ }
+ }
+
+ FreeToken(t);
+
+ return ret;
+}
+
+// Kill the process
+bool Win32TerminateProcess(void *handle)
+{
+ HANDLE h;
+ // Validate arguments
+ if (handle == NULL)
+ {
+ return false;
+ }
+
+ h = (HANDLE)handle;
+
+ TerminateProcess(h, 0);
+
+ return true;
+}
+
+// Close the process
+void Win32CloseProcess(void *handle)
+{
+ // Validate arguments
+ if (handle == NULL)
+ {
+ return;
+ }
+
+ CloseHandle((HANDLE)handle);
+}
+
+// Check whether the specified process is alive
+bool Win32IsProcessAlive(void *handle)
+{
+ HANDLE h;
+ // Validate arguments
+ if (handle == NULL)
+ {
+ return false;
+ }
+
+ h = (HANDLE)handle;
+
+ if (WaitForSingleObject(h, 0) == WAIT_OBJECT_0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Wait for the process termination
+bool Win32WaitProcess(void *h, UINT timeout)
+{
+ // Validate arguments
+ if (h == NULL)
+ {
+ return false;
+ }
+ if (timeout == 0)
+ {
+ timeout = INFINITE;
+ }
+
+ if (WaitForSingleObject((HANDLE)h, timeout) == WAIT_TIMEOUT)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Run the process and wait for terminate it
+bool Win32RunAndWaitProcess(wchar_t *filename, wchar_t *arg, bool hide, bool disableWow, UINT timeout)
+{
+ UINT process_id = 0;
+ void *p = Win32RunEx3W(filename, arg, hide, &process_id, disableWow);
+
+ if (p == NULL)
+ {
+ return false;
+ }
+
+ return Win32WaitProcess(p, timeout);
+}
+
+// Run the process (return the handle)
+void *Win32RunExW(wchar_t *filename, wchar_t *arg, bool hide)
+{
+ return Win32RunEx2W(filename, arg, hide, NULL);
+}
+void *Win32RunEx2W(wchar_t *filename, wchar_t *arg, bool hide, UINT *process_id)
+{
+ return Win32RunEx3W(filename, arg, hide, process_id, false);
+}
+void *Win32RunEx3W(wchar_t *filename, wchar_t *arg, bool hide, UINT *process_id, bool disableWow)
+{
+ STARTUPINFOW info;
+ PROCESS_INFORMATION ret;
+ wchar_t cmdline[MAX_SIZE];
+ wchar_t name[MAX_PATH];
+ void *p;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsNt() == false)
+ {
+ char *filename_a = CopyUniToStr(filename);
+ char *arg_a = CopyUniToStr(arg);
+ void *ret = Win32RunEx3(filename_a, arg_a, hide, process_id, disableWow);
+
+ Free(filename_a);
+ Free(arg_a);
+
+ return ret;
+ }
+
+ UniStrCpy(name, sizeof(name), filename);
+ UniTrim(name);
+
+ if (UniSearchStr(name, L"\"", 0) == INFINITE)
+ {
+ if (arg == NULL)
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"%s", name);
+ }
+ else
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"%s %s", name, arg);
+ }
+ }
+ else
+ {
+ if (arg == NULL)
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"\"%s\"", name);
+ }
+ else
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"\"%s\" %s", name, arg);
+ }
+ }
+
+ Zero(&info, sizeof(info));
+ Zero(&ret, sizeof(ret));
+ info.cb = sizeof(info);
+ info.dwFlags = STARTF_USESHOWWINDOW;
+ info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE);
+
+ UniTrim(cmdline);
+
+ if (disableWow)
+ {
+ p = MsDisableWow64FileSystemRedirection();
+ }
+
+ if (CreateProcessW(NULL, cmdline, NULL, NULL, FALSE,
+ (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS,
+ NULL, NULL, &info, &ret) == FALSE)
+ {
+ if (disableWow)
+ {
+ MsRestoreWow64FileSystemRedirection(p);
+ }
+ return NULL;
+ }
+
+ if (disableWow)
+ {
+ MsRestoreWow64FileSystemRedirection(p);
+ }
+
+ if (process_id != NULL)
+ {
+ *process_id = ret.dwProcessId;
+ }
+
+ CloseHandle(ret.hThread);
+ return ret.hProcess;
+}
+void *Win32RunEx(char *filename, char *arg, bool hide)
+{
+ return Win32RunEx2(filename, arg, hide, NULL);
+}
+void *Win32RunEx2(char *filename, char *arg, bool hide, UINT *process_id)
+{
+ return Win32RunEx3(filename, arg, hide, process_id, false);
+}
+void *Win32RunEx3(char *filename, char *arg, bool hide, UINT *process_id, bool disableWow)
+{
+ STARTUPINFO info;
+ PROCESS_INFORMATION ret;
+ char cmdline[MAX_SIZE];
+ char name[MAX_PATH];
+ void *p = NULL;
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ StrCpy(name, sizeof(name), filename);
+ Trim(name);
+
+ if (SearchStr(name, "\"", 0) == INFINITE)
+ {
+ if (arg == NULL)
+ {
+ Format(cmdline, sizeof(cmdline), "%s", name);
+ }
+ else
+ {
+ Format(cmdline, sizeof(cmdline), "%s %s", name, arg);
+ }
+ }
+ else
+ {
+ if (arg == NULL)
+ {
+ Format(cmdline, sizeof(cmdline), "\"%s\"", name);
+ }
+ else
+ {
+ Format(cmdline, sizeof(cmdline), "\"%s\" %s", name, arg);
+ }
+ }
+
+ Zero(&info, sizeof(info));
+ Zero(&ret, sizeof(ret));
+ info.cb = sizeof(info);
+ info.dwFlags = STARTF_USESHOWWINDOW;
+ info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE);
+
+ Trim(cmdline);
+
+ if (disableWow)
+ {
+ p = MsDisableWow64FileSystemRedirection();
+ }
+
+ if (CreateProcess(NULL, cmdline, NULL, NULL, FALSE,
+ (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS,
+ NULL, NULL, &info, &ret) == FALSE)
+ {
+ if (disableWow)
+ {
+ MsRestoreWow64FileSystemRedirection(p);
+ }
+ return NULL;
+ }
+ if (disableWow)
+ {
+ MsRestoreWow64FileSystemRedirection(p);
+ }
+
+ if (process_id != NULL)
+ {
+ *process_id = ret.dwProcessId;
+ }
+
+ CloseHandle(ret.hThread);
+ return ret.hProcess;
+}
+
+// Start the process
+bool Win32RunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
+{
+ STARTUPINFOW info;
+ PROCESS_INFORMATION ret;
+ wchar_t cmdline[MAX_SIZE];
+ wchar_t name[MAX_PATH];
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char *filename_a = CopyUniToStr(filename);
+ char *arg_a = CopyUniToStr(arg);
+ bool ret;
+
+ ret = Win32Run(filename_a, arg_a, hide, wait);
+
+ Free(filename_a);
+ Free(arg_a);
+
+ return ret;
+ }
+
+ UniStrCpy(name, sizeof(name), filename);
+ UniTrim(name);
+
+ if (UniSearchStr(name, L"\"", 0) == INFINITE)
+ {
+ if (arg == NULL)
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"%s", name);
+ }
+ else
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"%s %s", name, arg);
+ }
+ }
+ else
+ {
+ if (arg == NULL)
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"\"%s\"", name);
+ }
+ else
+ {
+ UniFormat(cmdline, sizeof(cmdline), L"\"%s\" %s", name, arg);
+ }
+ }
+
+ Zero(&info, sizeof(info));
+ Zero(&ret, sizeof(ret));
+ info.cb = sizeof(info);
+ info.dwFlags = STARTF_USESHOWWINDOW;
+ info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE);
+
+ UniTrim(cmdline);
+
+ if (CreateProcessW(NULL, cmdline, NULL, NULL, FALSE,
+ (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS,
+ NULL, NULL, &info, &ret) == FALSE)
+ {
+ return false;
+ }
+
+ if (wait)
+ {
+ WaitForSingleObject(ret.hProcess, INFINITE);
+ }
+
+ CloseHandle(ret.hThread);
+ CloseHandle(ret.hProcess);
+
+ return true;
+}
+bool Win32Run(char *filename, char *arg, bool hide, bool wait)
+{
+ STARTUPINFO info;
+ PROCESS_INFORMATION ret;
+ char cmdline[MAX_SIZE];
+ char name[MAX_PATH];
+ // Validate arguments
+ if (filename == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(name, sizeof(name), filename);
+ Trim(name);
+
+ if (SearchStr(name, "\"", 0) == INFINITE)
+ {
+ if (arg == NULL)
+ {
+ Format(cmdline, sizeof(cmdline), "%s", name);
+ }
+ else
+ {
+ Format(cmdline, sizeof(cmdline), "%s %s", name, arg);
+ }
+ }
+ else
+ {
+ if (arg == NULL)
+ {
+ Format(cmdline, sizeof(cmdline), "\"%s\"", name);
+ }
+ else
+ {
+ Format(cmdline, sizeof(cmdline), "\"%s\" %s", name, arg);
+ }
+ }
+
+ Zero(&info, sizeof(info));
+ Zero(&ret, sizeof(ret));
+ info.cb = sizeof(info);
+ info.dwFlags = STARTF_USESHOWWINDOW;
+ info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE);
+
+ Trim(cmdline);
+
+ if (CreateProcess(NULL, cmdline, NULL, NULL, FALSE,
+ (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS,
+ NULL, NULL, &info, &ret) == FALSE)
+ {
+ return false;
+ }
+
+ if (wait)
+ {
+ WaitForSingleObject(ret.hProcess, INFINITE);
+ }
+
+ CloseHandle(ret.hThread);
+ CloseHandle(ret.hProcess);
+
+ return true;
+}
+
+// Get the Thread ID
+UINT Win32ThreadId()
+{
+ return GetCurrentThreadId();
+}
+
+// Rename the file
+bool Win32FileRenameW(wchar_t *old_name, wchar_t *new_name)
+{
+ // Validate arguments
+ if (old_name == NULL || new_name == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char *old_name_a = CopyUniToStr(old_name);
+ char *new_name_a = CopyUniToStr(new_name);
+ bool ret = Win32FileRename(old_name_a, new_name_a);
+
+ Free(old_name_a);
+ Free(new_name_a);
+
+ return ret;
+ }
+
+ // Rename
+ if (MoveFileW(old_name, new_name) == FALSE)
+ {
+ return false;
+ }
+
+ return true;
+}
+bool Win32FileRename(char *old_name, char *new_name)
+{
+ // Validate arguments
+ if (old_name == NULL || new_name == NULL)
+ {
+ return false;
+ }
+
+ // Rename
+ if (MoveFile(old_name, new_name) == FALSE)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Getting the name of the directory where the EXE file is in
+void Win32GetExeDirW(wchar_t *name, UINT size)
+{
+ wchar_t exe_path[MAX_SIZE];
+ wchar_t exe_dir[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ if (IsNt() == false)
+ {
+ char name_a[MAX_PATH];
+
+ Win32GetExeDir(name_a, sizeof(name_a));
+
+ StrToUni(name, size, name_a);
+
+ return;
+ }
+
+ // Get the EXE file name
+ GetModuleFileNameW(NULL, exe_path, sizeof(exe_path));
+
+ // Get the directory name
+ Win32GetDirFromPathW(exe_dir, sizeof(exe_dir), exe_path);
+
+ UniStrCpy(name, size, exe_dir);
+}
+void Win32GetExeDir(char *name, UINT size)
+{
+ char exe_path[MAX_SIZE];
+ char exe_dir[MAX_SIZE];
+ // Validate arguments
+ if (name == NULL)
+ {
+ return;
+ }
+
+ // Get the EXE file name
+ GetModuleFileName(NULL, exe_path, sizeof(exe_path));
+
+ // Get the directory name
+ Win32GetDirFromPath(exe_dir, sizeof(exe_dir), exe_path);
+
+ StrCpy(name, size, exe_dir);
+}
+
+// Remove the '\' at the end
+void Win32NukuEnW(wchar_t *dst, UINT size, wchar_t *src)
+{
+ wchar_t str[MAX_SIZE];
+ int i;
+ if (src)
+ {
+ UniStrCpy(str, sizeof(str), src);
+ }
+ else
+ {
+ UniStrCpy(str, sizeof(str), dst);
+ }
+ i = UniStrLen(str);
+ if (str[i - 1] == L'\\')
+ {
+ str[i - 1] = 0;
+ }
+ UniStrCpy(dst, size, str);
+}
+void Win32NukuEn(char *dst, UINT size, char *src)
+{
+ char str[MAX_SIZE];
+ int i;
+ if (src)
+ {
+ StrCpy(str, sizeof(str), src);
+ }
+ else
+ {
+ StrCpy(str, sizeof(str), dst);
+ }
+ i = StrLen(str);
+ if (str[i - 1] == '\\')
+ {
+ str[i - 1] = 0;
+ }
+ StrCpy(dst, size, str);
+}
+
+// Get the directory name from path
+void Win32GetDirFromPathW(wchar_t *dst, UINT size, wchar_t *src)
+{
+ wchar_t str[MAX_SIZE];
+ int i,len;
+ wchar_t c;
+ wchar_t tmp[MAX_SIZE];
+ int wp;
+ if (src)
+ {
+ UniStrCpy(str, sizeof(str), src);
+ }
+ else
+ {
+ UniStrCpy(str, sizeof(str), dst);
+ }
+ Win32NukuEnW(str, sizeof(str), NULL);
+ wp = 0;
+ len = UniStrLen(str);
+ dst[0] = 0;
+ for (i = 0;i < len;i++)
+ {
+ c = str[i];
+ switch (c)
+ {
+ case L'\\':
+ tmp[wp] = 0;
+ wp = 0;
+ UniStrCat(dst, size, tmp);
+ UniStrCat(dst, size, L"\\");
+ break;
+ default:
+ tmp[wp] = c;
+ wp++;
+ break;
+ }
+ }
+ Win32NukuEnW(dst, size, NULL);
+}
+void Win32GetDirFromPath(char *dst, UINT size, char *src)
+{
+ char str[MAX_SIZE];
+ int i,len;
+ char c;
+ char tmp[MAX_SIZE];
+ int wp;
+ if (src)
+ {
+ StrCpy(str, sizeof(str), src);
+ }
+ else
+ {
+ StrCpy(str, sizeof(str), dst);
+ }
+ Win32NukuEn(str, sizeof(str), NULL);
+ wp = 0;
+ len = StrLen(str);
+ dst[0] = 0;
+ for (i = 0;i < len;i++)
+ {
+ c = str[i];
+ switch (c)
+ {
+ case '\\':
+ tmp[wp] = 0;
+ wp = 0;
+ StrCat(dst, size, tmp);
+ StrCat(dst, size, "\\");
+ break;
+ default:
+ tmp[wp] = c;
+ wp++;
+ break;
+ }
+ }
+ Win32NukuEn(dst, size, NULL);
+}
+
+// Delete the directory
+bool Win32DeleteDirW(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char *name_a = CopyUniToStr(name);
+ bool ret = Win32DeleteDir(name_a);
+
+ Free(name_a);
+
+ return ret;
+ }
+
+ if (RemoveDirectoryW(name) == FALSE)
+ {
+ return false;
+ }
+ return true;
+}
+bool Win32DeleteDir(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (RemoveDirectory(name) == FALSE)
+ {
+ return false;
+ }
+ return true;
+}
+
+// Create a directory
+bool Win32MakeDirW(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ char *name_a = CopyUniToStr(name);
+ bool ret = Win32MakeDir(name_a);
+
+ Free(name_a);
+
+ return ret;
+ }
+
+ if (CreateDirectoryW(name, NULL) == FALSE)
+ {
+ return false;
+ }
+
+ return true;
+}
+bool Win32MakeDir(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (CreateDirectory(name, NULL) == FALSE)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Delete the file
+bool Win32FileDeleteW(wchar_t *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (IsNt() == false)
+ {
+ bool ret;
+ char *name_a = CopyUniToStr(name);
+
+ ret = Win32FileDelete(name_a);
+
+ Free(name_a);
+
+ return ret;
+ }
+
+ if (DeleteFileW(name) == FALSE)
+ {
+ return false;
+ }
+ return true;
+}
+bool Win32FileDelete(char *name)
+{
+ // Validate arguments
+ if (name == NULL)
+ {
+ return false;
+ }
+
+ if (DeleteFile(name) == FALSE)
+ {
+ return false;
+ }
+ return true;
+}
+
+// Seek in the file
+bool Win32FileSeek(void *pData, UINT mode, int offset)
+{
+ WIN32IO *p;
+ DWORD ret;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return false;
+ }
+ if (mode != FILE_BEGIN && mode != FILE_END && mode != FILE_CURRENT)
+ {
+ return false;
+ }
+
+ p = (WIN32IO *)pData;
+ ret = SetFilePointer(p->hFile, (LONG)offset, NULL, mode);
+ if (ret == INVALID_SET_FILE_POINTER || ret == ERROR_NEGATIVE_SEEK)
+ {
+ return false;
+ }
+ return true;
+}
+
+// Get the file size
+UINT64 Win32FileSize(void *pData)
+{
+ WIN32IO *p;
+ UINT64 ret;
+ DWORD tmp;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return 0;
+ }
+
+ p = (WIN32IO *)pData;
+ tmp = 0;
+ ret = GetFileSize(p->hFile, &tmp);
+ if (ret == (DWORD)-1)
+ {
+ return 0;
+ }
+
+ if (tmp != 0)
+ {
+ ret += (UINT64)tmp * 4294967296ULL;
+ }
+
+ return ret;
+}
+
+// Write to the file
+bool Win32FileWrite(void *pData, void *buf, UINT size)
+{
+ WIN32IO *p;
+ DWORD write_size;
+ // Validate arguments
+ if (pData == NULL || buf == NULL || size == 0)
+ {
+ return false;
+ }
+
+ p = (WIN32IO *)pData;
+ if (WriteFile(p->hFile, buf, size, &write_size, NULL) == FALSE)
+ {
+ return false;
+ }
+
+ if (write_size != size)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Read from a file
+bool Win32FileRead(void *pData, void *buf, UINT size)
+{
+ WIN32IO *p;
+ DWORD read_size;
+ // Validate arguments
+ if (pData == NULL || buf == NULL || size == 0)
+ {
+ return false;
+ }
+
+ p = (WIN32IO *)pData;
+ if (ReadFile(p->hFile, buf, size, &read_size, NULL) == FALSE)
+ {
+ return false;
+ }
+
+ if (read_size != size)
+ {
+ return false;
+ }
+
+ return true;;
+}
+
+// Close the file
+void Win32FileClose(void *pData, bool no_flush)
+{
+ WIN32IO *p;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return;
+ }
+
+ p = (WIN32IO *)pData;
+ if (p->WriteMode && no_flush == false)
+ {
+ FlushFileBuffers(p->hFile);
+ }
+ CloseHandle(p->hFile);
+ p->hFile = NULL;
+
+ // Memory release
+ Win32MemoryFree(p);
+}
+
+// Get the date of the file
+bool Win32FileGetDate(void *pData, UINT64 *created_time, UINT64 *updated_time, UINT64 *accessed_date)
+{
+ WIN32IO *p;
+ BY_HANDLE_FILE_INFORMATION info;
+ SYSTEMTIME st_create, st_update, st_access;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return false;
+ }
+
+ p = (WIN32IO *)pData;
+
+ Zero(&info, sizeof(info));
+
+ if (GetFileInformationByHandle(p->hFile, &info) == false)
+ {
+ return false;
+ }
+
+ Zero(&st_create, sizeof(st_create));
+ Zero(&st_update, sizeof(st_update));
+ Zero(&st_access, sizeof(st_access));
+
+ FileTimeToSystemTime(&info.ftCreationTime, &st_create);
+ FileTimeToSystemTime(&info.ftLastWriteTime, &st_update);
+ FileTimeToSystemTime(&info.ftLastAccessTime, &st_access);
+
+ if (created_time != NULL)
+ {
+ *created_time = SystemToUINT64(&st_create);
+ }
+
+ if (updated_time != NULL)
+ {
+ *updated_time = SystemToUINT64(&st_update);
+ }
+
+ if (accessed_date != NULL)
+ {
+ *accessed_date = SystemToUINT64(&st_access);
+ }
+
+ return true;
+}
+
+// Set the date of the file
+bool Win32FileSetDate(void *pData, UINT64 created_time, UINT64 updated_time)
+{
+ WIN32IO *p;
+ SYSTEMTIME st_created_time, st_updated_time;
+ FILETIME ft_created_time, ft_updated_time;
+ FILETIME *p_created_time = NULL, *p_updated_time = NULL;
+ // Validate arguments
+ if (pData == NULL || (created_time == 0 && updated_time == 0))
+ {
+ return false;
+ }
+
+ p = (WIN32IO *)pData;
+
+ Zero(&st_created_time, sizeof(st_created_time));
+ Zero(&st_updated_time, sizeof(st_updated_time));
+
+ if (created_time != 0)
+ {
+ UINT64ToSystem(&st_created_time, created_time);
+
+ SystemTimeToFileTime(&st_created_time, &ft_created_time);
+
+ p_created_time = &ft_created_time;
+ }
+
+ if (updated_time != 0)
+ {
+ UINT64ToSystem(&st_updated_time, updated_time);
+
+ SystemTimeToFileTime(&st_updated_time, &ft_updated_time);
+
+ p_updated_time = &ft_updated_time;
+ }
+
+ return SetFileTime(p->hFile, p_created_time, NULL, p_updated_time);
+}
+
+// Flush to the file
+void Win32FileFlush(void *pData)
+{
+ WIN32IO *p;
+ // Validate arguments
+ if (pData == NULL)
+ {
+ return;
+ }
+
+ p = (WIN32IO *)pData;
+ if (p->WriteMode)
+ {
+ FlushFileBuffers(p->hFile);
+ }
+}
+
+// Open the file
+void *Win32FileOpenW(wchar_t *name, bool write_mode, bool read_lock)
+{
+ WIN32IO *p;
+ HANDLE h;
+ DWORD lock_mode;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsNt() == false)
+ {
+ void *ret;
+ char *name_a = CopyUniToStr(name);
+
+ ret = Win32FileOpen(name_a, write_mode, read_lock);
+
+ Free(name_a);
+
+ return ret;
+ }
+
+ if (write_mode)
+ {
+ lock_mode = FILE_SHARE_READ;
+ }
+ else
+ {
+ if (read_lock == false)
+ {
+ lock_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ }
+ else
+ {
+ lock_mode = FILE_SHARE_READ;
+ }
+ }
+
+ // Open the file
+ h = CreateFileW(name,
+ (write_mode ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ),
+ lock_mode,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ UINT ret = GetLastError();
+ // Failure
+ return NULL;
+ }
+
+ // Memory allocation
+ p = Win32MemoryAlloc(sizeof(WIN32IO));
+ // Store Handle
+ p->hFile = h;
+
+ p->WriteMode = write_mode;
+
+ return (void *)p;
+}
+void *Win32FileOpen(char *name, bool write_mode, bool read_lock)
+{
+ WIN32IO *p;
+ HANDLE h;
+ DWORD lock_mode;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (write_mode)
+ {
+ lock_mode = FILE_SHARE_READ;
+ }
+ else
+ {
+ if (read_lock == false)
+ {
+ lock_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ }
+ else
+ {
+ lock_mode = FILE_SHARE_READ;
+ }
+ }
+
+ // Open the file
+ h = CreateFile(name,
+ (write_mode ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ),
+ lock_mode,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ UINT ret = GetLastError();
+ // Failure
+ return NULL;
+ }
+
+ // Memory allocation
+ p = Win32MemoryAlloc(sizeof(WIN32IO));
+ // Store Handle
+ p->hFile = h;
+
+ p->WriteMode = write_mode;
+
+ return (void *)p;
+}
+
+// Create a file
+void *Win32FileCreateW(wchar_t *name)
+{
+ WIN32IO *p;
+ HANDLE h;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ if (IsNt() == false)
+ {
+ void *ret;
+ char *name_a = CopyUniToStr(name);
+
+ ret = Win32FileCreate(name_a);
+
+ Free(name_a);
+
+ return ret;
+ }
+
+ // Create a file
+ h = CreateFileW(name, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ h = CreateFileW(name, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN,
+ NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return NULL;
+ }
+ }
+
+ // Memory allocation
+ p = Win32MemoryAlloc(sizeof(WIN32IO));
+ // Store Handle
+ p->hFile = h;
+
+ p->WriteMode = true;
+
+ return (void *)p;
+}
+void *Win32FileCreate(char *name)
+{
+ WIN32IO *p;
+ HANDLE h;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ // Create a file
+ h = CreateFile(name, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ h = CreateFile(name, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN,
+ NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ return NULL;
+ }
+ }
+
+ // Memory allocation
+ p = Win32MemoryAlloc(sizeof(WIN32IO));
+ // Store Handle
+ p->hFile = h;
+
+ p->WriteMode = true;
+
+ return (void *)p;
+}
+
+#define SIZE_OF_CALLSTACK_SYM 10000
+#define CALLSTACK_DEPTH 12
+
+// Get the call stack
+CALLSTACK_DATA *Win32GetCallStack()
+{
+#ifndef WIN32_NO_DEBUG_HELP_DLL
+ DWORD current_eip32 = 0, current_esp32 = 0, current_ebp32 = 0;
+ UINT64 current_eip = 0, current_esp = 0, current_ebp = 0;
+ STACKFRAME64 sf;
+ CALLSTACK_DATA *cs = NULL, *s;
+
+#ifdef CPU_64
+ CONTEXT context;
+#endif // CPU_64
+
+ bool ret;
+ UINT depth = 0;
+
+#ifndef CPU_64
+ // Register acquisition (32 bit)
+ __asm
+ {
+ mov current_esp32, esp
+ mov current_ebp32, ebp
+ };
+
+ current_eip32 = (DWORD)Win32GetCallStack;
+
+ current_eip = (UINT64)current_eip32;
+ current_esp = (UINT64)current_esp32;
+ current_ebp = (UINT64)current_ebp32;
+#else // CPU_64
+ // Register acquisition (64 bit)
+ Zero(&context, sizeof(context));
+ context.ContextFlags = CONTEXT_FULL;
+ RtlCaptureContext(&context);
+#endif // CPU_64
+
+ Zero(&sf, sizeof(sf));
+
+#ifndef CPU_64
+ sf.AddrPC.Offset = current_eip;
+ sf.AddrStack.Offset = current_esp;
+ sf.AddrFrame.Offset = current_ebp;
+#else // CPU_64
+ sf.AddrPC.Offset = context.Rip;
+ sf.AddrStack.Offset = context.Rsp;
+ sf.AddrFrame.Offset = context.Rsp;
+#endif // CPU_64
+
+ sf.AddrPC.Mode = AddrModeFlat;
+ sf.AddrStack.Mode = AddrModeFlat;
+ sf.AddrFrame.Mode = AddrModeFlat;
+
+ while (true)
+ {
+ DWORD type = IMAGE_FILE_MACHINE_I386;
+
+#ifdef CPU_64
+ type = IMAGE_FILE_MACHINE_AMD64;
+#endif // CPU_64
+
+ if ((depth++) >= CALLSTACK_DEPTH)
+ {
+ break;
+ }
+
+#ifndef CPU_64
+ ret = StackWalk64(type,
+ hCurrentProcessHandle,
+ GetCurrentThread(),
+ &sf,
+ NULL, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL);
+#else // CPU_64
+ ret = StackWalk64(type,
+ hCurrentProcessHandle,
+ GetCurrentThread(),
+ &sf,
+ &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL);
+#endif // CPU_64
+ if (ret == false || sf.AddrFrame.Offset == 0)
+ {
+ break;
+ }
+
+ if (cs == NULL)
+ {
+ cs = OSMemoryAlloc(sizeof(CALLSTACK_DATA));
+ s = cs;
+ }
+ else
+ {
+ s->next = OSMemoryAlloc(sizeof(CALLSTACK_DATA));
+ s = s->next;
+ }
+ s->symbol_cache = false;
+ s->next = NULL;
+ s->offset = sf.AddrPC.Offset;
+ s->disp = 0;
+ s->name = NULL;
+ s->line = 0;
+ s->filename[0] = 0;
+ }
+
+ return cs;
+#else // WIN32_NO_DEBUG_HELP_DLL
+ return NULL;
+#endif // WIN32_NO_DEBUG_HELP_DLL
+}
+
+// Get the symbol information from the call stack
+bool Win32GetCallStackSymbolInfo(CALLSTACK_DATA *s)
+{
+#ifdef WIN32_NO_DEBUG_HELP_DLL
+ return false;
+#else // WIN32_NO_DEBUG_HELP_DLL
+ UINT64 disp;
+ UINT disp32, len;
+ IMAGEHLP_SYMBOL64 *sym;
+ IMAGEHLP_LINE64 line;
+ char tmp[MAX_PATH];
+ // Validate arguments
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ if (s->symbol_cache)
+ {
+ return true;
+ }
+
+ sym = OSMemoryAlloc(SIZE_OF_CALLSTACK_SYM);
+ sym->SizeOfStruct = SIZE_OF_CALLSTACK_SYM;
+ sym->MaxNameLength = SIZE_OF_CALLSTACK_SYM - sizeof(IMAGEHLP_SYMBOL64);
+
+ if (SymGetSymFromAddr64(hCurrentProcessHandle, s->offset, &disp, sym))
+ {
+ s->disp = disp;
+ s->name = OSMemoryAlloc((UINT)strlen(sym->Name) + 1);
+ lstrcpy(s->name, sym->Name);
+ }
+ else
+ {
+ s->disp = 0;
+ s->name = NULL;
+ }
+
+ Zero(&line, sizeof(line));
+ line.SizeOfStruct = sizeof(line);
+ if (SymGetLineFromAddr64(hCurrentProcessHandle, s->offset, &disp32, &line))
+ {
+ disp = (UINT64)disp32;
+ s->line = line.LineNumber;
+ lstrcpy(s->filename, line.FileName);
+ Win32GetDirFromPath(tmp, sizeof(tmp), s->filename);
+ len = lstrlen(tmp);
+ lstrcpy(tmp, &s->filename[len + 1]);
+ lstrcpy(s->filename, tmp);
+ }
+ else
+ {
+ s->line = 0;
+ s->filename[0] = 0;
+ }
+
+ OSMemoryFree(sym);
+
+ s->symbol_cache = true;
+
+ return true;
+#endif // WIN32_NO_DEBUG_HELP_DLL
+}
+
+// Default Win32 thread
+DWORD CALLBACK Win32DefaultThreadProc(void *param)
+{
+ WIN32THREADSTARTUPINFO *info = (WIN32THREADSTARTUPINFO *)param;
+ // Validate arguments
+ if (info == NULL)
+ {
+ return 0;
+ }
+
+ Win32InitNewThread();
+
+ CoInitialize(NULL);
+
+ // Call the thread function
+ info->thread_proc(info->thread, info->param);
+
+ // Release the reference
+ ReleaseThread(info->thread);
+
+ Win32MemoryFree(info);
+
+ FreeOpenSSLThreadState();
+
+ CoUninitialize();
+
+ _endthreadex(0);
+ return 0;
+}
+
+// Wait for the termination of the thread
+bool Win32WaitThread(THREAD *t)
+{
+ WIN32THREAD *w;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+ w = (WIN32THREAD *)t->pData;
+ if (w == NULL)
+ {
+ return false;
+ }
+
+ // Wait for the thread event
+ if (WaitForSingleObject(w->hThread, INFINITE) == WAIT_OBJECT_0)
+ {
+ // The thread was signaled
+ return true;
+ }
+
+ // Wait failure (time-out, etc.)
+ return false;
+}
+
+// Release the thread
+void Win32FreeThread(THREAD *t)
+{
+ WIN32THREAD *w;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return;
+ }
+ w = (WIN32THREAD *)t->pData;
+ if (w == NULL)
+ {
+ return;
+ }
+
+ // Close the handle
+ CloseHandle(w->hThread);
+
+ // Memory release
+ Win32MemoryFree(t->pData);
+ t->pData = NULL;
+}
+
+// Thread initialization
+bool Win32InitThread(THREAD *t)
+{
+ WIN32THREAD *w;
+ HANDLE hThread;
+ DWORD thread_id;
+ WIN32THREADSTARTUPINFO *info;
+ // Validate arguments
+ if (t == NULL)
+ {
+ return false;
+ }
+ if (t->thread_proc == NULL)
+ {
+ return false;
+ }
+
+ // Thread data generation
+ w = Win32MemoryAlloc(sizeof(WIN32THREAD));
+
+ // Creating the startup information
+ info = Win32MemoryAlloc(sizeof(WIN32THREADSTARTUPINFO));
+ info->param = t->param;
+ info->thread_proc = t->thread_proc;
+ info->thread = t;
+ AddRef(t->ref);
+
+ // Thread creation
+ t->pData = w;
+ hThread = (HANDLE)_beginthreadex(NULL, 0, Win32DefaultThreadProc, info, 0, &thread_id);
+ if (hThread == NULL)
+ {
+ // Thread creation failure
+ t->pData = NULL;
+ Release(t->ref);
+ Win32MemoryFree(info);
+ Win32MemoryFree(w);
+ return false;
+ }
+
+ // Save the thread information
+ w->hThread = hThread;
+ w->thread_id = thread_id;
+
+ return true;
+}
+
+// Initialize the library for Win32
+void Win32Init()
+{
+ INITCOMMONCONTROLSEX c;
+ OSVERSIONINFO os;
+
+ // Get whether it's in a Windows NT
+ Zero(&os, sizeof(os));
+ os.dwOSVersionInfoSize = sizeof(os);
+ GetVersionEx(&os);
+
+ if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ // NT system
+ win32_is_nt = true;
+ }
+ else
+ {
+ // 9x system
+ win32_is_nt = false;
+ }
+
+ // Open the stdout
+ if (hstdout == INVALID_HANDLE_VALUE)
+ {
+ hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ }
+
+ // Open the stdin
+ if (hstdin == INVALID_HANDLE_VALUE)
+ {
+ hstdin = GetStdHandle(STD_INPUT_HANDLE);
+ }
+
+ Win32InitNewThread();
+
+ CoInitialize(NULL);
+
+ InitializeCriticalSection(&fasttick_lock);
+
+#ifdef WIN32_USE_HEAP_API_FOR_MEMORY
+ use_heap_api = true;
+#else // WIN32_USE_HEAP_API_FOR_MEMORY
+ use_heap_api = false;
+#endif // WIN32_USE_HEAP_API_FOR_MEMORY
+
+ if (MayaquaIsDotNetMode())
+ {
+ // If an heap API is called from .NET API, it might crush
+ use_heap_api = false;
+ }
+
+ if (IsNt() == false)
+ {
+ // Do not use the heap related API in Win9x
+ use_heap_api = false;
+ }
+
+ if (use_heap_api)
+ {
+ heap_handle = HeapCreate(0, 0, 0);
+ }
+
+ // Get the process pseudo handle
+ hCurrentProcessHandle = GetCurrentProcess();
+
+ // Initialization of the current directory
+ // Win32InitCurrentDir(); /* Don't do */
+
+ // Initialization of the symbol handler
+ if (IsMemCheck())
+ {
+#ifndef WIN32_NO_DEBUG_HELP_DLL
+ SymInitialize(hCurrentProcessHandle, NULL, TRUE);
+#endif // WIN32_NO_DEBUG_HELP_DLL
+ }
+
+ // Initialization of the Common Control
+ Zero(&c, sizeof(INITCOMMONCONTROLSEX));
+ c.dwSize = sizeof(INITCOMMONCONTROLSEX);
+ c.dwICC = ICC_ANIMATE_CLASS | ICC_BAR_CLASSES | ICC_COOL_CLASSES |
+ ICC_DATE_CLASSES | ICC_HOTKEY_CLASS | ICC_INTERNET_CLASSES |
+ ICC_LISTVIEW_CLASSES | ICC_NATIVEFNTCTL_CLASS |
+ ICC_PAGESCROLLER_CLASS | ICC_PROGRESS_CLASS |
+ ICC_TAB_CLASSES | ICC_TREEVIEW_CLASSES | ICC_UPDOWN_CLASS | ICC_USEREX_CLASSES |
+ ICC_WIN95_CLASSES;
+ InitCommonControlsEx(&c);
+}
+
+// Release the library for Win32
+void Win32Free()
+{
+ // Close the symbol handler
+ if (IsMemCheck())
+ {
+#ifndef WIN32_NO_DEBUG_HELP_DLL
+ SymCleanup(hCurrentProcessHandle);
+#endif // WIN32_NO_DEBUG_HELP_DLL
+ }
+
+ if (use_heap_api)
+ {
+ HeapDestroy(heap_handle);
+ heap_handle = NULL;
+ }
+
+ CoUninitialize();
+
+ DeleteCriticalSection(&fasttick_lock);
+}
+
+// Memory allocation
+void *Win32MemoryAlloc(UINT size)
+{
+ if (use_heap_api)
+ {
+ return HeapAlloc(heap_handle, 0, size);
+ }
+ else
+ {
+ return malloc(size);
+ }
+}
+
+// Memory reallocation
+void *Win32MemoryReAlloc(void *addr, UINT size)
+{
+ if (use_heap_api)
+ {
+ return HeapReAlloc(heap_handle, 0, addr, size);
+ }
+ else
+ {
+ return realloc(addr, size);
+ }
+}
+
+// Memory allocation
+void Win32MemoryFree(void *addr)
+{
+ if (use_heap_api)
+ {
+ HeapFree(heap_handle, 0, addr);
+ }
+ else
+ {
+ free(addr);
+ }
+}
+
+// Get the system timer
+UINT Win32GetTick()
+{
+ return (UINT)timeGetTime();
+}
+
+// Get the System Time
+void Win32GetSystemTime(SYSTEMTIME *system_time)
+{
+ // Get the System Time
+ GetSystemTime(system_time);
+}
+
+// Increment of 32bit integer
+void Win32Inc32(UINT *value)
+{
+ InterlockedIncrement(value);
+}
+
+// Decrement of 32bit integer
+void Win32Dec32(UINT *value)
+{
+ InterlockedDecrement(value);
+}
+
+// Sleep the thread
+void Win32Sleep(UINT time)
+{
+ Sleep(time);
+}
+
+// Creating a lock
+LOCK *Win32NewLock()
+{
+ // Memory allocation
+ LOCK *lock = Win32MemoryAlloc(sizeof(LOCK));
+
+ // Allocate a critical section
+ CRITICAL_SECTION *critical_section = Win32MemoryAlloc(sizeof(CRITICAL_SECTION));
+
+ if (lock == NULL || critical_section == NULL)
+ {
+ Win32MemoryFree(lock);
+ Win32MemoryFree(critical_section);
+ return NULL;
+ }
+
+ // Initialize the critical section
+ InitializeCriticalSection(critical_section);
+
+ lock->pData = (void *)critical_section;
+ lock->Ready = true;
+
+ return lock;
+}
+
+// Lock
+bool Win32Lock(LOCK *lock)
+{
+ CRITICAL_SECTION *critical_section;
+ if (lock->Ready == false)
+ {
+ // State is invalid
+ return false;
+ }
+
+ // Enter the critical section
+ critical_section = (CRITICAL_SECTION *)lock->pData;
+ EnterCriticalSection(critical_section);
+
+ return true;
+}
+
+// Unlock
+void Win32Unlock(LOCK *lock)
+{
+ Win32UnlockEx(lock, false);
+}
+void Win32UnlockEx(LOCK *lock, bool inner)
+{
+ CRITICAL_SECTION *critical_section;
+ if (lock->Ready == false && inner == false)
+ {
+ // State is invalid
+ return;
+ }
+
+ // Leave the critical section
+ critical_section = (CRITICAL_SECTION *)lock->pData;
+ LeaveCriticalSection(critical_section);
+}
+
+// Delete the lock
+void Win32DeleteLock(LOCK *lock)
+{
+ CRITICAL_SECTION *critical_section;
+ // Reset the Ready flag safely
+ Win32Lock(lock);
+ lock->Ready = false;
+ Win32UnlockEx(lock, true);
+
+ // Delete the critical section
+ critical_section = (CRITICAL_SECTION *)lock->pData;
+ DeleteCriticalSection(critical_section);
+
+ // Memory release
+ Win32MemoryFree(critical_section);
+ Win32MemoryFree(lock);
+}
+
+// Initialization of the event
+void Win32InitEvent(EVENT *event)
+{
+ // Creating an auto-reset event
+ HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ event->pData = hEvent;
+}
+
+// Set the event
+void Win32SetEvent(EVENT *event)
+{
+ HANDLE hEvent = (HANDLE)event->pData;
+ if (hEvent == NULL)
+ {
+ return;
+ }
+
+ SetEvent(hEvent);
+}
+
+// Reset the event
+void Win32ResetEvent(EVENT *event)
+{
+ HANDLE hEvent = (HANDLE)event->pData;
+ if (hEvent == NULL)
+ {
+ return;
+ }
+
+ ResetEvent(hEvent);
+}
+
+// Wait for the event
+bool Win32WaitEvent(EVENT *event, UINT timeout)
+{
+ HANDLE hEvent = (HANDLE)event->pData;
+ UINT ret;
+ if (hEvent == NULL)
+ {
+ return false;
+ }
+
+ // Wait for an object
+ ret = WaitForSingleObject(hEvent, timeout);
+ if (ret == WAIT_TIMEOUT)
+ {
+ // Time-out
+ return false;
+ }
+ else
+ {
+ // Signaled state
+ return true;
+ }
+}
+
+// Release of the event
+void Win32FreeEvent(EVENT *event)
+{
+ HANDLE hEvent = (HANDLE)event->pData;
+ if (hEvent == NULL)
+ {
+ return;
+ }
+
+ CloseHandle(hEvent);
+}
+
+// Fast getting 64 bit Tick functions for only Win32
+UINT64 Win32FastTick64()
+{
+ static UINT last_tick = 0;
+ static UINT counter = 0;
+ UINT64 ret;
+ UINT tick;
+
+ EnterCriticalSection(&fasttick_lock);
+
+ // Get the current tick value
+ tick = Win32GetTick();
+
+ if (last_tick > tick)
+ {
+ // When the previously acquired tick value is larger than acquired this time,
+ // it can be considered that the counter have gone one around
+
+ counter++;
+ }
+
+ last_tick = tick;
+
+ ret = (UINT64)tick + (UINT64)counter * 4294967296ULL;
+
+ LeaveCriticalSection(&fasttick_lock);
+
+ if (start_tick == 0)
+ {
+ start_tick = ret;
+ ret = 0;
+ }
+ else
+ {
+ ret -= start_tick;
+ }
+
+ return ret + 1;
+}
+
+// Read a string from the console
+bool Win32InputW(wchar_t *str, UINT size)
+{
+ bool ret = false;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return false;
+ }
+ if (size == 0)
+ {
+ size = 0x7fffffff;
+ }
+
+ if (str == NULL || size <= sizeof(wchar_t))
+ {
+ if (str != NULL)
+ {
+ Zero(str, size);
+ }
+
+ return Win32InputFromFileW(NULL, 0);
+ }
+
+ if (IsNt())
+ {
+ DWORD read_size = 0;
+
+ if (ReadConsoleW(hstdin, str, (size - sizeof(wchar_t)), &read_size, NULL))
+ {
+ str[read_size] = 0;
+
+ UniTrimCrlf(str);
+
+ ret = true;
+ }
+ else
+ {
+ ret = Win32InputFromFileW(str, size);
+ }
+ }
+ else
+ {
+ DWORD read_size = 0;
+ UINT a_size = size / sizeof(wchar_t) + 16;
+ char *a;
+
+ a = ZeroMalloc(a_size);
+
+ if (ReadConsoleA(hstdin, a, a_size - 1, &read_size, NULL))
+ {
+ a[read_size] = 0;
+
+ StrToUni(str, size, a);
+
+ UniTrimCrlf(str);
+
+ ret = true;
+ }
+ else
+ {
+ ret = Win32InputFromFileW(str, size);
+ }
+
+ Free(a);
+ }
+
+ return ret;
+}
+// Get a line from standard input
+bool Win32InputFromFileW(wchar_t *str, UINT size)
+{
+ char *a;
+ if (str == NULL)
+ {
+ wchar_t tmp[MAX_SIZE];
+ Win32InputFromFileW(tmp, sizeof(tmp));
+ return false;
+ }
+
+ a = Win32InputFromFileLineA();
+ if (a == NULL)
+ {
+ UniStrCpy(str, size, L"");
+ return false;
+ }
+
+ UtfToUni(str, size, a);
+
+ UniTrimCrlf(str);
+
+ Free(a);
+
+ return true;
+}
+char *Win32InputFromFileLineA()
+{
+ BUF *b = NewBuf();
+ char zero = 0;
+ char *ret = NULL;
+ bool ok = true;
+
+ while (true)
+ {
+ char c;
+ UINT read_size = 0;
+
+ if (ReadFile(hstdin, &c, 1, &read_size, NULL) == false)
+ {
+ ok = false;
+ break;
+ }
+ if (read_size != 1)
+ {
+ ok = false;
+ break;
+ }
+
+ WriteBuf(b, &c, 1);
+
+ if (c == 10)
+ {
+ break;
+ }
+ }
+
+ WriteBuf(b, &zero, 1);
+
+ if (ok)
+ {
+ ret = CopyStr(b->Buf);
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// Print the string to the console
+void Win32PrintW(wchar_t *str)
+{
+ DWORD write_size = 0;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ if (IsNt())
+ {
+ if (WriteConsoleW(hstdout, str, UniStrLen(str), &write_size, NULL) == false)
+ {
+ Win32PrintToFileW(str);
+ }
+ }
+ else
+ {
+ char *ansi_str = CopyUniToStr(str);
+
+ if (WriteConsoleA(hstdout, ansi_str, StrLen(ansi_str), &write_size, NULL) == false)
+ {
+ Win32PrintToFileW(str);
+ }
+
+ Free(ansi_str);
+ }
+}
+void Win32PrintToFileW(wchar_t *str)
+{
+ char *utf;
+ DWORD size = 0;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return;
+ }
+
+ utf = CopyUniToUtf(str);
+
+ WriteFile(hstdout, utf, StrLen(utf), &size, NULL);
+
+ Free(utf);
+}
+
+
+#endif // WIN32
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/Win32.h b/src/Mayaqua/Win32.h
new file mode 100644
index 00000000..8a0f9617
--- /dev/null
+++ b/src/Mayaqua/Win32.h
@@ -0,0 +1,204 @@
+// SoftEther VPN Source Code
+// Mayaqua Kernel
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Win32.h
+// Header of Win32.c
+
+#ifdef OS_WIN32
+
+#ifndef WIN32_H
+#define WIN32_H
+
+// Function prototype
+OS_DISPATCH_TABLE *Win32GetDispatchTable();
+
+void Win32Init();
+void Win32Free();
+void *Win32MemoryAlloc(UINT size);
+void *Win32MemoryReAlloc(void *addr, UINT size);
+void Win32MemoryFree(void *addr);
+UINT Win32GetTick();
+void Win32GetSystemTime(SYSTEMTIME *system_time);
+void Win32Inc32(UINT *value);
+void Win32Dec32(UINT *value);
+void Win32Sleep(UINT time);
+LOCK *Win32NewLock();
+bool Win32Lock(LOCK *lock);
+void Win32Unlock(LOCK *lock);
+void Win32DeleteLock(LOCK *lock);
+void Win32InitEvent(EVENT *event);
+void Win32SetEvent(EVENT *event);
+void Win32ResetEvent(EVENT *event);
+bool Win32WaitEvent(EVENT *event, UINT timeout);
+void Win32FreeEvent(EVENT *event);
+bool Win32WaitThread(THREAD *t);
+void Win32FreeThread(THREAD *t);
+bool Win32InitThread(THREAD *t);
+UINT Win32ThreadId();
+void *Win32FileOpen(char *name, bool write_mode, bool read_lock);
+void *Win32FileOpenW(wchar_t *name, bool write_mode, bool read_lock);
+void *Win32FileCreate(char *name);
+void *Win32FileCreateW(wchar_t *name);
+bool Win32FileWrite(void *pData, void *buf, UINT size);
+bool Win32FileRead(void *pData, void *buf, UINT size);
+bool Win32FileSetDate(void *pData, UINT64 created_time, UINT64 updated_time);
+bool Win32FileGetDate(void *pData, UINT64 *created_time, UINT64 *updated_time, UINT64 *accessed_date);
+void Win32FileClose(void *pData, bool no_flush);
+void Win32FileFlush(void *pData);
+UINT64 Win32FileSize(void *pData);
+bool Win32FileSeek(void *pData, UINT mode, int offset);
+bool Win32FileDelete(char *name);
+bool Win32FileDeleteW(wchar_t *name);
+bool Win32MakeDir(char *name);
+bool Win32MakeDirW(wchar_t *name);
+bool Win32DeleteDir(char *name);
+bool Win32DeleteDirW(wchar_t *name);
+CALLSTACK_DATA *Win32GetCallStack();
+bool Win32GetCallStackSymbolInfo(CALLSTACK_DATA *s);
+bool Win32FileRename(char *old_name, char *new_name);
+bool Win32FileRenameW(wchar_t *old_name, wchar_t *new_name);
+bool Win32Run(char *filename, char *arg, bool hide, bool wait);
+bool Win32RunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait);
+void *Win32RunEx(char *filename, char *arg, bool hide);
+void *Win32RunEx2(char *filename, char *arg, bool hide, UINT *process_id);
+void *Win32RunEx3(char *filename, char *arg, bool hide, UINT *process_id, bool disableWow);
+void *Win32RunExW(wchar_t *filename, wchar_t *arg, bool hide);
+void *Win32RunEx2W(wchar_t *filename, wchar_t *arg, bool hide, UINT *process_id);
+void *Win32RunEx3W(wchar_t *filename, wchar_t *arg, bool hide, UINT *process_id, bool disableWow);
+bool Win32WaitProcess(void *h, UINT timeout);
+bool Win32RunAndWaitProcess(wchar_t *filename, wchar_t *arg, bool hide, bool disableWow, UINT timeout);
+bool Win32IsProcessAlive(void *handle);
+bool Win32TerminateProcess(void *handle);
+void Win32CloseProcess(void *handle);
+bool Win32IsSupportedOs();
+void Win32GetOsInfo(OS_INFO *info);
+void Win32Alert(char *msg, char *caption);
+void Win32AlertW(wchar_t *msg, wchar_t *caption);
+void Win32DebugAlert(char *msg);
+char* Win32GetProductId();
+void Win32SetHighPriority();
+void Win32RestorePriority();
+void *Win32NewSingleInstance(char *instance_name);
+void Win32FreeSingleInstance(void *data);
+void Win32GetMemInfo(MEMINFO *info);
+void Win32Yield();
+
+void Win32UnlockEx(LOCK *lock, bool inner);
+UINT Win32GetOsType();
+UINT Win32GetSpVer(char *str);
+UINT Win32GetOsSpVer();
+void Win32NukuEn(char *dst, UINT size, char *src);
+void Win32NukuEnW(wchar_t *dst, UINT size, wchar_t *src);
+void Win32GetDirFromPath(char *dst, UINT size, char *src);
+void Win32GetDirFromPathW(wchar_t *dst, UINT size, wchar_t *src);
+void Win32GetExeDir(char *name, UINT size);
+void Win32GetExeDirW(wchar_t *name, UINT size);
+void Win32GetCurrentDir(char *dir, UINT size);
+void Win32GetCurrentDirW(wchar_t *dir, UINT size);
+void Win32GetExeName(char *name, UINT size);
+void Win32GetExeNameW(wchar_t *name, UINT size);
+DIRLIST *Win32EnumDirEx(char *dirname, COMPARE *compare);
+DIRLIST *Win32EnumDirExW(wchar_t *dirname, COMPARE *compare);
+bool Win32GetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
+bool Win32GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
+bool Win32SetFolderCompress(char *path, bool compressed);
+bool Win32SetFolderCompressW(wchar_t *path, bool compressed);
+UINT64 Win32FastTick64();
+void Win32InitNewThread();
+bool Win32IsNt();
+bool Win32InputW(wchar_t *str, UINT size);
+bool Win32InputFromFileW(wchar_t *str, UINT size);
+char *Win32InputFromFileLineA();
+void Win32PrintW(wchar_t *str);
+void Win32PrintToFileW(wchar_t *str);
+bool Win32GetVersionExInternal(void *info);
+bool Win32GetVersionExInternalForWindows81orLater(void *info);
+
+void Win32SetThreadName(UINT thread_id, char *name);
+
+#endif // WIN32_H
+
+#endif // OS_WIN32
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/Mayaqua/cryptoki.h b/src/Mayaqua/cryptoki.h
new file mode 100644
index 00000000..7d85ca80
--- /dev/null
+++ b/src/Mayaqua/cryptoki.h
@@ -0,0 +1,66 @@
+/* cryptoki.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* This is a sample file containing the top level include directives
+ * for building Win32 Cryptoki libraries and applications.
+ */
+
+#ifndef ___CRYPTOKI_H_INC___
+#define ___CRYPTOKI_H_INC___
+
+#pragma pack(push, cryptoki, 1)
+
+/* Specifies that the function is a DLL entry point. */
+#define CK_IMPORT_SPEC __declspec(dllimport)
+
+/* Define CRYPTOKI_EXPORTS during the build of cryptoki libraries. Do
+ * not define it in applications.
+ */
+#ifdef CRYPTOKI_EXPORTS
+/* Specified that the function is an exported DLL entry point. */
+#define CK_EXPORT_SPEC __declspec(dllexport)
+#else
+#define CK_EXPORT_SPEC CK_IMPORT_SPEC
+#endif
+
+/* Ensures the calling convention for Win32 builds */
+#define CK_CALL_SPEC __cdecl
+
+#define CK_PTR *
+
+#define CK_DEFINE_FUNCTION(returnType, name) \
+ returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION(returnType, name) \
+ returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ returnType CK_IMPORT_SPEC (CK_CALL_SPEC CK_PTR name)
+
+#define CK_CALLBACK_FUNCTION(returnType, name) \
+ returnType (CK_CALL_SPEC CK_PTR name)
+
+#ifndef NULL_PTR
+#define NULL_PTR 0
+#endif
+
+#include "pkcs11.h"
+
+#pragma pack(pop, cryptoki)
+
+#endif /* ___CRYPTOKI_H_INC___ */
diff --git a/src/Mayaqua/intelaes/iaesni.h b/src/Mayaqua/intelaes/iaesni.h
new file mode 100644
index 00000000..b71a223a
--- /dev/null
+++ b/src/Mayaqua/intelaes/iaesni.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+*/
+
+
+#ifndef _IAESNI_H__
+#define _IAESNI_H__
+
+#include <stdlib.h>
+
+#define AES_INSTRCTIONS_CPUID_BIT (1<<25)
+
+//indicates input param
+#define _AES_IN
+
+//indicates output param
+#define _AES_OUT
+
+//indicates input/output param - based on context
+#define _AES_INOUT
+
+//typedef unsigned char UCHAR;
+
+
+/*#ifndef bool
+#define bool BOOL
+#endif*/
+//test if the processor actually supports the above functions
+//executing one the functions below without processor support will cause UD fault
+//bool check_for_aes_instructions(void);
+#if (__cplusplus)
+extern "C" {
+#endif
+int check_for_aes_instructions(void);
+
+#define ROUND_KEYS_UNALIGNED_TESTING
+
+#ifdef __linux__
+
+#ifdef ROUND_KEYS_UNALIGNED_TESTING
+
+#define DEFINE_ROUND_KEYS \
+ UCHAR __attribute__ ((aligned (16))) _expandedKey[16*16]; \
+ UCHAR *expandedKey = _expandedKey + 4; \
+
+
+#else
+
+
+
+#define DEFINE_ROUND_KEYS \
+ UCHAR __attribute__ ((aligned (16))) _expandedKey[16*16]; \
+ UCHAR *expandedKey = _expandedKey; \
+
+#endif
+
+#else // if not __linux__
+
+#ifdef ROUND_KEYS_UNALIGNED_TESTING
+
+#define DEFINE_ROUND_KEYS \
+ __declspec(align(16)) UCHAR _expandedKey[16*16]; \
+ UCHAR *expandedKey = _expandedKey + 4; \
+
+
+#else
+
+
+
+#define DEFINE_ROUND_KEYS \
+ __declspec(align(16)) UCHAR _expandedKey[16*16]; \
+ UCHAR *expandedKey = _expandedKey; \
+
+
+#endif
+
+#endif
+
+
+
+// encryption functions
+// plainText is pointer to input stream
+// cipherText is pointer to buffer to be filled with encrypted (cipher text) data
+// key is pointer to enc key (sizes are 16 bytes for AES-128, 24 bytes for AES-192, 32 for AES-256)
+// numBlocks is number of 16 bytes blocks to process - note that encryption is done of full 16 byte blocks
+void intel_AES_enc128(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+void intel_AES_enc192(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+void intel_AES_enc256(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+
+
+void intel_AES_enc128_CBC(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+void intel_AES_enc192_CBC(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+void intel_AES_enc256_CBC(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+
+
+// encryption functions
+// cipherText is pointer to encrypted stream
+// plainText is pointer to buffer to be filled with original (plain text) data
+// key is pointer to enc key (sizes are 16 bytes for AES-128, 24 bytes for AES-192, 32 for AES-256)
+// numBlocks is number of 16 bytes blocks to process - note that decryption is done of full 16 byte blocks
+void intel_AES_dec128(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+void intel_AES_dec192(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+void intel_AES_dec256(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+
+void intel_AES_dec128_CBC(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+void intel_AES_dec192_CBC(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+void intel_AES_dec256_CBC(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+
+void intel_AES_encdec128_CTR(_AES_IN UCHAR *input, _AES_OUT UCHAR *output, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *initial_counter);
+void intel_AES_encdec192_CTR(_AES_IN UCHAR *input, _AES_OUT UCHAR *output, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *initial_counter);
+void intel_AES_encdec256_CTR(_AES_IN UCHAR *input, _AES_OUT UCHAR *output, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *initial_counter);
+
+
+#if (__cplusplus)
+}
+#endif
+
+
+#endif
+
+
+
diff --git a/src/Mayaqua/pkcs11.h b/src/Mayaqua/pkcs11.h
new file mode 100644
index 00000000..5afbb7ac
--- /dev/null
+++ b/src/Mayaqua/pkcs11.h
@@ -0,0 +1,299 @@
+/* pkcs11.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+#ifndef _PKCS11_H_
+#define _PKCS11_H_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Before including this file (pkcs11.h) (or pkcs11t.h by
+ * itself), 6 platform-specific macros must be defined. These
+ * macros are described below, and typical definitions for them
+ * are also given. Be advised that these definitions can depend
+ * on both the platform and the compiler used (and possibly also
+ * on whether a Cryptoki library is linked statically or
+ * dynamically).
+ *
+ * In addition to defining these 6 macros, the packing convention
+ * for Cryptoki structures should be set. The Cryptoki
+ * convention on packing is that structures should be 1-byte
+ * aligned.
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, this might be done by using the following
+ * preprocessor directive before including pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(push, cryptoki, 1)
+ *
+ * and using the following preprocessor directive after including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(pop, cryptoki)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, this might be done by using
+ * the following preprocessor directive before including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(1)
+ *
+ * In a UNIX environment, you're on your own for this. You might
+ * not need to do (or be able to do!) anything.
+ *
+ *
+ * Now for the macros:
+ *
+ *
+ * 1. CK_PTR: The indirection string for making a pointer to an
+ * object. It can be used like this:
+ *
+ * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, it might be defined by:
+ *
+ * #define CK_PTR far *
+ *
+ * In a typical UNIX environment, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ *
+ * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
+ * an exportable Cryptoki library function definition out of a
+ * return type and a function name. It should be used in the
+ * following fashion to define the exposed Cryptoki functions in
+ * a Cryptoki library:
+ *
+ * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
+ * CK_VOID_PTR pReserved
+ * )
+ * {
+ * ...
+ * }
+ *
+ * If you're using Microsoft Developer Studio 5.0 to define a
+ * function in a Win32 Cryptoki .dll, it might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType __declspec(dllexport) name
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to define a function in a Win16 Cryptoki .dll, it
+ * might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType __export _far _pascal name
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType name
+ *
+ *
+ * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
+ * an importable Cryptoki library function declaration out of a
+ * return type and a function name. It should be used in the
+ * following fashion:
+ *
+ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
+ * CK_VOID_PTR pReserved
+ * );
+ *
+ * If you're using Microsoft Developer Studio 5.0 to declare a
+ * function in a Win32 Cryptoki .dll, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType __declspec(dllimport) name
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to declare a function in a Win16 Cryptoki .dll, it
+ * might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType __export _far _pascal name
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType name
+ *
+ *
+ * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
+ * which makes a Cryptoki API function pointer declaration or
+ * function pointer type declaration out of a return type and a
+ * function name. It should be used in the following fashion:
+ *
+ * // Define funcPtr to be a pointer to a Cryptoki API function
+ * // taking arguments args and returning CK_RV.
+ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
+ *
+ * or
+ *
+ * // Define funcPtrType to be the type of a pointer to a
+ * // Cryptoki API function taking arguments args and returning
+ * // CK_RV, and then define funcPtr to be a variable of type
+ * // funcPtrType.
+ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
+ * funcPtrType funcPtr;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to access
+ * functions in a Win32 Cryptoki .dll, in might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType __declspec(dllimport) (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to access functions in a Win16 Cryptoki .dll, it might
+ * be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType __export _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType (* name)
+ *
+ *
+ * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
+ * a function pointer type for an application callback out of
+ * a return type for the callback and a name for the callback.
+ * It should be used in the following fashion:
+ *
+ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
+ *
+ * to declare a function pointer, myCallback, to a callback
+ * which takes arguments args and returns a CK_RV. It can also
+ * be used like this:
+ *
+ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
+ * myCallbackType myCallback;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to do Win32
+ * Cryptoki development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to do Win16 development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType (* name)
+ *
+ *
+ * 6. NULL_PTR: This macro is the value of a NULL pointer.
+ *
+ * In any ANSI/ISO C environment (and in many others as well),
+ * this should best be defined by
+ *
+ * #ifndef NULL_PTR
+ * #define NULL_PTR 0
+ * #endif
+ */
+
+
+/* All the various Cryptoki types and #define'd values are in the
+ * file pkcs11t.h. */
+#include "pkcs11t.h"
+
+#define __PASTE(x,y) x##y
+
+
+/* ==============================================================
+ * Define the "extern" form of all the entry points.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST 1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ extern CK_DECLARE_FUNCTION(CK_RV, name)
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define the typedef form of all the entry points. That is, for
+ * each Cryptoki function C_XXX, define a type CK_C_XXX which is
+ * a pointer to that kind of function.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST 1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define structed vector of entry points. A CK_FUNCTION_LIST
+ * contains a CK_VERSION indicating a library's Cryptoki version
+ * and then a whole slew of function pointers to the routines in
+ * the library. This type was declared, but not defined, in
+ * pkcs11t.h.
+ * ==============================================================
+ */
+
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ __PASTE(CK_,name) name;
+
+struct CK_FUNCTION_LIST {
+
+ CK_VERSION version; /* Cryptoki version */
+
+/* Pile all the function pointers into the CK_FUNCTION_LIST. */
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+};
+
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+#undef __PASTE
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/pkcs11f.h b/src/Mayaqua/pkcs11f.h
new file mode 100644
index 00000000..30097535
--- /dev/null
+++ b/src/Mayaqua/pkcs11f.h
@@ -0,0 +1,912 @@
+/* pkcs11f.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* This header file contains pretty much everything about all the */
+/* Cryptoki function prototypes. Because this information is */
+/* used for more than just declaring function prototypes, the */
+/* order of the functions appearing herein is important, and */
+/* should not be altered. */
+
+/* General-purpose */
+
+/* C_Initialize initializes the Cryptoki library. */
+CK_PKCS11_FUNCTION_INFO(C_Initialize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
+ * cast to CK_C_INITIALIZE_ARGS_PTR
+ * and dereferenced */
+);
+#endif
+
+
+/* C_Finalize indicates that an application is done with the
+ * Cryptoki library. */
+CK_PKCS11_FUNCTION_INFO(C_Finalize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
+);
+#endif
+
+
+/* C_GetInfo returns general information about Cryptoki. */
+CK_PKCS11_FUNCTION_INFO(C_GetInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_INFO_PTR pInfo /* location that receives information */
+);
+#endif
+
+
+/* C_GetFunctionList returns the function list. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
+ * function list */
+);
+#endif
+
+
+
+/* Slot and token management */
+
+/* C_GetSlotList obtains a list of slots in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_BBOOL tokenPresent, /* only slots with tokens? */
+ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
+ CK_ULONG_PTR pulCount /* receives number of slots */
+);
+#endif
+
+
+/* C_GetSlotInfo obtains information about a particular slot in
+ * the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* the ID of the slot */
+ CK_SLOT_INFO_PTR pInfo /* receives the slot information */
+);
+#endif
+
+
+/* C_GetTokenInfo obtains information about a particular token
+ * in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_TOKEN_INFO_PTR pInfo /* receives the token information */
+);
+#endif
+
+
+/* C_GetMechanismList obtains a list of mechanism types
+ * supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of token's slot */
+ CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
+ CK_ULONG_PTR pulCount /* gets # of mechs. */
+);
+#endif
+
+
+/* C_GetMechanismInfo obtains information about a particular
+ * mechanism possibly supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_MECHANISM_TYPE type, /* type of mechanism */
+ CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
+);
+#endif
+
+
+/* C_InitToken initializes a token. */
+CK_PKCS11_FUNCTION_INFO(C_InitToken)
+#ifdef CK_NEED_ARG_LIST
+/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
+ CK_ULONG ulPinLen, /* length in bytes of the PIN */
+ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
+);
+#endif
+
+
+/* C_InitPIN initializes the normal user's PIN. */
+CK_PKCS11_FUNCTION_INFO(C_InitPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
+ CK_ULONG ulPinLen /* length in bytes of the PIN */
+);
+#endif
+
+
+/* C_SetPIN modifies the PIN of the user who is logged in. */
+CK_PKCS11_FUNCTION_INFO(C_SetPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
+ CK_ULONG ulOldLen, /* length of the old PIN */
+ CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
+ CK_ULONG ulNewLen /* length of the new PIN */
+);
+#endif
+
+
+
+/* Session management */
+
+/* C_OpenSession opens a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_OpenSession)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* the slot's ID */
+ CK_FLAGS flags, /* from CK_SESSION_INFO */
+ CK_VOID_PTR pApplication, /* passed to callback */
+ CK_NOTIFY Notify, /* callback function */
+ CK_SESSION_HANDLE_PTR phSession /* gets session handle */
+);
+#endif
+
+
+/* C_CloseSession closes a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseSession)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+/* C_CloseAllSessions closes all sessions with a token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID /* the token's slot */
+);
+#endif
+
+
+/* C_GetSessionInfo obtains information about the session. */
+CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_SESSION_INFO_PTR pInfo /* receives session info */
+);
+#endif
+
+
+/* C_GetOperationState obtains the state of the cryptographic operation
+ * in a session. */
+CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pOperationState, /* gets state */
+ CK_ULONG_PTR pulOperationStateLen /* gets state length */
+);
+#endif
+
+
+/* C_SetOperationState restores the state of the cryptographic
+ * operation in a session. */
+CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pOperationState, /* holds state */
+ CK_ULONG ulOperationStateLen, /* holds state length */
+ CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
+ CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
+);
+#endif
+
+
+/* C_Login logs a user into a token. */
+CK_PKCS11_FUNCTION_INFO(C_Login)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_USER_TYPE userType, /* the user type */
+ CK_UTF8CHAR_PTR pPin, /* the user's PIN */
+ CK_ULONG ulPinLen /* the length of the PIN */
+);
+#endif
+
+
+/* C_Logout logs a user out from a token. */
+CK_PKCS11_FUNCTION_INFO(C_Logout)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+
+/* Object management */
+
+/* C_CreateObject creates a new object. */
+CK_PKCS11_FUNCTION_INFO(C_CreateObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
+ CK_ULONG ulCount, /* attributes in template */
+ CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
+);
+#endif
+
+
+/* C_CopyObject copies an object, creating a new object for the
+ * copy. */
+CK_PKCS11_FUNCTION_INFO(C_CopyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
+ CK_ULONG ulCount, /* attributes in template */
+ CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
+);
+#endif
+
+
+/* C_DestroyObject destroys an object. */
+CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject /* the object's handle */
+);
+#endif
+
+
+/* C_GetObjectSize gets the size of an object in bytes. */
+CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ULONG_PTR pulSize /* receives size of object */
+);
+#endif
+
+
+/* C_GetAttributeValue obtains the value of one or more object
+ * attributes. */
+CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
+ CK_ULONG ulCount /* attributes in template */
+);
+#endif
+
+
+/* C_SetAttributeValue modifies the value of one or more object
+ * attributes */
+CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
+ CK_ULONG ulCount /* attributes in template */
+);
+#endif
+
+
+/* C_FindObjectsInit initializes a search for token and session
+ * objects that match a template. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
+ CK_ULONG ulCount /* attrs in search template */
+);
+#endif
+
+
+/* C_FindObjects continues a search for token and session
+ * objects that match a template, obtaining additional object
+ * handles. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjects)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
+ CK_ULONG ulMaxObjectCount, /* max handles to get */
+ CK_ULONG_PTR pulObjectCount /* actual # returned */
+);
+#endif
+
+
+/* C_FindObjectsFinal finishes a search for token and session
+ * objects. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+
+/* Encryption and decryption */
+
+/* C_EncryptInit initializes an encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of encryption key */
+);
+#endif
+
+
+/* C_Encrypt encrypts single-part data. */
+CK_PKCS11_FUNCTION_INFO(C_Encrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pData, /* the plaintext data */
+ CK_ULONG ulDataLen, /* bytes of plaintext */
+ CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptUpdate continues a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext data len */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptFinal finishes a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session handle */
+ CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
+ CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
+);
+#endif
+
+
+/* C_DecryptInit initializes a decryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of decryption key */
+);
+#endif
+
+
+/* C_Decrypt decrypts encrypted data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Decrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedData, /* ciphertext */
+ CK_ULONG ulEncryptedDataLen, /* ciphertext length */
+ CK_BYTE_PTR pData, /* gets plaintext */
+ CK_ULONG_PTR pulDataLen /* gets p-text size */
+);
+#endif
+
+
+/* C_DecryptUpdate continues a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* encrypted data */
+ CK_ULONG ulEncryptedPartLen, /* input length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* p-text size */
+);
+#endif
+
+
+/* C_DecryptFinal finishes a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pLastPart, /* gets plaintext */
+ CK_ULONG_PTR pulLastPartLen /* p-text size */
+);
+#endif
+
+
+
+/* Message digesting */
+
+/* C_DigestInit initializes a message-digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
+);
+#endif
+
+
+/* C_Digest digests data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Digest)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* data to be digested */
+ CK_ULONG ulDataLen, /* bytes of data to digest */
+ CK_BYTE_PTR pDigest, /* gets the message digest */
+ CK_ULONG_PTR pulDigestLen /* gets digest length */
+);
+#endif
+
+
+/* C_DigestUpdate continues a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* data to be digested */
+ CK_ULONG ulPartLen /* bytes of data to be digested */
+);
+#endif
+
+
+/* C_DigestKey continues a multi-part message-digesting
+ * operation, by digesting the value of a secret key as part of
+ * the data already digested. */
+CK_PKCS11_FUNCTION_INFO(C_DigestKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hKey /* secret key to digest */
+);
+#endif
+
+
+/* C_DigestFinal finishes a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pDigest, /* gets the message digest */
+ CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
+);
+#endif
+
+
+
+/* Signing and MACing */
+
+/* C_SignInit initializes a signature (private key encryption)
+ * operation, where the signature is (will be) an appendix to
+ * the data, and plaintext cannot be recovered from the
+ *signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of signature key */
+);
+#endif
+
+
+/* C_Sign signs (encrypts with private key) data in a single
+ * part, where the signature is (will be) an appendix to the
+ * data, and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Sign)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* the data to sign */
+ CK_ULONG ulDataLen, /* count of bytes to sign */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+/* C_SignUpdate continues a multiple-part signature operation,
+ * where the signature is (will be) an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* the data to sign */
+ CK_ULONG ulPartLen /* count of bytes to sign */
+);
+#endif
+
+
+/* C_SignFinal finishes a multiple-part signature operation,
+ * returning the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+/* C_SignRecoverInit initializes a signature operation, where
+ * the data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of the signature key */
+);
+#endif
+
+
+/* C_SignRecover signs data in a single operation, where the
+ * data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* the data to sign */
+ CK_ULONG ulDataLen, /* count of bytes to sign */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+
+/* Verifying signatures and MACs */
+
+/* C_VerifyInit initializes a verification operation, where the
+ * signature is an appendix to the data, and plaintext cannot
+ * cannot be recovered from the signature (e.g. DSA). */
+CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
+ CK_OBJECT_HANDLE hKey /* verification key */
+);
+#endif
+
+
+/* C_Verify verifies a signature in a single-part operation,
+ * where the signature is an appendix to the data, and plaintext
+ * cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Verify)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* signed data */
+ CK_ULONG ulDataLen, /* length of signed data */
+ CK_BYTE_PTR pSignature, /* signature */
+ CK_ULONG ulSignatureLen /* signature length*/
+);
+#endif
+
+
+/* C_VerifyUpdate continues a multiple-part verification
+ * operation, where the signature is an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* signed data */
+ CK_ULONG ulPartLen /* length of signed data */
+);
+#endif
+
+
+/* C_VerifyFinal finishes a multiple-part verification
+ * operation, checking the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* signature to verify */
+ CK_ULONG ulSignatureLen /* signature length */
+);
+#endif
+
+
+/* C_VerifyRecoverInit initializes a signature verification
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
+ CK_OBJECT_HANDLE hKey /* verification key */
+);
+#endif
+
+
+/* C_VerifyRecover verifies a signature in a single-part
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* signature to verify */
+ CK_ULONG ulSignatureLen, /* signature length */
+ CK_BYTE_PTR pData, /* gets signed data */
+ CK_ULONG_PTR pulDataLen /* gets signed data len */
+);
+#endif
+
+
+
+/* Dual-function cryptographic operations */
+
+/* C_DigestEncryptUpdate continues a multiple-part digesting
+ * and encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext length */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptDigestUpdate continues a multiple-part decryption and
+ * digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* gets plaintext len */
+);
+#endif
+
+
+/* C_SignEncryptUpdate continues a multiple-part signing and
+ * encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext length */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptVerifyUpdate continues a multiple-part decryption and
+ * verify operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* gets p-text length */
+);
+#endif
+
+
+
+/* Key management */
+
+/* C_GenerateKey generates a secret key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* key generation mech. */
+ CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
+ CK_ULONG ulCount, /* # of attrs in template */
+ CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
+);
+#endif
+
+
+/* C_GenerateKeyPair generates a public-key/private-key pair,
+ * creating new key objects. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session
+ * handle */
+ CK_MECHANISM_PTR pMechanism, /* key-gen
+ * mech. */
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template
+ * for pub.
+ * key */
+ CK_ULONG ulPublicKeyAttributeCount, /* # pub.
+ * attrs. */
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template
+ * for priv.
+ * key */
+ CK_ULONG ulPrivateKeyAttributeCount, /* # priv.
+ * attrs. */
+ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub.
+ * key
+ * handle */
+ CK_OBJECT_HANDLE_PTR phPrivateKey /* gets
+ * priv. key
+ * handle */
+);
+#endif
+
+
+/* C_WrapKey wraps (i.e., encrypts) a key. */
+CK_PKCS11_FUNCTION_INFO(C_WrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
+ CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
+ CK_OBJECT_HANDLE hKey, /* key to be wrapped */
+ CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
+ CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
+);
+#endif
+
+
+/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
+ * key object. */
+CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
+ CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
+ CK_BYTE_PTR pWrappedKey, /* the wrapped key */
+ CK_ULONG ulWrappedKeyLen, /* wrapped key len */
+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
+ CK_ULONG ulAttributeCount, /* template length */
+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
+);
+#endif
+
+
+/* C_DeriveKey derives a key from a base key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
+ CK_OBJECT_HANDLE hBaseKey, /* base key */
+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
+ CK_ULONG ulAttributeCount, /* template length */
+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
+);
+#endif
+
+
+
+/* Random number generation */
+
+/* C_SeedRandom mixes additional seed material into the token's
+ * random number generator. */
+CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSeed, /* the seed material */
+ CK_ULONG ulSeedLen /* length of seed material */
+);
+#endif
+
+
+/* C_GenerateRandom generates random data. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR RandomData, /* receives the random data */
+ CK_ULONG ulRandomLen /* # of bytes to generate */
+);
+#endif
+
+
+
+/* Parallel function management */
+
+/* C_GetFunctionStatus is a legacy function; it obtains an
+ * updated status of a function running in parallel with an
+ * application. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+/* C_CancelFunction is a legacy function; it cancels a function
+ * running in parallel. */
+CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+
+/* Functions added in for Cryptoki Version 2.01 or later */
+
+/* C_WaitForSlotEvent waits for a slot event (token insertion,
+ * removal, etc.) to occur. */
+CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_FLAGS flags, /* blocking/nonblocking flag */
+ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
+ CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
+);
+#endif
diff --git a/src/Mayaqua/pkcs11t.h b/src/Mayaqua/pkcs11t.h
new file mode 100644
index 00000000..7a0f4060
--- /dev/null
+++ b/src/Mayaqua/pkcs11t.h
@@ -0,0 +1,1440 @@
+/* pkcs11t.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* See top of pkcs11.h for information about the macros that
+ * must be defined and the structure-packing conventions that
+ * must be set before including this file. */
+
+#ifndef _PKCS11T_H_
+#define _PKCS11T_H_ 1
+
+#ifndef CK_DISABLE_TRUE_FALSE
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE !(FALSE)
+#endif
+#endif
+
+#define CK_TRUE 1
+#define CK_FALSE 0
+
+/* an unsigned 8-bit value */
+typedef unsigned char CK_BYTE;
+
+/* an unsigned 8-bit character */
+typedef CK_BYTE CK_CHAR;
+
+/* an 8-bit UTF-8 character */
+typedef CK_BYTE CK_UTF8CHAR;
+
+/* a BYTE-sized Boolean flag */
+typedef CK_BYTE CK_BBOOL;
+
+/* an unsigned value, at least 32 bits long */
+typedef unsigned long int CK_ULONG;
+
+/* a signed value, the same size as a CK_ULONG */
+/* CK_LONG is new for v2.0 */
+typedef long int CK_LONG;
+
+/* at least 32 bits; each bit is a Boolean flag */
+typedef CK_ULONG CK_FLAGS;
+
+
+/* some special values for certain CK_ULONG variables */
+#define CK_UNAVAILABLE_INFORMATION (~0UL)
+#define CK_EFFECTIVELY_INFINITE 0
+
+
+typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+typedef CK_CHAR CK_PTR CK_CHAR_PTR;
+typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR;
+typedef CK_ULONG CK_PTR CK_ULONG_PTR;
+typedef void CK_PTR CK_VOID_PTR;
+
+/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
+typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
+
+
+/* The following value is always invalid if used as a session */
+/* handle or object handle */
+#define CK_INVALID_HANDLE 0
+
+
+typedef struct CK_VERSION {
+ CK_BYTE major; /* integer portion of version number */
+ CK_BYTE minor; /* 1/100ths portion of version number */
+} CK_VERSION;
+
+typedef CK_VERSION CK_PTR CK_VERSION_PTR;
+
+
+typedef struct CK_INFO {
+ /* manufacturerID and libraryDecription have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_VERSION cryptokiVersion; /* Cryptoki interface ver */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_FLAGS flags; /* must be zero */
+
+ /* libraryDescription and libraryVersion are new for v2.0 */
+ CK_UTF8CHAR libraryDescription[32]; /* blank padded */
+ CK_VERSION libraryVersion; /* version of library */
+} CK_INFO;
+
+typedef CK_INFO CK_PTR CK_INFO_PTR;
+
+
+/* CK_NOTIFICATION enumerates the types of notifications that
+ * Cryptoki provides to an application */
+/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG CK_NOTIFICATION;
+#define CKN_SURRENDER 0
+
+
+typedef CK_ULONG CK_SLOT_ID;
+
+typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
+
+
+/* CK_SLOT_INFO provides information about a slot */
+typedef struct CK_SLOT_INFO {
+ /* slotDescription and manufacturerID have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_UTF8CHAR slotDescription[64]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_FLAGS flags;
+
+ /* hardwareVersion and firmwareVersion are new for v2.0 */
+ CK_VERSION hardwareVersion; /* version of hardware */
+ CK_VERSION firmwareVersion; /* version of firmware */
+} CK_SLOT_INFO;
+
+/* flags: bit flags that provide capabilities of the slot
+ * Bit Flag Mask Meaning
+ */
+#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */
+#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/
+#define CKF_HW_SLOT 0x00000004 /* hardware slot */
+
+typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
+
+
+/* CK_TOKEN_INFO provides information about a token */
+typedef struct CK_TOKEN_INFO {
+ /* label, manufacturerID, and model have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_UTF8CHAR label[32]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_UTF8CHAR model[16]; /* blank padded */
+ CK_CHAR serialNumber[16]; /* blank padded */
+ CK_FLAGS flags; /* see below */
+
+ /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
+ * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
+ * changed from CK_USHORT to CK_ULONG for v2.0 */
+ CK_ULONG ulMaxSessionCount; /* max open sessions */
+ CK_ULONG ulSessionCount; /* sess. now open */
+ CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */
+ CK_ULONG ulRwSessionCount; /* R/W sess. now open */
+ CK_ULONG ulMaxPinLen; /* in bytes */
+ CK_ULONG ulMinPinLen; /* in bytes */
+ CK_ULONG ulTotalPublicMemory; /* in bytes */
+ CK_ULONG ulFreePublicMemory; /* in bytes */
+ CK_ULONG ulTotalPrivateMemory; /* in bytes */
+ CK_ULONG ulFreePrivateMemory; /* in bytes */
+
+ /* hardwareVersion, firmwareVersion, and time are new for
+ * v2.0 */
+ CK_VERSION hardwareVersion; /* version of hardware */
+ CK_VERSION firmwareVersion; /* version of firmware */
+ CK_CHAR utcTime[16]; /* time */
+} CK_TOKEN_INFO;
+
+/* The flags parameter is defined as follows:
+ * Bit Flag Mask Meaning
+ */
+#define CKF_RNG 0x00000001 /* has random #
+ * generator */
+#define CKF_WRITE_PROTECTED 0x00000002 /* token is
+ * write-
+ * protected */
+#define CKF_LOGIN_REQUIRED 0x00000004 /* user must
+ * login */
+#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's
+ * PIN is set */
+
+/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set,
+ * that means that *every* time the state of cryptographic
+ * operations of a session is successfully saved, all keys
+ * needed to continue those operations are stored in the state */
+#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020
+
+/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means
+ * that the token has some sort of clock. The time on that
+ * clock is returned in the token info structure */
+#define CKF_CLOCK_ON_TOKEN 0x00000040
+
+/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is
+ * set, that means that there is some way for the user to login
+ * without sending a PIN through the Cryptoki library itself */
+#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100
+
+/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true,
+ * that means that a single session with the token can perform
+ * dual simultaneous cryptographic operations (digest and
+ * encrypt; decrypt and digest; sign and encrypt; and decrypt
+ * and sign) */
+#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200
+
+/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
+ * token has been initialized using C_InitializeToken or an
+ * equivalent mechanism outside the scope of PKCS #11.
+ * Calling C_InitializeToken when this flag is set will cause
+ * the token to be reinitialized. */
+#define CKF_TOKEN_INITIALIZED 0x00000400
+
+/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
+ * true, the token supports secondary authentication for
+ * private key objects. */
+#define CKF_SECONDARY_AUTHENTICATION 0x00000800
+
+/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect user login PIN has been entered at least once
+ * since the last successful authentication. */
+#define CKF_USER_PIN_COUNT_LOW 0x00010000
+
+/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect user PIN will it to become locked. */
+#define CKF_USER_PIN_FINAL_TRY 0x00020000
+
+/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
+ * user PIN has been locked. User login to the token is not
+ * possible. */
+#define CKF_USER_PIN_LOCKED 0x00040000
+
+/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the user PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000
+
+/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect SO login PIN has been entered at least once since
+ * the last successful authentication. */
+#define CKF_SO_PIN_COUNT_LOW 0x00100000
+
+/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect SO PIN will it to become locked. */
+#define CKF_SO_PIN_FINAL_TRY 0x00200000
+
+/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
+ * PIN has been locked. SO login to the token is not possible.
+ */
+#define CKF_SO_PIN_LOCKED 0x00400000
+
+/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the SO PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000
+
+typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
+
+
+/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
+ * identifies a session */
+typedef CK_ULONG CK_SESSION_HANDLE;
+
+typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
+
+
+/* CK_USER_TYPE enumerates the types of Cryptoki users */
+/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_USER_TYPE;
+/* Security Officer */
+#define CKU_SO 0
+/* Normal user */
+#define CKU_USER 1
+
+
+/* CK_STATE enumerates the session states */
+/* CK_STATE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_STATE;
+#define CKS_RO_PUBLIC_SESSION 0
+#define CKS_RO_USER_FUNCTIONS 1
+#define CKS_RW_PUBLIC_SESSION 2
+#define CKS_RW_USER_FUNCTIONS 3
+#define CKS_RW_SO_FUNCTIONS 4
+
+
+/* CK_SESSION_INFO provides information about a session */
+typedef struct CK_SESSION_INFO {
+ CK_SLOT_ID slotID;
+ CK_STATE state;
+ CK_FLAGS flags; /* see below */
+
+ /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulDeviceError; /* device-dependent error code */
+} CK_SESSION_INFO;
+
+/* The flags are defined in the following table:
+ * Bit Flag Mask Meaning
+ */
+#define CKF_RW_SESSION 0x00000002 /* session is r/w */
+#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */
+
+typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
+
+
+/* CK_OBJECT_HANDLE is a token-specific identifier for an
+ * object */
+typedef CK_ULONG CK_OBJECT_HANDLE;
+
+typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
+
+
+/* CK_OBJECT_CLASS is a value that identifies the classes (or
+ * types) of objects that Cryptoki recognizes. It is defined
+ * as follows: */
+/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_OBJECT_CLASS;
+
+/* The following classes of objects are defined: */
+/* CKO_HW_FEATURE is new for v2.10 */
+/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
+#define CKO_DATA 0x00000000
+#define CKO_CERTIFICATE 0x00000001
+#define CKO_PUBLIC_KEY 0x00000002
+#define CKO_PRIVATE_KEY 0x00000003
+#define CKO_SECRET_KEY 0x00000004
+#define CKO_HW_FEATURE 0x00000005
+#define CKO_DOMAIN_PARAMETERS 0x00000006
+#define CKO_VENDOR_DEFINED 0x80000000
+
+typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
+
+/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
+ * value that identifies the hardware feature type of an object
+ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
+typedef CK_ULONG CK_HW_FEATURE_TYPE;
+
+/* The following hardware feature types are defined */
+#define CKH_MONOTONIC_COUNTER 0x00000001
+#define CKH_CLOCK 0x00000002
+#define CKH_VENDOR_DEFINED 0x80000000
+
+/* CK_KEY_TYPE is a value that identifies a key type */
+/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG CK_KEY_TYPE;
+
+/* the following key types are defined: */
+#define CKK_RSA 0x00000000
+#define CKK_DSA 0x00000001
+#define CKK_DH 0x00000002
+
+/* CKK_ECDSA and CKK_KEA are new for v2.0 */
+/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
+#define CKK_ECDSA 0x00000003
+#define CKK_EC 0x00000003
+#define CKK_X9_42_DH 0x00000004
+#define CKK_KEA 0x00000005
+
+#define CKK_GENERIC_SECRET 0x00000010
+#define CKK_RC2 0x00000011
+#define CKK_RC4 0x00000012
+#define CKK_DES 0x00000013
+#define CKK_DES2 0x00000014
+#define CKK_DES3 0x00000015
+
+/* all these key types are new for v2.0 */
+#define CKK_CAST 0x00000016
+#define CKK_CAST3 0x00000017
+/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
+#define CKK_CAST5 0x00000018
+#define CKK_CAST128 0x00000018
+#define CKK_RC5 0x00000019
+#define CKK_IDEA 0x0000001A
+#define CKK_SKIPJACK 0x0000001B
+#define CKK_BATON 0x0000001C
+#define CKK_JUNIPER 0x0000001D
+#define CKK_CDMF 0x0000001E
+#define CKK_AES 0x0000001F
+
+#define CKK_VENDOR_DEFINED 0x80000000
+
+
+/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
+ * type */
+/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG CK_CERTIFICATE_TYPE;
+
+/* The following certificate types are defined: */
+/* CKC_X_509_ATTR_CERT is new for v2.10 */
+#define CKC_X_509 0x00000000
+#define CKC_X_509_ATTR_CERT 0x00000001
+#define CKC_VENDOR_DEFINED 0x80000000
+
+
+/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
+ * type */
+/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_ATTRIBUTE_TYPE;
+
+/* The following attribute types are defined: */
+#define CKA_CLASS 0x00000000
+#define CKA_TOKEN 0x00000001
+#define CKA_PRIVATE 0x00000002
+#define CKA_LABEL 0x00000003
+#define CKA_APPLICATION 0x00000010
+#define CKA_VALUE 0x00000011
+
+/* CKA_OBJECT_ID is new for v2.10 */
+#define CKA_OBJECT_ID 0x00000012
+
+#define CKA_CERTIFICATE_TYPE 0x00000080
+#define CKA_ISSUER 0x00000081
+#define CKA_SERIAL_NUMBER 0x00000082
+
+/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
+ * for v2.10 */
+#define CKA_AC_ISSUER 0x00000083
+#define CKA_OWNER 0x00000084
+#define CKA_ATTR_TYPES 0x00000085
+
+/* CKA_TRUSTED is new for v2.11 */
+#define CKA_TRUSTED 0x00000086
+
+#define CKA_KEY_TYPE 0x00000100
+#define CKA_SUBJECT 0x00000101
+#define CKA_ID 0x00000102
+#define CKA_SENSITIVE 0x00000103
+#define CKA_ENCRYPT 0x00000104
+#define CKA_DECRYPT 0x00000105
+#define CKA_WRAP 0x00000106
+#define CKA_UNWRAP 0x00000107
+#define CKA_SIGN 0x00000108
+#define CKA_SIGN_RECOVER 0x00000109
+#define CKA_VERIFY 0x0000010A
+#define CKA_VERIFY_RECOVER 0x0000010B
+#define CKA_DERIVE 0x0000010C
+#define CKA_START_DATE 0x00000110
+#define CKA_END_DATE 0x00000111
+#define CKA_MODULUS 0x00000120
+#define CKA_MODULUS_BITS 0x00000121
+#define CKA_PUBLIC_EXPONENT 0x00000122
+#define CKA_PRIVATE_EXPONENT 0x00000123
+#define CKA_PRIME_1 0x00000124
+#define CKA_PRIME_2 0x00000125
+#define CKA_EXPONENT_1 0x00000126
+#define CKA_EXPONENT_2 0x00000127
+#define CKA_COEFFICIENT 0x00000128
+#define CKA_PRIME 0x00000130
+#define CKA_SUBPRIME 0x00000131
+#define CKA_BASE 0x00000132
+
+/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
+#define CKA_PRIME_BITS 0x00000133
+#define CKA_SUBPRIME_BITS 0x00000134
+#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS
+/* (To retain backwards-compatibility) */
+
+#define CKA_VALUE_BITS 0x00000160
+#define CKA_VALUE_LEN 0x00000161
+
+/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
+ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
+ * and CKA_EC_POINT are new for v2.0 */
+#define CKA_EXTRACTABLE 0x00000162
+#define CKA_LOCAL 0x00000163
+#define CKA_NEVER_EXTRACTABLE 0x00000164
+#define CKA_ALWAYS_SENSITIVE 0x00000165
+
+/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
+#define CKA_KEY_GEN_MECHANISM 0x00000166
+
+#define CKA_MODIFIABLE 0x00000170
+
+/* CKA_ECDSA_PARAMS is deprecated in v2.11,
+ * CKA_EC_PARAMS is preferred. */
+#define CKA_ECDSA_PARAMS 0x00000180
+#define CKA_EC_PARAMS 0x00000180
+
+#define CKA_EC_POINT 0x00000181
+
+/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
+ * CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
+ * are new for v2.10 */
+#define CKA_SECONDARY_AUTH 0x00000200
+#define CKA_AUTH_PIN_FLAGS 0x00000201
+#define CKA_HW_FEATURE_TYPE 0x00000300
+#define CKA_RESET_ON_INIT 0x00000301
+#define CKA_HAS_RESET 0x00000302
+
+#define CKA_VENDOR_DEFINED 0x80000000
+
+
+/* CK_ATTRIBUTE is a structure that includes the type, length
+ * and value of an attribute */
+typedef struct CK_ATTRIBUTE {
+ CK_ATTRIBUTE_TYPE type;
+ CK_VOID_PTR pValue;
+
+ /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
+ CK_ULONG ulValueLen; /* in bytes */
+} CK_ATTRIBUTE;
+
+typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
+
+
+/* CK_DATE is a structure that defines a date */
+typedef struct CK_DATE{
+ CK_CHAR year[4]; /* the year ("1900" - "9999") */
+ CK_CHAR month[2]; /* the month ("01" - "12") */
+ CK_CHAR day[2]; /* the day ("01" - "31") */
+} CK_DATE;
+
+
+/* CK_MECHANISM_TYPE is a value that identifies a mechanism
+ * type */
+/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_MECHANISM_TYPE;
+
+/* the following mechanism types are defined: */
+#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000
+#define CKM_RSA_PKCS 0x00000001
+#define CKM_RSA_9796 0x00000002
+#define CKM_RSA_X_509 0x00000003
+
+/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
+ * are new for v2.0. They are mechanisms which hash and sign */
+#define CKM_MD2_RSA_PKCS 0x00000004
+#define CKM_MD5_RSA_PKCS 0x00000005
+#define CKM_SHA1_RSA_PKCS 0x00000006
+
+/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
+ * CKM_RSA_PKCS_OAEP are new for v2.10 */
+#define CKM_RIPEMD128_RSA_PKCS 0x00000007
+#define CKM_RIPEMD160_RSA_PKCS 0x00000008
+#define CKM_RSA_PKCS_OAEP 0x00000009
+
+/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
+ * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
+#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A
+#define CKM_RSA_X9_31 0x0000000B
+#define CKM_SHA1_RSA_X9_31 0x0000000C
+#define CKM_RSA_PKCS_PSS 0x0000000D
+#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E
+
+#define CKM_DSA_KEY_PAIR_GEN 0x00000010
+#define CKM_DSA 0x00000011
+#define CKM_DSA_SHA1 0x00000012
+#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
+#define CKM_DH_PKCS_DERIVE 0x00000021
+
+/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
+ * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
+ * v2.11 */
+#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030
+#define CKM_X9_42_DH_DERIVE 0x00000031
+#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032
+#define CKM_X9_42_MQV_DERIVE 0x00000033
+
+#define CKM_RC2_KEY_GEN 0x00000100
+#define CKM_RC2_ECB 0x00000101
+#define CKM_RC2_CBC 0x00000102
+#define CKM_RC2_MAC 0x00000103
+
+/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
+#define CKM_RC2_MAC_GENERAL 0x00000104
+#define CKM_RC2_CBC_PAD 0x00000105
+
+#define CKM_RC4_KEY_GEN 0x00000110
+#define CKM_RC4 0x00000111
+#define CKM_DES_KEY_GEN 0x00000120
+#define CKM_DES_ECB 0x00000121
+#define CKM_DES_CBC 0x00000122
+#define CKM_DES_MAC 0x00000123
+
+/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
+#define CKM_DES_MAC_GENERAL 0x00000124
+#define CKM_DES_CBC_PAD 0x00000125
+
+#define CKM_DES2_KEY_GEN 0x00000130
+#define CKM_DES3_KEY_GEN 0x00000131
+#define CKM_DES3_ECB 0x00000132
+#define CKM_DES3_CBC 0x00000133
+#define CKM_DES3_MAC 0x00000134
+
+/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
+ * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
+ * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
+#define CKM_DES3_MAC_GENERAL 0x00000135
+#define CKM_DES3_CBC_PAD 0x00000136
+#define CKM_CDMF_KEY_GEN 0x00000140
+#define CKM_CDMF_ECB 0x00000141
+#define CKM_CDMF_CBC 0x00000142
+#define CKM_CDMF_MAC 0x00000143
+#define CKM_CDMF_MAC_GENERAL 0x00000144
+#define CKM_CDMF_CBC_PAD 0x00000145
+
+#define CKM_MD2 0x00000200
+
+/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD2_HMAC 0x00000201
+#define CKM_MD2_HMAC_GENERAL 0x00000202
+
+#define CKM_MD5 0x00000210
+
+/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD5_HMAC 0x00000211
+#define CKM_MD5_HMAC_GENERAL 0x00000212
+
+#define CKM_SHA_1 0x00000220
+
+/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
+#define CKM_SHA_1_HMAC 0x00000221
+#define CKM_SHA_1_HMAC_GENERAL 0x00000222
+
+/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
+ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
+ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
+#define CKM_RIPEMD128 0x00000230
+#define CKM_RIPEMD128_HMAC 0x00000231
+#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232
+#define CKM_RIPEMD160 0x00000240
+#define CKM_RIPEMD160_HMAC 0x00000241
+#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242
+
+/* All of the following mechanisms are new for v2.0 */
+/* Note that CAST128 and CAST5 are the same algorithm */
+#define CKM_CAST_KEY_GEN 0x00000300
+#define CKM_CAST_ECB 0x00000301
+#define CKM_CAST_CBC 0x00000302
+#define CKM_CAST_MAC 0x00000303
+#define CKM_CAST_MAC_GENERAL 0x00000304
+#define CKM_CAST_CBC_PAD 0x00000305
+#define CKM_CAST3_KEY_GEN 0x00000310
+#define CKM_CAST3_ECB 0x00000311
+#define CKM_CAST3_CBC 0x00000312
+#define CKM_CAST3_MAC 0x00000313
+#define CKM_CAST3_MAC_GENERAL 0x00000314
+#define CKM_CAST3_CBC_PAD 0x00000315
+#define CKM_CAST5_KEY_GEN 0x00000320
+#define CKM_CAST128_KEY_GEN 0x00000320
+#define CKM_CAST5_ECB 0x00000321
+#define CKM_CAST128_ECB 0x00000321
+#define CKM_CAST5_CBC 0x00000322
+#define CKM_CAST128_CBC 0x00000322
+#define CKM_CAST5_MAC 0x00000323
+#define CKM_CAST128_MAC 0x00000323
+#define CKM_CAST5_MAC_GENERAL 0x00000324
+#define CKM_CAST128_MAC_GENERAL 0x00000324
+#define CKM_CAST5_CBC_PAD 0x00000325
+#define CKM_CAST128_CBC_PAD 0x00000325
+#define CKM_RC5_KEY_GEN 0x00000330
+#define CKM_RC5_ECB 0x00000331
+#define CKM_RC5_CBC 0x00000332
+#define CKM_RC5_MAC 0x00000333
+#define CKM_RC5_MAC_GENERAL 0x00000334
+#define CKM_RC5_CBC_PAD 0x00000335
+#define CKM_IDEA_KEY_GEN 0x00000340
+#define CKM_IDEA_ECB 0x00000341
+#define CKM_IDEA_CBC 0x00000342
+#define CKM_IDEA_MAC 0x00000343
+#define CKM_IDEA_MAC_GENERAL 0x00000344
+#define CKM_IDEA_CBC_PAD 0x00000345
+#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350
+#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360
+#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362
+#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363
+#define CKM_XOR_BASE_AND_DATA 0x00000364
+#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365
+#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370
+#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371
+#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372
+
+/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
+ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
+ * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373
+#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374
+#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375
+#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376
+#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377
+
+#define CKM_SSL3_MD5_MAC 0x00000380
+#define CKM_SSL3_SHA1_MAC 0x00000381
+#define CKM_MD5_KEY_DERIVATION 0x00000390
+#define CKM_MD2_KEY_DERIVATION 0x00000391
+#define CKM_SHA1_KEY_DERIVATION 0x00000392
+#define CKM_PBE_MD2_DES_CBC 0x000003A0
+#define CKM_PBE_MD5_DES_CBC 0x000003A1
+#define CKM_PBE_MD5_CAST_CBC 0x000003A2
+#define CKM_PBE_MD5_CAST3_CBC 0x000003A3
+#define CKM_PBE_MD5_CAST5_CBC 0x000003A4
+#define CKM_PBE_MD5_CAST128_CBC 0x000003A4
+#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5
+#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5
+#define CKM_PBE_SHA1_RC4_128 0x000003A6
+#define CKM_PBE_SHA1_RC4_40 0x000003A7
+#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8
+#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9
+#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA
+#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB
+
+/* CKM_PKCS5_PBKD2 is new for v2.10 */
+#define CKM_PKCS5_PBKD2 0x000003B0
+
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0
+#define CKM_KEY_WRAP_LYNKS 0x00000400
+#define CKM_KEY_WRAP_SET_OAEP 0x00000401
+
+/* Fortezza mechanisms */
+#define CKM_SKIPJACK_KEY_GEN 0x00001000
+#define CKM_SKIPJACK_ECB64 0x00001001
+#define CKM_SKIPJACK_CBC64 0x00001002
+#define CKM_SKIPJACK_OFB64 0x00001003
+#define CKM_SKIPJACK_CFB64 0x00001004
+#define CKM_SKIPJACK_CFB32 0x00001005
+#define CKM_SKIPJACK_CFB16 0x00001006
+#define CKM_SKIPJACK_CFB8 0x00001007
+#define CKM_SKIPJACK_WRAP 0x00001008
+#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009
+#define CKM_SKIPJACK_RELAYX 0x0000100a
+#define CKM_KEA_KEY_PAIR_GEN 0x00001010
+#define CKM_KEA_KEY_DERIVE 0x00001011
+#define CKM_FORTEZZA_TIMESTAMP 0x00001020
+#define CKM_BATON_KEY_GEN 0x00001030
+#define CKM_BATON_ECB128 0x00001031
+#define CKM_BATON_ECB96 0x00001032
+#define CKM_BATON_CBC128 0x00001033
+#define CKM_BATON_COUNTER 0x00001034
+#define CKM_BATON_SHUFFLE 0x00001035
+#define CKM_BATON_WRAP 0x00001036
+
+/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
+ * CKM_EC_KEY_PAIR_GEN is preferred */
+#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040
+#define CKM_EC_KEY_PAIR_GEN 0x00001040
+
+#define CKM_ECDSA 0x00001041
+#define CKM_ECDSA_SHA1 0x00001042
+
+/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
+ * are new for v2.11 */
+#define CKM_ECDH1_DERIVE 0x00001050
+#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051
+#define CKM_ECMQV_DERIVE 0x00001052
+
+#define CKM_JUNIPER_KEY_GEN 0x00001060
+#define CKM_JUNIPER_ECB128 0x00001061
+#define CKM_JUNIPER_CBC128 0x00001062
+#define CKM_JUNIPER_COUNTER 0x00001063
+#define CKM_JUNIPER_SHUFFLE 0x00001064
+#define CKM_JUNIPER_WRAP 0x00001065
+#define CKM_FASTHASH 0x00001070
+
+/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
+ * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
+ * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
+ * new for v2.11 */
+#define CKM_AES_KEY_GEN 0x00001080
+#define CKM_AES_ECB 0x00001081
+#define CKM_AES_CBC 0x00001082
+#define CKM_AES_MAC 0x00001083
+#define CKM_AES_MAC_GENERAL 0x00001084
+#define CKM_AES_CBC_PAD 0x00001085
+#define CKM_DSA_PARAMETER_GEN 0x00002000
+#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001
+#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002
+
+#define CKM_VENDOR_DEFINED 0x80000000
+
+typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
+
+
+/* CK_MECHANISM is a structure that specifies a particular
+ * mechanism */
+typedef struct CK_MECHANISM {
+ CK_MECHANISM_TYPE mechanism;
+ CK_VOID_PTR pParameter;
+
+ /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulParameterLen; /* in bytes */
+} CK_MECHANISM;
+
+typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
+
+
+/* CK_MECHANISM_INFO provides information about a particular
+ * mechanism */
+typedef struct CK_MECHANISM_INFO {
+ CK_ULONG ulMinKeySize;
+ CK_ULONG ulMaxKeySize;
+ CK_FLAGS flags;
+} CK_MECHANISM_INFO;
+
+/* The flags are defined as follows:
+ * Bit Flag Mask Meaning */
+#define CKF_HW 0x00000001 /* performed by HW */
+
+/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
+ * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
+ * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
+ * and CKF_DERIVE are new for v2.0. They specify whether or not
+ * a mechanism can be used for a particular task */
+#define CKF_ENCRYPT 0x00000100
+#define CKF_DECRYPT 0x00000200
+#define CKF_DIGEST 0x00000400
+#define CKF_SIGN 0x00000800
+#define CKF_SIGN_RECOVER 0x00001000
+#define CKF_VERIFY 0x00002000
+#define CKF_VERIFY_RECOVER 0x00004000
+#define CKF_GENERATE 0x00008000
+#define CKF_GENERATE_KEY_PAIR 0x00010000
+#define CKF_WRAP 0x00020000
+#define CKF_UNWRAP 0x00040000
+#define CKF_DERIVE 0x00080000
+
+/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
+ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
+ * describe a token's EC capabilities not available in mechanism
+ * information. */
+#define CKF_EC_F_P 0x00100000
+#define CKF_EC_F_2M 0x00200000
+#define CKF_EC_ECPARAMETERS 0x00400000
+#define CKF_EC_NAMEDCURVE 0x00800000
+#define CKF_EC_UNCOMPRESS 0x01000000
+#define CKF_EC_COMPRESS 0x02000000
+
+#define CKF_EXTENSION 0x80000000 /* FALSE for 2.01 */
+
+typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
+
+
+/* CK_RV is a value that identifies the return value of a
+ * Cryptoki function */
+/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG CK_RV;
+
+#define CKR_OK 0x00000000
+#define CKR_CANCEL 0x00000001
+#define CKR_HOST_MEMORY 0x00000002
+#define CKR_SLOT_ID_INVALID 0x00000003
+
+/* CKR_FLAGS_INVALID was removed for v2.0 */
+
+/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
+#define CKR_GENERAL_ERROR 0x00000005
+#define CKR_FUNCTION_FAILED 0x00000006
+
+/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
+ * and CKR_CANT_LOCK are new for v2.01 */
+#define CKR_ARGUMENTS_BAD 0x00000007
+#define CKR_NO_EVENT 0x00000008
+#define CKR_NEED_TO_CREATE_THREADS 0x00000009
+#define CKR_CANT_LOCK 0x0000000A
+
+#define CKR_ATTRIBUTE_READ_ONLY 0x00000010
+#define CKR_ATTRIBUTE_SENSITIVE 0x00000011
+#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012
+#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013
+#define CKR_DATA_INVALID 0x00000020
+#define CKR_DATA_LEN_RANGE 0x00000021
+#define CKR_DEVICE_ERROR 0x00000030
+#define CKR_DEVICE_MEMORY 0x00000031
+#define CKR_DEVICE_REMOVED 0x00000032
+#define CKR_ENCRYPTED_DATA_INVALID 0x00000040
+#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041
+#define CKR_FUNCTION_CANCELED 0x00000050
+#define CKR_FUNCTION_NOT_PARALLEL 0x00000051
+
+/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
+#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054
+
+#define CKR_KEY_HANDLE_INVALID 0x00000060
+
+/* CKR_KEY_SENSITIVE was removed for v2.0 */
+
+#define CKR_KEY_SIZE_RANGE 0x00000062
+#define CKR_KEY_TYPE_INCONSISTENT 0x00000063
+
+/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
+ * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
+ * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
+ * v2.0 */
+#define CKR_KEY_NOT_NEEDED 0x00000064
+#define CKR_KEY_CHANGED 0x00000065
+#define CKR_KEY_NEEDED 0x00000066
+#define CKR_KEY_INDIGESTIBLE 0x00000067
+#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068
+#define CKR_KEY_NOT_WRAPPABLE 0x00000069
+#define CKR_KEY_UNEXTRACTABLE 0x0000006A
+
+#define CKR_MECHANISM_INVALID 0x00000070
+#define CKR_MECHANISM_PARAM_INVALID 0x00000071
+
+/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
+ * were removed for v2.0 */
+#define CKR_OBJECT_HANDLE_INVALID 0x00000082
+#define CKR_OPERATION_ACTIVE 0x00000090
+#define CKR_OPERATION_NOT_INITIALIZED 0x00000091
+#define CKR_PIN_INCORRECT 0x000000A0
+#define CKR_PIN_INVALID 0x000000A1
+#define CKR_PIN_LEN_RANGE 0x000000A2
+
+/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
+#define CKR_PIN_EXPIRED 0x000000A3
+#define CKR_PIN_LOCKED 0x000000A4
+
+#define CKR_SESSION_CLOSED 0x000000B0
+#define CKR_SESSION_COUNT 0x000000B1
+#define CKR_SESSION_HANDLE_INVALID 0x000000B3
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4
+#define CKR_SESSION_READ_ONLY 0x000000B5
+#define CKR_SESSION_EXISTS 0x000000B6
+
+/* CKR_SESSION_READ_ONLY_EXISTS and
+ * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
+#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7
+#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8
+
+#define CKR_SIGNATURE_INVALID 0x000000C0
+#define CKR_SIGNATURE_LEN_RANGE 0x000000C1
+#define CKR_TEMPLATE_INCOMPLETE 0x000000D0
+#define CKR_TEMPLATE_INCONSISTENT 0x000000D1
+#define CKR_TOKEN_NOT_PRESENT 0x000000E0
+#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1
+#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2
+#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2
+#define CKR_USER_ALREADY_LOGGED_IN 0x00000100
+#define CKR_USER_NOT_LOGGED_IN 0x00000101
+#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102
+#define CKR_USER_TYPE_INVALID 0x00000103
+
+/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
+ * are new to v2.01 */
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104
+#define CKR_USER_TOO_MANY_TYPES 0x00000105
+
+#define CKR_WRAPPED_KEY_INVALID 0x00000110
+#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112
+#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113
+#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115
+#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120
+
+/* These are new to v2.0 */
+#define CKR_RANDOM_NO_RNG 0x00000121
+
+/* These are new to v2.11 */
+#define CKR_DOMAIN_PARAMS_INVALID 0x00000130
+
+/* These are new to v2.0 */
+#define CKR_BUFFER_TOO_SMALL 0x00000150
+#define CKR_SAVED_STATE_INVALID 0x00000160
+#define CKR_INFORMATION_SENSITIVE 0x00000170
+#define CKR_STATE_UNSAVEABLE 0x00000180
+
+/* These are new to v2.01 */
+#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191
+#define CKR_MUTEX_BAD 0x000001A0
+#define CKR_MUTEX_NOT_LOCKED 0x000001A1
+
+#define CKR_VENDOR_DEFINED 0x80000000
+
+
+/* CK_NOTIFY is an application callback that processes events */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_NOTIFICATION event,
+ CK_VOID_PTR pApplication /* passed to C_OpenSession */
+);
+
+
+/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
+ * version and pointers of appropriate types to all the
+ * Cryptoki functions */
+/* CK_FUNCTION_LIST is new for v2.0 */
+typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
+
+typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
+
+typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
+
+
+/* CK_CREATEMUTEX is an application callback for creating a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
+ CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */
+);
+
+
+/* CK_DESTROYMUTEX is an application callback for destroying a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_LOCKMUTEX is an application callback for locking a mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_UNLOCKMUTEX is an application callback for unlocking a
+ * mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_C_INITIALIZE_ARGS provides the optional arguments to
+ * C_Initialize */
+typedef struct CK_C_INITIALIZE_ARGS {
+ CK_CREATEMUTEX CreateMutex;
+ CK_DESTROYMUTEX DestroyMutex;
+ CK_LOCKMUTEX LockMutex;
+ CK_UNLOCKMUTEX UnlockMutex;
+ CK_FLAGS flags;
+ CK_VOID_PTR pReserved;
+} CK_C_INITIALIZE_ARGS;
+
+/* flags: bit flags that provide capabilities of the slot
+ * Bit Flag Mask Meaning
+ */
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001
+#define CKF_OS_LOCKING_OK 0x00000002
+
+typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
+
+
+/* additional flags for parameters to functions */
+
+/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
+#define CKF_DONT_BLOCK 1
+
+/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message
+ * Generation Function (MGF) applied to a message block when
+ * formatting a message block for the PKCS #1 OAEP encryption
+ * scheme. */
+typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
+
+typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
+
+/* The following MGFs are defined */
+#define CKG_MGF1_SHA1 0x00000001
+
+/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source
+ * of the encoding parameter when formatting a message block
+ * for the PKCS #1 OAEP encryption scheme. */
+typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
+
+typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
+
+/* The following encoding parameter sources are defined */
+#define CKZ_DATA_SPECIFIED 0x00000001
+
+/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
+ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_OAEP mechanism. */
+typedef struct CK_RSA_PKCS_OAEP_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
+ CK_VOID_PTR pSourceData;
+ CK_ULONG ulSourceDataLen;
+} CK_RSA_PKCS_OAEP_PARAMS;
+
+typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
+
+/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
+ * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_PSS mechanism(s). */
+typedef struct CK_RSA_PKCS_PSS_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_ULONG sLen;
+} CK_RSA_PKCS_PSS_PARAMS;
+
+typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
+
+/* CK_EC_KDF_TYPE is new for v2.11. */
+typedef CK_ULONG CK_EC_KDF_TYPE;
+
+/* The following EC Key Derivation Functions are defined */
+#define CKD_NULL 0x00000001
+#define CKD_SHA1_KDF 0x00000002
+
+/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.
+ * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
+ * where each party contributes one key pair.
+ */
+typedef struct CK_ECDH1_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_ECDH1_DERIVE_PARAMS;
+
+typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
+
+
+/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.
+ * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */
+typedef struct CK_ECDH2_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+} CK_ECDH2_DERIVE_PARAMS;
+
+typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
+
+/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
+ * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */
+typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
+typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
+
+/* The following X9.42 DH key derivation functions are defined: */
+#define CKD_NULL 0x00000001
+#define CKD_SHA1_KDF_ASN1 0x00000003
+#define CKD_SHA1_KDF_CONCATENATE 0x00000004
+
+/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.
+ * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
+ * contributes one key pair */
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_X9_42_DH1_DERIVE_PARAMS;
+
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
+
+/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.
+ * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
+ * mechanisms, where each party contributes two key pairs */
+typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+} CK_X9_42_DH2_DERIVE_PARAMS;
+
+typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
+
+/* CK_KEA_DERIVE_PARAMS provides the parameters to the
+ * CKM_KEA_DERIVE mechanism */
+/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
+typedef struct CK_KEA_DERIVE_PARAMS {
+ CK_BBOOL isSender;
+ CK_ULONG ulRandomLen;
+ CK_BYTE_PTR pRandomA;
+ CK_BYTE_PTR pRandomB;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_KEA_DERIVE_PARAMS;
+
+typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
+
+
+/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
+ * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just
+ * holds the effective keysize */
+typedef CK_ULONG CK_RC2_PARAMS;
+
+typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
+
+
+/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
+ * mechanism */
+typedef struct CK_RC2_CBC_PARAMS {
+ /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
+
+ CK_BYTE iv[8]; /* IV for CBC mode */
+} CK_RC2_CBC_PARAMS;
+
+typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
+
+
+/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC2_MAC_GENERAL mechanism */
+/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC2_MAC_GENERAL_PARAMS {
+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
+ CK_ULONG ulMacLength; /* Length of MAC in bytes */
+} CK_RC2_MAC_GENERAL_PARAMS;
+
+typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
+ CK_RC2_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
+ * CKM_RC5_MAC mechanisms */
+/* CK_RC5_PARAMS is new for v2.0 */
+typedef struct CK_RC5_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+} CK_RC5_PARAMS;
+
+typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
+
+
+/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
+ * mechanism */
+/* CK_RC5_CBC_PARAMS is new for v2.0 */
+typedef struct CK_RC5_CBC_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+ CK_BYTE_PTR pIv; /* pointer to IV */
+ CK_ULONG ulIvLen; /* length of IV in bytes */
+} CK_RC5_CBC_PARAMS;
+
+typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
+
+
+/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC5_MAC_GENERAL mechanism */
+/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC5_MAC_GENERAL_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+ CK_ULONG ulMacLength; /* Length of MAC in bytes */
+} CK_RC5_MAC_GENERAL_PARAMS;
+
+typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
+ CK_RC5_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
+ * ciphers' MAC_GENERAL mechanisms. Its value is the length of
+ * the MAC */
+/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef CK_ULONG CK_MAC_GENERAL_PARAMS;
+
+typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
+ CK_ULONG ulPasswordLen;
+ CK_BYTE_PTR pPassword;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPAndGLen;
+ CK_ULONG ulQLen;
+ CK_ULONG ulRandomLen;
+ CK_BYTE_PTR pRandomA;
+ CK_BYTE_PTR pPrimeP;
+ CK_BYTE_PTR pBaseG;
+ CK_BYTE_PTR pSubprimeQ;
+} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
+
+typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
+ CK_SKIPJACK_PRIVATE_WRAP_PTR;
+
+
+/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_RELAYX mechanism */
+/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_RELAYX_PARAMS {
+ CK_ULONG ulOldWrappedXLen;
+ CK_BYTE_PTR pOldWrappedX;
+ CK_ULONG ulOldPasswordLen;
+ CK_BYTE_PTR pOldPassword;
+ CK_ULONG ulOldPublicDataLen;
+ CK_BYTE_PTR pOldPublicData;
+ CK_ULONG ulOldRandomLen;
+ CK_BYTE_PTR pOldRandomA;
+ CK_ULONG ulNewPasswordLen;
+ CK_BYTE_PTR pNewPassword;
+ CK_ULONG ulNewPublicDataLen;
+ CK_BYTE_PTR pNewPublicData;
+ CK_ULONG ulNewRandomLen;
+ CK_BYTE_PTR pNewRandomA;
+} CK_SKIPJACK_RELAYX_PARAMS;
+
+typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
+ CK_SKIPJACK_RELAYX_PARAMS_PTR;
+
+
+typedef struct CK_PBE_PARAMS {
+ CK_BYTE_PTR pInitVector;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG ulPasswordLen;
+ CK_BYTE_PTR pSalt;
+ CK_ULONG ulSaltLen;
+ CK_ULONG ulIteration;
+} CK_PBE_PARAMS;
+
+typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
+
+
+/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
+ * CKM_KEY_WRAP_SET_OAEP mechanism */
+/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
+typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
+ CK_BYTE bBC; /* block contents byte */
+ CK_BYTE_PTR pX; /* extra data */
+ CK_ULONG ulXLen; /* length of extra data in bytes */
+} CK_KEY_WRAP_SET_OAEP_PARAMS;
+
+typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \
+ CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
+
+
+typedef struct CK_SSL3_RANDOM_DATA {
+ CK_BYTE_PTR pClientRandom;
+ CK_ULONG ulClientRandomLen;
+ CK_BYTE_PTR pServerRandom;
+ CK_ULONG ulServerRandomLen;
+} CK_SSL3_RANDOM_DATA;
+
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_VERSION_PTR pVersion;
+} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
+ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+
+typedef struct CK_SSL3_KEY_MAT_OUT {
+ CK_OBJECT_HANDLE hClientMacSecret;
+ CK_OBJECT_HANDLE hServerMacSecret;
+ CK_OBJECT_HANDLE hClientKey;
+ CK_OBJECT_HANDLE hServerKey;
+ CK_BYTE_PTR pIVClient;
+ CK_BYTE_PTR pIVServer;
+} CK_SSL3_KEY_MAT_OUT;
+
+typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
+
+
+typedef struct CK_SSL3_KEY_MAT_PARAMS {
+ CK_ULONG ulMacSizeInBits;
+ CK_ULONG ulKeySizeInBits;
+ CK_ULONG ulIVSizeInBits;
+ CK_BBOOL bIsExport;
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+} CK_SSL3_KEY_MAT_PARAMS;
+
+typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
+
+
+typedef struct CK_KEY_DERIVATION_STRING_DATA {
+ CK_BYTE_PTR pData;
+ CK_ULONG ulLen;
+} CK_KEY_DERIVATION_STRING_DATA;
+
+typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
+ CK_KEY_DERIVATION_STRING_DATA_PTR;
+
+
+/* The CK_EXTRACT_PARAMS is used for the
+ * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit
+ * of the base key should be used as the first bit of the
+ * derived key */
+/* CK_EXTRACT_PARAMS is new for v2.0 */
+typedef CK_ULONG CK_EXTRACT_PARAMS;
+
+typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
+
+/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
+ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
+ * indicate the Pseudo-Random Function (PRF) used to generate
+ * key bits using PKCS #5 PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
+
+typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
+
+/* The following PRFs are defined in PKCS #5 v2.0. */
+#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
+
+
+/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
+ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
+ * source of the salt value when deriving a key using PKCS #5
+ * PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
+
+typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
+
+/* The following salt value sources are defined in PKCS #5 v2.0. */
+#define CKZ_SALT_SPECIFIED 0x00000001
+
+/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
+ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
+ * parameters to the CKM_PKCS5_PBKD2 mechanism. */
+typedef struct CK_PKCS5_PBKD2_PARAMS {
+ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
+ CK_VOID_PTR pSaltSourceData;
+ CK_ULONG ulSaltSourceDataLen;
+ CK_ULONG iterations;
+ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
+ CK_VOID_PTR pPrfData;
+ CK_ULONG ulPrfDataLen;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG_PTR ulPasswordLen;
+} CK_PKCS5_PBKD2_PARAMS;
+
+typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/aes.h b/src/Mayaqua/win32_inc/openssl/aes.h
new file mode 100644
index 00000000..07ece721
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/aes.h
@@ -0,0 +1,148 @@
+/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#ifndef HEADER_AES_H
+#define HEADER_AES_H
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_AES
+#error AES is disabled.
+#endif
+
+#define AES_ENCRYPT 1
+#define AES_DECRYPT 0
+
+/* Because array size can't be a const in C, the following two are macros.
+ Both sizes are in bytes. */
+#define AES_MAXNR 14
+#define AES_BLOCK_SIZE 16
+
+#ifdef OPENSSL_FIPS
+#define FIPS_AES_SIZE_T int
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This should be a hidden type, but EVP requires that the size be known */
+struct aes_key_st {
+#ifdef AES_LONG
+ unsigned long rd_key[4 *(AES_MAXNR + 1)];
+#else
+ unsigned int rd_key[4 *(AES_MAXNR + 1)];
+#endif
+ int rounds;
+};
+typedef struct aes_key_st AES_KEY;
+
+const char *AES_options(void);
+
+int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+ AES_KEY *key);
+int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+ AES_KEY *key);
+
+void AES_encrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+void AES_decrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+
+void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key, const int enc);
+void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ unsigned char *ivec, const int enc);
+void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ unsigned char *ivec, int *num, const int enc);
+void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ unsigned char *ivec, int *num, const int enc);
+void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ unsigned char *ivec, int *num, const int enc);
+void AES_cfbr_encrypt_block(const unsigned char *in,unsigned char *out,
+ const int nbits,const AES_KEY *key,
+ unsigned char *ivec,const int enc);
+void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ unsigned char *ivec, int *num);
+void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ unsigned char ivec[AES_BLOCK_SIZE],
+ unsigned char ecount_buf[AES_BLOCK_SIZE],
+ unsigned int *num);
+
+/* For IGE, see also http://www.links.org/files/openssl-ige.pdf */
+/* NB: the IV is _two_ blocks long */
+void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ unsigned char *ivec, const int enc);
+/* NB: the IV is _four_ blocks long */
+void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
+ const unsigned long length, const AES_KEY *key,
+ const AES_KEY *key2, const unsigned char *ivec,
+ const int enc);
+
+int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
+ unsigned char *out,
+ const unsigned char *in, unsigned int inlen);
+int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
+ unsigned char *out,
+ const unsigned char *in, unsigned int inlen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !HEADER_AES_H */
diff --git a/src/Mayaqua/win32_inc/openssl/asn1.h b/src/Mayaqua/win32_inc/openssl/asn1.h
new file mode 100644
index 00000000..ba064087
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/asn1.h
@@ -0,0 +1,1332 @@
+/* crypto/asn1/asn1.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_ASN1_H
+#define HEADER_ASN1_H
+
+#include <time.h>
+#include <openssl/e_os2.h>
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#include <openssl/stack.h>
+#include <openssl/safestack.h>
+
+#include <openssl/symhacks.h>
+
+#include <openssl/ossl_typ.h>
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#endif
+
+#ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define V_ASN1_UNIVERSAL 0x00
+#define V_ASN1_APPLICATION 0x40
+#define V_ASN1_CONTEXT_SPECIFIC 0x80
+#define V_ASN1_PRIVATE 0xc0
+
+#define V_ASN1_CONSTRUCTED 0x20
+#define V_ASN1_PRIMITIVE_TAG 0x1f
+#define V_ASN1_PRIMATIVE_TAG 0x1f
+
+#define V_ASN1_APP_CHOOSE -2 /* let the recipient choose */
+#define V_ASN1_OTHER -3 /* used in ASN1_TYPE */
+#define V_ASN1_ANY -4 /* used in ASN1 template code */
+
+#define V_ASN1_NEG 0x100 /* negative flag */
+
+#define V_ASN1_UNDEF -1
+#define V_ASN1_EOC 0
+#define V_ASN1_BOOLEAN 1 /**/
+#define V_ASN1_INTEGER 2
+#define V_ASN1_NEG_INTEGER (2 | V_ASN1_NEG)
+#define V_ASN1_BIT_STRING 3
+#define V_ASN1_OCTET_STRING 4
+#define V_ASN1_NULL 5
+#define V_ASN1_OBJECT 6
+#define V_ASN1_OBJECT_DESCRIPTOR 7
+#define V_ASN1_EXTERNAL 8
+#define V_ASN1_REAL 9
+#define V_ASN1_ENUMERATED 10
+#define V_ASN1_NEG_ENUMERATED (10 | V_ASN1_NEG)
+#define V_ASN1_UTF8STRING 12
+#define V_ASN1_SEQUENCE 16
+#define V_ASN1_SET 17
+#define V_ASN1_NUMERICSTRING 18 /**/
+#define V_ASN1_PRINTABLESTRING 19
+#define V_ASN1_T61STRING 20
+#define V_ASN1_TELETEXSTRING 20 /* alias */
+#define V_ASN1_VIDEOTEXSTRING 21 /**/
+#define V_ASN1_IA5STRING 22
+#define V_ASN1_UTCTIME 23
+#define V_ASN1_GENERALIZEDTIME 24 /**/
+#define V_ASN1_GRAPHICSTRING 25 /**/
+#define V_ASN1_ISO64STRING 26 /**/
+#define V_ASN1_VISIBLESTRING 26 /* alias */
+#define V_ASN1_GENERALSTRING 27 /**/
+#define V_ASN1_UNIVERSALSTRING 28 /**/
+#define V_ASN1_BMPSTRING 30
+
+/* For use with d2i_ASN1_type_bytes() */
+#define B_ASN1_NUMERICSTRING 0x0001
+#define B_ASN1_PRINTABLESTRING 0x0002
+#define B_ASN1_T61STRING 0x0004
+#define B_ASN1_TELETEXSTRING 0x0004
+#define B_ASN1_VIDEOTEXSTRING 0x0008
+#define B_ASN1_IA5STRING 0x0010
+#define B_ASN1_GRAPHICSTRING 0x0020
+#define B_ASN1_ISO64STRING 0x0040
+#define B_ASN1_VISIBLESTRING 0x0040
+#define B_ASN1_GENERALSTRING 0x0080
+#define B_ASN1_UNIVERSALSTRING 0x0100
+#define B_ASN1_OCTET_STRING 0x0200
+#define B_ASN1_BIT_STRING 0x0400
+#define B_ASN1_BMPSTRING 0x0800
+#define B_ASN1_UNKNOWN 0x1000
+#define B_ASN1_UTF8STRING 0x2000
+#define B_ASN1_UTCTIME 0x4000
+#define B_ASN1_GENERALIZEDTIME 0x8000
+#define B_ASN1_SEQUENCE 0x10000
+
+/* For use with ASN1_mbstring_copy() */
+#define MBSTRING_FLAG 0x1000
+#define MBSTRING_UTF8 (MBSTRING_FLAG)
+#define MBSTRING_ASC (MBSTRING_FLAG|1)
+#define MBSTRING_BMP (MBSTRING_FLAG|2)
+#define MBSTRING_UNIV (MBSTRING_FLAG|4)
+
+#define SMIME_OLDMIME 0x400
+#define SMIME_CRLFEOL 0x800
+#define SMIME_STREAM 0x1000
+
+struct X509_algor_st;
+DECLARE_STACK_OF(X509_ALGOR)
+
+#define DECLARE_ASN1_SET_OF(type) /* filled in by mkstack.pl */
+#define IMPLEMENT_ASN1_SET_OF(type) /* nothing, no longer needed */
+
+/* We MUST make sure that, except for constness, asn1_ctx_st and
+ asn1_const_ctx are exactly the same. Fortunately, as soon as
+ the old ASN1 parsing macros are gone, we can throw this away
+ as well... */
+typedef struct asn1_ctx_st
+ {
+ unsigned char *p;/* work char pointer */
+ int eos; /* end of sequence read for indefinite encoding */
+ int error; /* error code to use when returning an error */
+ int inf; /* constructed if 0x20, indefinite is 0x21 */
+ int tag; /* tag from last 'get object' */
+ int xclass; /* class from last 'get object' */
+ long slen; /* length of last 'get object' */
+ unsigned char *max; /* largest value of p allowed */
+ unsigned char *q;/* temporary variable */
+ unsigned char **pp;/* variable */
+ int line; /* used in error processing */
+ } ASN1_CTX;
+
+typedef struct asn1_const_ctx_st
+ {
+ const unsigned char *p;/* work char pointer */
+ int eos; /* end of sequence read for indefinite encoding */
+ int error; /* error code to use when returning an error */
+ int inf; /* constructed if 0x20, indefinite is 0x21 */
+ int tag; /* tag from last 'get object' */
+ int xclass; /* class from last 'get object' */
+ long slen; /* length of last 'get object' */
+ const unsigned char *max; /* largest value of p allowed */
+ const unsigned char *q;/* temporary variable */
+ const unsigned char **pp;/* variable */
+ int line; /* used in error processing */
+ } ASN1_const_CTX;
+
+/* These are used internally in the ASN1_OBJECT to keep track of
+ * whether the names and data need to be free()ed */
+#define ASN1_OBJECT_FLAG_DYNAMIC 0x01 /* internal use */
+#define ASN1_OBJECT_FLAG_CRITICAL 0x02 /* critical x509v3 object id */
+#define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04 /* internal use */
+#define ASN1_OBJECT_FLAG_DYNAMIC_DATA 0x08 /* internal use */
+typedef struct asn1_object_st
+ {
+ const char *sn,*ln;
+ int nid;
+ int length;
+ unsigned char *data;
+ int flags; /* Should we free this one */
+ } ASN1_OBJECT;
+
+#define ASN1_STRING_FLAG_BITS_LEFT 0x08 /* Set if 0x07 has bits left value */
+/* This indicates that the ASN1_STRING is not a real value but just a place
+ * holder for the location where indefinite length constructed data should
+ * be inserted in the memory buffer
+ */
+#define ASN1_STRING_FLAG_NDEF 0x010
+
+/* This flag is used by the CMS code to indicate that a string is not
+ * complete and is a place holder for content when it had all been
+ * accessed. The flag will be reset when content has been written to it.
+ */
+#define ASN1_STRING_FLAG_CONT 0x020
+
+/* This is the base type that holds just about everything :-) */
+typedef struct asn1_string_st
+ {
+ int length;
+ int type;
+ unsigned char *data;
+ /* The value of the following field depends on the type being
+ * held. It is mostly being used for BIT_STRING so if the
+ * input data has a non-zero 'unused bits' value, it will be
+ * handled correctly */
+ long flags;
+ } ASN1_STRING;
+
+/* ASN1_ENCODING structure: this is used to save the received
+ * encoding of an ASN1 type. This is useful to get round
+ * problems with invalid encodings which can break signatures.
+ */
+
+typedef struct ASN1_ENCODING_st
+ {
+ unsigned char *enc; /* DER encoding */
+ long len; /* Length of encoding */
+ int modified; /* set to 1 if 'enc' is invalid */
+ } ASN1_ENCODING;
+
+/* Used with ASN1 LONG type: if a long is set to this it is omitted */
+#define ASN1_LONG_UNDEF 0x7fffffffL
+
+#define STABLE_FLAGS_MALLOC 0x01
+#define STABLE_NO_MASK 0x02
+#define DIRSTRING_TYPE \
+ (B_ASN1_PRINTABLESTRING|B_ASN1_T61STRING|B_ASN1_BMPSTRING|B_ASN1_UTF8STRING)
+#define PKCS9STRING_TYPE (DIRSTRING_TYPE|B_ASN1_IA5STRING)
+
+typedef struct asn1_string_table_st {
+ int nid;
+ long minsize;
+ long maxsize;
+ unsigned long mask;
+ unsigned long flags;
+} ASN1_STRING_TABLE;
+
+DECLARE_STACK_OF(ASN1_STRING_TABLE)
+
+/* size limits: this stuff is taken straight from RFC2459 */
+
+#define ub_name 32768
+#define ub_common_name 64
+#define ub_locality_name 128
+#define ub_state_name 128
+#define ub_organization_name 64
+#define ub_organization_unit_name 64
+#define ub_title 64
+#define ub_email_address 128
+
+/* Declarations for template structures: for full definitions
+ * see asn1t.h
+ */
+typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE;
+typedef struct ASN1_ITEM_st ASN1_ITEM;
+typedef struct ASN1_TLC_st ASN1_TLC;
+/* This is just an opaque pointer */
+typedef struct ASN1_VALUE_st ASN1_VALUE;
+
+/* Declare ASN1 functions: the implement macro in in asn1t.h */
+
+#define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type)
+
+#define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, type)
+
+#define DECLARE_ASN1_FUNCTIONS_name(type, name) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name)
+
+#define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name)
+
+#define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \
+ type *d2i_##name(type **a, const unsigned char **in, long len); \
+ int i2d_##name(type *a, unsigned char **out); \
+ DECLARE_ASN1_ITEM(itname)
+
+#define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \
+ type *d2i_##name(type **a, const unsigned char **in, long len); \
+ int i2d_##name(const type *a, unsigned char **out); \
+ DECLARE_ASN1_ITEM(name)
+
+#define DECLARE_ASN1_NDEF_FUNCTION(name) \
+ int i2d_##name##_NDEF(name *a, unsigned char **out);
+
+#define DECLARE_ASN1_FUNCTIONS_const(name) \
+ DECLARE_ASN1_ALLOC_FUNCTIONS(name) \
+ DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name)
+
+#define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
+ type *name##_new(void); \
+ void name##_free(type *a);
+
+#define D2I_OF(type) type *(*)(type **,const unsigned char **,long)
+#define I2D_OF(type) int (*)(type *,unsigned char **)
+#define I2D_OF_const(type) int (*)(const type *,unsigned char **)
+
+#define CHECKED_D2I_OF(type, d2i) \
+ ((d2i_of_void*) (1 ? d2i : ((D2I_OF(type))0)))
+#define CHECKED_I2D_OF(type, i2d) \
+ ((i2d_of_void*) (1 ? i2d : ((I2D_OF(type))0)))
+#define CHECKED_NEW_OF(type, xnew) \
+ ((void *(*)(void)) (1 ? xnew : ((type *(*)(void))0)))
+#define CHECKED_PTR_OF(type, p) \
+ ((void*) (1 ? p : (type*)0))
+#define CHECKED_PPTR_OF(type, p) \
+ ((void**) (1 ? p : (type**)0))
+#define CHECKED_PTR_OF_TO_CHAR(type, p) \
+ ((char*) (1 ? p : (type*)0))
+
+#define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **,const unsigned char **,long)
+#define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(type *,unsigned char **)
+#define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type)
+
+TYPEDEF_D2I2D_OF(void);
+
+/* The following macros and typedefs allow an ASN1_ITEM
+ * to be embedded in a structure and referenced. Since
+ * the ASN1_ITEM pointers need to be globally accessible
+ * (possibly from shared libraries) they may exist in
+ * different forms. On platforms that support it the
+ * ASN1_ITEM structure itself will be globally exported.
+ * Other platforms will export a function that returns
+ * an ASN1_ITEM pointer.
+ *
+ * To handle both cases transparently the macros below
+ * should be used instead of hard coding an ASN1_ITEM
+ * pointer in a structure.
+ *
+ * The structure will look like this:
+ *
+ * typedef struct SOMETHING_st {
+ * ...
+ * ASN1_ITEM_EXP *iptr;
+ * ...
+ * } SOMETHING;
+ *
+ * It would be initialised as e.g.:
+ *
+ * SOMETHING somevar = {...,ASN1_ITEM_ref(X509),...};
+ *
+ * and the actual pointer extracted with:
+ *
+ * const ASN1_ITEM *it = ASN1_ITEM_ptr(somevar.iptr);
+ *
+ * Finally an ASN1_ITEM pointer can be extracted from an
+ * appropriate reference with: ASN1_ITEM_rptr(X509). This
+ * would be used when a function takes an ASN1_ITEM * argument.
+ *
+ */
+
+#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+/* ASN1_ITEM pointer exported type */
+typedef const ASN1_ITEM ASN1_ITEM_EXP;
+
+/* Macro to obtain ASN1_ITEM pointer from exported type */
+#define ASN1_ITEM_ptr(iptr) (iptr)
+
+/* Macro to include ASN1_ITEM pointer from base type */
+#define ASN1_ITEM_ref(iptr) (&(iptr##_it))
+
+#define ASN1_ITEM_rptr(ref) (&(ref##_it))
+
+#define DECLARE_ASN1_ITEM(name) \
+ OPENSSL_EXTERN const ASN1_ITEM name##_it;
+
+#else
+
+/* Platforms that can't easily handle shared global variables are declared
+ * as functions returning ASN1_ITEM pointers.
+ */
+
+/* ASN1_ITEM pointer exported type */
+typedef const ASN1_ITEM * ASN1_ITEM_EXP(void);
+
+/* Macro to obtain ASN1_ITEM pointer from exported type */
+#define ASN1_ITEM_ptr(iptr) (iptr())
+
+/* Macro to include ASN1_ITEM pointer from base type */
+#define ASN1_ITEM_ref(iptr) (iptr##_it)
+
+#define ASN1_ITEM_rptr(ref) (ref##_it())
+
+#define DECLARE_ASN1_ITEM(name) \
+ const ASN1_ITEM * name##_it(void);
+
+#endif
+
+/* Parameters used by ASN1_STRING_print_ex() */
+
+/* These determine which characters to escape:
+ * RFC2253 special characters, control characters and
+ * MSB set characters
+ */
+
+#define ASN1_STRFLGS_ESC_2253 1
+#define ASN1_STRFLGS_ESC_CTRL 2
+#define ASN1_STRFLGS_ESC_MSB 4
+
+
+/* This flag determines how we do escaping: normally
+ * RC2253 backslash only, set this to use backslash and
+ * quote.
+ */
+
+#define ASN1_STRFLGS_ESC_QUOTE 8
+
+
+/* These three flags are internal use only. */
+
+/* Character is a valid PrintableString character */
+#define CHARTYPE_PRINTABLESTRING 0x10
+/* Character needs escaping if it is the first character */
+#define CHARTYPE_FIRST_ESC_2253 0x20
+/* Character needs escaping if it is the last character */
+#define CHARTYPE_LAST_ESC_2253 0x40
+
+/* NB the internal flags are safely reused below by flags
+ * handled at the top level.
+ */
+
+/* If this is set we convert all character strings
+ * to UTF8 first
+ */
+
+#define ASN1_STRFLGS_UTF8_CONVERT 0x10
+
+/* If this is set we don't attempt to interpret content:
+ * just assume all strings are 1 byte per character. This
+ * will produce some pretty odd looking output!
+ */
+
+#define ASN1_STRFLGS_IGNORE_TYPE 0x20
+
+/* If this is set we include the string type in the output */
+#define ASN1_STRFLGS_SHOW_TYPE 0x40
+
+/* This determines which strings to display and which to
+ * 'dump' (hex dump of content octets or DER encoding). We can
+ * only dump non character strings or everything. If we
+ * don't dump 'unknown' they are interpreted as character
+ * strings with 1 octet per character and are subject to
+ * the usual escaping options.
+ */
+
+#define ASN1_STRFLGS_DUMP_ALL 0x80
+#define ASN1_STRFLGS_DUMP_UNKNOWN 0x100
+
+/* These determine what 'dumping' does, we can dump the
+ * content octets or the DER encoding: both use the
+ * RFC2253 #XXXXX notation.
+ */
+
+#define ASN1_STRFLGS_DUMP_DER 0x200
+
+/* All the string flags consistent with RFC2253,
+ * escaping control characters isn't essential in
+ * RFC2253 but it is advisable anyway.
+ */
+
+#define ASN1_STRFLGS_RFC2253 (ASN1_STRFLGS_ESC_2253 | \
+ ASN1_STRFLGS_ESC_CTRL | \
+ ASN1_STRFLGS_ESC_MSB | \
+ ASN1_STRFLGS_UTF8_CONVERT | \
+ ASN1_STRFLGS_DUMP_UNKNOWN | \
+ ASN1_STRFLGS_DUMP_DER)
+
+DECLARE_STACK_OF(ASN1_INTEGER)
+DECLARE_ASN1_SET_OF(ASN1_INTEGER)
+
+DECLARE_STACK_OF(ASN1_GENERALSTRING)
+
+typedef struct asn1_type_st
+ {
+ int type;
+ union {
+ char *ptr;
+ ASN1_BOOLEAN boolean;
+ ASN1_STRING * asn1_string;
+ ASN1_OBJECT * object;
+ ASN1_INTEGER * integer;
+ ASN1_ENUMERATED * enumerated;
+ ASN1_BIT_STRING * bit_string;
+ ASN1_OCTET_STRING * octet_string;
+ ASN1_PRINTABLESTRING * printablestring;
+ ASN1_T61STRING * t61string;
+ ASN1_IA5STRING * ia5string;
+ ASN1_GENERALSTRING * generalstring;
+ ASN1_BMPSTRING * bmpstring;
+ ASN1_UNIVERSALSTRING * universalstring;
+ ASN1_UTCTIME * utctime;
+ ASN1_GENERALIZEDTIME * generalizedtime;
+ ASN1_VISIBLESTRING * visiblestring;
+ ASN1_UTF8STRING * utf8string;
+ /* set and sequence are left complete and still
+ * contain the set or sequence bytes */
+ ASN1_STRING * set;
+ ASN1_STRING * sequence;
+ ASN1_VALUE * asn1_value;
+ } value;
+ } ASN1_TYPE;
+
+DECLARE_STACK_OF(ASN1_TYPE)
+DECLARE_ASN1_SET_OF(ASN1_TYPE)
+
+typedef struct asn1_method_st
+ {
+ i2d_of_void *i2d;
+ d2i_of_void *d2i;
+ void *(*create)(void);
+ void (*destroy)(void *);
+ } ASN1_METHOD;
+
+/* This is used when parsing some Netscape objects */
+typedef struct asn1_header_st
+ {
+ ASN1_OCTET_STRING *header;
+ void *data;
+ ASN1_METHOD *meth;
+ } ASN1_HEADER;
+
+/* This is used to contain a list of bit names */
+typedef struct BIT_STRING_BITNAME_st {
+ int bitnum;
+ const char *lname;
+ const char *sname;
+} BIT_STRING_BITNAME;
+
+
+#define M_ASN1_STRING_length(x) ((x)->length)
+#define M_ASN1_STRING_length_set(x, n) ((x)->length = (n))
+#define M_ASN1_STRING_type(x) ((x)->type)
+#define M_ASN1_STRING_data(x) ((x)->data)
+
+/* Macros for string operations */
+#define M_ASN1_BIT_STRING_new() (ASN1_BIT_STRING *)\
+ ASN1_STRING_type_new(V_ASN1_BIT_STRING)
+#define M_ASN1_BIT_STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_BIT_STRING_dup(a) (ASN1_BIT_STRING *)\
+ ASN1_STRING_dup((ASN1_STRING *)a)
+#define M_ASN1_BIT_STRING_cmp(a,b) ASN1_STRING_cmp(\
+ (ASN1_STRING *)a,(ASN1_STRING *)b)
+#define M_ASN1_BIT_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c)
+
+#define M_ASN1_INTEGER_new() (ASN1_INTEGER *)\
+ ASN1_STRING_type_new(V_ASN1_INTEGER)
+#define M_ASN1_INTEGER_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_INTEGER_dup(a) (ASN1_INTEGER *)ASN1_STRING_dup((ASN1_STRING *)a)
+#define M_ASN1_INTEGER_cmp(a,b) ASN1_STRING_cmp(\
+ (ASN1_STRING *)a,(ASN1_STRING *)b)
+
+#define M_ASN1_ENUMERATED_new() (ASN1_ENUMERATED *)\
+ ASN1_STRING_type_new(V_ASN1_ENUMERATED)
+#define M_ASN1_ENUMERATED_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_ENUMERATED_dup(a) (ASN1_ENUMERATED *)ASN1_STRING_dup((ASN1_STRING *)a)
+#define M_ASN1_ENUMERATED_cmp(a,b) ASN1_STRING_cmp(\
+ (ASN1_STRING *)a,(ASN1_STRING *)b)
+
+#define M_ASN1_OCTET_STRING_new() (ASN1_OCTET_STRING *)\
+ ASN1_STRING_type_new(V_ASN1_OCTET_STRING)
+#define M_ASN1_OCTET_STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_OCTET_STRING_dup(a) (ASN1_OCTET_STRING *)\
+ ASN1_STRING_dup((ASN1_STRING *)a)
+#define M_ASN1_OCTET_STRING_cmp(a,b) ASN1_STRING_cmp(\
+ (ASN1_STRING *)a,(ASN1_STRING *)b)
+#define M_ASN1_OCTET_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c)
+#define M_ASN1_OCTET_STRING_print(a,b) ASN1_STRING_print(a,(ASN1_STRING *)b)
+#define M_i2d_ASN1_OCTET_STRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_OCTET_STRING,\
+ V_ASN1_UNIVERSAL)
+
+#define B_ASN1_TIME \
+ B_ASN1_UTCTIME | \
+ B_ASN1_GENERALIZEDTIME
+
+#define B_ASN1_PRINTABLE \
+ B_ASN1_NUMERICSTRING| \
+ B_ASN1_PRINTABLESTRING| \
+ B_ASN1_T61STRING| \
+ B_ASN1_IA5STRING| \
+ B_ASN1_BIT_STRING| \
+ B_ASN1_UNIVERSALSTRING|\
+ B_ASN1_BMPSTRING|\
+ B_ASN1_UTF8STRING|\
+ B_ASN1_SEQUENCE|\
+ B_ASN1_UNKNOWN
+
+#define B_ASN1_DIRECTORYSTRING \
+ B_ASN1_PRINTABLESTRING| \
+ B_ASN1_TELETEXSTRING|\
+ B_ASN1_BMPSTRING|\
+ B_ASN1_UNIVERSALSTRING|\
+ B_ASN1_UTF8STRING
+
+#define B_ASN1_DISPLAYTEXT \
+ B_ASN1_IA5STRING| \
+ B_ASN1_VISIBLESTRING| \
+ B_ASN1_BMPSTRING|\
+ B_ASN1_UTF8STRING
+
+#define M_ASN1_PRINTABLE_new() ASN1_STRING_type_new(V_ASN1_T61STRING)
+#define M_ASN1_PRINTABLE_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_PRINTABLE(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
+ pp,a->type,V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_PRINTABLE(a,pp,l) \
+ d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
+ B_ASN1_PRINTABLE)
+
+#define M_DIRECTORYSTRING_new() ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING)
+#define M_DIRECTORYSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_DIRECTORYSTRING(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
+ pp,a->type,V_ASN1_UNIVERSAL)
+#define M_d2i_DIRECTORYSTRING(a,pp,l) \
+ d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
+ B_ASN1_DIRECTORYSTRING)
+
+#define M_DISPLAYTEXT_new() ASN1_STRING_type_new(V_ASN1_VISIBLESTRING)
+#define M_DISPLAYTEXT_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_DISPLAYTEXT(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
+ pp,a->type,V_ASN1_UNIVERSAL)
+#define M_d2i_DISPLAYTEXT(a,pp,l) \
+ d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
+ B_ASN1_DISPLAYTEXT)
+
+#define M_ASN1_PRINTABLESTRING_new() (ASN1_PRINTABLESTRING *)\
+ ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING)
+#define M_ASN1_PRINTABLESTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_PRINTABLESTRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_PRINTABLESTRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_PRINTABLESTRING(a,pp,l) \
+ (ASN1_PRINTABLESTRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_PRINTABLESTRING)
+
+#define M_ASN1_T61STRING_new() (ASN1_T61STRING *)\
+ ASN1_STRING_type_new(V_ASN1_T61STRING)
+#define M_ASN1_T61STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_T61STRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_T61STRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_T61STRING(a,pp,l) \
+ (ASN1_T61STRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_T61STRING)
+
+#define M_ASN1_IA5STRING_new() (ASN1_IA5STRING *)\
+ ASN1_STRING_type_new(V_ASN1_IA5STRING)
+#define M_ASN1_IA5STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_IA5STRING_dup(a) \
+ (ASN1_IA5STRING *)ASN1_STRING_dup((ASN1_STRING *)a)
+#define M_i2d_ASN1_IA5STRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_IA5STRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_IA5STRING(a,pp,l) \
+ (ASN1_IA5STRING *)d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l,\
+ B_ASN1_IA5STRING)
+
+#define M_ASN1_UTCTIME_new() (ASN1_UTCTIME *)\
+ ASN1_STRING_type_new(V_ASN1_UTCTIME)
+#define M_ASN1_UTCTIME_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_UTCTIME_dup(a) (ASN1_UTCTIME *)ASN1_STRING_dup((ASN1_STRING *)a)
+
+#define M_ASN1_GENERALIZEDTIME_new() (ASN1_GENERALIZEDTIME *)\
+ ASN1_STRING_type_new(V_ASN1_GENERALIZEDTIME)
+#define M_ASN1_GENERALIZEDTIME_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_GENERALIZEDTIME_dup(a) (ASN1_GENERALIZEDTIME *)ASN1_STRING_dup(\
+ (ASN1_STRING *)a)
+
+#define M_ASN1_TIME_new() (ASN1_TIME *)\
+ ASN1_STRING_type_new(V_ASN1_UTCTIME)
+#define M_ASN1_TIME_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_ASN1_TIME_dup(a) (ASN1_TIME *)ASN1_STRING_dup((ASN1_STRING *)a)
+
+#define M_ASN1_GENERALSTRING_new() (ASN1_GENERALSTRING *)\
+ ASN1_STRING_type_new(V_ASN1_GENERALSTRING)
+#define M_ASN1_GENERALSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_GENERALSTRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_GENERALSTRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_GENERALSTRING(a,pp,l) \
+ (ASN1_GENERALSTRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_GENERALSTRING)
+
+#define M_ASN1_UNIVERSALSTRING_new() (ASN1_UNIVERSALSTRING *)\
+ ASN1_STRING_type_new(V_ASN1_UNIVERSALSTRING)
+#define M_ASN1_UNIVERSALSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_UNIVERSALSTRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UNIVERSALSTRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_UNIVERSALSTRING(a,pp,l) \
+ (ASN1_UNIVERSALSTRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_UNIVERSALSTRING)
+
+#define M_ASN1_BMPSTRING_new() (ASN1_BMPSTRING *)\
+ ASN1_STRING_type_new(V_ASN1_BMPSTRING)
+#define M_ASN1_BMPSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_BMPSTRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_BMPSTRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_BMPSTRING(a,pp,l) \
+ (ASN1_BMPSTRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_BMPSTRING)
+
+#define M_ASN1_VISIBLESTRING_new() (ASN1_VISIBLESTRING *)\
+ ASN1_STRING_type_new(V_ASN1_VISIBLESTRING)
+#define M_ASN1_VISIBLESTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_VISIBLESTRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_VISIBLESTRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_VISIBLESTRING(a,pp,l) \
+ (ASN1_VISIBLESTRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_VISIBLESTRING)
+
+#define M_ASN1_UTF8STRING_new() (ASN1_UTF8STRING *)\
+ ASN1_STRING_type_new(V_ASN1_UTF8STRING)
+#define M_ASN1_UTF8STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a)
+#define M_i2d_ASN1_UTF8STRING(a,pp) \
+ i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UTF8STRING,\
+ V_ASN1_UNIVERSAL)
+#define M_d2i_ASN1_UTF8STRING(a,pp,l) \
+ (ASN1_UTF8STRING *)d2i_ASN1_type_bytes\
+ ((ASN1_STRING **)a,pp,l,B_ASN1_UTF8STRING)
+
+ /* for the is_set parameter to i2d_ASN1_SET */
+#define IS_SEQUENCE 0
+#define IS_SET 1
+
+DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
+
+int ASN1_TYPE_get(ASN1_TYPE *a);
+void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value);
+int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value);
+
+ASN1_OBJECT * ASN1_OBJECT_new(void );
+void ASN1_OBJECT_free(ASN1_OBJECT *a);
+int i2d_ASN1_OBJECT(ASN1_OBJECT *a,unsigned char **pp);
+ASN1_OBJECT * c2i_ASN1_OBJECT(ASN1_OBJECT **a,const unsigned char **pp,
+ long length);
+ASN1_OBJECT * d2i_ASN1_OBJECT(ASN1_OBJECT **a,const unsigned char **pp,
+ long length);
+
+DECLARE_ASN1_ITEM(ASN1_OBJECT)
+
+DECLARE_STACK_OF(ASN1_OBJECT)
+DECLARE_ASN1_SET_OF(ASN1_OBJECT)
+
+ASN1_STRING * ASN1_STRING_new(void);
+void ASN1_STRING_free(ASN1_STRING *a);
+ASN1_STRING * ASN1_STRING_dup(ASN1_STRING *a);
+ASN1_STRING * ASN1_STRING_type_new(int type );
+int ASN1_STRING_cmp(ASN1_STRING *a, ASN1_STRING *b);
+ /* Since this is used to store all sorts of things, via macros, for now, make
+ its data void * */
+int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);
+void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len);
+int ASN1_STRING_length(ASN1_STRING *x);
+void ASN1_STRING_length_set(ASN1_STRING *x, int n);
+int ASN1_STRING_type(ASN1_STRING *x);
+unsigned char * ASN1_STRING_data(ASN1_STRING *x);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING)
+int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a,unsigned char **pp);
+ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,const unsigned char **pp,
+ long length);
+int ASN1_BIT_STRING_set(ASN1_BIT_STRING *a, unsigned char *d,
+ int length );
+int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value);
+int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n);
+
+#ifndef OPENSSL_NO_BIO
+int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
+ BIT_STRING_BITNAME *tbl, int indent);
+#endif
+int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl);
+int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value,
+ BIT_STRING_BITNAME *tbl);
+
+int i2d_ASN1_BOOLEAN(int a,unsigned char **pp);
+int d2i_ASN1_BOOLEAN(int *a,const unsigned char **pp,long length);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER)
+int i2c_ASN1_INTEGER(ASN1_INTEGER *a,unsigned char **pp);
+ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a,const unsigned char **pp,
+ long length);
+ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a,const unsigned char **pp,
+ long length);
+ASN1_INTEGER * ASN1_INTEGER_dup(ASN1_INTEGER *x);
+int ASN1_INTEGER_cmp(ASN1_INTEGER *x, ASN1_INTEGER *y);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED)
+
+int ASN1_UTCTIME_check(ASN1_UTCTIME *a);
+ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s,time_t t);
+int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str);
+int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t);
+#if 0
+time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s);
+#endif
+
+int ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *a);
+ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,time_t t);
+int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING)
+ASN1_OCTET_STRING * ASN1_OCTET_STRING_dup(ASN1_OCTET_STRING *a);
+int ASN1_OCTET_STRING_cmp(ASN1_OCTET_STRING *a, ASN1_OCTET_STRING *b);
+int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, const unsigned char *data, int len);
+
+DECLARE_ASN1_FUNCTIONS(ASN1_VISIBLESTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_NULL)
+DECLARE_ASN1_FUNCTIONS(ASN1_BMPSTRING)
+
+int UTF8_getc(const unsigned char *str, int len, unsigned long *val);
+int UTF8_putc(unsigned char *str, int len, unsigned long value);
+
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE)
+
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING)
+DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT)
+DECLARE_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_T61STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_IA5STRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_GENERALSTRING)
+DECLARE_ASN1_FUNCTIONS(ASN1_UTCTIME)
+DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME)
+DECLARE_ASN1_FUNCTIONS(ASN1_TIME)
+
+DECLARE_ASN1_ITEM(ASN1_OCTET_STRING_NDEF)
+
+ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s,time_t t);
+int ASN1_TIME_check(ASN1_TIME *t);
+ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out);
+
+int i2d_ASN1_SET(STACK *a, unsigned char **pp,
+ i2d_of_void *i2d, int ex_tag, int ex_class, int is_set);
+STACK * d2i_ASN1_SET(STACK **a, const unsigned char **pp, long length,
+ d2i_of_void *d2i, void (*free_func)(void *),
+ int ex_tag, int ex_class);
+
+#ifndef OPENSSL_NO_BIO
+int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a);
+int a2i_ASN1_INTEGER(BIO *bp,ASN1_INTEGER *bs,char *buf,int size);
+int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a);
+int a2i_ASN1_ENUMERATED(BIO *bp,ASN1_ENUMERATED *bs,char *buf,int size);
+int i2a_ASN1_OBJECT(BIO *bp,ASN1_OBJECT *a);
+int a2i_ASN1_STRING(BIO *bp,ASN1_STRING *bs,char *buf,int size);
+int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type);
+#endif
+int i2t_ASN1_OBJECT(char *buf,int buf_len,ASN1_OBJECT *a);
+
+int a2d_ASN1_OBJECT(unsigned char *out,int olen, const char *buf, int num);
+ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data,int len,
+ const char *sn, const char *ln);
+
+int ASN1_INTEGER_set(ASN1_INTEGER *a, long v);
+long ASN1_INTEGER_get(ASN1_INTEGER *a);
+ASN1_INTEGER *BN_to_ASN1_INTEGER(BIGNUM *bn, ASN1_INTEGER *ai);
+BIGNUM *ASN1_INTEGER_to_BN(ASN1_INTEGER *ai,BIGNUM *bn);
+
+int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v);
+long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a);
+ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai);
+BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai,BIGNUM *bn);
+
+/* General */
+/* given a string, return the correct type, max is the maximum length */
+int ASN1_PRINTABLE_type(const unsigned char *s, int max);
+
+int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass);
+ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
+ long length, int Ptag, int Pclass);
+unsigned long ASN1_tag2bit(int tag);
+/* type is one or more of the B_ASN1_ values. */
+ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a,const unsigned char **pp,
+ long length,int type);
+
+/* PARSING */
+int asn1_Finish(ASN1_CTX *c);
+int asn1_const_Finish(ASN1_const_CTX *c);
+
+/* SPECIALS */
+int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
+ int *pclass, long omax);
+int ASN1_check_infinite_end(unsigned char **p,long len);
+int ASN1_const_check_infinite_end(const unsigned char **p,long len);
+void ASN1_put_object(unsigned char **pp, int constructed, int length,
+ int tag, int xclass);
+int ASN1_put_eoc(unsigned char **pp);
+int ASN1_object_size(int constructed, int length, int tag);
+
+/* Used to implement other functions */
+void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x);
+
+#define ASN1_dup_of(type,i2d,d2i,x) \
+ ((type*)ASN1_dup(CHECKED_I2D_OF(type, i2d), \
+ CHECKED_D2I_OF(type, d2i), \
+ CHECKED_PTR_OF_TO_CHAR(type, x)))
+
+#define ASN1_dup_of_const(type,i2d,d2i,x) \
+ ((type*)ASN1_dup(CHECKED_I2D_OF(const type, i2d), \
+ CHECKED_D2I_OF(type, d2i), \
+ CHECKED_PTR_OF_TO_CHAR(const type, x)))
+
+void *ASN1_item_dup(const ASN1_ITEM *it, void *x);
+
+/* ASN1 alloc/free macros for when a type is only used internally */
+
+#define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type))
+#define M_ASN1_free_of(x, type) \
+ ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type))
+
+#ifndef OPENSSL_NO_FP_API
+void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x);
+
+#define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \
+ ((type*)ASN1_d2i_fp(CHECKED_NEW_OF(type, xnew), \
+ CHECKED_D2I_OF(type, d2i), \
+ in, \
+ CHECKED_PPTR_OF(type, x)))
+
+void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
+int ASN1_i2d_fp(i2d_of_void *i2d,FILE *out,void *x);
+
+#define ASN1_i2d_fp_of(type,i2d,out,x) \
+ (ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \
+ out, \
+ CHECKED_PTR_OF(type, x)))
+
+#define ASN1_i2d_fp_of_const(type,i2d,out,x) \
+ (ASN1_i2d_fp(CHECKED_I2D_OF(const type, i2d), \
+ out, \
+ CHECKED_PTR_OF(const type, x)))
+
+int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x);
+int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags);
+#endif
+
+int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in);
+
+#ifndef OPENSSL_NO_BIO
+void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x);
+
+#define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \
+ ((type*)ASN1_d2i_bio( CHECKED_NEW_OF(type, xnew), \
+ CHECKED_D2I_OF(type, d2i), \
+ in, \
+ CHECKED_PPTR_OF(type, x)))
+
+void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x);
+int ASN1_i2d_bio(i2d_of_void *i2d,BIO *out, unsigned char *x);
+
+#define ASN1_i2d_bio_of(type,i2d,out,x) \
+ (ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \
+ out, \
+ CHECKED_PTR_OF(type, x)))
+
+#define ASN1_i2d_bio_of_const(type,i2d,out,x) \
+ (ASN1_i2d_bio(CHECKED_I2D_OF(const type, i2d), \
+ out, \
+ CHECKED_PTR_OF(const type, x)))
+
+int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x);
+int ASN1_UTCTIME_print(BIO *fp,ASN1_UTCTIME *a);
+int ASN1_GENERALIZEDTIME_print(BIO *fp,ASN1_GENERALIZEDTIME *a);
+int ASN1_TIME_print(BIO *fp,ASN1_TIME *a);
+int ASN1_STRING_print(BIO *bp,ASN1_STRING *v);
+int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags);
+int ASN1_parse(BIO *bp,const unsigned char *pp,long len,int indent);
+int ASN1_parse_dump(BIO *bp,const unsigned char *pp,long len,int indent,int dump);
+#endif
+const char *ASN1_tag2str(int tag);
+
+/* Used to load and write netscape format cert/key */
+int i2d_ASN1_HEADER(ASN1_HEADER *a,unsigned char **pp);
+ASN1_HEADER *d2i_ASN1_HEADER(ASN1_HEADER **a,const unsigned char **pp, long length);
+ASN1_HEADER *ASN1_HEADER_new(void );
+void ASN1_HEADER_free(ASN1_HEADER *a);
+
+int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s);
+
+/* Not used that much at this point, except for the first two */
+ASN1_METHOD *X509_asn1_meth(void);
+ASN1_METHOD *RSAPrivateKey_asn1_meth(void);
+ASN1_METHOD *ASN1_IA5STRING_asn1_meth(void);
+ASN1_METHOD *ASN1_BIT_STRING_asn1_meth(void);
+
+int ASN1_TYPE_set_octetstring(ASN1_TYPE *a,
+ unsigned char *data, int len);
+int ASN1_TYPE_get_octetstring(ASN1_TYPE *a,
+ unsigned char *data, int max_len);
+int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num,
+ unsigned char *data, int len);
+int ASN1_TYPE_get_int_octetstring(ASN1_TYPE *a,long *num,
+ unsigned char *data, int max_len);
+
+STACK *ASN1_seq_unpack(const unsigned char *buf, int len,
+ d2i_of_void *d2i, void (*free_func)(void *));
+unsigned char *ASN1_seq_pack(STACK *safes, i2d_of_void *i2d,
+ unsigned char **buf, int *len );
+void *ASN1_unpack_string(ASN1_STRING *oct, d2i_of_void *d2i);
+void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it);
+ASN1_STRING *ASN1_pack_string(void *obj, i2d_of_void *i2d,
+ ASN1_OCTET_STRING **oct);
+
+#define ASN1_pack_string_of(type,obj,i2d,oct) \
+ (ASN1_pack_string(CHECKED_PTR_OF(type, obj), \
+ CHECKED_I2D_OF(type, i2d), \
+ oct))
+
+ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct);
+
+void ASN1_STRING_set_default_mask(unsigned long mask);
+int ASN1_STRING_set_default_mask_asc(const char *p);
+unsigned long ASN1_STRING_get_default_mask(void);
+int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
+ int inform, unsigned long mask);
+int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
+ int inform, unsigned long mask,
+ long minsize, long maxsize);
+
+ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
+ const unsigned char *in, int inlen, int inform, int nid);
+ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid);
+int ASN1_STRING_TABLE_add(int, long, long, unsigned long, unsigned long);
+void ASN1_STRING_TABLE_cleanup(void);
+
+/* ASN1 template functions */
+
+/* Old API compatible functions */
+ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it);
+void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it);
+ASN1_VALUE * ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_ITEM *it);
+int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
+int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
+
+void ASN1_add_oid_module(void);
+
+ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf);
+ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf);
+
+typedef int asn1_output_data_fn(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
+ const ASN1_ITEM *it);
+
+int int_smime_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+ int ctype_nid, int econt_nid,
+ STACK_OF(X509_ALGOR) *mdalgs,
+ asn1_output_data_fn *data_fn,
+ const ASN1_ITEM *it);
+ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ASN1_strings(void);
+
+/* Error codes for the ASN1 functions. */
+
+/* Function codes. */
+#define ASN1_F_A2D_ASN1_OBJECT 100
+#define ASN1_F_A2I_ASN1_ENUMERATED 101
+#define ASN1_F_A2I_ASN1_INTEGER 102
+#define ASN1_F_A2I_ASN1_STRING 103
+#define ASN1_F_APPEND_EXP 176
+#define ASN1_F_ASN1_BIT_STRING_SET_BIT 183
+#define ASN1_F_ASN1_CB 177
+#define ASN1_F_ASN1_CHECK_TLEN 104
+#define ASN1_F_ASN1_COLLATE_PRIMITIVE 105
+#define ASN1_F_ASN1_COLLECT 106
+#define ASN1_F_ASN1_D2I_EX_PRIMITIVE 108
+#define ASN1_F_ASN1_D2I_FP 109
+#define ASN1_F_ASN1_D2I_READ_BIO 107
+#define ASN1_F_ASN1_DIGEST 184
+#define ASN1_F_ASN1_DO_ADB 110
+#define ASN1_F_ASN1_DUP 111
+#define ASN1_F_ASN1_ENUMERATED_SET 112
+#define ASN1_F_ASN1_ENUMERATED_TO_BN 113
+#define ASN1_F_ASN1_EX_C2I 204
+#define ASN1_F_ASN1_FIND_END 190
+#define ASN1_F_ASN1_GENERALIZEDTIME_SET 185
+#define ASN1_F_ASN1_GENERATE_V3 178
+#define ASN1_F_ASN1_GET_OBJECT 114
+#define ASN1_F_ASN1_HEADER_NEW 115
+#define ASN1_F_ASN1_I2D_BIO 116
+#define ASN1_F_ASN1_I2D_FP 117
+#define ASN1_F_ASN1_INTEGER_SET 118
+#define ASN1_F_ASN1_INTEGER_TO_BN 119
+#define ASN1_F_ASN1_ITEM_D2I_FP 206
+#define ASN1_F_ASN1_ITEM_DUP 191
+#define ASN1_F_ASN1_ITEM_EX_COMBINE_NEW 121
+#define ASN1_F_ASN1_ITEM_EX_D2I 120
+#define ASN1_F_ASN1_ITEM_I2D_BIO 192
+#define ASN1_F_ASN1_ITEM_I2D_FP 193
+#define ASN1_F_ASN1_ITEM_PACK 198
+#define ASN1_F_ASN1_ITEM_SIGN 195
+#define ASN1_F_ASN1_ITEM_UNPACK 199
+#define ASN1_F_ASN1_ITEM_VERIFY 197
+#define ASN1_F_ASN1_MBSTRING_NCOPY 122
+#define ASN1_F_ASN1_OBJECT_NEW 123
+#define ASN1_F_ASN1_OUTPUT_DATA 207
+#define ASN1_F_ASN1_PACK_STRING 124
+#define ASN1_F_ASN1_PCTX_NEW 205
+#define ASN1_F_ASN1_PKCS5_PBE_SET 125
+#define ASN1_F_ASN1_SEQ_PACK 126
+#define ASN1_F_ASN1_SEQ_UNPACK 127
+#define ASN1_F_ASN1_SIGN 128
+#define ASN1_F_ASN1_STR2TYPE 179
+#define ASN1_F_ASN1_STRING_SET 186
+#define ASN1_F_ASN1_STRING_TABLE_ADD 129
+#define ASN1_F_ASN1_STRING_TYPE_NEW 130
+#define ASN1_F_ASN1_TEMPLATE_EX_D2I 132
+#define ASN1_F_ASN1_TEMPLATE_NEW 133
+#define ASN1_F_ASN1_TEMPLATE_NOEXP_D2I 131
+#define ASN1_F_ASN1_TIME_SET 175
+#define ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING 134
+#define ASN1_F_ASN1_TYPE_GET_OCTETSTRING 135
+#define ASN1_F_ASN1_UNPACK_STRING 136
+#define ASN1_F_ASN1_UTCTIME_SET 187
+#define ASN1_F_ASN1_VERIFY 137
+#define ASN1_F_B64_READ_ASN1 208
+#define ASN1_F_B64_WRITE_ASN1 209
+#define ASN1_F_BITSTR_CB 180
+#define ASN1_F_BN_TO_ASN1_ENUMERATED 138
+#define ASN1_F_BN_TO_ASN1_INTEGER 139
+#define ASN1_F_C2I_ASN1_BIT_STRING 189
+#define ASN1_F_C2I_ASN1_INTEGER 194
+#define ASN1_F_C2I_ASN1_OBJECT 196
+#define ASN1_F_COLLECT_DATA 140
+#define ASN1_F_D2I_ASN1_BIT_STRING 141
+#define ASN1_F_D2I_ASN1_BOOLEAN 142
+#define ASN1_F_D2I_ASN1_BYTES 143
+#define ASN1_F_D2I_ASN1_GENERALIZEDTIME 144
+#define ASN1_F_D2I_ASN1_HEADER 145
+#define ASN1_F_D2I_ASN1_INTEGER 146
+#define ASN1_F_D2I_ASN1_OBJECT 147
+#define ASN1_F_D2I_ASN1_SET 148
+#define ASN1_F_D2I_ASN1_TYPE_BYTES 149
+#define ASN1_F_D2I_ASN1_UINTEGER 150
+#define ASN1_F_D2I_ASN1_UTCTIME 151
+#define ASN1_F_D2I_NETSCAPE_RSA 152
+#define ASN1_F_D2I_NETSCAPE_RSA_2 153
+#define ASN1_F_D2I_PRIVATEKEY 154
+#define ASN1_F_D2I_PUBLICKEY 155
+#define ASN1_F_D2I_RSA_NET 200
+#define ASN1_F_D2I_RSA_NET_2 201
+#define ASN1_F_D2I_X509 156
+#define ASN1_F_D2I_X509_CINF 157
+#define ASN1_F_D2I_X509_PKEY 159
+#define ASN1_F_I2D_ASN1_SET 188
+#define ASN1_F_I2D_ASN1_TIME 160
+#define ASN1_F_I2D_DSA_PUBKEY 161
+#define ASN1_F_I2D_EC_PUBKEY 181
+#define ASN1_F_I2D_PRIVATEKEY 163
+#define ASN1_F_I2D_PUBLICKEY 164
+#define ASN1_F_I2D_RSA_NET 162
+#define ASN1_F_I2D_RSA_PUBKEY 165
+#define ASN1_F_LONG_C2I 166
+#define ASN1_F_OID_MODULE_INIT 174
+#define ASN1_F_PARSE_TAGGING 182
+#define ASN1_F_PKCS5_PBE2_SET 167
+#define ASN1_F_PKCS5_PBE_SET 202
+#define ASN1_F_SMIME_READ_ASN1 210
+#define ASN1_F_SMIME_TEXT 211
+#define ASN1_F_X509_CINF_NEW 168
+#define ASN1_F_X509_CRL_ADD0_REVOKED 169
+#define ASN1_F_X509_INFO_NEW 170
+#define ASN1_F_X509_NAME_ENCODE 203
+#define ASN1_F_X509_NAME_EX_D2I 158
+#define ASN1_F_X509_NAME_EX_NEW 171
+#define ASN1_F_X509_NEW 172
+#define ASN1_F_X509_PKEY_NEW 173
+
+/* Reason codes. */
+#define ASN1_R_ADDING_OBJECT 171
+#define ASN1_R_ASN1_PARSE_ERROR 198
+#define ASN1_R_ASN1_SIG_PARSE_ERROR 199
+#define ASN1_R_AUX_ERROR 100
+#define ASN1_R_BAD_CLASS 101
+#define ASN1_R_BAD_OBJECT_HEADER 102
+#define ASN1_R_BAD_PASSWORD_READ 103
+#define ASN1_R_BAD_TAG 104
+#define ASN1_R_BMPSTRING_IS_WRONG_LENGTH 210
+#define ASN1_R_BN_LIB 105
+#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106
+#define ASN1_R_BUFFER_TOO_SMALL 107
+#define ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 108
+#define ASN1_R_DATA_IS_WRONG 109
+#define ASN1_R_DECODE_ERROR 110
+#define ASN1_R_DECODING_ERROR 111
+#define ASN1_R_DEPTH_EXCEEDED 174
+#define ASN1_R_ENCODE_ERROR 112
+#define ASN1_R_ERROR_GETTING_TIME 173
+#define ASN1_R_ERROR_LOADING_SECTION 172
+#define ASN1_R_ERROR_PARSING_SET_ELEMENT 113
+#define ASN1_R_ERROR_SETTING_CIPHER_PARAMS 114
+#define ASN1_R_EXPECTING_AN_INTEGER 115
+#define ASN1_R_EXPECTING_AN_OBJECT 116
+#define ASN1_R_EXPECTING_A_BOOLEAN 117
+#define ASN1_R_EXPECTING_A_TIME 118
+#define ASN1_R_EXPLICIT_LENGTH_MISMATCH 119
+#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 120
+#define ASN1_R_FIELD_MISSING 121
+#define ASN1_R_FIRST_NUM_TOO_LARGE 122
+#define ASN1_R_HEADER_TOO_LONG 123
+#define ASN1_R_ILLEGAL_BITSTRING_FORMAT 175
+#define ASN1_R_ILLEGAL_BOOLEAN 176
+#define ASN1_R_ILLEGAL_CHARACTERS 124
+#define ASN1_R_ILLEGAL_FORMAT 177
+#define ASN1_R_ILLEGAL_HEX 178
+#define ASN1_R_ILLEGAL_IMPLICIT_TAG 179
+#define ASN1_R_ILLEGAL_INTEGER 180
+#define ASN1_R_ILLEGAL_NESTED_TAGGING 181
+#define ASN1_R_ILLEGAL_NULL 125
+#define ASN1_R_ILLEGAL_NULL_VALUE 182
+#define ASN1_R_ILLEGAL_OBJECT 183
+#define ASN1_R_ILLEGAL_OPTIONAL_ANY 126
+#define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 170
+#define ASN1_R_ILLEGAL_TAGGED_ANY 127
+#define ASN1_R_ILLEGAL_TIME_VALUE 184
+#define ASN1_R_INTEGER_NOT_ASCII_FORMAT 185
+#define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 128
+#define ASN1_R_INVALID_BMPSTRING_LENGTH 129
+#define ASN1_R_INVALID_DIGIT 130
+#define ASN1_R_INVALID_MIME_TYPE 200
+#define ASN1_R_INVALID_MODIFIER 186
+#define ASN1_R_INVALID_NUMBER 187
+#define ASN1_R_INVALID_OBJECT_ENCODING 212
+#define ASN1_R_INVALID_SEPARATOR 131
+#define ASN1_R_INVALID_TIME_FORMAT 132
+#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 133
+#define ASN1_R_INVALID_UTF8STRING 134
+#define ASN1_R_IV_TOO_LARGE 135
+#define ASN1_R_LENGTH_ERROR 136
+#define ASN1_R_LIST_ERROR 188
+#define ASN1_R_MIME_NO_CONTENT_TYPE 201
+#define ASN1_R_MIME_PARSE_ERROR 202
+#define ASN1_R_MIME_SIG_PARSE_ERROR 203
+#define ASN1_R_MISSING_EOC 137
+#define ASN1_R_MISSING_SECOND_NUMBER 138
+#define ASN1_R_MISSING_VALUE 189
+#define ASN1_R_MSTRING_NOT_UNIVERSAL 139
+#define ASN1_R_MSTRING_WRONG_TAG 140
+#define ASN1_R_NESTED_ASN1_STRING 197
+#define ASN1_R_NON_HEX_CHARACTERS 141
+#define ASN1_R_NOT_ASCII_FORMAT 190
+#define ASN1_R_NOT_ENOUGH_DATA 142
+#define ASN1_R_NO_CONTENT_TYPE 204
+#define ASN1_R_NO_MATCHING_CHOICE_TYPE 143
+#define ASN1_R_NO_MULTIPART_BODY_FAILURE 205
+#define ASN1_R_NO_MULTIPART_BOUNDARY 206
+#define ASN1_R_NO_SIG_CONTENT_TYPE 207
+#define ASN1_R_NULL_IS_WRONG_LENGTH 144
+#define ASN1_R_OBJECT_NOT_ASCII_FORMAT 191
+#define ASN1_R_ODD_NUMBER_OF_CHARS 145
+#define ASN1_R_PRIVATE_KEY_HEADER_MISSING 146
+#define ASN1_R_SECOND_NUMBER_TOO_LARGE 147
+#define ASN1_R_SEQUENCE_LENGTH_MISMATCH 148
+#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 149
+#define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 192
+#define ASN1_R_SHORT_LINE 150
+#define ASN1_R_SIG_INVALID_MIME_TYPE 208
+#define ASN1_R_STREAMING_NOT_SUPPORTED 209
+#define ASN1_R_STRING_TOO_LONG 151
+#define ASN1_R_STRING_TOO_SHORT 152
+#define ASN1_R_TAG_VALUE_TOO_HIGH 153
+#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 154
+#define ASN1_R_TIME_NOT_ASCII_FORMAT 193
+#define ASN1_R_TOO_LONG 155
+#define ASN1_R_TYPE_NOT_CONSTRUCTED 156
+#define ASN1_R_UNABLE_TO_DECODE_RSA_KEY 157
+#define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY 158
+#define ASN1_R_UNEXPECTED_EOC 159
+#define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 211
+#define ASN1_R_UNKNOWN_FORMAT 160
+#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 161
+#define ASN1_R_UNKNOWN_OBJECT_TYPE 162
+#define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE 163
+#define ASN1_R_UNKNOWN_TAG 194
+#define ASN1_R_UNKOWN_FORMAT 195
+#define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 164
+#define ASN1_R_UNSUPPORTED_CIPHER 165
+#define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM 166
+#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 167
+#define ASN1_R_UNSUPPORTED_TYPE 196
+#define ASN1_R_WRONG_TAG 168
+#define ASN1_R_WRONG_TYPE 169
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/asn1_mac.h b/src/Mayaqua/win32_inc/openssl/asn1_mac.h
new file mode 100644
index 00000000..1ac54cf1
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/asn1_mac.h
@@ -0,0 +1,571 @@
+/* crypto/asn1/asn1_mac.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_ASN1_MAC_H
+#define HEADER_ASN1_MAC_H
+
+#include <openssl/asn1.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef ASN1_MAC_ERR_LIB
+#define ASN1_MAC_ERR_LIB ERR_LIB_ASN1
+#endif
+
+#define ASN1_MAC_H_err(f,r,line) \
+ ERR_PUT_error(ASN1_MAC_ERR_LIB,(f),(r),__FILE__,(line))
+
+#define M_ASN1_D2I_vars(a,type,func) \
+ ASN1_const_CTX c; \
+ type ret=NULL; \
+ \
+ c.pp=(const unsigned char **)pp; \
+ c.q= *(const unsigned char **)pp; \
+ c.error=ERR_R_NESTED_ASN1_ERROR; \
+ if ((a == NULL) || ((*a) == NULL)) \
+ { if ((ret=(type)func()) == NULL) \
+ { c.line=__LINE__; goto err; } } \
+ else ret=(*a);
+
+#define M_ASN1_D2I_Init() \
+ c.p= *(const unsigned char **)pp; \
+ c.max=(length == 0)?0:(c.p+length);
+
+#define M_ASN1_D2I_Finish_2(a) \
+ if (!asn1_const_Finish(&c)) \
+ { c.line=__LINE__; goto err; } \
+ *(const unsigned char **)pp=c.p; \
+ if (a != NULL) (*a)=ret; \
+ return(ret);
+
+#define M_ASN1_D2I_Finish(a,func,e) \
+ M_ASN1_D2I_Finish_2(a); \
+err:\
+ ASN1_MAC_H_err((e),c.error,c.line); \
+ asn1_add_error(*(const unsigned char **)pp,(int)(c.q- *pp)); \
+ if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \
+ return(NULL)
+
+#define M_ASN1_D2I_start_sequence() \
+ if (!asn1_GetSequence(&c,&length)) \
+ { c.line=__LINE__; goto err; }
+/* Begin reading ASN1 without a surrounding sequence */
+#define M_ASN1_D2I_begin() \
+ c.slen = length;
+
+/* End reading ASN1 with no check on length */
+#define M_ASN1_D2I_Finish_nolen(a, func, e) \
+ *pp=c.p; \
+ if (a != NULL) (*a)=ret; \
+ return(ret); \
+err:\
+ ASN1_MAC_H_err((e),c.error,c.line); \
+ asn1_add_error(*pp,(int)(c.q- *pp)); \
+ if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \
+ return(NULL)
+
+#define M_ASN1_D2I_end_sequence() \
+ (((c.inf&1) == 0)?(c.slen <= 0): \
+ (c.eos=ASN1_const_check_infinite_end(&c.p,c.slen)))
+
+/* Don't use this with d2i_ASN1_BOOLEAN() */
+#define M_ASN1_D2I_get(b, func) \
+ c.q=c.p; \
+ if (func(&(b),&c.p,c.slen) == NULL) \
+ {c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+/* Don't use this with d2i_ASN1_BOOLEAN() */
+#define M_ASN1_D2I_get_x(type,b,func) \
+ c.q=c.p; \
+ if (((D2I_OF(type))func)(&(b),&c.p,c.slen) == NULL) \
+ {c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+/* use this instead () */
+#define M_ASN1_D2I_get_int(b,func) \
+ c.q=c.p; \
+ if (func(&(b),&c.p,c.slen) < 0) \
+ {c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_opt(b,func,type) \
+ if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) \
+ == (V_ASN1_UNIVERSAL|(type)))) \
+ { \
+ M_ASN1_D2I_get(b,func); \
+ }
+
+#define M_ASN1_D2I_get_imp(b,func, type) \
+ M_ASN1_next=(_tmp& V_ASN1_CONSTRUCTED)|type; \
+ c.q=c.p; \
+ if (func(&(b),&c.p,c.slen) == NULL) \
+ {c.line=__LINE__; M_ASN1_next_prev = _tmp; goto err; } \
+ c.slen-=(c.p-c.q);\
+ M_ASN1_next_prev=_tmp;
+
+#define M_ASN1_D2I_get_IMP_opt(b,func,tag,type) \
+ if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) == \
+ (V_ASN1_CONTEXT_SPECIFIC|(tag)))) \
+ { \
+ unsigned char _tmp = M_ASN1_next; \
+ M_ASN1_D2I_get_imp(b,func, type);\
+ }
+
+#define M_ASN1_D2I_get_set(r,func,free_func) \
+ M_ASN1_D2I_get_imp_set(r,func,free_func, \
+ V_ASN1_SET,V_ASN1_UNIVERSAL);
+
+#define M_ASN1_D2I_get_set_type(type,r,func,free_func) \
+ M_ASN1_D2I_get_imp_set_type(type,r,func,free_func, \
+ V_ASN1_SET,V_ASN1_UNIVERSAL);
+
+#define M_ASN1_D2I_get_set_opt(r,func,free_func) \
+ if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+ V_ASN1_CONSTRUCTED|V_ASN1_SET)))\
+ { M_ASN1_D2I_get_set(r,func,free_func); }
+
+#define M_ASN1_D2I_get_set_opt_type(type,r,func,free_func) \
+ if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+ V_ASN1_CONSTRUCTED|V_ASN1_SET)))\
+ { M_ASN1_D2I_get_set_type(type,r,func,free_func); }
+
+#define M_ASN1_I2D_len_SET_opt(a,f) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ M_ASN1_I2D_len_SET(a,f);
+
+#define M_ASN1_I2D_put_SET_opt(a,f) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ M_ASN1_I2D_put_SET(a,f);
+
+#define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ M_ASN1_I2D_put_SEQUENCE(a,f);
+
+#define M_ASN1_I2D_put_SEQUENCE_opt_type(type,a,f) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ M_ASN1_I2D_put_SEQUENCE_type(type,a,f);
+
+#define M_ASN1_D2I_get_IMP_set_opt(b,func,free_func,tag) \
+ if ((c.slen != 0) && \
+ (M_ASN1_next == \
+ (V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\
+ { \
+ M_ASN1_D2I_get_imp_set(b,func,free_func,\
+ tag,V_ASN1_CONTEXT_SPECIFIC); \
+ }
+
+#define M_ASN1_D2I_get_IMP_set_opt_type(type,b,func,free_func,tag) \
+ if ((c.slen != 0) && \
+ (M_ASN1_next == \
+ (V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\
+ { \
+ M_ASN1_D2I_get_imp_set_type(type,b,func,free_func,\
+ tag,V_ASN1_CONTEXT_SPECIFIC); \
+ }
+
+#define M_ASN1_D2I_get_seq(r,func,free_func) \
+ M_ASN1_D2I_get_imp_set(r,func,free_func,\
+ V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
+
+#define M_ASN1_D2I_get_seq_type(type,r,func,free_func) \
+ M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\
+ V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL)
+
+#define M_ASN1_D2I_get_seq_opt(r,func,free_func) \
+ if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+ V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\
+ { M_ASN1_D2I_get_seq(r,func,free_func); }
+
+#define M_ASN1_D2I_get_seq_opt_type(type,r,func,free_func) \
+ if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+ V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\
+ { M_ASN1_D2I_get_seq_type(type,r,func,free_func); }
+
+#define M_ASN1_D2I_get_IMP_set(r,func,free_func,x) \
+ M_ASN1_D2I_get_imp_set(r,func,free_func,\
+ x,V_ASN1_CONTEXT_SPECIFIC);
+
+#define M_ASN1_D2I_get_IMP_set_type(type,r,func,free_func,x) \
+ M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\
+ x,V_ASN1_CONTEXT_SPECIFIC);
+
+#define M_ASN1_D2I_get_imp_set(r,func,free_func,a,b) \
+ c.q=c.p; \
+ if (d2i_ASN1_SET(&(r),&c.p,c.slen,(char *(*)())func,\
+ (void (*)())free_func,a,b) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,a,b) \
+ c.q=c.p; \
+ if (d2i_ASN1_SET_OF_##type(&(r),&c.p,c.slen,func,\
+ free_func,a,b) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_set_strings(r,func,a,b) \
+ c.q=c.p; \
+ if (d2i_ASN1_STRING_SET(&(r),&c.p,c.slen,a,b) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_EXP_opt(r,func,tag) \
+ if ((c.slen != 0L) && (M_ASN1_next == \
+ (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+ { \
+ int Tinf,Ttag,Tclass; \
+ long Tlen; \
+ \
+ c.q=c.p; \
+ Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+ if (Tinf & 0x80) \
+ { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+ c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+ Tlen = c.slen - (c.p - c.q) - 2; \
+ if (func(&(r),&c.p,Tlen) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+ Tlen = c.slen - (c.p - c.q); \
+ if(!ASN1_const_check_infinite_end(&c.p, Tlen)) \
+ { c.error=ERR_R_MISSING_ASN1_EOS; \
+ c.line=__LINE__; goto err; } \
+ }\
+ c.slen-=(c.p-c.q); \
+ }
+
+#define M_ASN1_D2I_get_EXP_set_opt(r,func,free_func,tag,b) \
+ if ((c.slen != 0) && (M_ASN1_next == \
+ (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+ { \
+ int Tinf,Ttag,Tclass; \
+ long Tlen; \
+ \
+ c.q=c.p; \
+ Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+ if (Tinf & 0x80) \
+ { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+ c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+ Tlen = c.slen - (c.p - c.q) - 2; \
+ if (d2i_ASN1_SET(&(r),&c.p,Tlen,(char *(*)())func, \
+ (void (*)())free_func, \
+ b,V_ASN1_UNIVERSAL) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+ Tlen = c.slen - (c.p - c.q); \
+ if(!ASN1_check_infinite_end(&c.p, Tlen)) \
+ { c.error=ERR_R_MISSING_ASN1_EOS; \
+ c.line=__LINE__; goto err; } \
+ }\
+ c.slen-=(c.p-c.q); \
+ }
+
+#define M_ASN1_D2I_get_EXP_set_opt_type(type,r,func,free_func,tag,b) \
+ if ((c.slen != 0) && (M_ASN1_next == \
+ (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+ { \
+ int Tinf,Ttag,Tclass; \
+ long Tlen; \
+ \
+ c.q=c.p; \
+ Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+ if (Tinf & 0x80) \
+ { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+ c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+ Tlen = c.slen - (c.p - c.q) - 2; \
+ if (d2i_ASN1_SET_OF_##type(&(r),&c.p,Tlen,func, \
+ free_func,b,V_ASN1_UNIVERSAL) == NULL) \
+ { c.line=__LINE__; goto err; } \
+ if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+ Tlen = c.slen - (c.p - c.q); \
+ if(!ASN1_check_infinite_end(&c.p, Tlen)) \
+ { c.error=ERR_R_MISSING_ASN1_EOS; \
+ c.line=__LINE__; goto err; } \
+ }\
+ c.slen-=(c.p-c.q); \
+ }
+
+/* New macros */
+#define M_ASN1_New_Malloc(ret,type) \
+ if ((ret=(type *)OPENSSL_malloc(sizeof(type))) == NULL) \
+ { c.line=__LINE__; goto err2; }
+
+#define M_ASN1_New(arg,func) \
+ if (((arg)=func()) == NULL) return(NULL)
+
+#define M_ASN1_New_Error(a) \
+/* err: ASN1_MAC_H_err((a),ERR_R_NESTED_ASN1_ERROR,c.line); \
+ return(NULL);*/ \
+ err2: ASN1_MAC_H_err((a),ERR_R_MALLOC_FAILURE,c.line); \
+ return(NULL)
+
+
+/* BIG UGLY WARNING! This is so damn ugly I wanna puke. Unfortunately,
+ some macros that use ASN1_const_CTX still insist on writing in the input
+ stream. ARGH! ARGH! ARGH! Let's get rid of this macro package.
+ Please? -- Richard Levitte */
+#define M_ASN1_next (*((unsigned char *)(c.p)))
+#define M_ASN1_next_prev (*((unsigned char *)(c.q)))
+
+/*************************************************/
+
+#define M_ASN1_I2D_vars(a) int r=0,ret=0; \
+ unsigned char *p; \
+ if (a == NULL) return(0)
+
+/* Length Macros */
+#define M_ASN1_I2D_len(a,f) ret+=f(a,NULL)
+#define M_ASN1_I2D_len_IMP_opt(a,f) if (a != NULL) M_ASN1_I2D_len(a,f)
+
+#define M_ASN1_I2D_len_SET(a,f) \
+ ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET);
+
+#define M_ASN1_I2D_len_SET_type(type,a,f) \
+ ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SET, \
+ V_ASN1_UNIVERSAL,IS_SET);
+
+#define M_ASN1_I2D_len_SEQUENCE(a,f) \
+ ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \
+ IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_SEQUENCE_type(type,a,f) \
+ ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SEQUENCE, \
+ V_ASN1_UNIVERSAL,IS_SEQUENCE)
+
+#define M_ASN1_I2D_len_SEQUENCE_opt(a,f) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ M_ASN1_I2D_len_SEQUENCE(a,f);
+
+#define M_ASN1_I2D_len_SEQUENCE_opt_type(type,a,f) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ M_ASN1_I2D_len_SEQUENCE_type(type,a,f);
+
+#define M_ASN1_I2D_len_IMP_SET(a,f,x) \
+ ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SET_type(type,a,f,x) \
+ ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+ V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SET_opt(a,f,x) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SET_opt_type(type,a,f,x) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+ V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SEQUENCE(a,f,x) \
+ ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_IMP_SEQUENCE_opt(a,f,x) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_IMP_SEQUENCE_opt_type(type,a,f,x) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+ V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_EXP_opt(a,f,mtag,v) \
+ if (a != NULL)\
+ { \
+ v=f(a,NULL); \
+ ret+=ASN1_object_size(1,v,mtag); \
+ }
+
+#define M_ASN1_I2D_len_EXP_SET_opt(a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_num(a) != 0))\
+ { \
+ v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
+ ret+=ASN1_object_size(1,v,mtag); \
+ }
+
+#define M_ASN1_I2D_len_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_num(a) != 0))\
+ { \
+ v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL, \
+ IS_SEQUENCE); \
+ ret+=ASN1_object_size(1,v,mtag); \
+ }
+
+#define M_ASN1_I2D_len_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0))\
+ { \
+ v=i2d_ASN1_SET_OF_##type(a,NULL,f,tag, \
+ V_ASN1_UNIVERSAL, \
+ IS_SEQUENCE); \
+ ret+=ASN1_object_size(1,v,mtag); \
+ }
+
+/* Put Macros */
+#define M_ASN1_I2D_put(a,f) f(a,&p)
+
+#define M_ASN1_I2D_put_IMP_opt(a,f,t) \
+ if (a != NULL) \
+ { \
+ unsigned char *q=p; \
+ f(a,&p); \
+ *q=(V_ASN1_CONTEXT_SPECIFIC|t|(*q&V_ASN1_CONSTRUCTED));\
+ }
+
+#define M_ASN1_I2D_put_SET(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SET,\
+ V_ASN1_UNIVERSAL,IS_SET)
+#define M_ASN1_I2D_put_SET_type(type,a,f) \
+ i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET)
+#define M_ASN1_I2D_put_IMP_SET(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
+ V_ASN1_CONTEXT_SPECIFIC,IS_SET)
+#define M_ASN1_I2D_put_IMP_SET_type(type,a,f,x) \
+ i2d_ASN1_SET_OF_##type(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET)
+#define M_ASN1_I2D_put_IMP_SEQUENCE(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
+ V_ASN1_CONTEXT_SPECIFIC,IS_SEQUENCE)
+
+#define M_ASN1_I2D_put_SEQUENCE(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SEQUENCE,\
+ V_ASN1_UNIVERSAL,IS_SEQUENCE)
+
+#define M_ASN1_I2D_put_SEQUENCE_type(type,a,f) \
+ i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \
+ IS_SEQUENCE)
+
+#define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ M_ASN1_I2D_put_SEQUENCE(a,f);
+
+#define M_ASN1_I2D_put_IMP_SET_opt(a,f,x) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SET); }
+
+#define M_ASN1_I2D_put_IMP_SET_opt_type(type,a,f,x) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ { i2d_ASN1_SET_OF_##type(a,&p,f,x, \
+ V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SET); }
+
+#define M_ASN1_I2D_put_IMP_SEQUENCE_opt(a,f,x) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SEQUENCE); }
+
+#define M_ASN1_I2D_put_IMP_SEQUENCE_opt_type(type,a,f,x) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ { i2d_ASN1_SET_OF_##type(a,&p,f,x, \
+ V_ASN1_CONTEXT_SPECIFIC, \
+ IS_SEQUENCE); }
+
+#define M_ASN1_I2D_put_EXP_opt(a,f,tag,v) \
+ if (a != NULL) \
+ { \
+ ASN1_put_object(&p,1,v,tag,V_ASN1_CONTEXT_SPECIFIC); \
+ f(a,&p); \
+ }
+
+#define M_ASN1_I2D_put_EXP_SET_opt(a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ { \
+ ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+ i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
+ }
+
+#define M_ASN1_I2D_put_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_num(a) != 0)) \
+ { \
+ ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+ i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SEQUENCE); \
+ }
+
+#define M_ASN1_I2D_put_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \
+ if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+ { \
+ ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+ i2d_ASN1_SET_OF_##type(a,&p,f,tag,V_ASN1_UNIVERSAL, \
+ IS_SEQUENCE); \
+ }
+
+#define M_ASN1_I2D_seq_total() \
+ r=ASN1_object_size(1,ret,V_ASN1_SEQUENCE); \
+ if (pp == NULL) return(r); \
+ p= *pp; \
+ ASN1_put_object(&p,1,ret,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL)
+
+#define M_ASN1_I2D_INF_seq_start(tag,ctx) \
+ *(p++)=(V_ASN1_CONSTRUCTED|(tag)|(ctx)); \
+ *(p++)=0x80
+
+#define M_ASN1_I2D_INF_seq_end() *(p++)=0x00; *(p++)=0x00
+
+#define M_ASN1_I2D_finish() *pp=p; \
+ return(r);
+
+int asn1_GetSequence(ASN1_const_CTX *c, long *length);
+void asn1_add_error(const unsigned char *address,int offset);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/asn1t.h b/src/Mayaqua/win32_inc/openssl/asn1t.h
new file mode 100644
index 00000000..bc361156
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/asn1t.h
@@ -0,0 +1,893 @@
+/* asn1t.h */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_ASN1T_H
+#define HEADER_ASN1T_H
+
+#include <stddef.h>
+#include <openssl/e_os2.h>
+#include <openssl/asn1.h>
+
+#ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+#endif
+
+/* ASN1 template defines, structures and functions */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
+#define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr))
+
+
+/* Macros for start and end of ASN1_ITEM definition */
+
+#define ASN1_ITEM_start(itname) \
+ OPENSSL_GLOBAL const ASN1_ITEM itname##_it = {
+
+#define ASN1_ITEM_end(itname) \
+ };
+
+#else
+
+/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
+#define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr()))
+
+
+/* Macros for start and end of ASN1_ITEM definition */
+
+#define ASN1_ITEM_start(itname) \
+ const ASN1_ITEM * itname##_it(void) \
+ { \
+ static const ASN1_ITEM local_it = {
+
+#define ASN1_ITEM_end(itname) \
+ }; \
+ return &local_it; \
+ }
+
+#endif
+
+
+/* Macros to aid ASN1 template writing */
+
+#define ASN1_ITEM_TEMPLATE(tname) \
+ static const ASN1_TEMPLATE tname##_item_tt
+
+#define ASN1_ITEM_TEMPLATE_END(tname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_PRIMITIVE,\
+ -1,\
+ &tname##_item_tt,\
+ 0,\
+ NULL,\
+ 0,\
+ #tname \
+ ASN1_ITEM_end(tname)
+
+
+/* This is a ASN1 type which just embeds a template */
+
+/* This pair helps declare a SEQUENCE. We can do:
+ *
+ * ASN1_SEQUENCE(stname) = {
+ * ... SEQUENCE components ...
+ * } ASN1_SEQUENCE_END(stname)
+ *
+ * This will produce an ASN1_ITEM called stname_it
+ * for a structure called stname.
+ *
+ * If you want the same structure but a different
+ * name then use:
+ *
+ * ASN1_SEQUENCE(itname) = {
+ * ... SEQUENCE components ...
+ * } ASN1_SEQUENCE_END_name(stname, itname)
+ *
+ * This will create an item called itname_it using
+ * a structure called stname.
+ */
+
+#define ASN1_SEQUENCE(tname) \
+ static const ASN1_TEMPLATE tname##_seq_tt[]
+
+#define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname)
+
+#define ASN1_SEQUENCE_END_name(stname, tname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_SEQUENCE,\
+ V_ASN1_SEQUENCE,\
+ tname##_seq_tt,\
+ sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+ NULL,\
+ sizeof(stname),\
+ #stname \
+ ASN1_ITEM_end(tname)
+
+#define ASN1_NDEF_SEQUENCE(tname) \
+ ASN1_SEQUENCE(tname)
+
+#define ASN1_NDEF_SEQUENCE_cb(tname, cb) \
+ ASN1_SEQUENCE_cb(tname, cb)
+
+#define ASN1_SEQUENCE_cb(tname, cb) \
+ static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
+ ASN1_SEQUENCE(tname)
+
+#define ASN1_BROKEN_SEQUENCE(tname) \
+ static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \
+ ASN1_SEQUENCE(tname)
+
+#define ASN1_SEQUENCE_ref(tname, cb, lck) \
+ static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), lck, cb, 0}; \
+ ASN1_SEQUENCE(tname)
+
+#define ASN1_SEQUENCE_enc(tname, enc, cb) \
+ static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, 0, cb, offsetof(tname, enc)}; \
+ ASN1_SEQUENCE(tname)
+
+#define ASN1_NDEF_SEQUENCE_END(tname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_NDEF_SEQUENCE,\
+ V_ASN1_SEQUENCE,\
+ tname##_seq_tt,\
+ sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+ NULL,\
+ sizeof(tname),\
+ #tname \
+ ASN1_ITEM_end(tname)
+
+#define ASN1_BROKEN_SEQUENCE_END(stname) ASN1_SEQUENCE_END_ref(stname, stname)
+
+#define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
+
+#define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
+
+#define ASN1_SEQUENCE_END_ref(stname, tname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_SEQUENCE,\
+ V_ASN1_SEQUENCE,\
+ tname##_seq_tt,\
+ sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+ &tname##_aux,\
+ sizeof(stname),\
+ #stname \
+ ASN1_ITEM_end(tname)
+
+
+/* This pair helps declare a CHOICE type. We can do:
+ *
+ * ASN1_CHOICE(chname) = {
+ * ... CHOICE options ...
+ * ASN1_CHOICE_END(chname)
+ *
+ * This will produce an ASN1_ITEM called chname_it
+ * for a structure called chname. The structure
+ * definition must look like this:
+ * typedef struct {
+ * int type;
+ * union {
+ * ASN1_SOMETHING *opt1;
+ * ASN1_SOMEOTHER *opt2;
+ * } value;
+ * } chname;
+ *
+ * the name of the selector must be 'type'.
+ * to use an alternative selector name use the
+ * ASN1_CHOICE_END_selector() version.
+ */
+
+#define ASN1_CHOICE(tname) \
+ static const ASN1_TEMPLATE tname##_ch_tt[]
+
+#define ASN1_CHOICE_cb(tname, cb) \
+ static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
+ ASN1_CHOICE(tname)
+
+#define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname)
+
+#define ASN1_CHOICE_END_name(stname, tname) ASN1_CHOICE_END_selector(stname, tname, type)
+
+#define ASN1_CHOICE_END_selector(stname, tname, selname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_CHOICE,\
+ offsetof(stname,selname) ,\
+ tname##_ch_tt,\
+ sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
+ NULL,\
+ sizeof(stname),\
+ #stname \
+ ASN1_ITEM_end(tname)
+
+#define ASN1_CHOICE_END_cb(stname, tname, selname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_CHOICE,\
+ offsetof(stname,selname) ,\
+ tname##_ch_tt,\
+ sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\
+ &tname##_aux,\
+ sizeof(stname),\
+ #stname \
+ ASN1_ITEM_end(tname)
+
+/* This helps with the template wrapper form of ASN1_ITEM */
+
+#define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \
+ (flags), (tag), 0,\
+ #name, ASN1_ITEM_ref(type) }
+
+/* These help with SEQUENCE or CHOICE components */
+
+/* used to declare other types */
+
+#define ASN1_EX_TYPE(flags, tag, stname, field, type) { \
+ (flags), (tag), offsetof(stname, field),\
+ #field, ASN1_ITEM_ref(type) }
+
+/* used when the structure is combined with the parent */
+
+#define ASN1_EX_COMBINE(flags, tag, type) { \
+ (flags)|ASN1_TFLG_COMBINE, (tag), 0, NULL, ASN1_ITEM_ref(type) }
+
+/* implicit and explicit helper macros */
+
+#define ASN1_IMP_EX(stname, field, type, tag, ex) \
+ ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | ex, tag, stname, field, type)
+
+#define ASN1_EXP_EX(stname, field, type, tag, ex) \
+ ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | ex, tag, stname, field, type)
+
+/* Any defined by macros: the field used is in the table itself */
+
+#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+#define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) }
+#define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) }
+#else
+#define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, tblname##_adb }
+#define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, tblname##_adb }
+#endif
+/* Plain simple type */
+#define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type)
+
+/* OPTIONAL simple type */
+#define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type)
+
+/* IMPLICIT tagged simple type */
+#define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0)
+
+/* IMPLICIT tagged OPTIONAL simple type */
+#define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL)
+
+/* Same as above but EXPLICIT */
+
+#define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0)
+#define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL)
+
+/* SEQUENCE OF type */
+#define ASN1_SEQUENCE_OF(stname, field, type) \
+ ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type)
+
+/* OPTIONAL SEQUENCE OF */
+#define ASN1_SEQUENCE_OF_OPT(stname, field, type) \
+ ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type)
+
+/* Same as above but for SET OF */
+
+#define ASN1_SET_OF(stname, field, type) \
+ ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type)
+
+#define ASN1_SET_OF_OPT(stname, field, type) \
+ ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type)
+
+/* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */
+
+#define ASN1_IMP_SET_OF(stname, field, type, tag) \
+ ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF)
+
+#define ASN1_EXP_SET_OF(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF)
+
+#define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \
+ ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL)
+
+#define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL)
+
+#define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \
+ ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF)
+
+#define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \
+ ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
+
+#define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF)
+
+#define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
+
+/* EXPLICIT using indefinite length constructed form */
+#define ASN1_NDEF_EXP(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_NDEF)
+
+/* EXPLICIT OPTIONAL using indefinite length constructed form */
+#define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \
+ ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF)
+
+/* Macros for the ASN1_ADB structure */
+
+#define ASN1_ADB(name) \
+ static const ASN1_ADB_TABLE name##_adbtbl[]
+
+#ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+#define ASN1_ADB_END(name, flags, field, app_table, def, none) \
+ ;\
+ static const ASN1_ADB name##_adb = {\
+ flags,\
+ offsetof(name, field),\
+ app_table,\
+ name##_adbtbl,\
+ sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\
+ def,\
+ none\
+ }
+
+#else
+
+#define ASN1_ADB_END(name, flags, field, app_table, def, none) \
+ ;\
+ static const ASN1_ITEM *name##_adb(void) \
+ { \
+ static const ASN1_ADB internal_adb = \
+ {\
+ flags,\
+ offsetof(name, field),\
+ app_table,\
+ name##_adbtbl,\
+ sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\
+ def,\
+ none\
+ }; \
+ return (const ASN1_ITEM *) &internal_adb; \
+ } \
+ void dummy_function(void)
+
+#endif
+
+#define ADB_ENTRY(val, template) {val, template}
+
+#define ASN1_ADB_TEMPLATE(name) \
+ static const ASN1_TEMPLATE name##_tt
+
+/* This is the ASN1 template structure that defines
+ * a wrapper round the actual type. It determines the
+ * actual position of the field in the value structure,
+ * various flags such as OPTIONAL and the field name.
+ */
+
+struct ASN1_TEMPLATE_st {
+unsigned long flags; /* Various flags */
+long tag; /* tag, not used if no tagging */
+unsigned long offset; /* Offset of this field in structure */
+#ifndef NO_ASN1_FIELD_NAMES
+const char *field_name; /* Field name */
+#endif
+ASN1_ITEM_EXP *item; /* Relevant ASN1_ITEM or ASN1_ADB */
+};
+
+/* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */
+
+#define ASN1_TEMPLATE_item(t) (t->item_ptr)
+#define ASN1_TEMPLATE_adb(t) (t->item_ptr)
+
+typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE;
+typedef struct ASN1_ADB_st ASN1_ADB;
+
+struct ASN1_ADB_st {
+ unsigned long flags; /* Various flags */
+ unsigned long offset; /* Offset of selector field */
+ STACK_OF(ASN1_ADB_TABLE) **app_items; /* Application defined items */
+ const ASN1_ADB_TABLE *tbl; /* Table of possible types */
+ long tblcount; /* Number of entries in tbl */
+ const ASN1_TEMPLATE *default_tt; /* Type to use if no match */
+ const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */
+};
+
+struct ASN1_ADB_TABLE_st {
+ long value; /* NID for an object or value for an int */
+ const ASN1_TEMPLATE tt; /* item for this value */
+};
+
+/* template flags */
+
+/* Field is optional */
+#define ASN1_TFLG_OPTIONAL (0x1)
+
+/* Field is a SET OF */
+#define ASN1_TFLG_SET_OF (0x1 << 1)
+
+/* Field is a SEQUENCE OF */
+#define ASN1_TFLG_SEQUENCE_OF (0x2 << 1)
+
+/* Special case: this refers to a SET OF that
+ * will be sorted into DER order when encoded *and*
+ * the corresponding STACK will be modified to match
+ * the new order.
+ */
+#define ASN1_TFLG_SET_ORDER (0x3 << 1)
+
+/* Mask for SET OF or SEQUENCE OF */
+#define ASN1_TFLG_SK_MASK (0x3 << 1)
+
+/* These flags mean the tag should be taken from the
+ * tag field. If EXPLICIT then the underlying type
+ * is used for the inner tag.
+ */
+
+/* IMPLICIT tagging */
+#define ASN1_TFLG_IMPTAG (0x1 << 3)
+
+
+/* EXPLICIT tagging, inner tag from underlying type */
+#define ASN1_TFLG_EXPTAG (0x2 << 3)
+
+#define ASN1_TFLG_TAG_MASK (0x3 << 3)
+
+/* context specific IMPLICIT */
+#define ASN1_TFLG_IMPLICIT ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT
+
+/* context specific EXPLICIT */
+#define ASN1_TFLG_EXPLICIT ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT
+
+/* If tagging is in force these determine the
+ * type of tag to use. Otherwise the tag is
+ * determined by the underlying type. These
+ * values reflect the actual octet format.
+ */
+
+/* Universal tag */
+#define ASN1_TFLG_UNIVERSAL (0x0<<6)
+/* Application tag */
+#define ASN1_TFLG_APPLICATION (0x1<<6)
+/* Context specific tag */
+#define ASN1_TFLG_CONTEXT (0x2<<6)
+/* Private tag */
+#define ASN1_TFLG_PRIVATE (0x3<<6)
+
+#define ASN1_TFLG_TAG_CLASS (0x3<<6)
+
+/* These are for ANY DEFINED BY type. In this case
+ * the 'item' field points to an ASN1_ADB structure
+ * which contains a table of values to decode the
+ * relevant type
+ */
+
+#define ASN1_TFLG_ADB_MASK (0x3<<8)
+
+#define ASN1_TFLG_ADB_OID (0x1<<8)
+
+#define ASN1_TFLG_ADB_INT (0x1<<9)
+
+/* This flag means a parent structure is passed
+ * instead of the field: this is useful is a
+ * SEQUENCE is being combined with a CHOICE for
+ * example. Since this means the structure and
+ * item name will differ we need to use the
+ * ASN1_CHOICE_END_name() macro for example.
+ */
+
+#define ASN1_TFLG_COMBINE (0x1<<10)
+
+/* This flag when present in a SEQUENCE OF, SET OF
+ * or EXPLICIT causes indefinite length constructed
+ * encoding to be used if required.
+ */
+
+#define ASN1_TFLG_NDEF (0x1<<11)
+
+/* This is the actual ASN1 item itself */
+
+struct ASN1_ITEM_st {
+char itype; /* The item type, primitive, SEQUENCE, CHOICE or extern */
+long utype; /* underlying type */
+const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains the contents */
+long tcount; /* Number of templates if SEQUENCE or CHOICE */
+const void *funcs; /* functions that handle this type */
+long size; /* Structure size (usually)*/
+#ifndef NO_ASN1_FIELD_NAMES
+const char *sname; /* Structure name */
+#endif
+};
+
+/* These are values for the itype field and
+ * determine how the type is interpreted.
+ *
+ * For PRIMITIVE types the underlying type
+ * determines the behaviour if items is NULL.
+ *
+ * Otherwise templates must contain a single
+ * template and the type is treated in the
+ * same way as the type specified in the template.
+ *
+ * For SEQUENCE types the templates field points
+ * to the members, the size field is the
+ * structure size.
+ *
+ * For CHOICE types the templates field points
+ * to each possible member (typically a union)
+ * and the 'size' field is the offset of the
+ * selector.
+ *
+ * The 'funcs' field is used for application
+ * specific functions.
+ *
+ * For COMPAT types the funcs field gives a
+ * set of functions that handle this type, this
+ * supports the old d2i, i2d convention.
+ *
+ * The EXTERN type uses a new style d2i/i2d.
+ * The new style should be used where possible
+ * because it avoids things like the d2i IMPLICIT
+ * hack.
+ *
+ * MSTRING is a multiple string type, it is used
+ * for a CHOICE of character strings where the
+ * actual strings all occupy an ASN1_STRING
+ * structure. In this case the 'utype' field
+ * has a special meaning, it is used as a mask
+ * of acceptable types using the B_ASN1 constants.
+ *
+ * NDEF_SEQUENCE is the same as SEQUENCE except
+ * that it will use indefinite length constructed
+ * encoding if requested.
+ *
+ */
+
+#define ASN1_ITYPE_PRIMITIVE 0x0
+
+#define ASN1_ITYPE_SEQUENCE 0x1
+
+#define ASN1_ITYPE_CHOICE 0x2
+
+#define ASN1_ITYPE_COMPAT 0x3
+
+#define ASN1_ITYPE_EXTERN 0x4
+
+#define ASN1_ITYPE_MSTRING 0x5
+
+#define ASN1_ITYPE_NDEF_SEQUENCE 0x6
+
+/* Cache for ASN1 tag and length, so we
+ * don't keep re-reading it for things
+ * like CHOICE
+ */
+
+struct ASN1_TLC_st{
+ char valid; /* Values below are valid */
+ int ret; /* return value */
+ long plen; /* length */
+ int ptag; /* class value */
+ int pclass; /* class value */
+ int hdrlen; /* header length */
+};
+
+/* Typedefs for ASN1 function pointers */
+
+typedef ASN1_VALUE * ASN1_new_func(void);
+typedef void ASN1_free_func(ASN1_VALUE *a);
+typedef ASN1_VALUE * ASN1_d2i_func(ASN1_VALUE **a, const unsigned char ** in, long length);
+typedef int ASN1_i2d_func(ASN1_VALUE * a, unsigned char **in);
+
+typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it,
+ int tag, int aclass, char opt, ASN1_TLC *ctx);
+
+typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass);
+typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
+typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+typedef int ASN1_primitive_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
+typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
+
+typedef struct ASN1_COMPAT_FUNCS_st {
+ ASN1_new_func *asn1_new;
+ ASN1_free_func *asn1_free;
+ ASN1_d2i_func *asn1_d2i;
+ ASN1_i2d_func *asn1_i2d;
+} ASN1_COMPAT_FUNCS;
+
+typedef struct ASN1_EXTERN_FUNCS_st {
+ void *app_data;
+ ASN1_ex_new_func *asn1_ex_new;
+ ASN1_ex_free_func *asn1_ex_free;
+ ASN1_ex_free_func *asn1_ex_clear;
+ ASN1_ex_d2i *asn1_ex_d2i;
+ ASN1_ex_i2d *asn1_ex_i2d;
+} ASN1_EXTERN_FUNCS;
+
+typedef struct ASN1_PRIMITIVE_FUNCS_st {
+ void *app_data;
+ unsigned long flags;
+ ASN1_ex_new_func *prim_new;
+ ASN1_ex_free_func *prim_free;
+ ASN1_ex_free_func *prim_clear;
+ ASN1_primitive_c2i *prim_c2i;
+ ASN1_primitive_i2c *prim_i2c;
+} ASN1_PRIMITIVE_FUNCS;
+
+/* This is the ASN1_AUX structure: it handles various
+ * miscellaneous requirements. For example the use of
+ * reference counts and an informational callback.
+ *
+ * The "informational callback" is called at various
+ * points during the ASN1 encoding and decoding. It can
+ * be used to provide minor customisation of the structures
+ * used. This is most useful where the supplied routines
+ * *almost* do the right thing but need some extra help
+ * at a few points. If the callback returns zero then
+ * it is assumed a fatal error has occurred and the
+ * main operation should be abandoned.
+ *
+ * If major changes in the default behaviour are required
+ * then an external type is more appropriate.
+ */
+
+typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it);
+
+typedef struct ASN1_AUX_st {
+ void *app_data;
+ int flags;
+ int ref_offset; /* Offset of reference value */
+ int ref_lock; /* Lock type to use */
+ ASN1_aux_cb *asn1_cb;
+ int enc_offset; /* Offset of ASN1_ENCODING structure */
+} ASN1_AUX;
+
+/* Flags in ASN1_AUX */
+
+/* Use a reference count */
+#define ASN1_AFLG_REFCOUNT 1
+/* Save the encoding of structure (useful for signatures) */
+#define ASN1_AFLG_ENCODING 2
+/* The Sequence length is invalid */
+#define ASN1_AFLG_BROKEN 4
+
+/* operation values for asn1_cb */
+
+#define ASN1_OP_NEW_PRE 0
+#define ASN1_OP_NEW_POST 1
+#define ASN1_OP_FREE_PRE 2
+#define ASN1_OP_FREE_POST 3
+#define ASN1_OP_D2I_PRE 4
+#define ASN1_OP_D2I_POST 5
+#define ASN1_OP_I2D_PRE 6
+#define ASN1_OP_I2D_POST 7
+
+/* Macro to implement a primitive type */
+#define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0)
+#define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \
+ ASN1_ITEM_start(itname) \
+ ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \
+ ASN1_ITEM_end(itname)
+
+/* Macro to implement a multi string type */
+#define IMPLEMENT_ASN1_MSTRING(itname, mask) \
+ ASN1_ITEM_start(itname) \
+ ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \
+ ASN1_ITEM_end(itname)
+
+/* Macro to implement an ASN1_ITEM in terms of old style funcs */
+
+#define IMPLEMENT_COMPAT_ASN1(sname) IMPLEMENT_COMPAT_ASN1_type(sname, V_ASN1_SEQUENCE)
+
+#define IMPLEMENT_COMPAT_ASN1_type(sname, tag) \
+ static const ASN1_COMPAT_FUNCS sname##_ff = { \
+ (ASN1_new_func *)sname##_new, \
+ (ASN1_free_func *)sname##_free, \
+ (ASN1_d2i_func *)d2i_##sname, \
+ (ASN1_i2d_func *)i2d_##sname, \
+ }; \
+ ASN1_ITEM_start(sname) \
+ ASN1_ITYPE_COMPAT, \
+ tag, \
+ NULL, \
+ 0, \
+ &sname##_ff, \
+ 0, \
+ #sname \
+ ASN1_ITEM_end(sname)
+
+#define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \
+ ASN1_ITEM_start(sname) \
+ ASN1_ITYPE_EXTERN, \
+ tag, \
+ NULL, \
+ 0, \
+ &fptrs, \
+ 0, \
+ #sname \
+ ASN1_ITEM_end(sname)
+
+/* Macro to implement standard functions in terms of ASN1_ITEM structures */
+
+#define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname)
+
+#define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname)
+
+#define IMPLEMENT_ASN1_FUNCTIONS_ENCODE_name(stname, itname) \
+ IMPLEMENT_ASN1_FUNCTIONS_ENCODE_fname(stname, itname, itname)
+
+#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS(stname) \
+ IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, stname, stname)
+
+#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \
+ stname *fname##_new(void) \
+ { \
+ return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \
+ } \
+ void fname##_free(stname *a) \
+ { \
+ ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \
+ }
+
+#define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \
+ IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
+ IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname)
+
+#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
+ stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
+ { \
+ return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
+ } \
+ int i2d_##fname(stname *a, unsigned char **out) \
+ { \
+ return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
+ }
+
+#define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \
+ int i2d_##stname##_NDEF(stname *a, unsigned char **out) \
+ { \
+ return ASN1_item_ndef_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname));\
+ }
+
+/* This includes evil casts to remove const: they will go away when full
+ * ASN1 constification is done.
+ */
+#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
+ stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
+ { \
+ return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
+ } \
+ int i2d_##fname(const stname *a, unsigned char **out) \
+ { \
+ return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
+ }
+
+#define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \
+ stname * stname##_dup(stname *x) \
+ { \
+ return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \
+ }
+
+#define IMPLEMENT_ASN1_FUNCTIONS_const(name) \
+ IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name)
+
+#define IMPLEMENT_ASN1_FUNCTIONS_const_fname(stname, itname, fname) \
+ IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
+ IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname)
+
+/* external definitions for primitive types */
+
+DECLARE_ASN1_ITEM(ASN1_BOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_TBOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_FBOOLEAN)
+DECLARE_ASN1_ITEM(ASN1_SEQUENCE)
+DECLARE_ASN1_ITEM(CBIGNUM)
+DECLARE_ASN1_ITEM(BIGNUM)
+DECLARE_ASN1_ITEM(LONG)
+DECLARE_ASN1_ITEM(ZLONG)
+
+DECLARE_STACK_OF(ASN1_VALUE)
+
+/* Functions used internally by the ASN1 code */
+
+int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
+void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+int ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_TEMPLATE *tt);
+int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it,
+ int tag, int aclass, char opt, ASN1_TLC *ctx);
+
+int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass);
+int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt);
+void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
+int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
+
+int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int asn1_set_choice_selector(ASN1_VALUE **pval, int value, const ASN1_ITEM *it);
+
+ASN1_VALUE ** asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+
+const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, int nullerr);
+
+int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it);
+
+void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it);
+void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, const ASN1_ITEM *it);
+int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, const ASN1_ITEM *it);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/bio.h b/src/Mayaqua/win32_inc/openssl/bio.h
new file mode 100644
index 00000000..dabd7862
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/bio.h
@@ -0,0 +1,791 @@
+/* crypto/bio/bio.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BIO_H
+#define HEADER_BIO_H
+
+#include <openssl/e_os2.h>
+
+#ifndef OPENSSL_NO_FP_API
+# include <stdio.h>
+#endif
+#include <stdarg.h>
+
+#include <openssl/crypto.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These are the 'types' of BIOs */
+#define BIO_TYPE_NONE 0
+#define BIO_TYPE_MEM (1|0x0400)
+#define BIO_TYPE_FILE (2|0x0400)
+
+#define BIO_TYPE_FD (4|0x0400|0x0100)
+#define BIO_TYPE_SOCKET (5|0x0400|0x0100)
+#define BIO_TYPE_NULL (6|0x0400)
+#define BIO_TYPE_SSL (7|0x0200)
+#define BIO_TYPE_MD (8|0x0200) /* passive filter */
+#define BIO_TYPE_BUFFER (9|0x0200) /* filter */
+#define BIO_TYPE_CIPHER (10|0x0200) /* filter */
+#define BIO_TYPE_BASE64 (11|0x0200) /* filter */
+#define BIO_TYPE_CONNECT (12|0x0400|0x0100) /* socket - connect */
+#define BIO_TYPE_ACCEPT (13|0x0400|0x0100) /* socket for accept */
+#define BIO_TYPE_PROXY_CLIENT (14|0x0200) /* client proxy BIO */
+#define BIO_TYPE_PROXY_SERVER (15|0x0200) /* server proxy BIO */
+#define BIO_TYPE_NBIO_TEST (16|0x0200) /* server proxy BIO */
+#define BIO_TYPE_NULL_FILTER (17|0x0200)
+#define BIO_TYPE_BER (18|0x0200) /* BER -> bin filter */
+#define BIO_TYPE_BIO (19|0x0400) /* (half a) BIO pair */
+#define BIO_TYPE_LINEBUFFER (20|0x0200) /* filter */
+#define BIO_TYPE_DGRAM (21|0x0400|0x0100)
+#define BIO_TYPE_COMP (23|0x0200) /* filter */
+
+#define BIO_TYPE_DESCRIPTOR 0x0100 /* socket, fd, connect or accept */
+#define BIO_TYPE_FILTER 0x0200
+#define BIO_TYPE_SOURCE_SINK 0x0400
+
+/* BIO_FILENAME_READ|BIO_CLOSE to open or close on free.
+ * BIO_set_fp(in,stdin,BIO_NOCLOSE); */
+#define BIO_NOCLOSE 0x00
+#define BIO_CLOSE 0x01
+
+/* These are used in the following macros and are passed to
+ * BIO_ctrl() */
+#define BIO_CTRL_RESET 1 /* opt - rewind/zero etc */
+#define BIO_CTRL_EOF 2 /* opt - are we at the eof */
+#define BIO_CTRL_INFO 3 /* opt - extra tit-bits */
+#define BIO_CTRL_SET 4 /* man - set the 'IO' type */
+#define BIO_CTRL_GET 5 /* man - get the 'IO' type */
+#define BIO_CTRL_PUSH 6 /* opt - internal, used to signify change */
+#define BIO_CTRL_POP 7 /* opt - internal, used to signify change */
+#define BIO_CTRL_GET_CLOSE 8 /* man - set the 'close' on free */
+#define BIO_CTRL_SET_CLOSE 9 /* man - set the 'close' on free */
+#define BIO_CTRL_PENDING 10 /* opt - is their more data buffered */
+#define BIO_CTRL_FLUSH 11 /* opt - 'flush' buffered output */
+#define BIO_CTRL_DUP 12 /* man - extra stuff for 'duped' BIO */
+#define BIO_CTRL_WPENDING 13 /* opt - number of bytes still to write */
+/* callback is int cb(BIO *bio,state,ret); */
+#define BIO_CTRL_SET_CALLBACK 14 /* opt - set callback function */
+#define BIO_CTRL_GET_CALLBACK 15 /* opt - set callback function */
+
+#define BIO_CTRL_SET_FILENAME 30 /* BIO_s_file special */
+
+/* dgram BIO stuff */
+#define BIO_CTRL_DGRAM_CONNECT 31 /* BIO dgram special */
+#define BIO_CTRL_DGRAM_SET_CONNECTED 32 /* allow for an externally
+ * connected socket to be
+ * passed in */
+#define BIO_CTRL_DGRAM_SET_RECV_TIMEOUT 33 /* setsockopt, essentially */
+#define BIO_CTRL_DGRAM_GET_RECV_TIMEOUT 34 /* getsockopt, essentially */
+#define BIO_CTRL_DGRAM_SET_SEND_TIMEOUT 35 /* setsockopt, essentially */
+#define BIO_CTRL_DGRAM_GET_SEND_TIMEOUT 36 /* getsockopt, essentially */
+
+#define BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP 37 /* flag whether the last */
+#define BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP 38 /* I/O operation tiemd out */
+
+/* #ifdef IP_MTU_DISCOVER */
+#define BIO_CTRL_DGRAM_MTU_DISCOVER 39 /* set DF bit on egress packets */
+/* #endif */
+
+#define BIO_CTRL_DGRAM_QUERY_MTU 40 /* as kernel for current MTU */
+#define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47
+#define BIO_CTRL_DGRAM_GET_MTU 41 /* get cached value for MTU */
+#define BIO_CTRL_DGRAM_SET_MTU 42 /* set cached value for
+ * MTU. want to use this
+ * if asking the kernel
+ * fails */
+
+#define BIO_CTRL_DGRAM_MTU_EXCEEDED 43 /* check whether the MTU
+ * was exceed in the
+ * previous write
+ * operation */
+
+#define BIO_CTRL_DGRAM_GET_PEER 46
+#define BIO_CTRL_DGRAM_SET_PEER 44 /* Destination for the data */
+
+#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45 /* Next DTLS handshake timeout to
+ * adjust socket timeouts */
+
+/* modifiers */
+#define BIO_FP_READ 0x02
+#define BIO_FP_WRITE 0x04
+#define BIO_FP_APPEND 0x08
+#define BIO_FP_TEXT 0x10
+
+#define BIO_FLAGS_READ 0x01
+#define BIO_FLAGS_WRITE 0x02
+#define BIO_FLAGS_IO_SPECIAL 0x04
+#define BIO_FLAGS_RWS (BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL)
+#define BIO_FLAGS_SHOULD_RETRY 0x08
+#ifndef BIO_FLAGS_UPLINK
+/* "UPLINK" flag denotes file descriptors provided by application.
+ It defaults to 0, as most platforms don't require UPLINK interface. */
+#define BIO_FLAGS_UPLINK 0
+#endif
+
+/* Used in BIO_gethostbyname() */
+#define BIO_GHBN_CTRL_HITS 1
+#define BIO_GHBN_CTRL_MISSES 2
+#define BIO_GHBN_CTRL_CACHE_SIZE 3
+#define BIO_GHBN_CTRL_GET_ENTRY 4
+#define BIO_GHBN_CTRL_FLUSH 5
+
+/* Mostly used in the SSL BIO */
+/* Not used anymore
+ * #define BIO_FLAGS_PROTOCOL_DELAYED_READ 0x10
+ * #define BIO_FLAGS_PROTOCOL_DELAYED_WRITE 0x20
+ * #define BIO_FLAGS_PROTOCOL_STARTUP 0x40
+ */
+
+#define BIO_FLAGS_BASE64_NO_NL 0x100
+
+/* This is used with memory BIOs: it means we shouldn't free up or change the
+ * data in any way.
+ */
+#define BIO_FLAGS_MEM_RDONLY 0x200
+
+typedef struct bio_st BIO;
+
+void BIO_set_flags(BIO *b, int flags);
+int BIO_test_flags(const BIO *b, int flags);
+void BIO_clear_flags(BIO *b, int flags);
+
+#define BIO_get_flags(b) BIO_test_flags(b, ~(0x0))
+#define BIO_set_retry_special(b) \
+ BIO_set_flags(b, (BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY))
+#define BIO_set_retry_read(b) \
+ BIO_set_flags(b, (BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY))
+#define BIO_set_retry_write(b) \
+ BIO_set_flags(b, (BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY))
+
+/* These are normally used internally in BIOs */
+#define BIO_clear_retry_flags(b) \
+ BIO_clear_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
+#define BIO_get_retry_flags(b) \
+ BIO_test_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
+
+/* These should be used by the application to tell why we should retry */
+#define BIO_should_read(a) BIO_test_flags(a, BIO_FLAGS_READ)
+#define BIO_should_write(a) BIO_test_flags(a, BIO_FLAGS_WRITE)
+#define BIO_should_io_special(a) BIO_test_flags(a, BIO_FLAGS_IO_SPECIAL)
+#define BIO_retry_type(a) BIO_test_flags(a, BIO_FLAGS_RWS)
+#define BIO_should_retry(a) BIO_test_flags(a, BIO_FLAGS_SHOULD_RETRY)
+
+/* The next three are used in conjunction with the
+ * BIO_should_io_special() condition. After this returns true,
+ * BIO *BIO_get_retry_BIO(BIO *bio, int *reason); will walk the BIO
+ * stack and return the 'reason' for the special and the offending BIO.
+ * Given a BIO, BIO_get_retry_reason(bio) will return the code. */
+/* Returned from the SSL bio when the certificate retrieval code had an error */
+#define BIO_RR_SSL_X509_LOOKUP 0x01
+/* Returned from the connect BIO when a connect would have blocked */
+#define BIO_RR_CONNECT 0x02
+/* Returned from the accept BIO when an accept would have blocked */
+#define BIO_RR_ACCEPT 0x03
+
+/* These are passed by the BIO callback */
+#define BIO_CB_FREE 0x01
+#define BIO_CB_READ 0x02
+#define BIO_CB_WRITE 0x03
+#define BIO_CB_PUTS 0x04
+#define BIO_CB_GETS 0x05
+#define BIO_CB_CTRL 0x06
+
+/* The callback is called before and after the underling operation,
+ * The BIO_CB_RETURN flag indicates if it is after the call */
+#define BIO_CB_RETURN 0x80
+#define BIO_CB_return(a) ((a)|BIO_CB_RETURN))
+#define BIO_cb_pre(a) (!((a)&BIO_CB_RETURN))
+#define BIO_cb_post(a) ((a)&BIO_CB_RETURN)
+
+long (*BIO_get_callback(const BIO *b)) (struct bio_st *,int,const char *,int, long,long);
+void BIO_set_callback(BIO *b,
+ long (*callback)(struct bio_st *,int,const char *,int, long,long));
+char *BIO_get_callback_arg(const BIO *b);
+void BIO_set_callback_arg(BIO *b, char *arg);
+
+const char * BIO_method_name(const BIO *b);
+int BIO_method_type(const BIO *b);
+
+typedef void bio_info_cb(struct bio_st *, int, const char *, int, long, long);
+
+#ifndef OPENSSL_SYS_WIN16
+typedef struct bio_method_st
+ {
+ int type;
+ const char *name;
+ int (*bwrite)(BIO *, const char *, int);
+ int (*bread)(BIO *, char *, int);
+ int (*bputs)(BIO *, const char *);
+ int (*bgets)(BIO *, char *, int);
+ long (*ctrl)(BIO *, int, long, void *);
+ int (*create)(BIO *);
+ int (*destroy)(BIO *);
+ long (*callback_ctrl)(BIO *, int, bio_info_cb *);
+ } BIO_METHOD;
+#else
+typedef struct bio_method_st
+ {
+ int type;
+ const char *name;
+ int (_far *bwrite)();
+ int (_far *bread)();
+ int (_far *bputs)();
+ int (_far *bgets)();
+ long (_far *ctrl)();
+ int (_far *create)();
+ int (_far *destroy)();
+ long (_far *callback_ctrl)();
+ } BIO_METHOD;
+#endif
+
+struct bio_st
+ {
+ BIO_METHOD *method;
+ /* bio, mode, argp, argi, argl, ret */
+ long (*callback)(struct bio_st *,int,const char *,int, long,long);
+ char *cb_arg; /* first argument for the callback */
+
+ int init;
+ int shutdown;
+ int flags; /* extra storage */
+ int retry_reason;
+ int num;
+ void *ptr;
+ struct bio_st *next_bio; /* used by filter BIOs */
+ struct bio_st *prev_bio; /* used by filter BIOs */
+ int references;
+ unsigned long num_read;
+ unsigned long num_write;
+
+ CRYPTO_EX_DATA ex_data;
+ };
+
+DECLARE_STACK_OF(BIO)
+
+typedef struct bio_f_buffer_ctx_struct
+ {
+ /* Buffers are setup like this:
+ *
+ * <---------------------- size ----------------------->
+ * +---------------------------------------------------+
+ * | consumed | remaining | free space |
+ * +---------------------------------------------------+
+ * <-- off --><------- len ------->
+ */
+
+ /* BIO *bio; */ /* this is now in the BIO struct */
+ int ibuf_size; /* how big is the input buffer */
+ int obuf_size; /* how big is the output buffer */
+
+ char *ibuf; /* the char array */
+ int ibuf_len; /* how many bytes are in it */
+ int ibuf_off; /* write/read offset */
+
+ char *obuf; /* the char array */
+ int obuf_len; /* how many bytes are in it */
+ int obuf_off; /* write/read offset */
+ } BIO_F_BUFFER_CTX;
+
+/* connect BIO stuff */
+#define BIO_CONN_S_BEFORE 1
+#define BIO_CONN_S_GET_IP 2
+#define BIO_CONN_S_GET_PORT 3
+#define BIO_CONN_S_CREATE_SOCKET 4
+#define BIO_CONN_S_CONNECT 5
+#define BIO_CONN_S_OK 6
+#define BIO_CONN_S_BLOCKED_CONNECT 7
+#define BIO_CONN_S_NBIO 8
+/*#define BIO_CONN_get_param_hostname BIO_ctrl */
+
+#define BIO_C_SET_CONNECT 100
+#define BIO_C_DO_STATE_MACHINE 101
+#define BIO_C_SET_NBIO 102
+#define BIO_C_SET_PROXY_PARAM 103
+#define BIO_C_SET_FD 104
+#define BIO_C_GET_FD 105
+#define BIO_C_SET_FILE_PTR 106
+#define BIO_C_GET_FILE_PTR 107
+#define BIO_C_SET_FILENAME 108
+#define BIO_C_SET_SSL 109
+#define BIO_C_GET_SSL 110
+#define BIO_C_SET_MD 111
+#define BIO_C_GET_MD 112
+#define BIO_C_GET_CIPHER_STATUS 113
+#define BIO_C_SET_BUF_MEM 114
+#define BIO_C_GET_BUF_MEM_PTR 115
+#define BIO_C_GET_BUFF_NUM_LINES 116
+#define BIO_C_SET_BUFF_SIZE 117
+#define BIO_C_SET_ACCEPT 118
+#define BIO_C_SSL_MODE 119
+#define BIO_C_GET_MD_CTX 120
+#define BIO_C_GET_PROXY_PARAM 121
+#define BIO_C_SET_BUFF_READ_DATA 122 /* data to read first */
+#define BIO_C_GET_CONNECT 123
+#define BIO_C_GET_ACCEPT 124
+#define BIO_C_SET_SSL_RENEGOTIATE_BYTES 125
+#define BIO_C_GET_SSL_NUM_RENEGOTIATES 126
+#define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT 127
+#define BIO_C_FILE_SEEK 128
+#define BIO_C_GET_CIPHER_CTX 129
+#define BIO_C_SET_BUF_MEM_EOF_RETURN 130/*return end of input value*/
+#define BIO_C_SET_BIND_MODE 131
+#define BIO_C_GET_BIND_MODE 132
+#define BIO_C_FILE_TELL 133
+#define BIO_C_GET_SOCKS 134
+#define BIO_C_SET_SOCKS 135
+
+#define BIO_C_SET_WRITE_BUF_SIZE 136/* for BIO_s_bio */
+#define BIO_C_GET_WRITE_BUF_SIZE 137
+#define BIO_C_MAKE_BIO_PAIR 138
+#define BIO_C_DESTROY_BIO_PAIR 139
+#define BIO_C_GET_WRITE_GUARANTEE 140
+#define BIO_C_GET_READ_REQUEST 141
+#define BIO_C_SHUTDOWN_WR 142
+#define BIO_C_NREAD0 143
+#define BIO_C_NREAD 144
+#define BIO_C_NWRITE0 145
+#define BIO_C_NWRITE 146
+#define BIO_C_RESET_READ_REQUEST 147
+#define BIO_C_SET_MD_CTX 148
+
+
+#define BIO_set_app_data(s,arg) BIO_set_ex_data(s,0,arg)
+#define BIO_get_app_data(s) BIO_get_ex_data(s,0)
+
+/* BIO_s_connect() and BIO_s_socks4a_connect() */
+#define BIO_set_conn_hostname(b,name) BIO_ctrl(b,BIO_C_SET_CONNECT,0,(char *)name)
+#define BIO_set_conn_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,1,(char *)port)
+#define BIO_set_conn_ip(b,ip) BIO_ctrl(b,BIO_C_SET_CONNECT,2,(char *)ip)
+#define BIO_set_conn_int_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,3,(char *)port)
+#define BIO_get_conn_hostname(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0)
+#define BIO_get_conn_port(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1)
+#define BIO_get_conn_ip(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2)
+#define BIO_get_conn_int_port(b) BIO_int_ctrl(b,BIO_C_GET_CONNECT,3,0)
+
+
+#define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL)
+
+/* BIO_s_accept_socket() */
+#define BIO_set_accept_port(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0,(char *)name)
+#define BIO_get_accept_port(b) BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,0)
+/* #define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) */
+#define BIO_set_nbio_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,1,(n)?(void *)"a":NULL)
+#define BIO_set_accept_bios(b,bio) BIO_ctrl(b,BIO_C_SET_ACCEPT,2,(char *)bio)
+
+#define BIO_BIND_NORMAL 0
+#define BIO_BIND_REUSEADDR_IF_UNUSED 1
+#define BIO_BIND_REUSEADDR 2
+#define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,NULL)
+#define BIO_get_bind_mode(b,mode) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL)
+
+#define BIO_do_connect(b) BIO_do_handshake(b)
+#define BIO_do_accept(b) BIO_do_handshake(b)
+#define BIO_do_handshake(b) BIO_ctrl(b,BIO_C_DO_STATE_MACHINE,0,NULL)
+
+/* BIO_s_proxy_client() */
+#define BIO_set_url(b,url) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,0,(char *)(url))
+#define BIO_set_proxies(b,p) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,1,(char *)(p))
+/* BIO_set_nbio(b,n) */
+#define BIO_set_filter_bio(b,s) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,2,(char *)(s))
+/* BIO *BIO_get_filter_bio(BIO *bio); */
+#define BIO_set_proxy_cb(b,cb) BIO_callback_ctrl(b,BIO_C_SET_PROXY_PARAM,3,(void *(*cb)()))
+#define BIO_set_proxy_header(b,sk) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,4,(char *)sk)
+#define BIO_set_no_connect_return(b,bool) BIO_int_ctrl(b,BIO_C_SET_PROXY_PARAM,5,bool)
+
+#define BIO_get_proxy_header(b,skp) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,0,(char *)skp)
+#define BIO_get_proxies(b,pxy_p) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,1,(char *)(pxy_p))
+#define BIO_get_url(b,url) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,2,(char *)(url))
+#define BIO_get_no_connect_return(b) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,5,NULL)
+
+#define BIO_set_fd(b,fd,c) BIO_int_ctrl(b,BIO_C_SET_FD,c,fd)
+#define BIO_get_fd(b,c) BIO_ctrl(b,BIO_C_GET_FD,0,(char *)c)
+
+#define BIO_set_fp(b,fp,c) BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)fp)
+#define BIO_get_fp(b,fpp) BIO_ctrl(b,BIO_C_GET_FILE_PTR,0,(char *)fpp)
+
+#define BIO_seek(b,ofs) (int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL)
+#define BIO_tell(b) (int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL)
+
+/* name is cast to lose const, but might be better to route through a function
+ so we can do it safely */
+#ifdef CONST_STRICT
+/* If you are wondering why this isn't defined, its because CONST_STRICT is
+ * purely a compile-time kludge to allow const to be checked.
+ */
+int BIO_read_filename(BIO *b,const char *name);
+#else
+#define BIO_read_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+ BIO_CLOSE|BIO_FP_READ,(char *)name)
+#endif
+#define BIO_write_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+ BIO_CLOSE|BIO_FP_WRITE,name)
+#define BIO_append_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+ BIO_CLOSE|BIO_FP_APPEND,name)
+#define BIO_rw_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \
+ BIO_CLOSE|BIO_FP_READ|BIO_FP_WRITE,name)
+
+/* WARNING WARNING, this ups the reference count on the read bio of the
+ * SSL structure. This is because the ssl read BIO is now pointed to by
+ * the next_bio field in the bio. So when you free the BIO, make sure
+ * you are doing a BIO_free_all() to catch the underlying BIO. */
+#define BIO_set_ssl(b,ssl,c) BIO_ctrl(b,BIO_C_SET_SSL,c,(char *)ssl)
+#define BIO_get_ssl(b,sslp) BIO_ctrl(b,BIO_C_GET_SSL,0,(char *)sslp)
+#define BIO_set_ssl_mode(b,client) BIO_ctrl(b,BIO_C_SSL_MODE,client,NULL)
+#define BIO_set_ssl_renegotiate_bytes(b,num) \
+ BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_BYTES,num,NULL);
+#define BIO_get_num_renegotiates(b) \
+ BIO_ctrl(b,BIO_C_GET_SSL_NUM_RENEGOTIATES,0,NULL);
+#define BIO_set_ssl_renegotiate_timeout(b,seconds) \
+ BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT,seconds,NULL);
+
+/* defined in evp.h */
+/* #define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,1,(char *)md) */
+
+#define BIO_get_mem_data(b,pp) BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)pp)
+#define BIO_set_mem_buf(b,bm,c) BIO_ctrl(b,BIO_C_SET_BUF_MEM,c,(char *)bm)
+#define BIO_get_mem_ptr(b,pp) BIO_ctrl(b,BIO_C_GET_BUF_MEM_PTR,0,(char *)pp)
+#define BIO_set_mem_eof_return(b,v) \
+ BIO_ctrl(b,BIO_C_SET_BUF_MEM_EOF_RETURN,v,NULL)
+
+/* For the BIO_f_buffer() type */
+#define BIO_get_buffer_num_lines(b) BIO_ctrl(b,BIO_C_GET_BUFF_NUM_LINES,0,NULL)
+#define BIO_set_buffer_size(b,size) BIO_ctrl(b,BIO_C_SET_BUFF_SIZE,size,NULL)
+#define BIO_set_read_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,0)
+#define BIO_set_write_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,1)
+#define BIO_set_buffer_read_data(b,buf,num) BIO_ctrl(b,BIO_C_SET_BUFF_READ_DATA,num,buf)
+
+/* Don't use the next one unless you know what you are doing :-) */
+#define BIO_dup_state(b,ret) BIO_ctrl(b,BIO_CTRL_DUP,0,(char *)(ret))
+
+#define BIO_reset(b) (int)BIO_ctrl(b,BIO_CTRL_RESET,0,NULL)
+#define BIO_eof(b) (int)BIO_ctrl(b,BIO_CTRL_EOF,0,NULL)
+#define BIO_set_close(b,c) (int)BIO_ctrl(b,BIO_CTRL_SET_CLOSE,(c),NULL)
+#define BIO_get_close(b) (int)BIO_ctrl(b,BIO_CTRL_GET_CLOSE,0,NULL)
+#define BIO_pending(b) (int)BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL)
+#define BIO_wpending(b) (int)BIO_ctrl(b,BIO_CTRL_WPENDING,0,NULL)
+/* ...pending macros have inappropriate return type */
+size_t BIO_ctrl_pending(BIO *b);
+size_t BIO_ctrl_wpending(BIO *b);
+#define BIO_flush(b) (int)BIO_ctrl(b,BIO_CTRL_FLUSH,0,NULL)
+#define BIO_get_info_callback(b,cbp) (int)BIO_ctrl(b,BIO_CTRL_GET_CALLBACK,0, \
+ cbp)
+#define BIO_set_info_callback(b,cb) (int)BIO_callback_ctrl(b,BIO_CTRL_SET_CALLBACK,cb)
+
+/* For the BIO_f_buffer() type */
+#define BIO_buffer_get_num_lines(b) BIO_ctrl(b,BIO_CTRL_GET,0,NULL)
+
+/* For BIO_s_bio() */
+#define BIO_set_write_buf_size(b,size) (int)BIO_ctrl(b,BIO_C_SET_WRITE_BUF_SIZE,size,NULL)
+#define BIO_get_write_buf_size(b,size) (size_t)BIO_ctrl(b,BIO_C_GET_WRITE_BUF_SIZE,size,NULL)
+#define BIO_make_bio_pair(b1,b2) (int)BIO_ctrl(b1,BIO_C_MAKE_BIO_PAIR,0,b2)
+#define BIO_destroy_bio_pair(b) (int)BIO_ctrl(b,BIO_C_DESTROY_BIO_PAIR,0,NULL)
+#define BIO_shutdown_wr(b) (int)BIO_ctrl(b, BIO_C_SHUTDOWN_WR, 0, NULL)
+/* macros with inappropriate type -- but ...pending macros use int too: */
+#define BIO_get_write_guarantee(b) (int)BIO_ctrl(b,BIO_C_GET_WRITE_GUARANTEE,0,NULL)
+#define BIO_get_read_request(b) (int)BIO_ctrl(b,BIO_C_GET_READ_REQUEST,0,NULL)
+size_t BIO_ctrl_get_write_guarantee(BIO *b);
+size_t BIO_ctrl_get_read_request(BIO *b);
+int BIO_ctrl_reset_read_request(BIO *b);
+
+/* ctrl macros for dgram */
+#define BIO_ctrl_dgram_connect(b,peer) \
+ (int)BIO_ctrl(b,BIO_CTRL_DGRAM_CONNECT,0, (char *)peer)
+#define BIO_ctrl_set_connected(b, state, peer) \
+ (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_CONNECTED, state, (char *)peer)
+#define BIO_dgram_recv_timedout(b) \
+ (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP, 0, NULL)
+#define BIO_dgram_send_timedout(b) \
+ (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP, 0, NULL)
+#define BIO_dgram_get_peer(b,peer) \
+ (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, (char *)peer)
+#define BIO_dgram_set_peer(b,peer) \
+ (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)peer)
+
+/* These two aren't currently implemented */
+/* int BIO_get_ex_num(BIO *bio); */
+/* void BIO_set_ex_free_func(BIO *bio,int idx,void (*cb)()); */
+int BIO_set_ex_data(BIO *bio,int idx,void *data);
+void *BIO_get_ex_data(BIO *bio,int idx);
+int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+unsigned long BIO_number_read(BIO *bio);
+unsigned long BIO_number_written(BIO *bio);
+
+# ifndef OPENSSL_NO_FP_API
+# if defined(OPENSSL_SYS_WIN16) && defined(_WINDLL)
+BIO_METHOD *BIO_s_file_internal(void);
+BIO *BIO_new_file_internal(char *filename, char *mode);
+BIO *BIO_new_fp_internal(FILE *stream, int close_flag);
+# define BIO_s_file BIO_s_file_internal
+# define BIO_new_file BIO_new_file_internal
+# define BIO_new_fp BIO_new_fp_internal
+# else /* FP_API */
+BIO_METHOD *BIO_s_file(void );
+BIO *BIO_new_file(const char *filename, const char *mode);
+BIO *BIO_new_fp(FILE *stream, int close_flag);
+# define BIO_s_file_internal BIO_s_file
+# define BIO_new_file_internal BIO_new_file
+# define BIO_new_fp_internal BIO_s_file
+# endif /* FP_API */
+# endif
+BIO * BIO_new(BIO_METHOD *type);
+int BIO_set(BIO *a,BIO_METHOD *type);
+int BIO_free(BIO *a);
+void BIO_vfree(BIO *a);
+int BIO_read(BIO *b, void *data, int len);
+int BIO_gets(BIO *bp,char *buf, int size);
+int BIO_write(BIO *b, const void *data, int len);
+int BIO_puts(BIO *bp,const char *buf);
+int BIO_indent(BIO *b,int indent,int max);
+long BIO_ctrl(BIO *bp,int cmd,long larg,void *parg);
+long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long));
+char * BIO_ptr_ctrl(BIO *bp,int cmd,long larg);
+long BIO_int_ctrl(BIO *bp,int cmd,long larg,int iarg);
+BIO * BIO_push(BIO *b,BIO *append);
+BIO * BIO_pop(BIO *b);
+void BIO_free_all(BIO *a);
+BIO * BIO_find_type(BIO *b,int bio_type);
+BIO * BIO_next(BIO *b);
+BIO * BIO_get_retry_BIO(BIO *bio, int *reason);
+int BIO_get_retry_reason(BIO *bio);
+BIO * BIO_dup_chain(BIO *in);
+
+int BIO_nread0(BIO *bio, char **buf);
+int BIO_nread(BIO *bio, char **buf, int num);
+int BIO_nwrite0(BIO *bio, char **buf);
+int BIO_nwrite(BIO *bio, char **buf, int num);
+
+#ifndef OPENSSL_SYS_WIN16
+long BIO_debug_callback(BIO *bio,int cmd,const char *argp,int argi,
+ long argl,long ret);
+#else
+long _far _loadds BIO_debug_callback(BIO *bio,int cmd,const char *argp,int argi,
+ long argl,long ret);
+#endif
+
+BIO_METHOD *BIO_s_mem(void);
+BIO *BIO_new_mem_buf(void *buf, int len);
+BIO_METHOD *BIO_s_socket(void);
+BIO_METHOD *BIO_s_connect(void);
+BIO_METHOD *BIO_s_accept(void);
+BIO_METHOD *BIO_s_fd(void);
+#ifndef OPENSSL_SYS_OS2
+BIO_METHOD *BIO_s_log(void);
+#endif
+BIO_METHOD *BIO_s_bio(void);
+BIO_METHOD *BIO_s_null(void);
+BIO_METHOD *BIO_f_null(void);
+BIO_METHOD *BIO_f_buffer(void);
+#ifdef OPENSSL_SYS_VMS
+BIO_METHOD *BIO_f_linebuffer(void);
+#endif
+BIO_METHOD *BIO_f_nbio_test(void);
+#ifndef OPENSSL_NO_DGRAM
+BIO_METHOD *BIO_s_datagram(void);
+#endif
+
+/* BIO_METHOD *BIO_f_ber(void); */
+
+int BIO_sock_should_retry(int i);
+int BIO_sock_non_fatal_error(int error);
+int BIO_dgram_non_fatal_error(int error);
+
+int BIO_fd_should_retry(int i);
+int BIO_fd_non_fatal_error(int error);
+int BIO_dump_cb(int (*cb)(const void *data, size_t len, void *u),
+ void *u, const char *s, int len);
+int BIO_dump_indent_cb(int (*cb)(const void *data, size_t len, void *u),
+ void *u, const char *s, int len, int indent);
+int BIO_dump(BIO *b,const char *bytes,int len);
+int BIO_dump_indent(BIO *b,const char *bytes,int len,int indent);
+#ifndef OPENSSL_NO_FP_API
+int BIO_dump_fp(FILE *fp, const char *s, int len);
+int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent);
+#endif
+struct hostent *BIO_gethostbyname(const char *name);
+/* We might want a thread-safe interface too:
+ * struct hostent *BIO_gethostbyname_r(const char *name,
+ * struct hostent *result, void *buffer, size_t buflen);
+ * or something similar (caller allocates a struct hostent,
+ * pointed to by "result", and additional buffer space for the various
+ * substructures; if the buffer does not suffice, NULL is returned
+ * and an appropriate error code is set).
+ */
+int BIO_sock_error(int sock);
+int BIO_socket_ioctl(int fd, long type, void *arg);
+int BIO_socket_nbio(int fd,int mode);
+int BIO_get_port(const char *str, unsigned short *port_ptr);
+int BIO_get_host_ip(const char *str, unsigned char *ip);
+int BIO_get_accept_socket(char *host_port,int mode);
+int BIO_accept(int sock,char **ip_port);
+int BIO_sock_init(void );
+void BIO_sock_cleanup(void);
+int BIO_set_tcp_ndelay(int sock,int turn_on);
+
+BIO *BIO_new_socket(int sock, int close_flag);
+BIO *BIO_new_dgram(int fd, int close_flag);
+BIO *BIO_new_fd(int fd, int close_flag);
+BIO *BIO_new_connect(char *host_port);
+BIO *BIO_new_accept(char *host_port);
+
+int BIO_new_bio_pair(BIO **bio1, size_t writebuf1,
+ BIO **bio2, size_t writebuf2);
+/* If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints.
+ * Otherwise returns 0 and sets *bio1 and *bio2 to NULL.
+ * Size 0 uses default value.
+ */
+
+void BIO_copy_next_retry(BIO *b);
+
+/*long BIO_ghbn_ctrl(int cmd,int iarg,char *parg);*/
+
+#ifdef __GNUC__
+# define __bio_h__attr__ __attribute__
+#else
+# define __bio_h__attr__(x)
+#endif
+int BIO_printf(BIO *bio, const char *format, ...)
+ __bio_h__attr__((__format__(__printf__,2,3)));
+int BIO_vprintf(BIO *bio, const char *format, va_list args)
+ __bio_h__attr__((__format__(__printf__,2,0)));
+int BIO_snprintf(char *buf, size_t n, const char *format, ...)
+ __bio_h__attr__((__format__(__printf__,3,4)));
+int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
+ __bio_h__attr__((__format__(__printf__,3,0)));
+#undef __bio_h__attr__
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_BIO_strings(void);
+
+/* Error codes for the BIO functions. */
+
+/* Function codes. */
+#define BIO_F_ACPT_STATE 100
+#define BIO_F_BIO_ACCEPT 101
+#define BIO_F_BIO_BER_GET_HEADER 102
+#define BIO_F_BIO_CALLBACK_CTRL 131
+#define BIO_F_BIO_CTRL 103
+#define BIO_F_BIO_GETHOSTBYNAME 120
+#define BIO_F_BIO_GETS 104
+#define BIO_F_BIO_GET_ACCEPT_SOCKET 105
+#define BIO_F_BIO_GET_HOST_IP 106
+#define BIO_F_BIO_GET_PORT 107
+#define BIO_F_BIO_MAKE_PAIR 121
+#define BIO_F_BIO_NEW 108
+#define BIO_F_BIO_NEW_FILE 109
+#define BIO_F_BIO_NEW_MEM_BUF 126
+#define BIO_F_BIO_NREAD 123
+#define BIO_F_BIO_NREAD0 124
+#define BIO_F_BIO_NWRITE 125
+#define BIO_F_BIO_NWRITE0 122
+#define BIO_F_BIO_PUTS 110
+#define BIO_F_BIO_READ 111
+#define BIO_F_BIO_SOCK_INIT 112
+#define BIO_F_BIO_WRITE 113
+#define BIO_F_BUFFER_CTRL 114
+#define BIO_F_CONN_CTRL 127
+#define BIO_F_CONN_STATE 115
+#define BIO_F_FILE_CTRL 116
+#define BIO_F_FILE_READ 130
+#define BIO_F_LINEBUFFER_CTRL 129
+#define BIO_F_MEM_READ 128
+#define BIO_F_MEM_WRITE 117
+#define BIO_F_SSL_NEW 118
+#define BIO_F_WSASTARTUP 119
+
+/* Reason codes. */
+#define BIO_R_ACCEPT_ERROR 100
+#define BIO_R_BAD_FOPEN_MODE 101
+#define BIO_R_BAD_HOSTNAME_LOOKUP 102
+#define BIO_R_BROKEN_PIPE 124
+#define BIO_R_CONNECT_ERROR 103
+#define BIO_R_EOF_ON_MEMORY_BIO 127
+#define BIO_R_ERROR_SETTING_NBIO 104
+#define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET 105
+#define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET 106
+#define BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET 107
+#define BIO_R_INVALID_ARGUMENT 125
+#define BIO_R_INVALID_IP_ADDRESS 108
+#define BIO_R_IN_USE 123
+#define BIO_R_KEEPALIVE 109
+#define BIO_R_NBIO_CONNECT_ERROR 110
+#define BIO_R_NO_ACCEPT_PORT_SPECIFIED 111
+#define BIO_R_NO_HOSTNAME_SPECIFIED 112
+#define BIO_R_NO_PORT_DEFINED 113
+#define BIO_R_NO_PORT_SPECIFIED 114
+#define BIO_R_NO_SUCH_FILE 128
+#define BIO_R_NULL_PARAMETER 115
+#define BIO_R_TAG_MISMATCH 116
+#define BIO_R_UNABLE_TO_BIND_SOCKET 117
+#define BIO_R_UNABLE_TO_CREATE_SOCKET 118
+#define BIO_R_UNABLE_TO_LISTEN_SOCKET 119
+#define BIO_R_UNINITIALIZED 120
+#define BIO_R_UNSUPPORTED_METHOD 121
+#define BIO_R_WRITE_TO_READ_ONLY_BIO 126
+#define BIO_R_WSASTARTUP 122
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/blowfish.h b/src/Mayaqua/win32_inc/openssl/blowfish.h
new file mode 100644
index 00000000..832a97dd
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/blowfish.h
@@ -0,0 +1,129 @@
+/* crypto/bf/blowfish.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BLOWFISH_H
+#define HEADER_BLOWFISH_H
+
+#include <openssl/e_os2.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_BF
+#error BF is disabled.
+#endif
+
+#define BF_ENCRYPT 1
+#define BF_DECRYPT 0
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! BF_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! BF_LONG_LOG2 has to be defined along. !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define BF_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define BF_LONG unsigned long
+#define BF_LONG_LOG2 3
+/*
+ * _CRAY note. I could declare short, but I have no idea what impact
+ * does it have on performance on none-T3E machines. I could declare
+ * int, but at least on C90 sizeof(int) can be chosen at compile time.
+ * So I've chosen long...
+ * <appro@fy.chalmers.se>
+ */
+#else
+#define BF_LONG unsigned int
+#endif
+
+#define BF_ROUNDS 16
+#define BF_BLOCK 8
+
+typedef struct bf_key_st
+ {
+ BF_LONG P[BF_ROUNDS+2];
+ BF_LONG S[4*256];
+ } BF_KEY;
+
+#ifdef OPENSSL_FIPS
+void private_BF_set_key(BF_KEY *key, int len, const unsigned char *data);
+#endif
+void BF_set_key(BF_KEY *key, int len, const unsigned char *data);
+
+void BF_encrypt(BF_LONG *data,const BF_KEY *key);
+void BF_decrypt(BF_LONG *data,const BF_KEY *key);
+
+void BF_ecb_encrypt(const unsigned char *in, unsigned char *out,
+ const BF_KEY *key, int enc);
+void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+ const BF_KEY *schedule, unsigned char *ivec, int enc);
+void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out, long length,
+ const BF_KEY *schedule, unsigned char *ivec, int *num, int enc);
+void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out, long length,
+ const BF_KEY *schedule, unsigned char *ivec, int *num);
+const char *BF_options(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/bn.h b/src/Mayaqua/win32_inc/openssl/bn.h
new file mode 100644
index 00000000..dd9cd3eb
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/bn.h
@@ -0,0 +1,855 @@
+/* crypto/bn/bn.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the Eric Young open source
+ * license provided above.
+ *
+ * The binary polynomial arithmetic software is originally written by
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+#ifndef HEADER_BN_H
+#define HEADER_BN_H
+
+#include <openssl/e_os2.h>
+#ifndef OPENSSL_NO_FP_API
+#include <stdio.h> /* FILE */
+#endif
+#include <openssl/ossl_typ.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These preprocessor symbols control various aspects of the bignum headers and
+ * library code. They're not defined by any "normal" configuration, as they are
+ * intended for development and testing purposes. NB: defining all three can be
+ * useful for debugging application code as well as openssl itself.
+ *
+ * BN_DEBUG - turn on various debugging alterations to the bignum code
+ * BN_DEBUG_RAND - uses random poisoning of unused words to trip up
+ * mismanagement of bignum internals. You must also define BN_DEBUG.
+ */
+/* #define BN_DEBUG */
+/* #define BN_DEBUG_RAND */
+
+#define BN_MUL_COMBA
+#define BN_SQR_COMBA
+#define BN_RECURSION
+
+/* This next option uses the C libraries (2 word)/(1 word) function.
+ * If it is not defined, I use my C version (which is slower).
+ * The reason for this flag is that when the particular C compiler
+ * library routine is used, and the library is linked with a different
+ * compiler, the library is missing. This mostly happens when the
+ * library is built with gcc and then linked using normal cc. This would
+ * be a common occurrence because gcc normally produces code that is
+ * 2 times faster than system compilers for the big number stuff.
+ * For machines with only one compiler (or shared libraries), this should
+ * be on. Again this in only really a problem on machines
+ * using "long long's", are 32bit, and are not using my assembler code. */
+#if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || \
+ defined(OPENSSL_SYS_WIN32) || defined(linux)
+# ifndef BN_DIV2W
+# define BN_DIV2W
+# endif
+#endif
+
+/* assuming long is 64bit - this is the DEC Alpha
+ * unsigned long long is only 64 bits :-(, don't define
+ * BN_LLONG for the DEC Alpha */
+#ifdef SIXTY_FOUR_BIT_LONG
+#define BN_ULLONG unsigned long long
+#define BN_ULONG unsigned long
+#define BN_LONG long
+#define BN_BITS 128
+#define BN_BYTES 8
+#define BN_BITS2 64
+#define BN_BITS4 32
+#define BN_MASK (0xffffffffffffffffffffffffffffffffLL)
+#define BN_MASK2 (0xffffffffffffffffL)
+#define BN_MASK2l (0xffffffffL)
+#define BN_MASK2h (0xffffffff00000000L)
+#define BN_MASK2h1 (0xffffffff80000000L)
+#define BN_TBIT (0x8000000000000000L)
+#define BN_DEC_CONV (10000000000000000000UL)
+#define BN_DEC_FMT1 "%lu"
+#define BN_DEC_FMT2 "%019lu"
+#define BN_DEC_NUM 19
+#endif
+
+/* This is where the long long data type is 64 bits, but long is 32.
+ * For machines where there are 64bit registers, this is the mode to use.
+ * IRIX, on R4000 and above should use this mode, along with the relevant
+ * assembler code :-). Do NOT define BN_LLONG.
+ */
+#ifdef SIXTY_FOUR_BIT
+#undef BN_LLONG
+#undef BN_ULLONG
+#define BN_ULONG unsigned long long
+#define BN_LONG long long
+#define BN_BITS 128
+#define BN_BYTES 8
+#define BN_BITS2 64
+#define BN_BITS4 32
+#define BN_MASK2 (0xffffffffffffffffLL)
+#define BN_MASK2l (0xffffffffL)
+#define BN_MASK2h (0xffffffff00000000LL)
+#define BN_MASK2h1 (0xffffffff80000000LL)
+#define BN_TBIT (0x8000000000000000LL)
+#define BN_DEC_CONV (10000000000000000000ULL)
+#define BN_DEC_FMT1 "%llu"
+#define BN_DEC_FMT2 "%019llu"
+#define BN_DEC_NUM 19
+#endif
+
+#ifdef THIRTY_TWO_BIT
+#ifdef BN_LLONG
+# if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__)
+# define BN_ULLONG unsigned __int64
+# else
+# define BN_ULLONG unsigned long long
+# endif
+#endif
+#define BN_ULONG unsigned long
+#define BN_LONG long
+#define BN_BITS 64
+#define BN_BYTES 4
+#define BN_BITS2 32
+#define BN_BITS4 16
+#ifdef OPENSSL_SYS_WIN32
+/* VC++ doesn't like the LL suffix */
+#define BN_MASK (0xffffffffffffffffL)
+#else
+#define BN_MASK (0xffffffffffffffffLL)
+#endif
+#define BN_MASK2 (0xffffffffL)
+#define BN_MASK2l (0xffff)
+#define BN_MASK2h1 (0xffff8000L)
+#define BN_MASK2h (0xffff0000L)
+#define BN_TBIT (0x80000000L)
+#define BN_DEC_CONV (1000000000L)
+#define BN_DEC_FMT1 "%lu"
+#define BN_DEC_FMT2 "%09lu"
+#define BN_DEC_NUM 9
+#endif
+
+#ifdef SIXTEEN_BIT
+#ifndef BN_DIV2W
+#define BN_DIV2W
+#endif
+#define BN_ULLONG unsigned long
+#define BN_ULONG unsigned short
+#define BN_LONG short
+#define BN_BITS 32
+#define BN_BYTES 2
+#define BN_BITS2 16
+#define BN_BITS4 8
+#define BN_MASK (0xffffffff)
+#define BN_MASK2 (0xffff)
+#define BN_MASK2l (0xff)
+#define BN_MASK2h1 (0xff80)
+#define BN_MASK2h (0xff00)
+#define BN_TBIT (0x8000)
+#define BN_DEC_CONV (100000)
+#define BN_DEC_FMT1 "%u"
+#define BN_DEC_FMT2 "%05u"
+#define BN_DEC_NUM 5
+#endif
+
+#ifdef EIGHT_BIT
+#ifndef BN_DIV2W
+#define BN_DIV2W
+#endif
+#define BN_ULLONG unsigned short
+#define BN_ULONG unsigned char
+#define BN_LONG char
+#define BN_BITS 16
+#define BN_BYTES 1
+#define BN_BITS2 8
+#define BN_BITS4 4
+#define BN_MASK (0xffff)
+#define BN_MASK2 (0xff)
+#define BN_MASK2l (0xf)
+#define BN_MASK2h1 (0xf8)
+#define BN_MASK2h (0xf0)
+#define BN_TBIT (0x80)
+#define BN_DEC_CONV (100)
+#define BN_DEC_FMT1 "%u"
+#define BN_DEC_FMT2 "%02u"
+#define BN_DEC_NUM 2
+#endif
+
+#define BN_DEFAULT_BITS 1280
+
+#define BN_FLG_MALLOCED 0x01
+#define BN_FLG_STATIC_DATA 0x02
+#define BN_FLG_CONSTTIME 0x04 /* avoid leaking exponent information through timing,
+ * BN_mod_exp_mont() will call BN_mod_exp_mont_consttime,
+ * BN_div() will call BN_div_no_branch,
+ * BN_mod_inverse() will call BN_mod_inverse_no_branch.
+ */
+
+#ifndef OPENSSL_NO_DEPRECATED
+#define BN_FLG_EXP_CONSTTIME BN_FLG_CONSTTIME /* deprecated name for the flag */
+ /* avoid leaking exponent information through timings
+ * (BN_mod_exp_mont() will call BN_mod_exp_mont_consttime) */
+#endif
+
+#ifndef OPENSSL_NO_DEPRECATED
+#define BN_FLG_FREE 0x8000 /* used for debuging */
+#endif
+#define BN_set_flags(b,n) ((b)->flags|=(n))
+#define BN_get_flags(b,n) ((b)->flags&(n))
+
+/* get a clone of a BIGNUM with changed flags, for *temporary* use only
+ * (the two BIGNUMs cannot not be used in parallel!) */
+#define BN_with_flags(dest,b,n) ((dest)->d=(b)->d, \
+ (dest)->top=(b)->top, \
+ (dest)->dmax=(b)->dmax, \
+ (dest)->neg=(b)->neg, \
+ (dest)->flags=(((dest)->flags & BN_FLG_MALLOCED) \
+ | ((b)->flags & ~BN_FLG_MALLOCED) \
+ | BN_FLG_STATIC_DATA \
+ | (n)))
+
+/* Already declared in ossl_typ.h */
+#if 0
+typedef struct bignum_st BIGNUM;
+/* Used for temp variables (declaration hidden in bn_lcl.h) */
+typedef struct bignum_ctx BN_CTX;
+typedef struct bn_blinding_st BN_BLINDING;
+typedef struct bn_mont_ctx_st BN_MONT_CTX;
+typedef struct bn_recp_ctx_st BN_RECP_CTX;
+typedef struct bn_gencb_st BN_GENCB;
+#endif
+
+struct bignum_st
+ {
+ BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */
+ int top; /* Index of last used d +1. */
+ /* The next are internal book keeping for bn_expand. */
+ int dmax; /* Size of the d array. */
+ int neg; /* one if the number is negative */
+ int flags;
+ };
+
+/* Used for montgomery multiplication */
+struct bn_mont_ctx_st
+ {
+ int ri; /* number of bits in R */
+ BIGNUM RR; /* used to convert to montgomery form */
+ BIGNUM N; /* The modulus */
+ BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1
+ * (Ni is only stored for bignum algorithm) */
+#if 0
+ /* OpenSSL 0.9.9 preview: */
+ BN_ULONG n0[2];/* least significant word(s) of Ni */
+#else
+ BN_ULONG n0; /* least significant word of Ni */
+#endif
+ int flags;
+ };
+
+/* Used for reciprocal division/mod functions
+ * It cannot be shared between threads
+ */
+struct bn_recp_ctx_st
+ {
+ BIGNUM N; /* the divisor */
+ BIGNUM Nr; /* the reciprocal */
+ int num_bits;
+ int shift;
+ int flags;
+ };
+
+/* Used for slow "generation" functions. */
+struct bn_gencb_st
+ {
+ unsigned int ver; /* To handle binary (in)compatibility */
+ void *arg; /* callback-specific data */
+ union
+ {
+ /* if(ver==1) - handles old style callbacks */
+ void (*cb_1)(int, int, void *);
+ /* if(ver==2) - new callback style */
+ int (*cb_2)(int, int, BN_GENCB *);
+ } cb;
+ };
+/* Wrapper function to make using BN_GENCB easier, */
+int BN_GENCB_call(BN_GENCB *cb, int a, int b);
+/* Macro to populate a BN_GENCB structure with an "old"-style callback */
+#define BN_GENCB_set_old(gencb, callback, cb_arg) { \
+ BN_GENCB *tmp_gencb = (gencb); \
+ tmp_gencb->ver = 1; \
+ tmp_gencb->arg = (cb_arg); \
+ tmp_gencb->cb.cb_1 = (callback); }
+/* Macro to populate a BN_GENCB structure with a "new"-style callback */
+#define BN_GENCB_set(gencb, callback, cb_arg) { \
+ BN_GENCB *tmp_gencb = (gencb); \
+ tmp_gencb->ver = 2; \
+ tmp_gencb->arg = (cb_arg); \
+ tmp_gencb->cb.cb_2 = (callback); }
+
+#define BN_prime_checks 0 /* default: select number of iterations
+ based on the size of the number */
+
+/* number of Miller-Rabin iterations for an error rate of less than 2^-80
+ * for random 'b'-bit input, b >= 100 (taken from table 4.4 in the Handbook
+ * of Applied Cryptography [Menezes, van Oorschot, Vanstone; CRC Press 1996];
+ * original paper: Damgaard, Landrock, Pomerance: Average case error estimates
+ * for the strong probable prime test. -- Math. Comp. 61 (1993) 177-194) */
+#define BN_prime_checks_for_size(b) ((b) >= 1300 ? 2 : \
+ (b) >= 850 ? 3 : \
+ (b) >= 650 ? 4 : \
+ (b) >= 550 ? 5 : \
+ (b) >= 450 ? 6 : \
+ (b) >= 400 ? 7 : \
+ (b) >= 350 ? 8 : \
+ (b) >= 300 ? 9 : \
+ (b) >= 250 ? 12 : \
+ (b) >= 200 ? 15 : \
+ (b) >= 150 ? 18 : \
+ /* b >= 100 */ 27)
+
+#define BN_num_bytes(a) ((BN_num_bits(a)+7)/8)
+
+/* Note that BN_abs_is_word didn't work reliably for w == 0 until 0.9.8 */
+#define BN_abs_is_word(a,w) ((((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w))) || \
+ (((w) == 0) && ((a)->top == 0)))
+#define BN_is_zero(a) ((a)->top == 0)
+#define BN_is_one(a) (BN_abs_is_word((a),1) && !(a)->neg)
+#define BN_is_word(a,w) (BN_abs_is_word((a),(w)) && (!(w) || !(a)->neg))
+#define BN_is_odd(a) (((a)->top > 0) && ((a)->d[0] & 1))
+
+#define BN_one(a) (BN_set_word((a),1))
+#define BN_zero_ex(a) \
+ do { \
+ BIGNUM *_tmp_bn = (a); \
+ _tmp_bn->top = 0; \
+ _tmp_bn->neg = 0; \
+ } while(0)
+#ifdef OPENSSL_NO_DEPRECATED
+#define BN_zero(a) BN_zero_ex(a)
+#else
+#define BN_zero(a) (BN_set_word((a),0))
+#endif
+
+const BIGNUM *BN_value_one(void);
+char * BN_options(void);
+BN_CTX *BN_CTX_new(void);
+#ifndef OPENSSL_NO_DEPRECATED
+void BN_CTX_init(BN_CTX *c);
+#endif
+void BN_CTX_free(BN_CTX *c);
+void BN_CTX_start(BN_CTX *ctx);
+BIGNUM *BN_CTX_get(BN_CTX *ctx);
+void BN_CTX_end(BN_CTX *ctx);
+int BN_rand(BIGNUM *rnd, int bits, int top,int bottom);
+int BN_pseudo_rand(BIGNUM *rnd, int bits, int top,int bottom);
+int BN_rand_range(BIGNUM *rnd, const BIGNUM *range);
+int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range);
+int BN_num_bits(const BIGNUM *a);
+int BN_num_bits_word(BN_ULONG);
+BIGNUM *BN_new(void);
+void BN_init(BIGNUM *);
+void BN_clear_free(BIGNUM *a);
+BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b);
+void BN_swap(BIGNUM *a, BIGNUM *b);
+BIGNUM *BN_bin2bn(const unsigned char *s,int len,BIGNUM *ret);
+int BN_bn2bin(const BIGNUM *a, unsigned char *to);
+BIGNUM *BN_mpi2bn(const unsigned char *s,int len,BIGNUM *ret);
+int BN_bn2mpi(const BIGNUM *a, unsigned char *to);
+int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
+int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
+int BN_sqr(BIGNUM *r, const BIGNUM *a,BN_CTX *ctx);
+/** BN_set_negative sets sign of a BIGNUM
+ * \param b pointer to the BIGNUM object
+ * \param n 0 if the BIGNUM b should be positive and a value != 0 otherwise
+ */
+void BN_set_negative(BIGNUM *b, int n);
+/** BN_is_negative returns 1 if the BIGNUM is negative
+ * \param a pointer to the BIGNUM object
+ * \return 1 if a < 0 and 0 otherwise
+ */
+#define BN_is_negative(a) ((a)->neg != 0)
+
+int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
+ BN_CTX *ctx);
+#define BN_mod(rem,m,d,ctx) BN_div(NULL,(rem),(m),(d),(ctx))
+int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx);
+int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m);
+int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m);
+int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m);
+int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m);
+
+BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w);
+BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w);
+int BN_mul_word(BIGNUM *a, BN_ULONG w);
+int BN_add_word(BIGNUM *a, BN_ULONG w);
+int BN_sub_word(BIGNUM *a, BN_ULONG w);
+int BN_set_word(BIGNUM *a, BN_ULONG w);
+BN_ULONG BN_get_word(const BIGNUM *a);
+
+int BN_cmp(const BIGNUM *a, const BIGNUM *b);
+void BN_free(BIGNUM *a);
+int BN_is_bit_set(const BIGNUM *a, int n);
+int BN_lshift(BIGNUM *r, const BIGNUM *a, int n);
+int BN_lshift1(BIGNUM *r, const BIGNUM *a);
+int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,BN_CTX *ctx);
+
+int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m,BN_CTX *ctx);
+int BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont);
+int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p1,
+ const BIGNUM *a2, const BIGNUM *p2,const BIGNUM *m,
+ BN_CTX *ctx,BN_MONT_CTX *m_ctx);
+int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m,BN_CTX *ctx);
+
+int BN_mask_bits(BIGNUM *a,int n);
+#ifndef OPENSSL_NO_FP_API
+int BN_print_fp(FILE *fp, const BIGNUM *a);
+#endif
+#ifdef HEADER_BIO_H
+int BN_print(BIO *fp, const BIGNUM *a);
+#else
+int BN_print(void *fp, const BIGNUM *a);
+#endif
+int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx);
+int BN_rshift(BIGNUM *r, const BIGNUM *a, int n);
+int BN_rshift1(BIGNUM *r, const BIGNUM *a);
+void BN_clear(BIGNUM *a);
+BIGNUM *BN_dup(const BIGNUM *a);
+int BN_ucmp(const BIGNUM *a, const BIGNUM *b);
+int BN_set_bit(BIGNUM *a, int n);
+int BN_clear_bit(BIGNUM *a, int n);
+char * BN_bn2hex(const BIGNUM *a);
+char * BN_bn2dec(const BIGNUM *a);
+int BN_hex2bn(BIGNUM **a, const char *str);
+int BN_dec2bn(BIGNUM **a, const char *str);
+int BN_gcd(BIGNUM *r,const BIGNUM *a,const BIGNUM *b,BN_CTX *ctx);
+int BN_kronecker(const BIGNUM *a,const BIGNUM *b,BN_CTX *ctx); /* returns -2 for error */
+BIGNUM *BN_mod_inverse(BIGNUM *ret,
+ const BIGNUM *a, const BIGNUM *n,BN_CTX *ctx);
+BIGNUM *BN_mod_sqrt(BIGNUM *ret,
+ const BIGNUM *a, const BIGNUM *n,BN_CTX *ctx);
+
+/* Deprecated versions */
+#ifndef OPENSSL_NO_DEPRECATED
+BIGNUM *BN_generate_prime(BIGNUM *ret,int bits,int safe,
+ const BIGNUM *add, const BIGNUM *rem,
+ void (*callback)(int,int,void *),void *cb_arg);
+int BN_is_prime(const BIGNUM *p,int nchecks,
+ void (*callback)(int,int,void *),
+ BN_CTX *ctx,void *cb_arg);
+int BN_is_prime_fasttest(const BIGNUM *p,int nchecks,
+ void (*callback)(int,int,void *),BN_CTX *ctx,void *cb_arg,
+ int do_trial_division);
+#endif /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* Newer versions */
+int BN_generate_prime_ex(BIGNUM *ret,int bits,int safe, const BIGNUM *add,
+ const BIGNUM *rem, BN_GENCB *cb);
+int BN_is_prime_ex(const BIGNUM *p,int nchecks, BN_CTX *ctx, BN_GENCB *cb);
+int BN_is_prime_fasttest_ex(const BIGNUM *p,int nchecks, BN_CTX *ctx,
+ int do_trial_division, BN_GENCB *cb);
+
+int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx);
+
+int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+ const BIGNUM *Xp, const BIGNUM *Xp1, const BIGNUM *Xp2,
+ const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb);
+int BN_X931_generate_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+ BIGNUM *Xp1, BIGNUM *Xp2,
+ const BIGNUM *Xp,
+ const BIGNUM *e, BN_CTX *ctx,
+ BN_GENCB *cb);
+
+BN_MONT_CTX *BN_MONT_CTX_new(void );
+void BN_MONT_CTX_init(BN_MONT_CTX *ctx);
+int BN_mod_mul_montgomery(BIGNUM *r,const BIGNUM *a,const BIGNUM *b,
+ BN_MONT_CTX *mont, BN_CTX *ctx);
+#define BN_to_montgomery(r,a,mont,ctx) BN_mod_mul_montgomery(\
+ (r),(a),&((mont)->RR),(mont),(ctx))
+int BN_from_montgomery(BIGNUM *r,const BIGNUM *a,
+ BN_MONT_CTX *mont, BN_CTX *ctx);
+void BN_MONT_CTX_free(BN_MONT_CTX *mont);
+int BN_MONT_CTX_set(BN_MONT_CTX *mont,const BIGNUM *mod,BN_CTX *ctx);
+BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to,BN_MONT_CTX *from);
+BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock,
+ const BIGNUM *mod, BN_CTX *ctx);
+
+/* BN_BLINDING flags */
+#define BN_BLINDING_NO_UPDATE 0x00000001
+#define BN_BLINDING_NO_RECREATE 0x00000002
+
+BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, /* const */ BIGNUM *mod);
+void BN_BLINDING_free(BN_BLINDING *b);
+int BN_BLINDING_update(BN_BLINDING *b,BN_CTX *ctx);
+int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
+int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
+int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *);
+int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *);
+unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *);
+void BN_BLINDING_set_thread_id(BN_BLINDING *, unsigned long);
+unsigned long BN_BLINDING_get_flags(const BN_BLINDING *);
+void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long);
+BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
+ const BIGNUM *e, /* const */ BIGNUM *m, BN_CTX *ctx,
+ int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx),
+ BN_MONT_CTX *m_ctx);
+
+#ifndef OPENSSL_NO_DEPRECATED
+void BN_set_params(int mul,int high,int low,int mont);
+int BN_get_params(int which); /* 0, mul, 1 high, 2 low, 3 mont */
+#endif
+
+void BN_RECP_CTX_init(BN_RECP_CTX *recp);
+BN_RECP_CTX *BN_RECP_CTX_new(void);
+void BN_RECP_CTX_free(BN_RECP_CTX *recp);
+int BN_RECP_CTX_set(BN_RECP_CTX *recp,const BIGNUM *rdiv,BN_CTX *ctx);
+int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y,
+ BN_RECP_CTX *recp,BN_CTX *ctx);
+int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx);
+int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
+ BN_RECP_CTX *recp, BN_CTX *ctx);
+
+/* Functions for arithmetic over binary polynomials represented by BIGNUMs.
+ *
+ * The BIGNUM::neg property of BIGNUMs representing binary polynomials is
+ * ignored.
+ *
+ * Note that input arguments are not const so that their bit arrays can
+ * be expanded to the appropriate size if needed.
+ */
+
+int BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); /*r = a + b*/
+#define BN_GF2m_sub(r, a, b) BN_GF2m_add(r, a, b)
+int BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p); /*r=a mod p*/
+int BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *p, BN_CTX *ctx); /* r = (a * b) mod p */
+int BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ BN_CTX *ctx); /* r = (a * a) mod p */
+int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *b, const BIGNUM *p,
+ BN_CTX *ctx); /* r = (1 / b) mod p */
+int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *p, BN_CTX *ctx); /* r = (a / b) mod p */
+int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *p, BN_CTX *ctx); /* r = (a ^ b) mod p */
+int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ BN_CTX *ctx); /* r = sqrt(a) mod p */
+int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ BN_CTX *ctx); /* r^2 + r = a mod p */
+#define BN_GF2m_cmp(a, b) BN_ucmp((a), (b))
+/* Some functions allow for representation of the irreducible polynomials
+ * as an unsigned int[], say p. The irreducible f(t) is then of the form:
+ * t^p[0] + t^p[1] + ... + t^p[k]
+ * where m = p[0] > p[1] > ... > p[k] = 0.
+ */
+int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[]);
+ /* r = a mod p */
+int BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const unsigned int p[], BN_CTX *ctx); /* r = (a * b) mod p */
+int BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[],
+ BN_CTX *ctx); /* r = (a * a) mod p */
+int BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *b, const unsigned int p[],
+ BN_CTX *ctx); /* r = (1 / b) mod p */
+int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const unsigned int p[], BN_CTX *ctx); /* r = (a / b) mod p */
+int BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const unsigned int p[], BN_CTX *ctx); /* r = (a ^ b) mod p */
+int BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a,
+ const unsigned int p[], BN_CTX *ctx); /* r = sqrt(a) mod p */
+int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a,
+ const unsigned int p[], BN_CTX *ctx); /* r^2 + r = a mod p */
+int BN_GF2m_poly2arr(const BIGNUM *a, unsigned int p[], int max);
+int BN_GF2m_arr2poly(const unsigned int p[], BIGNUM *a);
+
+/* faster mod functions for the 'NIST primes'
+ * 0 <= a < p^2 */
+int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+
+const BIGNUM *BN_get0_nist_prime_192(void);
+const BIGNUM *BN_get0_nist_prime_224(void);
+const BIGNUM *BN_get0_nist_prime_256(void);
+const BIGNUM *BN_get0_nist_prime_384(void);
+const BIGNUM *BN_get0_nist_prime_521(void);
+
+/* library internal functions */
+
+#define bn_expand(a,bits) ((((((bits+BN_BITS2-1))/BN_BITS2)) <= (a)->dmax)?\
+ (a):bn_expand2((a),(bits+BN_BITS2-1)/BN_BITS2))
+#define bn_wexpand(a,words) (((words) <= (a)->dmax)?(a):bn_expand2((a),(words)))
+BIGNUM *bn_expand2(BIGNUM *a, int words);
+#ifndef OPENSSL_NO_DEPRECATED
+BIGNUM *bn_dup_expand(const BIGNUM *a, int words); /* unused */
+#endif
+
+/* Bignum consistency macros
+ * There is one "API" macro, bn_fix_top(), for stripping leading zeroes from
+ * bignum data after direct manipulations on the data. There is also an
+ * "internal" macro, bn_check_top(), for verifying that there are no leading
+ * zeroes. Unfortunately, some auditing is required due to the fact that
+ * bn_fix_top() has become an overabused duct-tape because bignum data is
+ * occasionally passed around in an inconsistent state. So the following
+ * changes have been made to sort this out;
+ * - bn_fix_top()s implementation has been moved to bn_correct_top()
+ * - if BN_DEBUG isn't defined, bn_fix_top() maps to bn_correct_top(), and
+ * bn_check_top() is as before.
+ * - if BN_DEBUG *is* defined;
+ * - bn_check_top() tries to pollute unused words even if the bignum 'top' is
+ * consistent. (ed: only if BN_DEBUG_RAND is defined)
+ * - bn_fix_top() maps to bn_check_top() rather than "fixing" anything.
+ * The idea is to have debug builds flag up inconsistent bignums when they
+ * occur. If that occurs in a bn_fix_top(), we examine the code in question; if
+ * the use of bn_fix_top() was appropriate (ie. it follows directly after code
+ * that manipulates the bignum) it is converted to bn_correct_top(), and if it
+ * was not appropriate, we convert it permanently to bn_check_top() and track
+ * down the cause of the bug. Eventually, no internal code should be using the
+ * bn_fix_top() macro. External applications and libraries should try this with
+ * their own code too, both in terms of building against the openssl headers
+ * with BN_DEBUG defined *and* linking with a version of OpenSSL built with it
+ * defined. This not only improves external code, it provides more test
+ * coverage for openssl's own code.
+ */
+
+#ifdef BN_DEBUG
+
+/* We only need assert() when debugging */
+#include <assert.h>
+
+#ifdef BN_DEBUG_RAND
+/* To avoid "make update" cvs wars due to BN_DEBUG, use some tricks */
+#ifndef RAND_pseudo_bytes
+int RAND_pseudo_bytes(unsigned char *buf,int num);
+#define BN_DEBUG_TRIX
+#endif
+#define bn_pollute(a) \
+ do { \
+ const BIGNUM *_bnum1 = (a); \
+ if(_bnum1->top < _bnum1->dmax) { \
+ unsigned char _tmp_char; \
+ /* We cast away const without the compiler knowing, any \
+ * *genuinely* constant variables that aren't mutable \
+ * wouldn't be constructed with top!=dmax. */ \
+ BN_ULONG *_not_const; \
+ memcpy(&_not_const, &_bnum1->d, sizeof(BN_ULONG*)); \
+ RAND_pseudo_bytes(&_tmp_char, 1); \
+ memset((unsigned char *)(_not_const + _bnum1->top), _tmp_char, \
+ (_bnum1->dmax - _bnum1->top) * sizeof(BN_ULONG)); \
+ } \
+ } while(0)
+#ifdef BN_DEBUG_TRIX
+#undef RAND_pseudo_bytes
+#endif
+#else
+#define bn_pollute(a)
+#endif
+#define bn_check_top(a) \
+ do { \
+ const BIGNUM *_bnum2 = (a); \
+ if (_bnum2 != NULL) { \
+ assert((_bnum2->top == 0) || \
+ (_bnum2->d[_bnum2->top - 1] != 0)); \
+ bn_pollute(_bnum2); \
+ } \
+ } while(0)
+
+#define bn_fix_top(a) bn_check_top(a)
+
+#else /* !BN_DEBUG */
+
+#define bn_pollute(a)
+#define bn_check_top(a)
+#define bn_fix_top(a) bn_correct_top(a)
+
+#endif
+
+#define bn_correct_top(a) \
+ { \
+ BN_ULONG *ftl; \
+ if ((a)->top > 0) \
+ { \
+ for (ftl= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \
+ if (*(ftl--)) break; \
+ } \
+ bn_pollute(a); \
+ }
+
+BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
+BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
+void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
+BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
+BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
+BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
+
+/* Primes from RFC 2409 */
+BIGNUM *get_rfc2409_prime_768(BIGNUM *bn);
+BIGNUM *get_rfc2409_prime_1024(BIGNUM *bn);
+
+/* Primes from RFC 3526 */
+BIGNUM *get_rfc3526_prime_1536(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_2048(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_3072(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_4096(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_6144(BIGNUM *bn);
+BIGNUM *get_rfc3526_prime_8192(BIGNUM *bn);
+
+int BN_bntest_rand(BIGNUM *rnd, int bits, int top,int bottom);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_BN_strings(void);
+
+/* Error codes for the BN functions. */
+
+/* Function codes. */
+#define BN_F_BNRAND 127
+#define BN_F_BN_BLINDING_CONVERT_EX 100
+#define BN_F_BN_BLINDING_CREATE_PARAM 128
+#define BN_F_BN_BLINDING_INVERT_EX 101
+#define BN_F_BN_BLINDING_NEW 102
+#define BN_F_BN_BLINDING_UPDATE 103
+#define BN_F_BN_BN2DEC 104
+#define BN_F_BN_BN2HEX 105
+#define BN_F_BN_CTX_GET 116
+#define BN_F_BN_CTX_NEW 106
+#define BN_F_BN_CTX_START 129
+#define BN_F_BN_DIV 107
+#define BN_F_BN_DIV_NO_BRANCH 138
+#define BN_F_BN_DIV_RECP 130
+#define BN_F_BN_EXP 123
+#define BN_F_BN_EXPAND2 108
+#define BN_F_BN_EXPAND_INTERNAL 120
+#define BN_F_BN_GF2M_MOD 131
+#define BN_F_BN_GF2M_MOD_EXP 132
+#define BN_F_BN_GF2M_MOD_MUL 133
+#define BN_F_BN_GF2M_MOD_SOLVE_QUAD 134
+#define BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR 135
+#define BN_F_BN_GF2M_MOD_SQR 136
+#define BN_F_BN_GF2M_MOD_SQRT 137
+#define BN_F_BN_MOD_EXP2_MONT 118
+#define BN_F_BN_MOD_EXP_MONT 109
+#define BN_F_BN_MOD_EXP_MONT_CONSTTIME 124
+#define BN_F_BN_MOD_EXP_MONT_WORD 117
+#define BN_F_BN_MOD_EXP_RECP 125
+#define BN_F_BN_MOD_EXP_SIMPLE 126
+#define BN_F_BN_MOD_INVERSE 110
+#define BN_F_BN_MOD_INVERSE_NO_BRANCH 139
+#define BN_F_BN_MOD_LSHIFT_QUICK 119
+#define BN_F_BN_MOD_MUL_RECIPROCAL 111
+#define BN_F_BN_MOD_SQRT 121
+#define BN_F_BN_MPI2BN 112
+#define BN_F_BN_NEW 113
+#define BN_F_BN_RAND 114
+#define BN_F_BN_RAND_RANGE 122
+#define BN_F_BN_USUB 115
+
+/* Reason codes. */
+#define BN_R_ARG2_LT_ARG3 100
+#define BN_R_BAD_RECIPROCAL 101
+#define BN_R_BIGNUM_TOO_LONG 114
+#define BN_R_CALLED_WITH_EVEN_MODULUS 102
+#define BN_R_DIV_BY_ZERO 103
+#define BN_R_ENCODING_ERROR 104
+#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA 105
+#define BN_R_INPUT_NOT_REDUCED 110
+#define BN_R_INVALID_LENGTH 106
+#define BN_R_INVALID_RANGE 115
+#define BN_R_NOT_A_SQUARE 111
+#define BN_R_NOT_INITIALIZED 107
+#define BN_R_NO_INVERSE 108
+#define BN_R_NO_SOLUTION 116
+#define BN_R_P_IS_NOT_PRIME 112
+#define BN_R_TOO_MANY_ITERATIONS 113
+#define BN_R_TOO_MANY_TEMPORARY_VARIABLES 109
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/buffer.h b/src/Mayaqua/win32_inc/openssl/buffer.h
new file mode 100644
index 00000000..e3f394cb
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/buffer.h
@@ -0,0 +1,118 @@
+/* crypto/buffer/buffer.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BUFFER_H
+#define HEADER_BUFFER_H
+
+#include <openssl/ossl_typ.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+
+#if !defined(NO_SYS_TYPES_H)
+#include <sys/types.h>
+#endif
+
+/* Already declared in ossl_typ.h */
+/* typedef struct buf_mem_st BUF_MEM; */
+
+struct buf_mem_st
+ {
+ int length; /* current number of bytes */
+ char *data;
+ int max; /* size of buffer */
+ };
+
+BUF_MEM *BUF_MEM_new(void);
+void BUF_MEM_free(BUF_MEM *a);
+int BUF_MEM_grow(BUF_MEM *str, int len);
+int BUF_MEM_grow_clean(BUF_MEM *str, int len);
+char * BUF_strdup(const char *str);
+char * BUF_strndup(const char *str, size_t siz);
+void * BUF_memdup(const void *data, size_t siz);
+
+/* safe string functions */
+size_t BUF_strlcpy(char *dst,const char *src,size_t siz);
+size_t BUF_strlcat(char *dst,const char *src,size_t siz);
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_BUF_strings(void);
+
+/* Error codes for the BUF functions. */
+
+/* Function codes. */
+#define BUF_F_BUF_MEMDUP 103
+#define BUF_F_BUF_MEM_GROW 100
+#define BUF_F_BUF_MEM_GROW_CLEAN 105
+#define BUF_F_BUF_MEM_NEW 101
+#define BUF_F_BUF_STRDUP 102
+#define BUF_F_BUF_STRNDUP 104
+
+/* Reason codes. */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/cast.h b/src/Mayaqua/win32_inc/openssl/cast.h
new file mode 100644
index 00000000..fd1bc9cf
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/cast.h
@@ -0,0 +1,107 @@
+/* crypto/cast/cast.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_CAST_H
+#define HEADER_CAST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_CAST
+#error CAST is disabled.
+#endif
+
+#define CAST_ENCRYPT 1
+#define CAST_DECRYPT 0
+
+#define CAST_LONG unsigned long
+
+#define CAST_BLOCK 8
+#define CAST_KEY_LENGTH 16
+
+typedef struct cast_key_st
+ {
+ CAST_LONG data[32];
+ int short_key; /* Use reduced rounds for short key */
+ } CAST_KEY;
+
+#ifdef OPENSSL_FIPS
+void private_CAST_set_key(CAST_KEY *key, int len, const unsigned char *data);
+#endif
+void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data);
+void CAST_ecb_encrypt(const unsigned char *in, unsigned char *out, const CAST_KEY *key,
+ int enc);
+void CAST_encrypt(CAST_LONG *data, const CAST_KEY *key);
+void CAST_decrypt(CAST_LONG *data, const CAST_KEY *key);
+void CAST_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+ const CAST_KEY *ks, unsigned char *iv, int enc);
+void CAST_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, const CAST_KEY *schedule, unsigned char *ivec,
+ int *num, int enc);
+void CAST_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, const CAST_KEY *schedule, unsigned char *ivec,
+ int *num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/comp.h b/src/Mayaqua/win32_inc/openssl/comp.h
new file mode 100644
index 00000000..15ad4f24
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/comp.h
@@ -0,0 +1,80 @@
+
+#ifndef HEADER_COMP_H
+#define HEADER_COMP_H
+
+#include <openssl/crypto.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct comp_ctx_st COMP_CTX;
+
+typedef struct comp_method_st
+ {
+ int type; /* NID for compression library */
+ const char *name; /* A text string to identify the library */
+ int (*init)(COMP_CTX *ctx);
+ void (*finish)(COMP_CTX *ctx);
+ int (*compress)(COMP_CTX *ctx,
+ unsigned char *out, unsigned int olen,
+ unsigned char *in, unsigned int ilen);
+ int (*expand)(COMP_CTX *ctx,
+ unsigned char *out, unsigned int olen,
+ unsigned char *in, unsigned int ilen);
+ /* The following two do NOTHING, but are kept for backward compatibility */
+ long (*ctrl)(void);
+ long (*callback_ctrl)(void);
+ } COMP_METHOD;
+
+struct comp_ctx_st
+ {
+ COMP_METHOD *meth;
+ unsigned long compress_in;
+ unsigned long compress_out;
+ unsigned long expand_in;
+ unsigned long expand_out;
+
+ CRYPTO_EX_DATA ex_data;
+ };
+
+
+COMP_CTX *COMP_CTX_new(COMP_METHOD *meth);
+void COMP_CTX_free(COMP_CTX *ctx);
+int COMP_compress_block(COMP_CTX *ctx, unsigned char *out, int olen,
+ unsigned char *in, int ilen);
+int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen,
+ unsigned char *in, int ilen);
+COMP_METHOD *COMP_rle(void );
+COMP_METHOD *COMP_zlib(void );
+void COMP_zlib_cleanup(void);
+
+#ifdef HEADER_BIO_H
+#ifdef ZLIB
+BIO_METHOD *BIO_f_zlib(void);
+#endif
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_COMP_strings(void);
+
+/* Error codes for the COMP functions. */
+
+/* Function codes. */
+#define COMP_F_BIO_ZLIB_FLUSH 99
+#define COMP_F_BIO_ZLIB_NEW 100
+#define COMP_F_BIO_ZLIB_READ 101
+#define COMP_F_BIO_ZLIB_WRITE 102
+
+/* Reason codes. */
+#define COMP_R_ZLIB_DEFLATE_ERROR 99
+#define COMP_R_ZLIB_INFLATE_ERROR 100
+#define COMP_R_ZLIB_NOT_SUPPORTED 101
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/conf.h b/src/Mayaqua/win32_inc/openssl/conf.h
new file mode 100644
index 00000000..5ae4b90d
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/conf.h
@@ -0,0 +1,254 @@
+/* crypto/conf/conf.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_CONF_H
+#define HEADER_CONF_H
+
+#include <openssl/bio.h>
+#include <openssl/lhash.h>
+#include <openssl/stack.h>
+#include <openssl/safestack.h>
+#include <openssl/e_os2.h>
+
+#include <openssl/ossl_typ.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct
+ {
+ char *section;
+ char *name;
+ char *value;
+ } CONF_VALUE;
+
+DECLARE_STACK_OF(CONF_VALUE)
+DECLARE_STACK_OF(CONF_MODULE)
+DECLARE_STACK_OF(CONF_IMODULE)
+
+struct conf_st;
+struct conf_method_st;
+typedef struct conf_method_st CONF_METHOD;
+
+struct conf_method_st
+ {
+ const char *name;
+ CONF *(*create)(CONF_METHOD *meth);
+ int (*init)(CONF *conf);
+ int (*destroy)(CONF *conf);
+ int (*destroy_data)(CONF *conf);
+ int (*load_bio)(CONF *conf, BIO *bp, long *eline);
+ int (*dump)(const CONF *conf, BIO *bp);
+ int (*is_number)(const CONF *conf, char c);
+ int (*to_int)(const CONF *conf, char c);
+ int (*load)(CONF *conf, const char *name, long *eline);
+ };
+
+/* Module definitions */
+
+typedef struct conf_imodule_st CONF_IMODULE;
+typedef struct conf_module_st CONF_MODULE;
+
+/* DSO module function typedefs */
+typedef int conf_init_func(CONF_IMODULE *md, const CONF *cnf);
+typedef void conf_finish_func(CONF_IMODULE *md);
+
+#define CONF_MFLAGS_IGNORE_ERRORS 0x1
+#define CONF_MFLAGS_IGNORE_RETURN_CODES 0x2
+#define CONF_MFLAGS_SILENT 0x4
+#define CONF_MFLAGS_NO_DSO 0x8
+#define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10
+#define CONF_MFLAGS_DEFAULT_SECTION 0x20
+
+int CONF_set_default_method(CONF_METHOD *meth);
+void CONF_set_nconf(CONF *conf,LHASH *hash);
+LHASH *CONF_load(LHASH *conf,const char *file,long *eline);
+#ifndef OPENSSL_NO_FP_API
+LHASH *CONF_load_fp(LHASH *conf, FILE *fp,long *eline);
+#endif
+LHASH *CONF_load_bio(LHASH *conf, BIO *bp,long *eline);
+STACK_OF(CONF_VALUE) *CONF_get_section(LHASH *conf,const char *section);
+char *CONF_get_string(LHASH *conf,const char *group,const char *name);
+long CONF_get_number(LHASH *conf,const char *group,const char *name);
+void CONF_free(LHASH *conf);
+int CONF_dump_fp(LHASH *conf, FILE *out);
+int CONF_dump_bio(LHASH *conf, BIO *out);
+
+void OPENSSL_config(const char *config_name);
+void OPENSSL_no_config(void);
+
+/* New conf code. The semantics are different from the functions above.
+ If that wasn't the case, the above functions would have been replaced */
+
+struct conf_st
+ {
+ CONF_METHOD *meth;
+ void *meth_data;
+ LHASH *data;
+ };
+
+CONF *NCONF_new(CONF_METHOD *meth);
+CONF_METHOD *NCONF_default(void);
+CONF_METHOD *NCONF_WIN32(void);
+#if 0 /* Just to give you an idea of what I have in mind */
+CONF_METHOD *NCONF_XML(void);
+#endif
+void NCONF_free(CONF *conf);
+void NCONF_free_data(CONF *conf);
+
+int NCONF_load(CONF *conf,const char *file,long *eline);
+#ifndef OPENSSL_NO_FP_API
+int NCONF_load_fp(CONF *conf, FILE *fp,long *eline);
+#endif
+int NCONF_load_bio(CONF *conf, BIO *bp,long *eline);
+STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf,const char *section);
+char *NCONF_get_string(const CONF *conf,const char *group,const char *name);
+int NCONF_get_number_e(const CONF *conf,const char *group,const char *name,
+ long *result);
+int NCONF_dump_fp(const CONF *conf, FILE *out);
+int NCONF_dump_bio(const CONF *conf, BIO *out);
+
+#if 0 /* The following function has no error checking,
+ and should therefore be avoided */
+long NCONF_get_number(CONF *conf,char *group,char *name);
+#else
+#define NCONF_get_number(c,g,n,r) NCONF_get_number_e(c,g,n,r)
+#endif
+
+/* Module functions */
+
+int CONF_modules_load(const CONF *cnf, const char *appname,
+ unsigned long flags);
+int CONF_modules_load_file(const char *filename, const char *appname,
+ unsigned long flags);
+void CONF_modules_unload(int all);
+void CONF_modules_finish(void);
+void CONF_modules_free(void);
+int CONF_module_add(const char *name, conf_init_func *ifunc,
+ conf_finish_func *ffunc);
+
+const char *CONF_imodule_get_name(const CONF_IMODULE *md);
+const char *CONF_imodule_get_value(const CONF_IMODULE *md);
+void *CONF_imodule_get_usr_data(const CONF_IMODULE *md);
+void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data);
+CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md);
+unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md);
+void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags);
+void *CONF_module_get_usr_data(CONF_MODULE *pmod);
+void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data);
+
+char *CONF_get1_default_config_file(void);
+
+int CONF_parse_list(const char *list, int sep, int nospc,
+ int (*list_cb)(const char *elem, int len, void *usr), void *arg);
+
+void OPENSSL_load_builtin_modules(void);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_CONF_strings(void);
+
+/* Error codes for the CONF functions. */
+
+/* Function codes. */
+#define CONF_F_CONF_DUMP_FP 104
+#define CONF_F_CONF_LOAD 100
+#define CONF_F_CONF_LOAD_BIO 102
+#define CONF_F_CONF_LOAD_FP 103
+#define CONF_F_CONF_MODULES_LOAD 116
+#define CONF_F_DEF_LOAD 120
+#define CONF_F_DEF_LOAD_BIO 121
+#define CONF_F_MODULE_INIT 115
+#define CONF_F_MODULE_LOAD_DSO 117
+#define CONF_F_MODULE_RUN 118
+#define CONF_F_NCONF_DUMP_BIO 105
+#define CONF_F_NCONF_DUMP_FP 106
+#define CONF_F_NCONF_GET_NUMBER 107
+#define CONF_F_NCONF_GET_NUMBER_E 112
+#define CONF_F_NCONF_GET_SECTION 108
+#define CONF_F_NCONF_GET_STRING 109
+#define CONF_F_NCONF_LOAD 113
+#define CONF_F_NCONF_LOAD_BIO 110
+#define CONF_F_NCONF_LOAD_FP 114
+#define CONF_F_NCONF_NEW 111
+#define CONF_F_STR_COPY 101
+
+/* Reason codes. */
+#define CONF_R_ERROR_LOADING_DSO 110
+#define CONF_R_MISSING_CLOSE_SQUARE_BRACKET 100
+#define CONF_R_MISSING_EQUAL_SIGN 101
+#define CONF_R_MISSING_FINISH_FUNCTION 111
+#define CONF_R_MISSING_INIT_FUNCTION 112
+#define CONF_R_MODULE_INITIALIZATION_ERROR 109
+#define CONF_R_NO_CLOSE_BRACE 102
+#define CONF_R_NO_CONF 105
+#define CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE 106
+#define CONF_R_NO_SECTION 107
+#define CONF_R_NO_SUCH_FILE 114
+#define CONF_R_NO_VALUE 108
+#define CONF_R_UNABLE_TO_CREATE_NEW_SECTION 103
+#define CONF_R_UNKNOWN_MODULE_NAME 113
+#define CONF_R_VARIABLE_HAS_NO_VALUE 104
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/conf_api.h b/src/Mayaqua/win32_inc/openssl/conf_api.h
new file mode 100644
index 00000000..8e7d5d50
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/conf_api.h
@@ -0,0 +1,89 @@
+/* conf_api.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_CONF_API_H
+#define HEADER_CONF_API_H
+
+#include <openssl/lhash.h>
+#include <openssl/conf.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Up until OpenSSL 0.9.5a, this was new_section */
+CONF_VALUE *_CONF_new_section(CONF *conf, const char *section);
+/* Up until OpenSSL 0.9.5a, this was get_section */
+CONF_VALUE *_CONF_get_section(const CONF *conf, const char *section);
+/* Up until OpenSSL 0.9.5a, this was CONF_get_section */
+STACK_OF(CONF_VALUE) *_CONF_get_section_values(const CONF *conf,
+ const char *section);
+
+int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value);
+char *_CONF_get_string(const CONF *conf, const char *section,
+ const char *name);
+long _CONF_get_number(const CONF *conf, const char *section, const char *name);
+
+int _CONF_new_data(CONF *conf);
+void _CONF_free_data(CONF *conf);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/crypto.h b/src/Mayaqua/win32_inc/openssl/crypto.h
new file mode 100644
index 00000000..60ad49b3
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/crypto.h
@@ -0,0 +1,619 @@
+/* crypto/crypto.h */
+/* ====================================================================
+ * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_CRYPTO_H
+#define HEADER_CRYPTO_H
+
+#include <stdlib.h>
+
+#include <openssl/e_os2.h>
+
+#ifndef OPENSSL_NO_FP_API
+#include <stdio.h>
+#endif
+
+#include <openssl/stack.h>
+#include <openssl/safestack.h>
+#include <openssl/opensslv.h>
+#include <openssl/ossl_typ.h>
+
+#ifdef CHARSET_EBCDIC
+#include <openssl/ebcdic.h>
+#endif
+
+/* Resolve problems on some operating systems with symbol names that clash
+ one way or another */
+#include <openssl/symhacks.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Backward compatibility to SSLeay */
+/* This is more to be used to check the correct DLL is being used
+ * in the MS world. */
+#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER
+#define SSLEAY_VERSION 0
+/* #define SSLEAY_OPTIONS 1 no longer supported */
+#define SSLEAY_CFLAGS 2
+#define SSLEAY_BUILT_ON 3
+#define SSLEAY_PLATFORM 4
+#define SSLEAY_DIR 5
+
+/* Already declared in ossl_typ.h */
+#if 0
+typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
+/* Called when a new object is created */
+typedef int CRYPTO_EX_new(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+ int idx, long argl, void *argp);
+/* Called when an object is free()ed */
+typedef void CRYPTO_EX_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+ int idx, long argl, void *argp);
+/* Called when we need to dup an object */
+typedef int CRYPTO_EX_dup(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, void *from_d,
+ int idx, long argl, void *argp);
+#endif
+
+/* A generic structure to pass assorted data in a expandable way */
+typedef struct openssl_item_st
+ {
+ int code;
+ void *value; /* Not used for flag attributes */
+ size_t value_size; /* Max size of value for output, length for input */
+ size_t *value_length; /* Returned length of value for output */
+ } OPENSSL_ITEM;
+
+
+/* When changing the CRYPTO_LOCK_* list, be sure to maintin the text lock
+ * names in cryptlib.c
+ */
+
+#define CRYPTO_LOCK_ERR 1
+#define CRYPTO_LOCK_EX_DATA 2
+#define CRYPTO_LOCK_X509 3
+#define CRYPTO_LOCK_X509_INFO 4
+#define CRYPTO_LOCK_X509_PKEY 5
+#define CRYPTO_LOCK_X509_CRL 6
+#define CRYPTO_LOCK_X509_REQ 7
+#define CRYPTO_LOCK_DSA 8
+#define CRYPTO_LOCK_RSA 9
+#define CRYPTO_LOCK_EVP_PKEY 10
+#define CRYPTO_LOCK_X509_STORE 11
+#define CRYPTO_LOCK_SSL_CTX 12
+#define CRYPTO_LOCK_SSL_CERT 13
+#define CRYPTO_LOCK_SSL_SESSION 14
+#define CRYPTO_LOCK_SSL_SESS_CERT 15
+#define CRYPTO_LOCK_SSL 16
+#define CRYPTO_LOCK_SSL_METHOD 17
+#define CRYPTO_LOCK_RAND 18
+#define CRYPTO_LOCK_RAND2 19
+#define CRYPTO_LOCK_MALLOC 20
+#define CRYPTO_LOCK_BIO 21
+#define CRYPTO_LOCK_GETHOSTBYNAME 22
+#define CRYPTO_LOCK_GETSERVBYNAME 23
+#define CRYPTO_LOCK_READDIR 24
+#define CRYPTO_LOCK_RSA_BLINDING 25
+#define CRYPTO_LOCK_DH 26
+#define CRYPTO_LOCK_MALLOC2 27
+#define CRYPTO_LOCK_DSO 28
+#define CRYPTO_LOCK_DYNLOCK 29
+#define CRYPTO_LOCK_ENGINE 30
+#define CRYPTO_LOCK_UI 31
+#define CRYPTO_LOCK_ECDSA 32
+#define CRYPTO_LOCK_EC 33
+#define CRYPTO_LOCK_ECDH 34
+#define CRYPTO_LOCK_BN 35
+#define CRYPTO_LOCK_EC_PRE_COMP 36
+#define CRYPTO_LOCK_STORE 37
+#define CRYPTO_LOCK_COMP 38
+#ifndef OPENSSL_FIPS
+#define CRYPTO_NUM_LOCKS 39
+#else
+#define CRYPTO_LOCK_FIPS 39
+#define CRYPTO_LOCK_FIPS2 40
+#define CRYPTO_NUM_LOCKS 41
+#endif
+
+#define CRYPTO_LOCK 1
+#define CRYPTO_UNLOCK 2
+#define CRYPTO_READ 4
+#define CRYPTO_WRITE 8
+
+#ifndef OPENSSL_NO_LOCKING
+#ifndef CRYPTO_w_lock
+#define CRYPTO_w_lock(type) \
+ CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
+#define CRYPTO_w_unlock(type) \
+ CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
+#define CRYPTO_r_lock(type) \
+ CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,__FILE__,__LINE__)
+#define CRYPTO_r_unlock(type) \
+ CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,__FILE__,__LINE__)
+#define CRYPTO_add(addr,amount,type) \
+ CRYPTO_add_lock(addr,amount,type,__FILE__,__LINE__)
+#endif
+#else
+#define CRYPTO_w_lock(a)
+#define CRYPTO_w_unlock(a)
+#define CRYPTO_r_lock(a)
+#define CRYPTO_r_unlock(a)
+#define CRYPTO_add(a,b,c) ((*(a))+=(b))
+#endif
+
+/* Some applications as well as some parts of OpenSSL need to allocate
+ and deallocate locks in a dynamic fashion. The following typedef
+ makes this possible in a type-safe manner. */
+/* struct CRYPTO_dynlock_value has to be defined by the application. */
+typedef struct
+ {
+ int references;
+ struct CRYPTO_dynlock_value *data;
+ } CRYPTO_dynlock;
+
+
+/* The following can be used to detect memory leaks in the SSLeay library.
+ * It used, it turns on malloc checking */
+
+#define CRYPTO_MEM_CHECK_OFF 0x0 /* an enume */
+#define CRYPTO_MEM_CHECK_ON 0x1 /* a bit */
+#define CRYPTO_MEM_CHECK_ENABLE 0x2 /* a bit */
+#define CRYPTO_MEM_CHECK_DISABLE 0x3 /* an enume */
+
+/* The following are bit values to turn on or off options connected to the
+ * malloc checking functionality */
+
+/* Adds time to the memory checking information */
+#define V_CRYPTO_MDEBUG_TIME 0x1 /* a bit */
+/* Adds thread number to the memory checking information */
+#define V_CRYPTO_MDEBUG_THREAD 0x2 /* a bit */
+
+#define V_CRYPTO_MDEBUG_ALL (V_CRYPTO_MDEBUG_TIME | V_CRYPTO_MDEBUG_THREAD)
+
+
+/* predec of the BIO type */
+typedef struct bio_st BIO_dummy;
+
+struct crypto_ex_data_st
+ {
+ STACK *sk;
+ int dummy; /* gcc is screwing up this data structure :-( */
+ };
+
+/* This stuff is basically class callback functions
+ * The current classes are SSL_CTX, SSL, SSL_SESSION, and a few more */
+
+typedef struct crypto_ex_data_func_st
+ {
+ long argl; /* Arbitary long */
+ void *argp; /* Arbitary void * */
+ CRYPTO_EX_new *new_func;
+ CRYPTO_EX_free *free_func;
+ CRYPTO_EX_dup *dup_func;
+ } CRYPTO_EX_DATA_FUNCS;
+
+DECLARE_STACK_OF(CRYPTO_EX_DATA_FUNCS)
+
+/* Per class, we have a STACK of CRYPTO_EX_DATA_FUNCS for each CRYPTO_EX_DATA
+ * entry.
+ */
+
+#define CRYPTO_EX_INDEX_BIO 0
+#define CRYPTO_EX_INDEX_SSL 1
+#define CRYPTO_EX_INDEX_SSL_CTX 2
+#define CRYPTO_EX_INDEX_SSL_SESSION 3
+#define CRYPTO_EX_INDEX_X509_STORE 4
+#define CRYPTO_EX_INDEX_X509_STORE_CTX 5
+#define CRYPTO_EX_INDEX_RSA 6
+#define CRYPTO_EX_INDEX_DSA 7
+#define CRYPTO_EX_INDEX_DH 8
+#define CRYPTO_EX_INDEX_ENGINE 9
+#define CRYPTO_EX_INDEX_X509 10
+#define CRYPTO_EX_INDEX_UI 11
+#define CRYPTO_EX_INDEX_ECDSA 12
+#define CRYPTO_EX_INDEX_ECDH 13
+#define CRYPTO_EX_INDEX_COMP 14
+#define CRYPTO_EX_INDEX_STORE 15
+
+/* Dynamically assigned indexes start from this value (don't use directly, use
+ * via CRYPTO_ex_data_new_class). */
+#define CRYPTO_EX_INDEX_USER 100
+
+
+/* This is the default callbacks, but we can have others as well:
+ * this is needed in Win32 where the application malloc and the
+ * library malloc may not be the same.
+ */
+#define CRYPTO_malloc_init() CRYPTO_set_mem_functions(\
+ malloc, realloc, free)
+
+#if defined CRYPTO_MDEBUG_ALL || defined CRYPTO_MDEBUG_TIME || defined CRYPTO_MDEBUG_THREAD
+# ifndef CRYPTO_MDEBUG /* avoid duplicate #define */
+# define CRYPTO_MDEBUG
+# endif
+#endif
+
+/* Set standard debugging functions (not done by default
+ * unless CRYPTO_MDEBUG is defined) */
+void CRYPTO_malloc_debug_init(void);
+
+int CRYPTO_mem_ctrl(int mode);
+int CRYPTO_is_mem_check_on(void);
+
+/* for applications */
+#define MemCheck_start() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON)
+#define MemCheck_stop() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF)
+
+/* for library-internal use */
+#define MemCheck_on() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE)
+#define MemCheck_off() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE)
+#define is_MemCheck_on() CRYPTO_is_mem_check_on()
+
+#define OPENSSL_malloc(num) CRYPTO_malloc((int)num,__FILE__,__LINE__)
+#define OPENSSL_strdup(str) CRYPTO_strdup((str),__FILE__,__LINE__)
+#define OPENSSL_realloc(addr,num) \
+ CRYPTO_realloc((char *)addr,(int)num,__FILE__,__LINE__)
+#define OPENSSL_realloc_clean(addr,old_num,num) \
+ CRYPTO_realloc_clean(addr,old_num,num,__FILE__,__LINE__)
+#define OPENSSL_remalloc(addr,num) \
+ CRYPTO_remalloc((char **)addr,(int)num,__FILE__,__LINE__)
+#define OPENSSL_freeFunc CRYPTO_free
+#define OPENSSL_free(addr) CRYPTO_free(addr)
+
+#define OPENSSL_malloc_locked(num) \
+ CRYPTO_malloc_locked((int)num,__FILE__,__LINE__)
+#define OPENSSL_free_locked(addr) CRYPTO_free_locked(addr)
+
+
+const char *SSLeay_version(int type);
+unsigned long SSLeay(void);
+
+int OPENSSL_issetugid(void);
+
+/* An opaque type representing an implementation of "ex_data" support */
+typedef struct st_CRYPTO_EX_DATA_IMPL CRYPTO_EX_DATA_IMPL;
+/* Return an opaque pointer to the current "ex_data" implementation */
+const CRYPTO_EX_DATA_IMPL *CRYPTO_get_ex_data_implementation(void);
+/* Sets the "ex_data" implementation to be used (if it's not too late) */
+int CRYPTO_set_ex_data_implementation(const CRYPTO_EX_DATA_IMPL *i);
+/* Get a new "ex_data" class, and return the corresponding "class_index" */
+int CRYPTO_ex_data_new_class(void);
+/* Within a given class, get/register a new index */
+int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
+ CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
+ CRYPTO_EX_free *free_func);
+/* Initialise/duplicate/free CRYPTO_EX_DATA variables corresponding to a given
+ * class (invokes whatever per-class callbacks are applicable) */
+int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad);
+int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
+ CRYPTO_EX_DATA *from);
+void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad);
+/* Get/set data in a CRYPTO_EX_DATA variable corresponding to a particular index
+ * (relative to the class type involved) */
+int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val);
+void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad,int idx);
+/* This function cleans up all "ex_data" state. It mustn't be called under
+ * potential race-conditions. */
+void CRYPTO_cleanup_all_ex_data(void);
+
+int CRYPTO_get_new_lockid(char *name);
+
+int CRYPTO_num_locks(void); /* return CRYPTO_NUM_LOCKS (shared libs!) */
+void CRYPTO_lock(int mode, int type,const char *file,int line);
+void CRYPTO_set_locking_callback(void (*func)(int mode,int type,
+ const char *file,int line));
+void (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file,
+ int line);
+void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type,
+ const char *file, int line));
+int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type,
+ const char *file,int line);
+void CRYPTO_set_id_callback(unsigned long (*func)(void));
+unsigned long (*CRYPTO_get_id_callback(void))(void);
+unsigned long CRYPTO_thread_id(void);
+const char *CRYPTO_get_lock_name(int type);
+int CRYPTO_add_lock(int *pointer,int amount,int type, const char *file,
+ int line);
+
+void int_CRYPTO_set_do_dynlock_callback(
+ void (*do_dynlock_cb)(int mode, int type, const char *file, int line));
+
+int CRYPTO_get_new_dynlockid(void);
+void CRYPTO_destroy_dynlockid(int i);
+struct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i);
+void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*dyn_create_function)(const char *file, int line));
+void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line));
+void CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function)(struct CRYPTO_dynlock_value *l, const char *file, int line));
+struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void))(const char *file,int line);
+void (*CRYPTO_get_dynlock_lock_callback(void))(int mode, struct CRYPTO_dynlock_value *l, const char *file,int line);
+void (*CRYPTO_get_dynlock_destroy_callback(void))(struct CRYPTO_dynlock_value *l, const char *file,int line);
+
+/* CRYPTO_set_mem_functions includes CRYPTO_set_locked_mem_functions --
+ * call the latter last if you need different functions */
+int CRYPTO_set_mem_functions(void *(*m)(size_t),void *(*r)(void *,size_t), void (*f)(void *));
+int CRYPTO_set_locked_mem_functions(void *(*m)(size_t), void (*free_func)(void *));
+int CRYPTO_set_mem_ex_functions(void *(*m)(size_t,const char *,int),
+ void *(*r)(void *,size_t,const char *,int),
+ void (*f)(void *));
+int CRYPTO_set_locked_mem_ex_functions(void *(*m)(size_t,const char *,int),
+ void (*free_func)(void *));
+int CRYPTO_set_mem_debug_functions(void (*m)(void *,int,const char *,int,int),
+ void (*r)(void *,void *,int,const char *,int,int),
+ void (*f)(void *,int),
+ void (*so)(long),
+ long (*go)(void));
+void CRYPTO_set_mem_info_functions(
+ int (*push_info_fn)(const char *info, const char *file, int line),
+ int (*pop_info_fn)(void),
+ int (*remove_all_info_fn)(void));
+void CRYPTO_get_mem_functions(void *(**m)(size_t),void *(**r)(void *, size_t), void (**f)(void *));
+void CRYPTO_get_locked_mem_functions(void *(**m)(size_t), void (**f)(void *));
+void CRYPTO_get_mem_ex_functions(void *(**m)(size_t,const char *,int),
+ void *(**r)(void *, size_t,const char *,int),
+ void (**f)(void *));
+void CRYPTO_get_locked_mem_ex_functions(void *(**m)(size_t,const char *,int),
+ void (**f)(void *));
+void CRYPTO_get_mem_debug_functions(void (**m)(void *,int,const char *,int,int),
+ void (**r)(void *,void *,int,const char *,int,int),
+ void (**f)(void *,int),
+ void (**so)(long),
+ long (**go)(void));
+
+void *CRYPTO_malloc_locked(int num, const char *file, int line);
+void CRYPTO_free_locked(void *);
+void *CRYPTO_malloc(int num, const char *file, int line);
+char *CRYPTO_strdup(const char *str, const char *file, int line);
+void CRYPTO_free(void *);
+void *CRYPTO_realloc(void *addr,int num, const char *file, int line);
+void *CRYPTO_realloc_clean(void *addr,int old_num,int num,const char *file,
+ int line);
+void *CRYPTO_remalloc(void *addr,int num, const char *file, int line);
+
+void OPENSSL_cleanse(void *ptr, size_t len);
+
+void CRYPTO_set_mem_debug_options(long bits);
+long CRYPTO_get_mem_debug_options(void);
+
+#define CRYPTO_push_info(info) \
+ CRYPTO_push_info_(info, __FILE__, __LINE__);
+int CRYPTO_push_info_(const char *info, const char *file, int line);
+int CRYPTO_pop_info(void);
+int CRYPTO_remove_all_info(void);
+
+
+/* Default debugging functions (enabled by CRYPTO_malloc_debug_init() macro;
+ * used as default in CRYPTO_MDEBUG compilations): */
+/* The last argument has the following significance:
+ *
+ * 0: called before the actual memory allocation has taken place
+ * 1: called after the actual memory allocation has taken place
+ */
+void CRYPTO_dbg_malloc(void *addr,int num,const char *file,int line,int before_p);
+void CRYPTO_dbg_realloc(void *addr1,void *addr2,int num,const char *file,int line,int before_p);
+void CRYPTO_dbg_free(void *addr,int before_p);
+/* Tell the debugging code about options. By default, the following values
+ * apply:
+ *
+ * 0: Clear all options.
+ * V_CRYPTO_MDEBUG_TIME (1): Set the "Show Time" option.
+ * V_CRYPTO_MDEBUG_THREAD (2): Set the "Show Thread Number" option.
+ * V_CRYPTO_MDEBUG_ALL (3): 1 + 2
+ */
+void CRYPTO_dbg_set_options(long bits);
+long CRYPTO_dbg_get_options(void);
+
+int CRYPTO_dbg_push_info(const char *info, const char *file, int line);
+int CRYPTO_dbg_pop_info(void);
+int CRYPTO_dbg_remove_all_info(void);
+
+#ifndef OPENSSL_NO_FP_API
+void CRYPTO_mem_leaks_fp(FILE *);
+#endif
+void CRYPTO_mem_leaks(struct bio_st *bio);
+/* unsigned long order, char *file, int line, int num_bytes, char *addr */
+typedef void *CRYPTO_MEM_LEAK_CB(unsigned long, const char *, int, int, void *);
+void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb);
+
+/* die if we have to */
+void OpenSSLDie(const char *file,int line,const char *assertion);
+#define OPENSSL_assert(e) (void)((e) ? 0 : (OpenSSLDie(__FILE__, __LINE__, #e),1))
+
+unsigned long *OPENSSL_ia32cap_loc(void);
+#define OPENSSL_ia32cap (*(OPENSSL_ia32cap_loc()))
+int OPENSSL_isservice(void);
+
+#ifdef OPENSSL_FIPS
+#define FIPS_ERROR_IGNORED(alg) OpenSSLDie(__FILE__, __LINE__, \
+ alg " previous FIPS forbidden algorithm error ignored");
+
+#define FIPS_BAD_ABORT(alg) OpenSSLDie(__FILE__, __LINE__, \
+ #alg " Algorithm forbidden in FIPS mode");
+
+#ifdef OPENSSL_FIPS_STRICT
+#define FIPS_BAD_ALGORITHM(alg) FIPS_BAD_ABORT(alg)
+#else
+#define FIPS_BAD_ALGORITHM(alg) \
+ { \
+ FIPSerr(FIPS_F_HASH_FINAL,FIPS_R_NON_FIPS_METHOD); \
+ ERR_add_error_data(2, "Algorithm=", #alg); \
+ return 0; \
+ }
+#endif
+
+/* Low level digest API blocking macro */
+
+#define FIPS_NON_FIPS_MD_Init(alg) \
+ int alg##_Init(alg##_CTX *c) \
+ { \
+ if (FIPS_mode()) \
+ FIPS_BAD_ALGORITHM(alg) \
+ return private_##alg##_Init(c); \
+ } \
+ int private_##alg##_Init(alg##_CTX *c)
+
+/* For ciphers the API often varies from cipher to cipher and each needs to
+ * be treated as a special case. Variable key length ciphers (Blowfish, RC4,
+ * CAST) however are very similar and can use a blocking macro.
+ */
+
+#define FIPS_NON_FIPS_VCIPHER_Init(alg) \
+ void alg##_set_key(alg##_KEY *key, int len, const unsigned char *data) \
+ { \
+ if (FIPS_mode()) \
+ FIPS_BAD_ABORT(alg) \
+ private_##alg##_set_key(key, len, data); \
+ } \
+ void private_##alg##_set_key(alg##_KEY *key, int len, \
+ const unsigned char *data)
+
+#else
+
+#define FIPS_NON_FIPS_VCIPHER_Init(alg) \
+ void alg##_set_key(alg##_KEY *key, int len, const unsigned char *data)
+
+#define FIPS_NON_FIPS_MD_Init(alg) \
+ int alg##_Init(alg##_CTX *c)
+
+#endif /* def OPENSSL_FIPS */
+
+#define OPENSSL_HAVE_INIT 1
+void OPENSSL_init(void);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_CRYPTO_strings(void);
+
+/* Error codes for the CRYPTO functions. */
+
+/* Function codes. */
+#define CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX 100
+#define CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID 103
+#define CRYPTO_F_CRYPTO_GET_NEW_LOCKID 101
+#define CRYPTO_F_CRYPTO_SET_EX_DATA 102
+#define CRYPTO_F_DEF_ADD_INDEX 104
+#define CRYPTO_F_DEF_GET_CLASS 105
+#define CRYPTO_F_INT_DUP_EX_DATA 106
+#define CRYPTO_F_INT_FREE_EX_DATA 107
+#define CRYPTO_F_INT_NEW_EX_DATA 108
+
+/* Reason codes. */
+#define CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK 100
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/des.h b/src/Mayaqua/win32_inc/openssl/des.h
new file mode 100644
index 00000000..bd10b944
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/des.h
@@ -0,0 +1,245 @@
+/* crypto/des/des.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_NEW_DES_H
+#define HEADER_NEW_DES_H
+
+#include <openssl/e_os2.h> /* OPENSSL_EXTERN, OPENSSL_NO_DES,
+ DES_LONG (via openssl/opensslconf.h */
+
+#ifdef OPENSSL_NO_DES
+#error DES is disabled.
+#endif
+
+#ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned char DES_cblock[8];
+typedef /* const */ unsigned char const_DES_cblock[8];
+/* With "const", gcc 2.8.1 on Solaris thinks that DES_cblock *
+ * and const_DES_cblock * are incompatible pointer types. */
+
+typedef struct DES_ks
+ {
+ union
+ {
+ DES_cblock cblock;
+ /* make sure things are correct size on machines with
+ * 8 byte longs */
+ DES_LONG deslong[2];
+ } ks[16];
+ } DES_key_schedule;
+
+#ifndef OPENSSL_DISABLE_OLD_DES_SUPPORT
+# ifndef OPENSSL_ENABLE_OLD_DES_SUPPORT
+# define OPENSSL_ENABLE_OLD_DES_SUPPORT
+# endif
+#endif
+
+#ifdef OPENSSL_ENABLE_OLD_DES_SUPPORT
+# include <openssl/des_old.h>
+#endif
+
+#define DES_KEY_SZ (sizeof(DES_cblock))
+#define DES_SCHEDULE_SZ (sizeof(DES_key_schedule))
+
+#define DES_ENCRYPT 1
+#define DES_DECRYPT 0
+
+#define DES_CBC_MODE 0
+#define DES_PCBC_MODE 1
+
+#define DES_ecb2_encrypt(i,o,k1,k2,e) \
+ DES_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))
+
+#define DES_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
+ DES_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))
+
+#define DES_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
+ DES_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))
+
+#define DES_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
+ DES_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))
+
+OPENSSL_DECLARE_GLOBAL(int,DES_check_key); /* defaults to false */
+#define DES_check_key OPENSSL_GLOBAL_REF(DES_check_key)
+OPENSSL_DECLARE_GLOBAL(int,DES_rw_mode); /* defaults to DES_PCBC_MODE */
+#define DES_rw_mode OPENSSL_GLOBAL_REF(DES_rw_mode)
+
+const char *DES_options(void);
+void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output,
+ DES_key_schedule *ks1,DES_key_schedule *ks2,
+ DES_key_schedule *ks3, int enc);
+DES_LONG DES_cbc_cksum(const unsigned char *input,DES_cblock *output,
+ long length,DES_key_schedule *schedule,
+ const_DES_cblock *ivec);
+/* DES_cbc_encrypt does not update the IV! Use DES_ncbc_encrypt instead. */
+void DES_cbc_encrypt(const unsigned char *input,unsigned char *output,
+ long length,DES_key_schedule *schedule,DES_cblock *ivec,
+ int enc);
+void DES_ncbc_encrypt(const unsigned char *input,unsigned char *output,
+ long length,DES_key_schedule *schedule,DES_cblock *ivec,
+ int enc);
+void DES_xcbc_encrypt(const unsigned char *input,unsigned char *output,
+ long length,DES_key_schedule *schedule,DES_cblock *ivec,
+ const_DES_cblock *inw,const_DES_cblock *outw,int enc);
+void DES_cfb_encrypt(const unsigned char *in,unsigned char *out,int numbits,
+ long length,DES_key_schedule *schedule,DES_cblock *ivec,
+ int enc);
+void DES_ecb_encrypt(const_DES_cblock *input,DES_cblock *output,
+ DES_key_schedule *ks,int enc);
+
+/* This is the DES encryption function that gets called by just about
+ every other DES routine in the library. You should not use this
+ function except to implement 'modes' of DES. I say this because the
+ functions that call this routine do the conversion from 'char *' to
+ long, and this needs to be done to make sure 'non-aligned' memory
+ access do not occur. The characters are loaded 'little endian'.
+ Data is a pointer to 2 unsigned long's and ks is the
+ DES_key_schedule to use. enc, is non zero specifies encryption,
+ zero if decryption. */
+void DES_encrypt1(DES_LONG *data,DES_key_schedule *ks, int enc);
+
+/* This functions is the same as DES_encrypt1() except that the DES
+ initial permutation (IP) and final permutation (FP) have been left
+ out. As for DES_encrypt1(), you should not use this function.
+ It is used by the routines in the library that implement triple DES.
+ IP() DES_encrypt2() DES_encrypt2() DES_encrypt2() FP() is the same
+ as DES_encrypt1() DES_encrypt1() DES_encrypt1() except faster :-). */
+void DES_encrypt2(DES_LONG *data,DES_key_schedule *ks, int enc);
+
+void DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1,
+ DES_key_schedule *ks2, DES_key_schedule *ks3);
+void DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1,
+ DES_key_schedule *ks2, DES_key_schedule *ks3);
+void DES_ede3_cbc_encrypt(const unsigned char *input,unsigned char *output,
+ long length,
+ DES_key_schedule *ks1,DES_key_schedule *ks2,
+ DES_key_schedule *ks3,DES_cblock *ivec,int enc);
+void DES_ede3_cbcm_encrypt(const unsigned char *in,unsigned char *out,
+ long length,
+ DES_key_schedule *ks1,DES_key_schedule *ks2,
+ DES_key_schedule *ks3,
+ DES_cblock *ivec1,DES_cblock *ivec2,
+ int enc);
+void DES_ede3_cfb64_encrypt(const unsigned char *in,unsigned char *out,
+ long length,DES_key_schedule *ks1,
+ DES_key_schedule *ks2,DES_key_schedule *ks3,
+ DES_cblock *ivec,int *num,int enc);
+void DES_ede3_cfb_encrypt(const unsigned char *in,unsigned char *out,
+ int numbits,long length,DES_key_schedule *ks1,
+ DES_key_schedule *ks2,DES_key_schedule *ks3,
+ DES_cblock *ivec,int enc);
+void DES_ede3_ofb64_encrypt(const unsigned char *in,unsigned char *out,
+ long length,DES_key_schedule *ks1,
+ DES_key_schedule *ks2,DES_key_schedule *ks3,
+ DES_cblock *ivec,int *num);
+#if 0
+void DES_xwhite_in2out(const_DES_cblock *DES_key,const_DES_cblock *in_white,
+ DES_cblock *out_white);
+#endif
+
+int DES_enc_read(int fd,void *buf,int len,DES_key_schedule *sched,
+ DES_cblock *iv);
+int DES_enc_write(int fd,const void *buf,int len,DES_key_schedule *sched,
+ DES_cblock *iv);
+char *DES_fcrypt(const char *buf,const char *salt, char *ret);
+char *DES_crypt(const char *buf,const char *salt);
+void DES_ofb_encrypt(const unsigned char *in,unsigned char *out,int numbits,
+ long length,DES_key_schedule *schedule,DES_cblock *ivec);
+void DES_pcbc_encrypt(const unsigned char *input,unsigned char *output,
+ long length,DES_key_schedule *schedule,DES_cblock *ivec,
+ int enc);
+DES_LONG DES_quad_cksum(const unsigned char *input,DES_cblock output[],
+ long length,int out_count,DES_cblock *seed);
+int DES_random_key(DES_cblock *ret);
+void DES_set_odd_parity(DES_cblock *key);
+int DES_check_key_parity(const_DES_cblock *key);
+int DES_is_weak_key(const_DES_cblock *key);
+/* DES_set_key (= set_key = DES_key_sched = key_sched) calls
+ * DES_set_key_checked if global variable DES_check_key is set,
+ * DES_set_key_unchecked otherwise. */
+int DES_set_key(const_DES_cblock *key,DES_key_schedule *schedule);
+int DES_key_sched(const_DES_cblock *key,DES_key_schedule *schedule);
+int DES_set_key_checked(const_DES_cblock *key,DES_key_schedule *schedule);
+void DES_set_key_unchecked(const_DES_cblock *key,DES_key_schedule *schedule);
+void DES_string_to_key(const char *str,DES_cblock *key);
+void DES_string_to_2keys(const char *str,DES_cblock *key1,DES_cblock *key2);
+void DES_cfb64_encrypt(const unsigned char *in,unsigned char *out,long length,
+ DES_key_schedule *schedule,DES_cblock *ivec,int *num,
+ int enc);
+void DES_ofb64_encrypt(const unsigned char *in,unsigned char *out,long length,
+ DES_key_schedule *schedule,DES_cblock *ivec,int *num);
+
+int DES_read_password(DES_cblock *key, const char *prompt, int verify);
+int DES_read_2passwords(DES_cblock *key1, DES_cblock *key2, const char *prompt,
+ int verify);
+
+#define DES_fixup_key_parity DES_set_odd_parity
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/des_old.h b/src/Mayaqua/win32_inc/openssl/des_old.h
new file mode 100644
index 00000000..833899fc
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/des_old.h
@@ -0,0 +1,446 @@
+/* crypto/des/des_old.h -*- mode:C; c-file-style: "eay" -*- */
+
+/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ *
+ * The function names in here are deprecated and are only present to
+ * provide an interface compatible with openssl 0.9.6 and older as
+ * well as libdes. OpenSSL now provides functions where "des_" has
+ * been replaced with "DES_" in the names, to make it possible to
+ * make incompatible changes that are needed for C type security and
+ * other stuff.
+ *
+ * This include files has two compatibility modes:
+ *
+ * - If OPENSSL_DES_LIBDES_COMPATIBILITY is defined, you get an API
+ * that is compatible with libdes and SSLeay.
+ * - If OPENSSL_DES_LIBDES_COMPATIBILITY isn't defined, you get an
+ * API that is compatible with OpenSSL 0.9.5x to 0.9.6x.
+ *
+ * Note that these modes break earlier snapshots of OpenSSL, where
+ * libdes compatibility was the only available mode or (later on) the
+ * prefered compatibility mode. However, after much consideration
+ * (and more or less violent discussions with external parties), it
+ * was concluded that OpenSSL should be compatible with earlier versions
+ * of itself before anything else. Also, in all honesty, libdes is
+ * an old beast that shouldn't really be used any more.
+ *
+ * Please consider starting to use the DES_ functions rather than the
+ * des_ ones. The des_ functions will disappear completely before
+ * OpenSSL 1.0!
+ *
+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ */
+
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_DES_H
+#define HEADER_DES_H
+
+#include <openssl/e_os2.h> /* OPENSSL_EXTERN, OPENSSL_NO_DES, DES_LONG */
+
+#ifdef OPENSSL_NO_DES
+#error DES is disabled.
+#endif
+
+#ifndef HEADER_NEW_DES_H
+#error You must include des.h, not des_old.h directly.
+#endif
+
+#ifdef _KERBEROS_DES_H
+#error <openssl/des_old.h> replaces <kerberos/des.h>.
+#endif
+
+#include <openssl/symhacks.h>
+
+#ifdef OPENSSL_BUILD_SHLIBCRYPTO
+# undef OPENSSL_EXTERN
+# define OPENSSL_EXTERN OPENSSL_EXPORT
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _
+#undef _
+#endif
+
+typedef unsigned char _ossl_old_des_cblock[8];
+typedef struct _ossl_old_des_ks_struct
+ {
+ union {
+ _ossl_old_des_cblock _;
+ /* make sure things are correct size on machines with
+ * 8 byte longs */
+ DES_LONG pad[2];
+ } ks;
+ } _ossl_old_des_key_schedule[16];
+
+#ifndef OPENSSL_DES_LIBDES_COMPATIBILITY
+#define des_cblock DES_cblock
+#define const_des_cblock const_DES_cblock
+#define des_key_schedule DES_key_schedule
+#define des_ecb3_encrypt(i,o,k1,k2,k3,e)\
+ DES_ecb3_encrypt((i),(o),&(k1),&(k2),&(k3),(e))
+#define des_ede3_cbc_encrypt(i,o,l,k1,k2,k3,iv,e)\
+ DES_ede3_cbc_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv),(e))
+#define des_ede3_cbcm_encrypt(i,o,l,k1,k2,k3,iv1,iv2,e)\
+ DES_ede3_cbcm_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv1),(iv2),(e))
+#define des_ede3_cfb64_encrypt(i,o,l,k1,k2,k3,iv,n,e)\
+ DES_ede3_cfb64_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv),(n),(e))
+#define des_ede3_ofb64_encrypt(i,o,l,k1,k2,k3,iv,n)\
+ DES_ede3_ofb64_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv),(n))
+#define des_options()\
+ DES_options()
+#define des_cbc_cksum(i,o,l,k,iv)\
+ DES_cbc_cksum((i),(o),(l),&(k),(iv))
+#define des_cbc_encrypt(i,o,l,k,iv,e)\
+ DES_cbc_encrypt((i),(o),(l),&(k),(iv),(e))
+#define des_ncbc_encrypt(i,o,l,k,iv,e)\
+ DES_ncbc_encrypt((i),(o),(l),&(k),(iv),(e))
+#define des_xcbc_encrypt(i,o,l,k,iv,inw,outw,e)\
+ DES_xcbc_encrypt((i),(o),(l),&(k),(iv),(inw),(outw),(e))
+#define des_cfb_encrypt(i,o,n,l,k,iv,e)\
+ DES_cfb_encrypt((i),(o),(n),(l),&(k),(iv),(e))
+#define des_ecb_encrypt(i,o,k,e)\
+ DES_ecb_encrypt((i),(o),&(k),(e))
+#define des_encrypt1(d,k,e)\
+ DES_encrypt1((d),&(k),(e))
+#define des_encrypt2(d,k,e)\
+ DES_encrypt2((d),&(k),(e))
+#define des_encrypt3(d,k1,k2,k3)\
+ DES_encrypt3((d),&(k1),&(k2),&(k3))
+#define des_decrypt3(d,k1,k2,k3)\
+ DES_decrypt3((d),&(k1),&(k2),&(k3))
+#define des_xwhite_in2out(k,i,o)\
+ DES_xwhite_in2out((k),(i),(o))
+#define des_enc_read(f,b,l,k,iv)\
+ DES_enc_read((f),(b),(l),&(k),(iv))
+#define des_enc_write(f,b,l,k,iv)\
+ DES_enc_write((f),(b),(l),&(k),(iv))
+#define des_fcrypt(b,s,r)\
+ DES_fcrypt((b),(s),(r))
+#if 0
+#define des_crypt(b,s)\
+ DES_crypt((b),(s))
+#if !defined(PERL5) && !defined(__FreeBSD__) && !defined(NeXT) && !defined(__OpenBSD__)
+#define crypt(b,s)\
+ DES_crypt((b),(s))
+#endif
+#endif
+#define des_ofb_encrypt(i,o,n,l,k,iv)\
+ DES_ofb_encrypt((i),(o),(n),(l),&(k),(iv))
+#define des_pcbc_encrypt(i,o,l,k,iv,e)\
+ DES_pcbc_encrypt((i),(o),(l),&(k),(iv),(e))
+#define des_quad_cksum(i,o,l,c,s)\
+ DES_quad_cksum((i),(o),(l),(c),(s))
+#define des_random_seed(k)\
+ _ossl_096_des_random_seed((k))
+#define des_random_key(r)\
+ DES_random_key((r))
+#define des_read_password(k,p,v) \
+ DES_read_password((k),(p),(v))
+#define des_read_2passwords(k1,k2,p,v) \
+ DES_read_2passwords((k1),(k2),(p),(v))
+#define des_set_odd_parity(k)\
+ DES_set_odd_parity((k))
+#define des_check_key_parity(k)\
+ DES_check_key_parity((k))
+#define des_is_weak_key(k)\
+ DES_is_weak_key((k))
+#define des_set_key(k,ks)\
+ DES_set_key((k),&(ks))
+#define des_key_sched(k,ks)\
+ DES_key_sched((k),&(ks))
+#define des_set_key_checked(k,ks)\
+ DES_set_key_checked((k),&(ks))
+#define des_set_key_unchecked(k,ks)\
+ DES_set_key_unchecked((k),&(ks))
+#define des_string_to_key(s,k)\
+ DES_string_to_key((s),(k))
+#define des_string_to_2keys(s,k1,k2)\
+ DES_string_to_2keys((s),(k1),(k2))
+#define des_cfb64_encrypt(i,o,l,ks,iv,n,e)\
+ DES_cfb64_encrypt((i),(o),(l),&(ks),(iv),(n),(e))
+#define des_ofb64_encrypt(i,o,l,ks,iv,n)\
+ DES_ofb64_encrypt((i),(o),(l),&(ks),(iv),(n))
+
+
+#define des_ecb2_encrypt(i,o,k1,k2,e) \
+ des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))
+
+#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
+ des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))
+
+#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
+ des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))
+
+#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
+ des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))
+
+#define des_check_key DES_check_key
+#define des_rw_mode DES_rw_mode
+#else /* libdes compatibility */
+/* Map all symbol names to _ossl_old_des_* form, so we avoid all
+ clashes with libdes */
+#define des_cblock _ossl_old_des_cblock
+#define des_key_schedule _ossl_old_des_key_schedule
+#define des_ecb3_encrypt(i,o,k1,k2,k3,e)\
+ _ossl_old_des_ecb3_encrypt((i),(o),(k1),(k2),(k3),(e))
+#define des_ede3_cbc_encrypt(i,o,l,k1,k2,k3,iv,e)\
+ _ossl_old_des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k3),(iv),(e))
+#define des_ede3_cfb64_encrypt(i,o,l,k1,k2,k3,iv,n,e)\
+ _ossl_old_des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k3),(iv),(n),(e))
+#define des_ede3_ofb64_encrypt(i,o,l,k1,k2,k3,iv,n)\
+ _ossl_old_des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k3),(iv),(n))
+#define des_options()\
+ _ossl_old_des_options()
+#define des_cbc_cksum(i,o,l,k,iv)\
+ _ossl_old_des_cbc_cksum((i),(o),(l),(k),(iv))
+#define des_cbc_encrypt(i,o,l,k,iv,e)\
+ _ossl_old_des_cbc_encrypt((i),(o),(l),(k),(iv),(e))
+#define des_ncbc_encrypt(i,o,l,k,iv,e)\
+ _ossl_old_des_ncbc_encrypt((i),(o),(l),(k),(iv),(e))
+#define des_xcbc_encrypt(i,o,l,k,iv,inw,outw,e)\
+ _ossl_old_des_xcbc_encrypt((i),(o),(l),(k),(iv),(inw),(outw),(e))
+#define des_cfb_encrypt(i,o,n,l,k,iv,e)\
+ _ossl_old_des_cfb_encrypt((i),(o),(n),(l),(k),(iv),(e))
+#define des_ecb_encrypt(i,o,k,e)\
+ _ossl_old_des_ecb_encrypt((i),(o),(k),(e))
+#define des_encrypt(d,k,e)\
+ _ossl_old_des_encrypt((d),(k),(e))
+#define des_encrypt2(d,k,e)\
+ _ossl_old_des_encrypt2((d),(k),(e))
+#define des_encrypt3(d,k1,k2,k3)\
+ _ossl_old_des_encrypt3((d),(k1),(k2),(k3))
+#define des_decrypt3(d,k1,k2,k3)\
+ _ossl_old_des_decrypt3((d),(k1),(k2),(k3))
+#define des_xwhite_in2out(k,i,o)\
+ _ossl_old_des_xwhite_in2out((k),(i),(o))
+#define des_enc_read(f,b,l,k,iv)\
+ _ossl_old_des_enc_read((f),(b),(l),(k),(iv))
+#define des_enc_write(f,b,l,k,iv)\
+ _ossl_old_des_enc_write((f),(b),(l),(k),(iv))
+#define des_fcrypt(b,s,r)\
+ _ossl_old_des_fcrypt((b),(s),(r))
+#define des_crypt(b,s)\
+ _ossl_old_des_crypt((b),(s))
+#if 0
+#define crypt(b,s)\
+ _ossl_old_crypt((b),(s))
+#endif
+#define des_ofb_encrypt(i,o,n,l,k,iv)\
+ _ossl_old_des_ofb_encrypt((i),(o),(n),(l),(k),(iv))
+#define des_pcbc_encrypt(i,o,l,k,iv,e)\
+ _ossl_old_des_pcbc_encrypt((i),(o),(l),(k),(iv),(e))
+#define des_quad_cksum(i,o,l,c,s)\
+ _ossl_old_des_quad_cksum((i),(o),(l),(c),(s))
+#define des_random_seed(k)\
+ _ossl_old_des_random_seed((k))
+#define des_random_key(r)\
+ _ossl_old_des_random_key((r))
+#define des_read_password(k,p,v) \
+ _ossl_old_des_read_password((k),(p),(v))
+#define des_read_2passwords(k1,k2,p,v) \
+ _ossl_old_des_read_2passwords((k1),(k2),(p),(v))
+#define des_set_odd_parity(k)\
+ _ossl_old_des_set_odd_parity((k))
+#define des_is_weak_key(k)\
+ _ossl_old_des_is_weak_key((k))
+#define des_set_key(k,ks)\
+ _ossl_old_des_set_key((k),(ks))
+#define des_key_sched(k,ks)\
+ _ossl_old_des_key_sched((k),(ks))
+#define des_string_to_key(s,k)\
+ _ossl_old_des_string_to_key((s),(k))
+#define des_string_to_2keys(s,k1,k2)\
+ _ossl_old_des_string_to_2keys((s),(k1),(k2))
+#define des_cfb64_encrypt(i,o,l,ks,iv,n,e)\
+ _ossl_old_des_cfb64_encrypt((i),(o),(l),(ks),(iv),(n),(e))
+#define des_ofb64_encrypt(i,o,l,ks,iv,n)\
+ _ossl_old_des_ofb64_encrypt((i),(o),(l),(ks),(iv),(n))
+
+
+#define des_ecb2_encrypt(i,o,k1,k2,e) \
+ des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))
+
+#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \
+ des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))
+
+#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \
+ des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))
+
+#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \
+ des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))
+
+#define des_check_key DES_check_key
+#define des_rw_mode DES_rw_mode
+#endif
+
+const char *_ossl_old_des_options(void);
+void _ossl_old_des_ecb3_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,
+ _ossl_old_des_key_schedule ks1,_ossl_old_des_key_schedule ks2,
+ _ossl_old_des_key_schedule ks3, int enc);
+DES_LONG _ossl_old_des_cbc_cksum(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,
+ long length,_ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec);
+void _ossl_old_des_cbc_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,long length,
+ _ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec,int enc);
+void _ossl_old_des_ncbc_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,long length,
+ _ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec,int enc);
+void _ossl_old_des_xcbc_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,long length,
+ _ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec,
+ _ossl_old_des_cblock *inw,_ossl_old_des_cblock *outw,int enc);
+void _ossl_old_des_cfb_encrypt(unsigned char *in,unsigned char *out,int numbits,
+ long length,_ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec,int enc);
+void _ossl_old_des_ecb_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,
+ _ossl_old_des_key_schedule ks,int enc);
+void _ossl_old_des_encrypt(DES_LONG *data,_ossl_old_des_key_schedule ks, int enc);
+void _ossl_old_des_encrypt2(DES_LONG *data,_ossl_old_des_key_schedule ks, int enc);
+void _ossl_old_des_encrypt3(DES_LONG *data, _ossl_old_des_key_schedule ks1,
+ _ossl_old_des_key_schedule ks2, _ossl_old_des_key_schedule ks3);
+void _ossl_old_des_decrypt3(DES_LONG *data, _ossl_old_des_key_schedule ks1,
+ _ossl_old_des_key_schedule ks2, _ossl_old_des_key_schedule ks3);
+void _ossl_old_des_ede3_cbc_encrypt(_ossl_old_des_cblock *input, _ossl_old_des_cblock *output,
+ long length, _ossl_old_des_key_schedule ks1, _ossl_old_des_key_schedule ks2,
+ _ossl_old_des_key_schedule ks3, _ossl_old_des_cblock *ivec, int enc);
+void _ossl_old_des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out,
+ long length, _ossl_old_des_key_schedule ks1, _ossl_old_des_key_schedule ks2,
+ _ossl_old_des_key_schedule ks3, _ossl_old_des_cblock *ivec, int *num, int enc);
+void _ossl_old_des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out,
+ long length, _ossl_old_des_key_schedule ks1, _ossl_old_des_key_schedule ks2,
+ _ossl_old_des_key_schedule ks3, _ossl_old_des_cblock *ivec, int *num);
+#if 0
+void _ossl_old_des_xwhite_in2out(_ossl_old_des_cblock (*des_key), _ossl_old_des_cblock (*in_white),
+ _ossl_old_des_cblock (*out_white));
+#endif
+
+int _ossl_old_des_enc_read(int fd,char *buf,int len,_ossl_old_des_key_schedule sched,
+ _ossl_old_des_cblock *iv);
+int _ossl_old_des_enc_write(int fd,char *buf,int len,_ossl_old_des_key_schedule sched,
+ _ossl_old_des_cblock *iv);
+char *_ossl_old_des_fcrypt(const char *buf,const char *salt, char *ret);
+char *_ossl_old_des_crypt(const char *buf,const char *salt);
+#if !defined(PERL5) && !defined(NeXT)
+char *_ossl_old_crypt(const char *buf,const char *salt);
+#endif
+void _ossl_old_des_ofb_encrypt(unsigned char *in,unsigned char *out,
+ int numbits,long length,_ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec);
+void _ossl_old_des_pcbc_encrypt(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,long length,
+ _ossl_old_des_key_schedule schedule,_ossl_old_des_cblock *ivec,int enc);
+DES_LONG _ossl_old_des_quad_cksum(_ossl_old_des_cblock *input,_ossl_old_des_cblock *output,
+ long length,int out_count,_ossl_old_des_cblock *seed);
+void _ossl_old_des_random_seed(_ossl_old_des_cblock key);
+void _ossl_old_des_random_key(_ossl_old_des_cblock ret);
+int _ossl_old_des_read_password(_ossl_old_des_cblock *key,const char *prompt,int verify);
+int _ossl_old_des_read_2passwords(_ossl_old_des_cblock *key1,_ossl_old_des_cblock *key2,
+ const char *prompt,int verify);
+void _ossl_old_des_set_odd_parity(_ossl_old_des_cblock *key);
+int _ossl_old_des_is_weak_key(_ossl_old_des_cblock *key);
+int _ossl_old_des_set_key(_ossl_old_des_cblock *key,_ossl_old_des_key_schedule schedule);
+int _ossl_old_des_key_sched(_ossl_old_des_cblock *key,_ossl_old_des_key_schedule schedule);
+void _ossl_old_des_string_to_key(char *str,_ossl_old_des_cblock *key);
+void _ossl_old_des_string_to_2keys(char *str,_ossl_old_des_cblock *key1,_ossl_old_des_cblock *key2);
+void _ossl_old_des_cfb64_encrypt(unsigned char *in, unsigned char *out, long length,
+ _ossl_old_des_key_schedule schedule, _ossl_old_des_cblock *ivec, int *num, int enc);
+void _ossl_old_des_ofb64_encrypt(unsigned char *in, unsigned char *out, long length,
+ _ossl_old_des_key_schedule schedule, _ossl_old_des_cblock *ivec, int *num);
+
+void _ossl_096_des_random_seed(des_cblock *key);
+
+/* The following definitions provide compatibility with the MIT Kerberos
+ * library. The _ossl_old_des_key_schedule structure is not binary compatible. */
+
+#define _KERBEROS_DES_H
+
+#define KRBDES_ENCRYPT DES_ENCRYPT
+#define KRBDES_DECRYPT DES_DECRYPT
+
+#ifdef KERBEROS
+# define ENCRYPT DES_ENCRYPT
+# define DECRYPT DES_DECRYPT
+#endif
+
+#ifndef NCOMPAT
+# define C_Block des_cblock
+# define Key_schedule des_key_schedule
+# define KEY_SZ DES_KEY_SZ
+# define string_to_key des_string_to_key
+# define read_pw_string des_read_pw_string
+# define random_key des_random_key
+# define pcbc_encrypt des_pcbc_encrypt
+# define set_key des_set_key
+# define key_sched des_key_sched
+# define ecb_encrypt des_ecb_encrypt
+# define cbc_encrypt des_cbc_encrypt
+# define ncbc_encrypt des_ncbc_encrypt
+# define xcbc_encrypt des_xcbc_encrypt
+# define cbc_cksum des_cbc_cksum
+# define quad_cksum des_quad_cksum
+# define check_parity des_check_key_parity
+#endif
+
+#define des_fixup_key_parity DES_fixup_key_parity
+
+#ifdef __cplusplus
+}
+#endif
+
+/* for DES_read_pw_string et al */
+#include <openssl/ui_compat.h>
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/dh.h b/src/Mayaqua/win32_inc/openssl/dh.h
new file mode 100644
index 00000000..18d787f9
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/dh.h
@@ -0,0 +1,245 @@
+/* crypto/dh/dh.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_DH_H
+#define HEADER_DH_H
+
+#include <openssl/e_os2.h>
+
+#ifdef OPENSSL_NO_DH
+#error DH is disabled.
+#endif
+
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#include <openssl/ossl_typ.h>
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#endif
+
+#ifndef OPENSSL_DH_MAX_MODULUS_BITS
+# define OPENSSL_DH_MAX_MODULUS_BITS 10000
+#endif
+
+#define OPENSSL_DH_FIPS_MIN_MODULUS_BITS 1024
+
+#define DH_FLAG_CACHE_MONT_P 0x01
+#define DH_FLAG_NO_EXP_CONSTTIME 0x02 /* new with 0.9.7h; the built-in DH
+ * implementation now uses constant time
+ * modular exponentiation for secret exponents
+ * by default. This flag causes the
+ * faster variable sliding window method to
+ * be used for all exponents.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct dh_st DH; */
+/* typedef struct dh_method DH_METHOD; */
+
+struct dh_method
+ {
+ const char *name;
+ /* Methods here */
+ int (*generate_key)(DH *dh);
+ int (*compute_key)(unsigned char *key,const BIGNUM *pub_key,DH *dh);
+ int (*bn_mod_exp)(const DH *dh, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx); /* Can be null */
+
+ int (*init)(DH *dh);
+ int (*finish)(DH *dh);
+ int flags;
+ char *app_data;
+ /* If this is non-NULL, it will be used to generate parameters */
+ int (*generate_params)(DH *dh, int prime_len, int generator, BN_GENCB *cb);
+ };
+
+struct dh_st
+ {
+ /* This first argument is used to pick up errors when
+ * a DH is passed instead of a EVP_PKEY */
+ int pad;
+ int version;
+ BIGNUM *p;
+ BIGNUM *g;
+ long length; /* optional */
+ BIGNUM *pub_key; /* g^x */
+ BIGNUM *priv_key; /* x */
+
+ int flags;
+ BN_MONT_CTX *method_mont_p;
+ /* Place holders if we want to do X9.42 DH */
+ BIGNUM *q;
+ BIGNUM *j;
+ unsigned char *seed;
+ int seedlen;
+ BIGNUM *counter;
+
+ int references;
+ CRYPTO_EX_DATA ex_data;
+ const DH_METHOD *meth;
+ ENGINE *engine;
+ };
+
+#define DH_GENERATOR_2 2
+/* #define DH_GENERATOR_3 3 */
+#define DH_GENERATOR_5 5
+
+/* DH_check error codes */
+#define DH_CHECK_P_NOT_PRIME 0x01
+#define DH_CHECK_P_NOT_SAFE_PRIME 0x02
+#define DH_UNABLE_TO_CHECK_GENERATOR 0x04
+#define DH_NOT_SUITABLE_GENERATOR 0x08
+
+/* DH_check_pub_key error codes */
+#define DH_CHECK_PUBKEY_TOO_SMALL 0x01
+#define DH_CHECK_PUBKEY_TOO_LARGE 0x02
+
+/* primes p where (p-1)/2 is prime too are called "safe"; we define
+ this for backward compatibility: */
+#define DH_CHECK_P_NOT_STRONG_PRIME DH_CHECK_P_NOT_SAFE_PRIME
+
+#define DHparams_dup(x) ASN1_dup_of_const(DH,i2d_DHparams,d2i_DHparams,x)
+#define d2i_DHparams_fp(fp,x) (DH *)ASN1_d2i_fp((char *(*)())DH_new, \
+ (char *(*)())d2i_DHparams,(fp),(unsigned char **)(x))
+#define i2d_DHparams_fp(fp,x) ASN1_i2d_fp(i2d_DHparams,(fp), \
+ (unsigned char *)(x))
+#define d2i_DHparams_bio(bp,x) ASN1_d2i_bio_of(DH,DH_new,d2i_DHparams,bp,x)
+#define i2d_DHparams_bio(bp,x) ASN1_i2d_bio_of_const(DH,i2d_DHparams,bp,x)
+
+const DH_METHOD *DH_OpenSSL(void);
+
+#ifdef OPENSSL_FIPS
+DH * FIPS_dh_new(void);
+void FIPS_dh_free(DH *dh);
+#endif
+
+void DH_set_default_method(const DH_METHOD *meth);
+const DH_METHOD *DH_get_default_method(void);
+int DH_set_method(DH *dh, const DH_METHOD *meth);
+DH *DH_new_method(ENGINE *engine);
+
+DH * DH_new(void);
+void DH_free(DH *dh);
+int DH_up_ref(DH *dh);
+int DH_size(const DH *dh);
+int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int DH_set_ex_data(DH *d, int idx, void *arg);
+void *DH_get_ex_data(DH *d, int idx);
+
+/* Deprecated version */
+#ifndef OPENSSL_NO_DEPRECATED
+DH * DH_generate_parameters(int prime_len,int generator,
+ void (*callback)(int,int,void *),void *cb_arg);
+#endif /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* New version */
+int DH_generate_parameters_ex(DH *dh, int prime_len,int generator, BN_GENCB *cb);
+
+int DH_check(const DH *dh,int *codes);
+int DH_check_pub_key(const DH *dh,const BIGNUM *pub_key, int *codes);
+int DH_generate_key(DH *dh);
+int DH_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh);
+DH * d2i_DHparams(DH **a,const unsigned char **pp, long length);
+int i2d_DHparams(const DH *a,unsigned char **pp);
+#ifndef OPENSSL_NO_FP_API
+int DHparams_print_fp(FILE *fp, const DH *x);
+#endif
+#ifndef OPENSSL_NO_BIO
+int DHparams_print(BIO *bp, const DH *x);
+#else
+int DHparams_print(char *bp, const DH *x);
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_DH_strings(void);
+
+/* Error codes for the DH functions. */
+
+/* Function codes. */
+#define DH_F_COMPUTE_KEY 102
+#define DH_F_DHPARAMS_PRINT 100
+#define DH_F_DHPARAMS_PRINT_FP 101
+#define DH_F_DH_BUILTIN_GENPARAMS 106
+#define DH_F_DH_COMPUTE_KEY 107
+#define DH_F_DH_GENERATE_KEY 108
+#define DH_F_DH_GENERATE_PARAMETERS 109
+#define DH_F_DH_NEW_METHOD 105
+#define DH_F_GENERATE_KEY 103
+#define DH_F_GENERATE_PARAMETERS 104
+
+/* Reason codes. */
+#define DH_R_BAD_GENERATOR 101
+#define DH_R_INVALID_PUBKEY 102
+#define DH_R_KEY_SIZE_TOO_SMALL 104
+#define DH_R_MODULUS_TOO_LARGE 103
+#define DH_R_NO_PRIVATE_VALUE 100
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/dsa.h b/src/Mayaqua/win32_inc/openssl/dsa.h
new file mode 100644
index 00000000..a826ffe5
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/dsa.h
@@ -0,0 +1,324 @@
+/* crypto/dsa/dsa.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/*
+ * The DSS routines are based on patches supplied by
+ * Steven Schoch <schoch@sheba.arc.nasa.gov>. He basically did the
+ * work and I have just tweaked them a little to fit into my
+ * stylistic vision for SSLeay :-) */
+
+#ifndef HEADER_DSA_H
+#define HEADER_DSA_H
+
+#include <openssl/e_os2.h>
+
+#ifdef OPENSSL_NO_DSA
+#error DSA is disabled.
+#endif
+
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#include <openssl/crypto.h>
+#include <openssl/ossl_typ.h>
+
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_DH
+# include <openssl/dh.h>
+#endif
+#endif
+
+#ifndef OPENSSL_DSA_MAX_MODULUS_BITS
+# define OPENSSL_DSA_MAX_MODULUS_BITS 10000
+#endif
+
+#define OPENSSL_DSA_FIPS_MIN_MODULUS_BITS 1024
+
+#define DSA_FLAG_CACHE_MONT_P 0x01
+#define DSA_FLAG_NO_EXP_CONSTTIME 0x02 /* new with 0.9.7h; the built-in DSA
+ * implementation now uses constant time
+ * modular exponentiation for secret exponents
+ * by default. This flag causes the
+ * faster variable sliding window method to
+ * be used for all exponents.
+ */
+
+/* If this flag is set the DSA method is FIPS compliant and can be used
+ * in FIPS mode. This is set in the validated module method. If an
+ * application sets this flag in its own methods it is its reposibility
+ * to ensure the result is compliant.
+ */
+
+#define DSA_FLAG_FIPS_METHOD 0x0400
+
+/* If this flag is set the operations normally disabled in FIPS mode are
+ * permitted it is then the applications responsibility to ensure that the
+ * usage is compliant.
+ */
+
+#define DSA_FLAG_NON_FIPS_ALLOW 0x0400
+
+#ifdef OPENSSL_FIPS
+#define FIPS_DSA_SIZE_T int
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct dsa_st DSA; */
+/* typedef struct dsa_method DSA_METHOD; */
+
+typedef struct DSA_SIG_st
+ {
+ BIGNUM *r;
+ BIGNUM *s;
+ } DSA_SIG;
+
+struct dsa_method
+ {
+ const char *name;
+ DSA_SIG * (*dsa_do_sign)(const unsigned char *dgst, int dlen, DSA *dsa);
+ int (*dsa_sign_setup)(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
+ BIGNUM **rp);
+ int (*dsa_do_verify)(const unsigned char *dgst, int dgst_len,
+ DSA_SIG *sig, DSA *dsa);
+ int (*dsa_mod_exp)(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1,
+ BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *in_mont);
+ int (*bn_mod_exp)(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx); /* Can be null */
+ int (*init)(DSA *dsa);
+ int (*finish)(DSA *dsa);
+ int flags;
+ char *app_data;
+ /* If this is non-NULL, it is used to generate DSA parameters */
+ int (*dsa_paramgen)(DSA *dsa, int bits,
+ unsigned char *seed, int seed_len,
+ int *counter_ret, unsigned long *h_ret,
+ BN_GENCB *cb);
+ /* If this is non-NULL, it is used to generate DSA keys */
+ int (*dsa_keygen)(DSA *dsa);
+ };
+
+struct dsa_st
+ {
+ /* This first variable is used to pick up errors where
+ * a DSA is passed instead of of a EVP_PKEY */
+ int pad;
+ long version;
+ int write_params;
+ BIGNUM *p;
+ BIGNUM *q; /* == 20 */
+ BIGNUM *g;
+
+ BIGNUM *pub_key; /* y public key */
+ BIGNUM *priv_key; /* x private key */
+
+ BIGNUM *kinv; /* Signing pre-calc */
+ BIGNUM *r; /* Signing pre-calc */
+
+ int flags;
+ /* Normally used to cache montgomery values */
+ BN_MONT_CTX *method_mont_p;
+ int references;
+ CRYPTO_EX_DATA ex_data;
+ const DSA_METHOD *meth;
+ /* functional reference if 'meth' is ENGINE-provided */
+ ENGINE *engine;
+ };
+
+#define DSAparams_dup(x) ASN1_dup_of_const(DSA,i2d_DSAparams,d2i_DSAparams,x)
+#define d2i_DSAparams_fp(fp,x) (DSA *)ASN1_d2i_fp((char *(*)())DSA_new, \
+ (char *(*)())d2i_DSAparams,(fp),(unsigned char **)(x))
+#define i2d_DSAparams_fp(fp,x) ASN1_i2d_fp(i2d_DSAparams,(fp), \
+ (unsigned char *)(x))
+#define d2i_DSAparams_bio(bp,x) ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSAparams,bp,x)
+#define i2d_DSAparams_bio(bp,x) ASN1_i2d_bio_of_const(DSA,i2d_DSAparams,bp,x)
+
+
+DSA_SIG * DSA_SIG_new(void);
+void DSA_SIG_free(DSA_SIG *a);
+int i2d_DSA_SIG(const DSA_SIG *a, unsigned char **pp);
+DSA_SIG * d2i_DSA_SIG(DSA_SIG **v, const unsigned char **pp, long length);
+
+DSA_SIG * DSA_do_sign(const unsigned char *dgst,int dlen,DSA *dsa);
+int DSA_do_verify(const unsigned char *dgst,int dgst_len,
+ DSA_SIG *sig,DSA *dsa);
+
+const DSA_METHOD *DSA_OpenSSL(void);
+
+void DSA_set_default_method(const DSA_METHOD *);
+const DSA_METHOD *DSA_get_default_method(void);
+int DSA_set_method(DSA *dsa, const DSA_METHOD *);
+
+#ifdef OPENSSL_FIPS
+DSA * FIPS_dsa_new(void);
+void FIPS_dsa_free (DSA *r);
+#endif
+
+DSA * DSA_new(void);
+DSA * DSA_new_method(ENGINE *engine);
+void DSA_free (DSA *r);
+/* "up" the DSA object's reference count */
+int DSA_up_ref(DSA *r);
+int DSA_size(const DSA *);
+ /* next 4 return -1 on error */
+int DSA_sign_setup( DSA *dsa,BN_CTX *ctx_in,BIGNUM **kinvp,BIGNUM **rp);
+int DSA_sign(int type,const unsigned char *dgst,int dlen,
+ unsigned char *sig, unsigned int *siglen, DSA *dsa);
+int DSA_verify(int type,const unsigned char *dgst,int dgst_len,
+ const unsigned char *sigbuf, int siglen, DSA *dsa);
+int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int DSA_set_ex_data(DSA *d, int idx, void *arg);
+void *DSA_get_ex_data(DSA *d, int idx);
+
+DSA * d2i_DSAPublicKey(DSA **a, const unsigned char **pp, long length);
+DSA * d2i_DSAPrivateKey(DSA **a, const unsigned char **pp, long length);
+DSA * d2i_DSAparams(DSA **a, const unsigned char **pp, long length);
+
+/* Deprecated version */
+#ifndef OPENSSL_NO_DEPRECATED
+DSA * DSA_generate_parameters(int bits,
+ unsigned char *seed,int seed_len,
+ int *counter_ret, unsigned long *h_ret,void
+ (*callback)(int, int, void *),void *cb_arg);
+#endif /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* New version */
+int DSA_generate_parameters_ex(DSA *dsa, int bits,
+ unsigned char *seed,int seed_len,
+ int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
+
+int DSA_generate_key(DSA *a);
+int i2d_DSAPublicKey(const DSA *a, unsigned char **pp);
+int i2d_DSAPrivateKey(const DSA *a, unsigned char **pp);
+int i2d_DSAparams(const DSA *a,unsigned char **pp);
+
+#ifndef OPENSSL_NO_BIO
+int DSAparams_print(BIO *bp, const DSA *x);
+int DSA_print(BIO *bp, const DSA *x, int off);
+#endif
+#ifndef OPENSSL_NO_FP_API
+int DSAparams_print_fp(FILE *fp, const DSA *x);
+int DSA_print_fp(FILE *bp, const DSA *x, int off);
+#endif
+
+#define DSS_prime_checks 50
+/* Primality test according to FIPS PUB 186[-1], Appendix 2.1:
+ * 50 rounds of Rabin-Miller */
+#define DSA_is_prime(n, callback, cb_arg) \
+ BN_is_prime(n, DSS_prime_checks, callback, NULL, cb_arg)
+
+#ifndef OPENSSL_NO_DH
+/* Convert DSA structure (key or just parameters) into DH structure
+ * (be careful to avoid small subgroup attacks when using this!) */
+DH *DSA_dup_DH(const DSA *r);
+#endif
+
+#ifdef OPENSSL_FIPS
+int FIPS_dsa_sig_encode(unsigned char *out, DSA_SIG *sig);
+int FIPS_dsa_sig_decode(DSA_SIG *sig, const unsigned char *in, int inlen);
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_DSA_strings(void);
+
+/* Error codes for the DSA functions. */
+
+/* Function codes. */
+#define DSA_F_D2I_DSA_SIG 110
+#define DSA_F_DSAPARAMS_PRINT 100
+#define DSA_F_DSAPARAMS_PRINT_FP 101
+#define DSA_F_DSA_BUILTIN_KEYGEN 119
+#define DSA_F_DSA_BUILTIN_PARAMGEN 118
+#define DSA_F_DSA_DO_SIGN 112
+#define DSA_F_DSA_DO_VERIFY 113
+#define DSA_F_DSA_GENERATE_PARAMETERS 117
+#define DSA_F_DSA_NEW_METHOD 103
+#define DSA_F_DSA_PRINT 104
+#define DSA_F_DSA_PRINT_FP 105
+#define DSA_F_DSA_SET_DEFAULT_METHOD 115
+#define DSA_F_DSA_SET_METHOD 116
+#define DSA_F_DSA_SIGN 106
+#define DSA_F_DSA_SIGN_SETUP 107
+#define DSA_F_DSA_SIG_NEW 109
+#define DSA_F_DSA_VERIFY 108
+#define DSA_F_I2D_DSA_SIG 111
+#define DSA_F_SIG_CB 114
+
+/* Reason codes. */
+#define DSA_R_BAD_Q_VALUE 102
+#define DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 100
+#define DSA_R_KEY_SIZE_TOO_SMALL 106
+#define DSA_R_MISSING_PARAMETERS 101
+#define DSA_R_MODULUS_TOO_LARGE 103
+#define DSA_R_NON_FIPS_METHOD 104
+#define DSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE 105
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/dso.h b/src/Mayaqua/win32_inc/openssl/dso.h
new file mode 100644
index 00000000..18362319
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/dso.h
@@ -0,0 +1,368 @@
+/* dso.h -*- mode:C; c-file-style: "eay" -*- */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_DSO_H
+#define HEADER_DSO_H
+
+#include <openssl/crypto.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These values are used as commands to DSO_ctrl() */
+#define DSO_CTRL_GET_FLAGS 1
+#define DSO_CTRL_SET_FLAGS 2
+#define DSO_CTRL_OR_FLAGS 3
+
+/* By default, DSO_load() will translate the provided filename into a form
+ * typical for the platform (more specifically the DSO_METHOD) using the
+ * dso_name_converter function of the method. Eg. win32 will transform "blah"
+ * into "blah.dll", and dlfcn will transform it into "libblah.so". The
+ * behaviour can be overriden by setting the name_converter callback in the DSO
+ * object (using DSO_set_name_converter()). This callback could even utilise
+ * the DSO_METHOD's converter too if it only wants to override behaviour for
+ * one or two possible DSO methods. However, the following flag can be set in a
+ * DSO to prevent *any* native name-translation at all - eg. if the caller has
+ * prompted the user for a path to a driver library so the filename should be
+ * interpreted as-is. */
+#define DSO_FLAG_NO_NAME_TRANSLATION 0x01
+/* An extra flag to give if only the extension should be added as
+ * translation. This is obviously only of importance on Unix and
+ * other operating systems where the translation also may prefix
+ * the name with something, like 'lib', and ignored everywhere else.
+ * This flag is also ignored if DSO_FLAG_NO_NAME_TRANSLATION is used
+ * at the same time. */
+#define DSO_FLAG_NAME_TRANSLATION_EXT_ONLY 0x02
+
+/* The following flag controls the translation of symbol names to upper
+ * case. This is currently only being implemented for OpenVMS.
+ */
+#define DSO_FLAG_UPCASE_SYMBOL 0x10
+
+/* This flag loads the library with public symbols.
+ * Meaning: The exported symbols of this library are public
+ * to all libraries loaded after this library.
+ * At the moment only implemented in unix.
+ */
+#define DSO_FLAG_GLOBAL_SYMBOLS 0x20
+
+
+typedef void (*DSO_FUNC_TYPE)(void);
+
+typedef struct dso_st DSO;
+
+/* The function prototype used for method functions (or caller-provided
+ * callbacks) that transform filenames. They are passed a DSO structure pointer
+ * (or NULL if they are to be used independantly of a DSO object) and a
+ * filename to transform. They should either return NULL (if there is an error
+ * condition) or a newly allocated string containing the transformed form that
+ * the caller will need to free with OPENSSL_free() when done. */
+typedef char* (*DSO_NAME_CONVERTER_FUNC)(DSO *, const char *);
+/* The function prototype used for method functions (or caller-provided
+ * callbacks) that merge two file specifications. They are passed a
+ * DSO structure pointer (or NULL if they are to be used independantly of
+ * a DSO object) and two file specifications to merge. They should
+ * either return NULL (if there is an error condition) or a newly allocated
+ * string containing the result of merging that the caller will need
+ * to free with OPENSSL_free() when done.
+ * Here, merging means that bits and pieces are taken from each of the
+ * file specifications and added together in whatever fashion that is
+ * sensible for the DSO method in question. The only rule that really
+ * applies is that if the two specification contain pieces of the same
+ * type, the copy from the first string takes priority. One could see
+ * it as the first specification is the one given by the user and the
+ * second being a bunch of defaults to add on if they're missing in the
+ * first. */
+typedef char* (*DSO_MERGER_FUNC)(DSO *, const char *, const char *);
+
+typedef struct dso_meth_st
+ {
+ const char *name;
+ /* Loads a shared library, NB: new DSO_METHODs must ensure that a
+ * successful load populates the loaded_filename field, and likewise a
+ * successful unload OPENSSL_frees and NULLs it out. */
+ int (*dso_load)(DSO *dso);
+ /* Unloads a shared library */
+ int (*dso_unload)(DSO *dso);
+ /* Binds a variable */
+ void *(*dso_bind_var)(DSO *dso, const char *symname);
+ /* Binds a function - assumes a return type of DSO_FUNC_TYPE.
+ * This should be cast to the real function prototype by the
+ * caller. Platforms that don't have compatible representations
+ * for different prototypes (this is possible within ANSI C)
+ * are highly unlikely to have shared libraries at all, let
+ * alone a DSO_METHOD implemented for them. */
+ DSO_FUNC_TYPE (*dso_bind_func)(DSO *dso, const char *symname);
+
+/* I don't think this would actually be used in any circumstances. */
+#if 0
+ /* Unbinds a variable */
+ int (*dso_unbind_var)(DSO *dso, char *symname, void *symptr);
+ /* Unbinds a function */
+ int (*dso_unbind_func)(DSO *dso, char *symname, DSO_FUNC_TYPE symptr);
+#endif
+ /* The generic (yuck) "ctrl()" function. NB: Negative return
+ * values (rather than zero) indicate errors. */
+ long (*dso_ctrl)(DSO *dso, int cmd, long larg, void *parg);
+ /* The default DSO_METHOD-specific function for converting filenames to
+ * a canonical native form. */
+ DSO_NAME_CONVERTER_FUNC dso_name_converter;
+ /* The default DSO_METHOD-specific function for converting filenames to
+ * a canonical native form. */
+ DSO_MERGER_FUNC dso_merger;
+
+ /* [De]Initialisation handlers. */
+ int (*init)(DSO *dso);
+ int (*finish)(DSO *dso);
+ } DSO_METHOD;
+
+/**********************************************************************/
+/* The low-level handle type used to refer to a loaded shared library */
+
+struct dso_st
+ {
+ DSO_METHOD *meth;
+ /* Standard dlopen uses a (void *). Win32 uses a HANDLE. VMS
+ * doesn't use anything but will need to cache the filename
+ * for use in the dso_bind handler. All in all, let each
+ * method control its own destiny. "Handles" and such go in
+ * a STACK. */
+ STACK *meth_data;
+ int references;
+ int flags;
+ /* For use by applications etc ... use this for your bits'n'pieces,
+ * don't touch meth_data! */
+ CRYPTO_EX_DATA ex_data;
+ /* If this callback function pointer is set to non-NULL, then it will
+ * be used in DSO_load() in place of meth->dso_name_converter. NB: This
+ * should normally set using DSO_set_name_converter(). */
+ DSO_NAME_CONVERTER_FUNC name_converter;
+ /* If this callback function pointer is set to non-NULL, then it will
+ * be used in DSO_load() in place of meth->dso_merger. NB: This
+ * should normally set using DSO_set_merger(). */
+ DSO_MERGER_FUNC merger;
+ /* This is populated with (a copy of) the platform-independant
+ * filename used for this DSO. */
+ char *filename;
+ /* This is populated with (a copy of) the translated filename by which
+ * the DSO was actually loaded. It is NULL iff the DSO is not currently
+ * loaded. NB: This is here because the filename translation process
+ * may involve a callback being invoked more than once not only to
+ * convert to a platform-specific form, but also to try different
+ * filenames in the process of trying to perform a load. As such, this
+ * variable can be used to indicate (a) whether this DSO structure
+ * corresponds to a loaded library or not, and (b) the filename with
+ * which it was actually loaded. */
+ char *loaded_filename;
+ };
+
+
+DSO * DSO_new(void);
+DSO * DSO_new_method(DSO_METHOD *method);
+int DSO_free(DSO *dso);
+int DSO_flags(DSO *dso);
+int DSO_up_ref(DSO *dso);
+long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg);
+
+/* This function sets the DSO's name_converter callback. If it is non-NULL,
+ * then it will be used instead of the associated DSO_METHOD's function. If
+ * oldcb is non-NULL then it is set to the function pointer value being
+ * replaced. Return value is non-zero for success. */
+int DSO_set_name_converter(DSO *dso, DSO_NAME_CONVERTER_FUNC cb,
+ DSO_NAME_CONVERTER_FUNC *oldcb);
+/* These functions can be used to get/set the platform-independant filename
+ * used for a DSO. NB: set will fail if the DSO is already loaded. */
+const char *DSO_get_filename(DSO *dso);
+int DSO_set_filename(DSO *dso, const char *filename);
+/* This function will invoke the DSO's name_converter callback to translate a
+ * filename, or if the callback isn't set it will instead use the DSO_METHOD's
+ * converter. If "filename" is NULL, the "filename" in the DSO itself will be
+ * used. If the DSO_FLAG_NO_NAME_TRANSLATION flag is set, then the filename is
+ * simply duplicated. NB: This function is usually called from within a
+ * DSO_METHOD during the processing of a DSO_load() call, and is exposed so that
+ * caller-created DSO_METHODs can do the same thing. A non-NULL return value
+ * will need to be OPENSSL_free()'d. */
+char *DSO_convert_filename(DSO *dso, const char *filename);
+/* This function will invoke the DSO's merger callback to merge two file
+ * specifications, or if the callback isn't set it will instead use the
+ * DSO_METHOD's merger. A non-NULL return value will need to be
+ * OPENSSL_free()'d. */
+char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2);
+/* If the DSO is currently loaded, this returns the filename that it was loaded
+ * under, otherwise it returns NULL. So it is also useful as a test as to
+ * whether the DSO is currently loaded. NB: This will not necessarily return
+ * the same value as DSO_convert_filename(dso, dso->filename), because the
+ * DSO_METHOD's load function may have tried a variety of filenames (with
+ * and/or without the aid of the converters) before settling on the one it
+ * actually loaded. */
+const char *DSO_get_loaded_filename(DSO *dso);
+
+void DSO_set_default_method(DSO_METHOD *meth);
+DSO_METHOD *DSO_get_default_method(void);
+DSO_METHOD *DSO_get_method(DSO *dso);
+DSO_METHOD *DSO_set_method(DSO *dso, DSO_METHOD *meth);
+
+/* The all-singing all-dancing load function, you normally pass NULL
+ * for the first and third parameters. Use DSO_up and DSO_free for
+ * subsequent reference count handling. Any flags passed in will be set
+ * in the constructed DSO after its init() function but before the
+ * load operation. If 'dso' is non-NULL, 'flags' is ignored. */
+DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags);
+
+/* This function binds to a variable inside a shared library. */
+void *DSO_bind_var(DSO *dso, const char *symname);
+
+/* This function binds to a function inside a shared library. */
+DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname);
+
+/* This method is the default, but will beg, borrow, or steal whatever
+ * method should be the default on any particular platform (including
+ * DSO_METH_null() if necessary). */
+DSO_METHOD *DSO_METHOD_openssl(void);
+
+/* This method is defined for all platforms - if a platform has no
+ * DSO support then this will be the only method! */
+DSO_METHOD *DSO_METHOD_null(void);
+
+/* If DSO_DLFCN is defined, the standard dlfcn.h-style functions
+ * (dlopen, dlclose, dlsym, etc) will be used and incorporated into
+ * this method. If not, this method will return NULL. */
+DSO_METHOD *DSO_METHOD_dlfcn(void);
+
+/* If DSO_DL is defined, the standard dl.h-style functions (shl_load,
+ * shl_unload, shl_findsym, etc) will be used and incorporated into
+ * this method. If not, this method will return NULL. */
+DSO_METHOD *DSO_METHOD_dl(void);
+
+/* If WIN32 is defined, use DLLs. If not, return NULL. */
+DSO_METHOD *DSO_METHOD_win32(void);
+
+/* If VMS is defined, use shared images. If not, return NULL. */
+DSO_METHOD *DSO_METHOD_vms(void);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_DSO_strings(void);
+
+/* Error codes for the DSO functions. */
+
+/* Function codes. */
+#define DSO_F_DLFCN_BIND_FUNC 100
+#define DSO_F_DLFCN_BIND_VAR 101
+#define DSO_F_DLFCN_LOAD 102
+#define DSO_F_DLFCN_MERGER 130
+#define DSO_F_DLFCN_NAME_CONVERTER 123
+#define DSO_F_DLFCN_UNLOAD 103
+#define DSO_F_DL_BIND_FUNC 104
+#define DSO_F_DL_BIND_VAR 105
+#define DSO_F_DL_LOAD 106
+#define DSO_F_DL_MERGER 131
+#define DSO_F_DL_NAME_CONVERTER 124
+#define DSO_F_DL_UNLOAD 107
+#define DSO_F_DSO_BIND_FUNC 108
+#define DSO_F_DSO_BIND_VAR 109
+#define DSO_F_DSO_CONVERT_FILENAME 126
+#define DSO_F_DSO_CTRL 110
+#define DSO_F_DSO_FREE 111
+#define DSO_F_DSO_GET_FILENAME 127
+#define DSO_F_DSO_GET_LOADED_FILENAME 128
+#define DSO_F_DSO_LOAD 112
+#define DSO_F_DSO_MERGE 132
+#define DSO_F_DSO_NEW_METHOD 113
+#define DSO_F_DSO_SET_FILENAME 129
+#define DSO_F_DSO_SET_NAME_CONVERTER 122
+#define DSO_F_DSO_UP_REF 114
+#define DSO_F_VMS_BIND_SYM 115
+#define DSO_F_VMS_LOAD 116
+#define DSO_F_VMS_MERGER 133
+#define DSO_F_VMS_UNLOAD 117
+#define DSO_F_WIN32_BIND_FUNC 118
+#define DSO_F_WIN32_BIND_VAR 119
+#define DSO_F_WIN32_JOINER 135
+#define DSO_F_WIN32_LOAD 120
+#define DSO_F_WIN32_MERGER 134
+#define DSO_F_WIN32_NAME_CONVERTER 125
+#define DSO_F_WIN32_SPLITTER 136
+#define DSO_F_WIN32_UNLOAD 121
+
+/* Reason codes. */
+#define DSO_R_CTRL_FAILED 100
+#define DSO_R_DSO_ALREADY_LOADED 110
+#define DSO_R_EMPTY_FILE_STRUCTURE 113
+#define DSO_R_FAILURE 114
+#define DSO_R_FILENAME_TOO_BIG 101
+#define DSO_R_FINISH_FAILED 102
+#define DSO_R_INCORRECT_FILE_SYNTAX 115
+#define DSO_R_LOAD_FAILED 103
+#define DSO_R_NAME_TRANSLATION_FAILED 109
+#define DSO_R_NO_FILENAME 111
+#define DSO_R_NO_FILE_SPECIFICATION 116
+#define DSO_R_NULL_HANDLE 104
+#define DSO_R_SET_FILENAME_FAILED 112
+#define DSO_R_STACK_ERROR 105
+#define DSO_R_SYM_FAILURE 106
+#define DSO_R_UNLOAD_FAILED 107
+#define DSO_R_UNSUPPORTED 108
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/dtls1.h b/src/Mayaqua/win32_inc/openssl/dtls1.h
new file mode 100644
index 00000000..d196356b
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/dtls1.h
@@ -0,0 +1,265 @@
+/* ssl/dtls1.h */
+/*
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_DTLS1_H
+#define HEADER_DTLS1_H
+
+#include <openssl/buffer.h>
+#include <openssl/pqueue.h>
+#ifdef OPENSSL_SYS_VMS
+#include <resource.h>
+#include <sys/timeb.h>
+#endif
+#ifdef OPENSSL_SYS_WIN32
+/* Needed for struct timeval */
+#include <winsock.h>
+#elif defined(OPENSSL_SYS_NETWARE) && !defined(_WINSOCK2API_)
+#include <sys/timeval.h>
+#else
+#include <sys/time.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DTLS1_VERSION 0xFEFF
+#define DTLS1_BAD_VER 0x0100
+
+#if 0
+/* this alert description is not specified anywhere... */
+#define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE 110
+#endif
+
+/* lengths of messages */
+#define DTLS1_COOKIE_LENGTH 256
+
+#define DTLS1_RT_HEADER_LENGTH 13
+
+#define DTLS1_HM_HEADER_LENGTH 12
+
+#define DTLS1_HM_BAD_FRAGMENT -2
+#define DTLS1_HM_FRAGMENT_RETRY -3
+
+#define DTLS1_CCS_HEADER_LENGTH 1
+
+#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
+#define DTLS1_AL_HEADER_LENGTH 7
+#else
+#define DTLS1_AL_HEADER_LENGTH 2
+#endif
+
+
+typedef struct dtls1_bitmap_st
+ {
+ PQ_64BIT map;
+ unsigned long length; /* sizeof the bitmap in bits */
+ PQ_64BIT max_seq_num; /* max record number seen so far */
+ } DTLS1_BITMAP;
+
+struct dtls1_retransmit_state
+ {
+ EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */
+ const EVP_MD *write_hash; /* used for mac generation */
+#ifndef OPENSSL_NO_COMP
+ COMP_CTX *compress; /* compression */
+#else
+ char *compress;
+#endif
+ SSL_SESSION *session;
+ unsigned short epoch;
+ };
+
+struct hm_header_st
+ {
+ unsigned char type;
+ unsigned long msg_len;
+ unsigned short seq;
+ unsigned long frag_off;
+ unsigned long frag_len;
+ unsigned int is_ccs;
+ struct dtls1_retransmit_state saved_retransmit_state;
+ };
+
+struct ccs_header_st
+ {
+ unsigned char type;
+ unsigned short seq;
+ };
+
+struct dtls1_timeout_st
+ {
+ /* Number of read timeouts so far */
+ unsigned int read_timeouts;
+
+ /* Number of write timeouts so far */
+ unsigned int write_timeouts;
+
+ /* Number of alerts received so far */
+ unsigned int num_alerts;
+ };
+
+typedef struct record_pqueue_st
+ {
+ unsigned short epoch;
+ pqueue q;
+ } record_pqueue;
+
+typedef struct hm_fragment_st
+ {
+ struct hm_header_st msg_header;
+ unsigned char *fragment;
+ unsigned char *reassembly;
+ } hm_fragment;
+
+typedef struct dtls1_state_st
+ {
+ unsigned int send_cookie;
+ unsigned char cookie[DTLS1_COOKIE_LENGTH];
+ unsigned char rcvd_cookie[DTLS1_COOKIE_LENGTH];
+ unsigned int cookie_len;
+
+ /*
+ * The current data and handshake epoch. This is initially
+ * undefined, and starts at zero once the initial handshake is
+ * completed
+ */
+ unsigned short r_epoch;
+ unsigned short w_epoch;
+
+ /* records being received in the current epoch */
+ DTLS1_BITMAP bitmap;
+
+ /* renegotiation starts a new set of sequence numbers */
+ DTLS1_BITMAP next_bitmap;
+
+ /* handshake message numbers */
+ unsigned short handshake_write_seq;
+ unsigned short next_handshake_write_seq;
+
+ unsigned short handshake_read_seq;
+
+ /* save last sequence number for retransmissions */
+ unsigned char last_write_sequence[8];
+
+ /* Received handshake records (processed and unprocessed) */
+ record_pqueue unprocessed_rcds;
+ record_pqueue processed_rcds;
+
+ /* Buffered handshake messages */
+ pqueue buffered_messages;
+
+ /* Buffered (sent) handshake records */
+ pqueue sent_messages;
+
+ /* Buffered application records.
+ * Only for records between CCS and Finished
+ * to prevent either protocol violation or
+ * unnecessary message loss.
+ */
+ record_pqueue buffered_app_data;
+
+ /* Is set when listening for new connections with dtls1_listen() */
+ unsigned int listen;
+
+ unsigned int mtu; /* max DTLS packet size */
+
+ struct hm_header_st w_msg_hdr;
+ struct hm_header_st r_msg_hdr;
+
+ struct dtls1_timeout_st timeout;
+
+ /* Indicates when the last handshake msg sent will timeout */
+ struct timeval next_timeout;
+
+ /* Timeout duration */
+ unsigned short timeout_duration;
+
+ /* storage for Alert/Handshake protocol data received but not
+ * yet processed by ssl3_read_bytes: */
+ unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH];
+ unsigned int alert_fragment_len;
+ unsigned char handshake_fragment[DTLS1_HM_HEADER_LENGTH];
+ unsigned int handshake_fragment_len;
+
+ unsigned int retransmitting;
+ unsigned int change_cipher_spec_ok;
+
+ } DTLS1_STATE;
+
+typedef struct dtls1_record_data_st
+ {
+ unsigned char *packet;
+ unsigned int packet_length;
+ SSL3_BUFFER rbuf;
+ SSL3_RECORD rrec;
+ } DTLS1_RECORD_DATA;
+
+
+/* Timeout multipliers (timeout slice is defined in apps/timeouts.h */
+#define DTLS1_TMO_READ_COUNT 2
+#define DTLS1_TMO_WRITE_COUNT 2
+
+#define DTLS1_TMO_ALERT_COUNT 12
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/e_os2.h b/src/Mayaqua/win32_inc/openssl/e_os2.h
new file mode 100644
index 00000000..79bfe248
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/e_os2.h
@@ -0,0 +1,279 @@
+/* e_os2.h */
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <openssl/opensslconf.h>
+
+#ifndef HEADER_E_OS2_H
+#define HEADER_E_OS2_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************
+ * Detect operating systems. This probably needs completing.
+ * The result is that at least one OPENSSL_SYS_os macro should be defined.
+ * However, if none is defined, Unix is assumed.
+ **/
+
+#define OPENSSL_SYS_UNIX
+
+/* ----------------------- Macintosh, before MacOS X ----------------------- */
+#if defined(__MWERKS__) && defined(macintosh) || defined(OPENSSL_SYSNAME_MAC)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_MACINTOSH_CLASSIC
+#endif
+
+/* ----------------------- NetWare ----------------------------------------- */
+#if defined(NETWARE) || defined(OPENSSL_SYSNAME_NETWARE)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_NETWARE
+#endif
+
+/* ---------------------- Microsoft operating systems ---------------------- */
+
+/* Note that MSDOS actually denotes 32-bit environments running on top of
+ MS-DOS, such as DJGPP one. */
+#if defined(OPENSSL_SYSNAME_MSDOS)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_MSDOS
+#endif
+
+/* For 32 bit environment, there seems to be the CygWin environment and then
+ all the others that try to do the same thing Microsoft does... */
+#if defined(OPENSSL_SYSNAME_UWIN)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_WIN32_UWIN
+#else
+# if defined(__CYGWIN32__) || defined(OPENSSL_SYSNAME_CYGWIN32)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_WIN32_CYGWIN
+# else
+# if defined(_WIN32) || defined(OPENSSL_SYSNAME_WIN32)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_WIN32
+# endif
+# if defined(OPENSSL_SYSNAME_WINNT)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_WINNT
+# endif
+# if defined(OPENSSL_SYSNAME_WINCE)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_WINCE
+# endif
+# endif
+#endif
+
+/* Anything that tries to look like Microsoft is "Windows" */
+#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WINNT) || defined(OPENSSL_SYS_WINCE)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_WINDOWS
+# ifndef OPENSSL_SYS_MSDOS
+# define OPENSSL_SYS_MSDOS
+# endif
+#endif
+
+/* DLL settings. This part is a bit tough, because it's up to the application
+ implementor how he or she will link the application, so it requires some
+ macro to be used. */
+#ifdef OPENSSL_SYS_WINDOWS
+# ifndef OPENSSL_OPT_WINDLL
+# if defined(_WINDLL) /* This is used when building OpenSSL to indicate that
+ DLL linkage should be used */
+# define OPENSSL_OPT_WINDLL
+# endif
+# endif
+#endif
+
+/* -------------------------------- OpenVMS -------------------------------- */
+#if defined(__VMS) || defined(VMS) || defined(OPENSSL_SYSNAME_VMS)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_VMS
+# if defined(__DECC)
+# define OPENSSL_SYS_VMS_DECC
+# elif defined(__DECCXX)
+# define OPENSSL_SYS_VMS_DECC
+# define OPENSSL_SYS_VMS_DECCXX
+# else
+# define OPENSSL_SYS_VMS_NODECC
+# endif
+#endif
+
+/* --------------------------------- OS/2 ---------------------------------- */
+#if defined(__EMX__) || defined(__OS2__)
+# undef OPENSSL_SYS_UNIX
+# define OPENSSL_SYS_OS2
+#endif
+
+/* --------------------------------- Unix ---------------------------------- */
+#ifdef OPENSSL_SYS_UNIX
+# if defined(linux) || defined(__linux__) || defined(OPENSSL_SYSNAME_LINUX)
+# define OPENSSL_SYS_LINUX
+# endif
+# ifdef OPENSSL_SYSNAME_MPE
+# define OPENSSL_SYS_MPE
+# endif
+# ifdef OPENSSL_SYSNAME_SNI
+# define OPENSSL_SYS_SNI
+# endif
+# ifdef OPENSSL_SYSNAME_ULTRASPARC
+# define OPENSSL_SYS_ULTRASPARC
+# endif
+# ifdef OPENSSL_SYSNAME_NEWS4
+# define OPENSSL_SYS_NEWS4
+# endif
+# ifdef OPENSSL_SYSNAME_MACOSX
+# define OPENSSL_SYS_MACOSX
+# endif
+# ifdef OPENSSL_SYSNAME_MACOSX_RHAPSODY
+# define OPENSSL_SYS_MACOSX_RHAPSODY
+# define OPENSSL_SYS_MACOSX
+# endif
+# ifdef OPENSSL_SYSNAME_SUNOS
+# define OPENSSL_SYS_SUNOS
+#endif
+# if defined(_CRAY) || defined(OPENSSL_SYSNAME_CRAY)
+# define OPENSSL_SYS_CRAY
+# endif
+# if defined(_AIX) || defined(OPENSSL_SYSNAME_AIX)
+# define OPENSSL_SYS_AIX
+# endif
+#endif
+
+/* --------------------------------- VOS ----------------------------------- */
+#ifdef OPENSSL_SYSNAME_VOS
+# define OPENSSL_SYS_VOS
+#endif
+
+/* ------------------------------- VxWorks --------------------------------- */
+#ifdef OPENSSL_SYSNAME_VXWORKS
+# define OPENSSL_SYS_VXWORKS
+#endif
+
+/**
+ * That's it for OS-specific stuff
+ *****************************************************************************/
+
+
+/* Specials for I/O an exit */
+#ifdef OPENSSL_SYS_MSDOS
+# define OPENSSL_UNISTD_IO <io.h>
+# define OPENSSL_DECLARE_EXIT extern void exit(int);
+#else
+# define OPENSSL_UNISTD_IO OPENSSL_UNISTD
+# define OPENSSL_DECLARE_EXIT /* declared in unistd.h */
+#endif
+
+/* Definitions of OPENSSL_GLOBAL and OPENSSL_EXTERN, to define and declare
+ certain global symbols that, with some compilers under VMS, have to be
+ defined and declared explicitely with globaldef and globalref.
+ Definitions of OPENSSL_EXPORT and OPENSSL_IMPORT, to define and declare
+ DLL exports and imports for compilers under Win32. These are a little
+ more complicated to use. Basically, for any library that exports some
+ global variables, the following code must be present in the header file
+ that declares them, before OPENSSL_EXTERN is used:
+
+ #ifdef SOME_BUILD_FLAG_MACRO
+ # undef OPENSSL_EXTERN
+ # define OPENSSL_EXTERN OPENSSL_EXPORT
+ #endif
+
+ The default is to have OPENSSL_EXPORT, OPENSSL_IMPORT and OPENSSL_GLOBAL
+ have some generally sensible values, and for OPENSSL_EXTERN to have the
+ value OPENSSL_IMPORT.
+*/
+
+#if defined(OPENSSL_SYS_VMS_NODECC)
+# define OPENSSL_EXPORT globalref
+# define OPENSSL_IMPORT globalref
+# define OPENSSL_GLOBAL globaldef
+#elif defined(OPENSSL_SYS_WINDOWS) && defined(OPENSSL_OPT_WINDLL)
+# define OPENSSL_EXPORT extern __declspec(dllexport)
+# define OPENSSL_IMPORT extern __declspec(dllimport)
+# define OPENSSL_GLOBAL
+#else
+# define OPENSSL_EXPORT extern
+# define OPENSSL_IMPORT extern
+# define OPENSSL_GLOBAL
+#endif
+#define OPENSSL_EXTERN OPENSSL_IMPORT
+
+/* Macros to allow global variables to be reached through function calls when
+ required (if a shared library version requvres it, for example.
+ The way it's done allows definitions like this:
+
+ // in foobar.c
+ OPENSSL_IMPLEMENT_GLOBAL(int,foobar) = 0;
+ // in foobar.h
+ OPENSSL_DECLARE_GLOBAL(int,foobar);
+ #define foobar OPENSSL_GLOBAL_REF(foobar)
+*/
+#ifdef OPENSSL_EXPORT_VAR_AS_FUNCTION
+# define OPENSSL_IMPLEMENT_GLOBAL(type,name) \
+ extern type _hide_##name; \
+ type *_shadow_##name(void) { return &_hide_##name; } \
+ static type _hide_##name
+# define OPENSSL_DECLARE_GLOBAL(type,name) type *_shadow_##name(void)
+# define OPENSSL_GLOBAL_REF(name) (*(_shadow_##name()))
+#else
+# define OPENSSL_IMPLEMENT_GLOBAL(type,name) OPENSSL_GLOBAL type _shadow_##name
+# define OPENSSL_DECLARE_GLOBAL(type,name) OPENSSL_EXPORT type _shadow_##name
+# define OPENSSL_GLOBAL_REF(name) _shadow_##name
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ebcdic.h b/src/Mayaqua/win32_inc/openssl/ebcdic.h
new file mode 100644
index 00000000..0941c8be
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ebcdic.h
@@ -0,0 +1,19 @@
+/* crypto/ebcdic.h */
+
+#ifndef HEADER_EBCDIC_H
+#define HEADER_EBCDIC_H
+
+#include <sys/types.h>
+
+/* Avoid name clashes with other applications */
+#define os_toascii _openssl_os_toascii
+#define os_toebcdic _openssl_os_toebcdic
+#define ebcdic2ascii _openssl_ebcdic2ascii
+#define ascii2ebcdic _openssl_ascii2ebcdic
+
+extern const unsigned char os_toascii[256];
+extern const unsigned char os_toebcdic[256];
+void *ebcdic2ascii(void *dest, const void *srce, size_t count);
+void *ascii2ebcdic(void *dest, const void *srce, size_t count);
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ec.h b/src/Mayaqua/win32_inc/openssl/ec.h
new file mode 100644
index 00000000..b29901a4
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ec.h
@@ -0,0 +1,526 @@
+/* crypto/ec/ec.h */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * The elliptic curve binary polynomial software is originally written by
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+#ifndef HEADER_EC_H
+#define HEADER_EC_H
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_EC
+#error EC is disabled.
+#endif
+
+#include <openssl/asn1.h>
+#include <openssl/symhacks.h>
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#elif defined(__SUNPRO_C)
+# if __SUNPRO_C >= 0x520
+# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
+# endif
+#endif
+
+
+#ifndef OPENSSL_ECC_MAX_FIELD_BITS
+# define OPENSSL_ECC_MAX_FIELD_BITS 661
+#endif
+
+typedef enum {
+ /* values as defined in X9.62 (ECDSA) and elsewhere */
+ POINT_CONVERSION_COMPRESSED = 2,
+ POINT_CONVERSION_UNCOMPRESSED = 4,
+ POINT_CONVERSION_HYBRID = 6
+} point_conversion_form_t;
+
+
+typedef struct ec_method_st EC_METHOD;
+
+typedef struct ec_group_st
+ /*
+ EC_METHOD *meth;
+ -- field definition
+ -- curve coefficients
+ -- optional generator with associated information (order, cofactor)
+ -- optional extra data (precomputed table for fast computation of multiples of generator)
+ -- ASN1 stuff
+ */
+ EC_GROUP;
+
+typedef struct ec_point_st EC_POINT;
+
+
+/* EC_METHODs for curves over GF(p).
+ * EC_GFp_simple_method provides the basis for the optimized methods.
+ */
+const EC_METHOD *EC_GFp_simple_method(void);
+const EC_METHOD *EC_GFp_mont_method(void);
+const EC_METHOD *EC_GFp_nist_method(void);
+
+/* EC_METHOD for curves over GF(2^m).
+ */
+const EC_METHOD *EC_GF2m_simple_method(void);
+
+
+EC_GROUP *EC_GROUP_new(const EC_METHOD *);
+void EC_GROUP_free(EC_GROUP *);
+void EC_GROUP_clear_free(EC_GROUP *);
+int EC_GROUP_copy(EC_GROUP *, const EC_GROUP *);
+EC_GROUP *EC_GROUP_dup(const EC_GROUP *);
+
+const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *);
+int EC_METHOD_get_field_type(const EC_METHOD *);
+
+int EC_GROUP_set_generator(EC_GROUP *, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor);
+const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *);
+int EC_GROUP_get_order(const EC_GROUP *, BIGNUM *order, BN_CTX *);
+int EC_GROUP_get_cofactor(const EC_GROUP *, BIGNUM *cofactor, BN_CTX *);
+
+void EC_GROUP_set_curve_name(EC_GROUP *, int nid);
+int EC_GROUP_get_curve_name(const EC_GROUP *);
+
+void EC_GROUP_set_asn1_flag(EC_GROUP *, int flag);
+int EC_GROUP_get_asn1_flag(const EC_GROUP *);
+
+void EC_GROUP_set_point_conversion_form(EC_GROUP *, point_conversion_form_t);
+point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *);
+
+unsigned char *EC_GROUP_get0_seed(const EC_GROUP *);
+size_t EC_GROUP_get_seed_len(const EC_GROUP *);
+size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len);
+
+int EC_GROUP_set_curve_GFp(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+int EC_GROUP_get_curve_GFp(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
+int EC_GROUP_set_curve_GF2m(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+int EC_GROUP_get_curve_GF2m(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
+
+/* returns the number of bits needed to represent a field element */
+int EC_GROUP_get_degree(const EC_GROUP *);
+
+/* EC_GROUP_check() returns 1 if 'group' defines a valid group, 0 otherwise */
+int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx);
+/* EC_GROUP_check_discriminant() returns 1 if the discriminant of the
+ * elliptic curve is not zero, 0 otherwise */
+int EC_GROUP_check_discriminant(const EC_GROUP *, BN_CTX *);
+
+/* EC_GROUP_cmp() returns 0 if both groups are equal and 1 otherwise */
+int EC_GROUP_cmp(const EC_GROUP *, const EC_GROUP *, BN_CTX *);
+
+/* EC_GROUP_new_GF*() calls EC_GROUP_new() and EC_GROUP_set_GF*()
+ * after choosing an appropriate EC_METHOD */
+EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+
+/* EC_GROUP_new_by_curve_name() creates a EC_GROUP structure
+ * specified by a curve name (in form of a NID) */
+EC_GROUP *EC_GROUP_new_by_curve_name(int nid);
+/* handling of internal curves */
+typedef struct {
+ int nid;
+ const char *comment;
+ } EC_builtin_curve;
+/* EC_builtin_curves(EC_builtin_curve *r, size_t size) returns number
+ * of all available curves or zero if a error occurred.
+ * In case r ist not zero nitems EC_builtin_curve structures
+ * are filled with the data of the first nitems internal groups */
+size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems);
+
+
+/* EC_POINT functions */
+
+EC_POINT *EC_POINT_new(const EC_GROUP *);
+void EC_POINT_free(EC_POINT *);
+void EC_POINT_clear_free(EC_POINT *);
+int EC_POINT_copy(EC_POINT *, const EC_POINT *);
+EC_POINT *EC_POINT_dup(const EC_POINT *, const EC_GROUP *);
+
+const EC_METHOD *EC_POINT_method_of(const EC_POINT *);
+
+int EC_POINT_set_to_infinity(const EC_GROUP *, EC_POINT *);
+int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *);
+int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *, const EC_POINT *,
+ BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *);
+int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x, const BIGNUM *y, BN_CTX *);
+int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *, const EC_POINT *,
+ BIGNUM *x, BIGNUM *y, BN_CTX *);
+int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x, int y_bit, BN_CTX *);
+
+int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x, const BIGNUM *y, BN_CTX *);
+int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *, const EC_POINT *,
+ BIGNUM *x, BIGNUM *y, BN_CTX *);
+int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *, EC_POINT *,
+ const BIGNUM *x, int y_bit, BN_CTX *);
+
+size_t EC_POINT_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form,
+ unsigned char *buf, size_t len, BN_CTX *);
+int EC_POINT_oct2point(const EC_GROUP *, EC_POINT *,
+ const unsigned char *buf, size_t len, BN_CTX *);
+
+/* other interfaces to point2oct/oct2point: */
+BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *,
+ point_conversion_form_t form, BIGNUM *, BN_CTX *);
+EC_POINT *EC_POINT_bn2point(const EC_GROUP *, const BIGNUM *,
+ EC_POINT *, BN_CTX *);
+char *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *,
+ point_conversion_form_t form, BN_CTX *);
+EC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *,
+ EC_POINT *, BN_CTX *);
+
+int EC_POINT_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
+int EC_POINT_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *);
+int EC_POINT_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
+
+int EC_POINT_is_at_infinity(const EC_GROUP *, const EC_POINT *);
+int EC_POINT_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);
+int EC_POINT_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
+
+int EC_POINT_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
+int EC_POINTs_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *);
+
+
+int EC_POINTs_mul(const EC_GROUP *, EC_POINT *r, const BIGNUM *, size_t num, const EC_POINT *[], const BIGNUM *[], BN_CTX *);
+int EC_POINT_mul(const EC_GROUP *, EC_POINT *r, const BIGNUM *, const EC_POINT *, const BIGNUM *, BN_CTX *);
+
+/* EC_GROUP_precompute_mult() stores multiples of generator for faster point multiplication */
+int EC_GROUP_precompute_mult(EC_GROUP *, BN_CTX *);
+/* EC_GROUP_have_precompute_mult() reports whether such precomputation has been done */
+int EC_GROUP_have_precompute_mult(const EC_GROUP *);
+
+
+
+/* ASN1 stuff */
+
+/* EC_GROUP_get_basis_type() returns the NID of the basis type
+ * used to represent the field elements */
+int EC_GROUP_get_basis_type(const EC_GROUP *);
+int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k);
+int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1,
+ unsigned int *k2, unsigned int *k3);
+
+#define OPENSSL_EC_NAMED_CURVE 0x001
+
+typedef struct ecpk_parameters_st ECPKPARAMETERS;
+
+EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len);
+int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out);
+
+#define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x)
+#define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x)
+#define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \
+ (char *(*)())d2i_ECPKParameters,(fp),(unsigned char **)(x))
+#define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \
+ (unsigned char *)(x))
+
+#ifndef OPENSSL_NO_BIO
+int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off);
+#endif
+#ifndef OPENSSL_NO_FP_API
+int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off);
+#endif
+
+/* the EC_KEY stuff */
+typedef struct ec_key_st EC_KEY;
+
+/* some values for the encoding_flag */
+#define EC_PKEY_NO_PARAMETERS 0x001
+#define EC_PKEY_NO_PUBKEY 0x002
+
+EC_KEY *EC_KEY_new(void);
+EC_KEY *EC_KEY_new_by_curve_name(int nid);
+void EC_KEY_free(EC_KEY *);
+EC_KEY *EC_KEY_copy(EC_KEY *, const EC_KEY *);
+EC_KEY *EC_KEY_dup(const EC_KEY *);
+
+int EC_KEY_up_ref(EC_KEY *);
+
+const EC_GROUP *EC_KEY_get0_group(const EC_KEY *);
+int EC_KEY_set_group(EC_KEY *, const EC_GROUP *);
+const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *);
+int EC_KEY_set_private_key(EC_KEY *, const BIGNUM *);
+const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *);
+int EC_KEY_set_public_key(EC_KEY *, const EC_POINT *);
+unsigned EC_KEY_get_enc_flags(const EC_KEY *);
+void EC_KEY_set_enc_flags(EC_KEY *, unsigned int);
+point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *);
+void EC_KEY_set_conv_form(EC_KEY *, point_conversion_form_t);
+/* functions to set/get method specific data */
+void *EC_KEY_get_key_method_data(EC_KEY *,
+ void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
+void EC_KEY_insert_key_method_data(EC_KEY *, void *data,
+ void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
+/* wrapper functions for the underlying EC_GROUP object */
+void EC_KEY_set_asn1_flag(EC_KEY *, int);
+int EC_KEY_precompute_mult(EC_KEY *, BN_CTX *ctx);
+
+/* EC_KEY_generate_key() creates a ec private (public) key */
+int EC_KEY_generate_key(EC_KEY *);
+/* EC_KEY_check_key() */
+int EC_KEY_check_key(const EC_KEY *);
+
+/* de- and encoding functions for SEC1 ECPrivateKey */
+EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len);
+int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out);
+/* de- and encoding functions for EC parameters */
+EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len);
+int i2d_ECParameters(EC_KEY *a, unsigned char **out);
+/* de- and encoding functions for EC public key
+ * (octet string, not DER -- hence 'o2i' and 'i2o') */
+EC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len);
+int i2o_ECPublicKey(EC_KEY *a, unsigned char **out);
+
+#ifndef OPENSSL_NO_BIO
+int ECParameters_print(BIO *bp, const EC_KEY *x);
+int EC_KEY_print(BIO *bp, const EC_KEY *x, int off);
+#endif
+#ifndef OPENSSL_NO_FP_API
+int ECParameters_print_fp(FILE *fp, const EC_KEY *x);
+int EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off);
+#endif
+
+#define ECParameters_dup(x) ASN1_dup_of(EC_KEY,i2d_ECParameters,d2i_ECParameters,x)
+
+#ifndef __cplusplus
+#if defined(__SUNPRO_C)
+# if __SUNPRO_C >= 0x520
+# pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
+# endif
+# endif
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_EC_strings(void);
+
+/* Error codes for the EC functions. */
+
+/* Function codes. */
+#define EC_F_COMPUTE_WNAF 143
+#define EC_F_D2I_ECPARAMETERS 144
+#define EC_F_D2I_ECPKPARAMETERS 145
+#define EC_F_D2I_ECPRIVATEKEY 146
+#define EC_F_ECPARAMETERS_PRINT 147
+#define EC_F_ECPARAMETERS_PRINT_FP 148
+#define EC_F_ECPKPARAMETERS_PRINT 149
+#define EC_F_ECPKPARAMETERS_PRINT_FP 150
+#define EC_F_ECP_NIST_MOD_192 203
+#define EC_F_ECP_NIST_MOD_224 204
+#define EC_F_ECP_NIST_MOD_256 205
+#define EC_F_ECP_NIST_MOD_521 206
+#define EC_F_EC_ASN1_GROUP2CURVE 153
+#define EC_F_EC_ASN1_GROUP2FIELDID 154
+#define EC_F_EC_ASN1_GROUP2PARAMETERS 155
+#define EC_F_EC_ASN1_GROUP2PKPARAMETERS 156
+#define EC_F_EC_ASN1_PARAMETERS2GROUP 157
+#define EC_F_EC_ASN1_PKPARAMETERS2GROUP 158
+#define EC_F_EC_EX_DATA_SET_DATA 211
+#define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY 208
+#define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT 159
+#define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE 195
+#define EC_F_EC_GF2M_SIMPLE_OCT2POINT 160
+#define EC_F_EC_GF2M_SIMPLE_POINT2OCT 161
+#define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162
+#define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163
+#define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES 164
+#define EC_F_EC_GFP_MONT_FIELD_DECODE 133
+#define EC_F_EC_GFP_MONT_FIELD_ENCODE 134
+#define EC_F_EC_GFP_MONT_FIELD_MUL 131
+#define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE 209
+#define EC_F_EC_GFP_MONT_FIELD_SQR 132
+#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 189
+#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP 135
+#define EC_F_EC_GFP_NIST_FIELD_MUL 200
+#define EC_F_EC_GFP_NIST_FIELD_SQR 201
+#define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 202
+#define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT 165
+#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE 166
+#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP 100
+#define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR 101
+#define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 102
+#define EC_F_EC_GFP_SIMPLE_OCT2POINT 103
+#define EC_F_EC_GFP_SIMPLE_POINT2OCT 104
+#define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE 137
+#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES 167
+#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 105
+#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES 168
+#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP 128
+#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES 169
+#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP 129
+#define EC_F_EC_GROUP_CHECK 170
+#define EC_F_EC_GROUP_CHECK_DISCRIMINANT 171
+#define EC_F_EC_GROUP_COPY 106
+#define EC_F_EC_GROUP_GET0_GENERATOR 139
+#define EC_F_EC_GROUP_GET_COFACTOR 140
+#define EC_F_EC_GROUP_GET_CURVE_GF2M 172
+#define EC_F_EC_GROUP_GET_CURVE_GFP 130
+#define EC_F_EC_GROUP_GET_DEGREE 173
+#define EC_F_EC_GROUP_GET_ORDER 141
+#define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS 193
+#define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS 194
+#define EC_F_EC_GROUP_NEW 108
+#define EC_F_EC_GROUP_NEW_BY_CURVE_NAME 174
+#define EC_F_EC_GROUP_NEW_FROM_DATA 175
+#define EC_F_EC_GROUP_PRECOMPUTE_MULT 142
+#define EC_F_EC_GROUP_SET_CURVE_GF2M 176
+#define EC_F_EC_GROUP_SET_CURVE_GFP 109
+#define EC_F_EC_GROUP_SET_EXTRA_DATA 110
+#define EC_F_EC_GROUP_SET_GENERATOR 111
+#define EC_F_EC_KEY_CHECK_KEY 177
+#define EC_F_EC_KEY_COPY 178
+#define EC_F_EC_KEY_GENERATE_KEY 179
+#define EC_F_EC_KEY_NEW 182
+#define EC_F_EC_KEY_PRINT 180
+#define EC_F_EC_KEY_PRINT_FP 181
+#define EC_F_EC_POINTS_MAKE_AFFINE 136
+#define EC_F_EC_POINTS_MUL 138
+#define EC_F_EC_POINT_ADD 112
+#define EC_F_EC_POINT_CMP 113
+#define EC_F_EC_POINT_COPY 114
+#define EC_F_EC_POINT_DBL 115
+#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M 183
+#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP 116
+#define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP 117
+#define EC_F_EC_POINT_INVERT 210
+#define EC_F_EC_POINT_IS_AT_INFINITY 118
+#define EC_F_EC_POINT_IS_ON_CURVE 119
+#define EC_F_EC_POINT_MAKE_AFFINE 120
+#define EC_F_EC_POINT_MUL 184
+#define EC_F_EC_POINT_NEW 121
+#define EC_F_EC_POINT_OCT2POINT 122
+#define EC_F_EC_POINT_POINT2OCT 123
+#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M 185
+#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP 124
+#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M 186
+#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP 125
+#define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP 126
+#define EC_F_EC_POINT_SET_TO_INFINITY 127
+#define EC_F_EC_PRE_COMP_DUP 207
+#define EC_F_EC_PRE_COMP_NEW 196
+#define EC_F_EC_WNAF_MUL 187
+#define EC_F_EC_WNAF_PRECOMPUTE_MULT 188
+#define EC_F_I2D_ECPARAMETERS 190
+#define EC_F_I2D_ECPKPARAMETERS 191
+#define EC_F_I2D_ECPRIVATEKEY 192
+#define EC_F_I2O_ECPUBLICKEY 151
+#define EC_F_O2I_ECPUBLICKEY 152
+
+/* Reason codes. */
+#define EC_R_ASN1_ERROR 115
+#define EC_R_ASN1_UNKNOWN_FIELD 116
+#define EC_R_BUFFER_TOO_SMALL 100
+#define EC_R_D2I_ECPKPARAMETERS_FAILURE 117
+#define EC_R_DISCRIMINANT_IS_ZERO 118
+#define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119
+#define EC_R_FIELD_TOO_LARGE 138
+#define EC_R_GROUP2PKPARAMETERS_FAILURE 120
+#define EC_R_I2D_ECPKPARAMETERS_FAILURE 121
+#define EC_R_INCOMPATIBLE_OBJECTS 101
+#define EC_R_INVALID_ARGUMENT 112
+#define EC_R_INVALID_COMPRESSED_POINT 110
+#define EC_R_INVALID_COMPRESSION_BIT 109
+#define EC_R_INVALID_ENCODING 102
+#define EC_R_INVALID_FIELD 103
+#define EC_R_INVALID_FORM 104
+#define EC_R_INVALID_GROUP_ORDER 122
+#define EC_R_INVALID_PENTANOMIAL_BASIS 132
+#define EC_R_INVALID_PRIVATE_KEY 123
+#define EC_R_INVALID_TRINOMIAL_BASIS 137
+#define EC_R_MISSING_PARAMETERS 124
+#define EC_R_MISSING_PRIVATE_KEY 125
+#define EC_R_NOT_A_NIST_PRIME 135
+#define EC_R_NOT_A_SUPPORTED_NIST_PRIME 136
+#define EC_R_NOT_IMPLEMENTED 126
+#define EC_R_NOT_INITIALIZED 111
+#define EC_R_NO_FIELD_MOD 133
+#define EC_R_PASSED_NULL_PARAMETER 134
+#define EC_R_PKPARAMETERS2GROUP_FAILURE 127
+#define EC_R_POINT_AT_INFINITY 106
+#define EC_R_POINT_IS_NOT_ON_CURVE 107
+#define EC_R_SLOT_FULL 108
+#define EC_R_UNDEFINED_GENERATOR 113
+#define EC_R_UNDEFINED_ORDER 128
+#define EC_R_UNKNOWN_GROUP 129
+#define EC_R_UNKNOWN_ORDER 114
+#define EC_R_UNSUPPORTED_FIELD 131
+#define EC_R_WRONG_ORDER 130
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ecdh.h b/src/Mayaqua/win32_inc/openssl/ecdh.h
new file mode 100644
index 00000000..c2c00b8a
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ecdh.h
@@ -0,0 +1,123 @@
+/* crypto/ecdh/ecdh.h */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
+ * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
+ * to the OpenSSL project.
+ *
+ * The ECC Code is licensed pursuant to the OpenSSL open source
+ * license provided below.
+ *
+ * The ECDH software is originally written by Douglas Stebila of
+ * Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_ECDH_H
+#define HEADER_ECDH_H
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_ECDH
+#error ECDH is disabled.
+#endif
+
+#include <openssl/ec.h>
+#include <openssl/ossl_typ.h>
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const ECDH_METHOD *ECDH_OpenSSL(void);
+
+void ECDH_set_default_method(const ECDH_METHOD *);
+const ECDH_METHOD *ECDH_get_default_method(void);
+int ECDH_set_method(EC_KEY *, const ECDH_METHOD *);
+
+int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh,
+ void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen));
+
+int ECDH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new
+ *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int ECDH_set_ex_data(EC_KEY *d, int idx, void *arg);
+void *ECDH_get_ex_data(EC_KEY *d, int idx);
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ECDH_strings(void);
+
+/* Error codes for the ECDH functions. */
+
+/* Function codes. */
+#define ECDH_F_ECDH_COMPUTE_KEY 100
+#define ECDH_F_ECDH_DATA_NEW_METHOD 101
+
+/* Reason codes. */
+#define ECDH_R_KDF_FAILED 102
+#define ECDH_R_NO_PRIVATE_VALUE 100
+#define ECDH_R_POINT_ARITHMETIC_FAILURE 101
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ecdsa.h b/src/Mayaqua/win32_inc/openssl/ecdsa.h
new file mode 100644
index 00000000..294e2ba7
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ecdsa.h
@@ -0,0 +1,271 @@
+/* crypto/ecdsa/ecdsa.h */
+/**
+ * \file crypto/ecdsa/ecdsa.h Include file for the OpenSSL ECDSA functions
+ * \author Written by Nils Larsch for the OpenSSL project
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2003 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_ECDSA_H
+#define HEADER_ECDSA_H
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_ECDSA
+#error ECDSA is disabled.
+#endif
+
+#include <openssl/ec.h>
+#include <openssl/ossl_typ.h>
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ECDSA_SIG_st
+ {
+ BIGNUM *r;
+ BIGNUM *s;
+ } ECDSA_SIG;
+
+/** ECDSA_SIG *ECDSA_SIG_new(void)
+ * allocates and initialize a ECDSA_SIG structure
+ * \return pointer to a ECDSA_SIG structure or NULL if an error occurred
+ */
+ECDSA_SIG *ECDSA_SIG_new(void);
+
+/** ECDSA_SIG_free
+ * frees a ECDSA_SIG structure
+ * \param a pointer to the ECDSA_SIG structure
+ */
+void ECDSA_SIG_free(ECDSA_SIG *a);
+
+/** i2d_ECDSA_SIG
+ * DER encode content of ECDSA_SIG object (note: this function modifies *pp
+ * (*pp += length of the DER encoded signature)).
+ * \param a pointer to the ECDSA_SIG object
+ * \param pp pointer to a unsigned char pointer for the output or NULL
+ * \return the length of the DER encoded ECDSA_SIG object or 0
+ */
+int i2d_ECDSA_SIG(const ECDSA_SIG *a, unsigned char **pp);
+
+/** d2i_ECDSA_SIG
+ * decodes a DER encoded ECDSA signature (note: this function changes *pp
+ * (*pp += len)).
+ * \param v pointer to ECDSA_SIG pointer (may be NULL)
+ * \param pp buffer with the DER encoded signature
+ * \param len bufferlength
+ * \return pointer to the decoded ECDSA_SIG structure (or NULL)
+ */
+ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **v, const unsigned char **pp, long len);
+
+/** ECDSA_do_sign
+ * computes the ECDSA signature of the given hash value using
+ * the supplied private key and returns the created signature.
+ * \param dgst pointer to the hash value
+ * \param dgst_len length of the hash value
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \return pointer to a ECDSA_SIG structure or NULL
+ */
+ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst,int dgst_len,EC_KEY *eckey);
+
+/** ECDSA_do_sign_ex
+ * computes ECDSA signature of a given hash value using the supplied
+ * private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
+ * \param dgst pointer to the hash value to sign
+ * \param dgstlen length of the hash value
+ * \param kinv optional pointer to a pre-computed inverse k
+ * \param rp optional pointer to the pre-computed rp value (see
+ * ECDSA_sign_setup
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \return pointer to a ECDSA_SIG structure or NULL
+ */
+ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen,
+ const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey);
+
+/** ECDSA_do_verify
+ * verifies that the supplied signature is a valid ECDSA
+ * signature of the supplied hash value using the supplied public key.
+ * \param dgst pointer to the hash value
+ * \param dgst_len length of the hash value
+ * \param sig pointer to the ECDSA_SIG structure
+ * \param eckey pointer to the EC_KEY object containing a public EC key
+ * \return 1 if the signature is valid, 0 if the signature is invalid and -1 on error
+ */
+int ECDSA_do_verify(const unsigned char *dgst, int dgst_len,
+ const ECDSA_SIG *sig, EC_KEY* eckey);
+
+const ECDSA_METHOD *ECDSA_OpenSSL(void);
+
+/** ECDSA_set_default_method
+ * sets the default ECDSA method
+ * \param meth the new default ECDSA_METHOD
+ */
+void ECDSA_set_default_method(const ECDSA_METHOD *meth);
+
+/** ECDSA_get_default_method
+ * returns the default ECDSA method
+ * \return pointer to ECDSA_METHOD structure containing the default method
+ */
+const ECDSA_METHOD *ECDSA_get_default_method(void);
+
+/** ECDSA_set_method
+ * sets method to be used for the ECDSA operations
+ * \param eckey pointer to the EC_KEY object
+ * \param meth pointer to the new method
+ * \return 1 on success and 0 otherwise
+ */
+int ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth);
+
+/** ECDSA_size
+ * returns the maximum length of the DER encoded signature
+ * \param eckey pointer to a EC_KEY object
+ * \return numbers of bytes required for the DER encoded signature
+ */
+int ECDSA_size(const EC_KEY *eckey);
+
+/** ECDSA_sign_setup
+ * precompute parts of the signing operation.
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \param ctx pointer to a BN_CTX object (may be NULL)
+ * \param kinv pointer to a BIGNUM pointer for the inverse of k
+ * \param rp pointer to a BIGNUM pointer for x coordinate of k * generator
+ * \return 1 on success and 0 otherwise
+ */
+int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv,
+ BIGNUM **rp);
+
+/** ECDSA_sign
+ * computes ECDSA signature of a given hash value using the supplied
+ * private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
+ * \param type this parameter is ignored
+ * \param dgst pointer to the hash value to sign
+ * \param dgstlen length of the hash value
+ * \param sig buffer to hold the DER encoded signature
+ * \param siglen pointer to the length of the returned signature
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \return 1 on success and 0 otherwise
+ */
+int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen,
+ unsigned char *sig, unsigned int *siglen, EC_KEY *eckey);
+
+
+/** ECDSA_sign_ex
+ * computes ECDSA signature of a given hash value using the supplied
+ * private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
+ * \param type this parameter is ignored
+ * \param dgst pointer to the hash value to sign
+ * \param dgstlen length of the hash value
+ * \param sig buffer to hold the DER encoded signature
+ * \param siglen pointer to the length of the returned signature
+ * \param kinv optional pointer to a pre-computed inverse k
+ * \param rp optional pointer to the pre-computed rp value (see
+ * ECDSA_sign_setup
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \return 1 on success and 0 otherwise
+ */
+int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen,
+ unsigned char *sig, unsigned int *siglen, const BIGNUM *kinv,
+ const BIGNUM *rp, EC_KEY *eckey);
+
+/** ECDSA_verify
+ * verifies that the given signature is valid ECDSA signature
+ * of the supplied hash value using the specified public key.
+ * \param type this parameter is ignored
+ * \param dgst pointer to the hash value
+ * \param dgstlen length of the hash value
+ * \param sig pointer to the DER encoded signature
+ * \param siglen length of the DER encoded signature
+ * \param eckey pointer to the EC_KEY object containing a public EC key
+ * \return 1 if the signature is valid, 0 if the signature is invalid and -1 on error
+ */
+int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen,
+ const unsigned char *sig, int siglen, EC_KEY *eckey);
+
+/* the standard ex_data functions */
+int ECDSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new
+ *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg);
+void *ECDSA_get_ex_data(EC_KEY *d, int idx);
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ECDSA_strings(void);
+
+/* Error codes for the ECDSA functions. */
+
+/* Function codes. */
+#define ECDSA_F_ECDSA_DATA_NEW_METHOD 100
+#define ECDSA_F_ECDSA_DO_SIGN 101
+#define ECDSA_F_ECDSA_DO_VERIFY 102
+#define ECDSA_F_ECDSA_SIGN_SETUP 103
+
+/* Reason codes. */
+#define ECDSA_R_BAD_SIGNATURE 100
+#define ECDSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 101
+#define ECDSA_R_ERR_EC_LIB 102
+#define ECDSA_R_MISSING_PARAMETERS 103
+#define ECDSA_R_NEED_NEW_SETUP_VALUES 106
+#define ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED 104
+#define ECDSA_R_SIGNATURE_MALLOC_FAILED 105
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/engine.h b/src/Mayaqua/win32_inc/openssl/engine.h
new file mode 100644
index 00000000..a64e92e1
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/engine.h
@@ -0,0 +1,804 @@
+/* openssl/engine.h */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_ENGINE_H
+#define HEADER_ENGINE_H
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_ENGINE
+#error ENGINE is disabled.
+#endif
+
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#endif
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+#ifndef OPENSSL_NO_ECDH
+#include <openssl/ecdh.h>
+#endif
+#ifndef OPENSSL_NO_ECDSA
+#include <openssl/ecdsa.h>
+#endif
+#include <openssl/rand.h>
+#include <openssl/store.h>
+#include <openssl/ui.h>
+#include <openssl/err.h>
+#endif
+
+#include <openssl/x509.h>
+
+#include <openssl/ossl_typ.h>
+#include <openssl/symhacks.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These flags are used to control combinations of algorithm (methods)
+ * by bitwise "OR"ing. */
+#define ENGINE_METHOD_RSA (unsigned int)0x0001
+#define ENGINE_METHOD_DSA (unsigned int)0x0002
+#define ENGINE_METHOD_DH (unsigned int)0x0004
+#define ENGINE_METHOD_RAND (unsigned int)0x0008
+#define ENGINE_METHOD_ECDH (unsigned int)0x0010
+#define ENGINE_METHOD_ECDSA (unsigned int)0x0020
+#define ENGINE_METHOD_CIPHERS (unsigned int)0x0040
+#define ENGINE_METHOD_DIGESTS (unsigned int)0x0080
+#define ENGINE_METHOD_STORE (unsigned int)0x0100
+/* Obvious all-or-nothing cases. */
+#define ENGINE_METHOD_ALL (unsigned int)0xFFFF
+#define ENGINE_METHOD_NONE (unsigned int)0x0000
+
+/* This(ese) flag(s) controls behaviour of the ENGINE_TABLE mechanism used
+ * internally to control registration of ENGINE implementations, and can be set
+ * by ENGINE_set_table_flags(). The "NOINIT" flag prevents attempts to
+ * initialise registered ENGINEs if they are not already initialised. */
+#define ENGINE_TABLE_FLAG_NOINIT (unsigned int)0x0001
+
+/* ENGINE flags that can be set by ENGINE_set_flags(). */
+/* #define ENGINE_FLAGS_MALLOCED 0x0001 */ /* Not used */
+
+/* This flag is for ENGINEs that wish to handle the various 'CMD'-related
+ * control commands on their own. Without this flag, ENGINE_ctrl() handles these
+ * control commands on behalf of the ENGINE using their "cmd_defns" data. */
+#define ENGINE_FLAGS_MANUAL_CMD_CTRL (int)0x0002
+
+/* This flag is for ENGINEs who return new duplicate structures when found via
+ * "ENGINE_by_id()". When an ENGINE must store state (eg. if ENGINE_ctrl()
+ * commands are called in sequence as part of some stateful process like
+ * key-generation setup and execution), it can set this flag - then each attempt
+ * to obtain the ENGINE will result in it being copied into a new structure.
+ * Normally, ENGINEs don't declare this flag so ENGINE_by_id() just increments
+ * the existing ENGINE's structural reference count. */
+#define ENGINE_FLAGS_BY_ID_COPY (int)0x0004
+
+/* ENGINEs can support their own command types, and these flags are used in
+ * ENGINE_CTRL_GET_CMD_FLAGS to indicate to the caller what kind of input each
+ * command expects. Currently only numeric and string input is supported. If a
+ * control command supports none of the _NUMERIC, _STRING, or _NO_INPUT options,
+ * then it is regarded as an "internal" control command - and not for use in
+ * config setting situations. As such, they're not available to the
+ * ENGINE_ctrl_cmd_string() function, only raw ENGINE_ctrl() access. Changes to
+ * this list of 'command types' should be reflected carefully in
+ * ENGINE_cmd_is_executable() and ENGINE_ctrl_cmd_string(). */
+
+/* accepts a 'long' input value (3rd parameter to ENGINE_ctrl) */
+#define ENGINE_CMD_FLAG_NUMERIC (unsigned int)0x0001
+/* accepts string input (cast from 'void*' to 'const char *', 4th parameter to
+ * ENGINE_ctrl) */
+#define ENGINE_CMD_FLAG_STRING (unsigned int)0x0002
+/* Indicates that the control command takes *no* input. Ie. the control command
+ * is unparameterised. */
+#define ENGINE_CMD_FLAG_NO_INPUT (unsigned int)0x0004
+/* Indicates that the control command is internal. This control command won't
+ * be shown in any output, and is only usable through the ENGINE_ctrl_cmd()
+ * function. */
+#define ENGINE_CMD_FLAG_INTERNAL (unsigned int)0x0008
+
+/* NB: These 3 control commands are deprecated and should not be used. ENGINEs
+ * relying on these commands should compile conditional support for
+ * compatibility (eg. if these symbols are defined) but should also migrate the
+ * same functionality to their own ENGINE-specific control functions that can be
+ * "discovered" by calling applications. The fact these control commands
+ * wouldn't be "executable" (ie. usable by text-based config) doesn't change the
+ * fact that application code can find and use them without requiring per-ENGINE
+ * hacking. */
+
+/* These flags are used to tell the ctrl function what should be done.
+ * All command numbers are shared between all engines, even if some don't
+ * make sense to some engines. In such a case, they do nothing but return
+ * the error ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED. */
+#define ENGINE_CTRL_SET_LOGSTREAM 1
+#define ENGINE_CTRL_SET_PASSWORD_CALLBACK 2
+#define ENGINE_CTRL_HUP 3 /* Close and reinitialise any
+ handles/connections etc. */
+#define ENGINE_CTRL_SET_USER_INTERFACE 4 /* Alternative to callback */
+#define ENGINE_CTRL_SET_CALLBACK_DATA 5 /* User-specific data, used
+ when calling the password
+ callback and the user
+ interface */
+#define ENGINE_CTRL_LOAD_CONFIGURATION 6 /* Load a configuration, given
+ a string that represents a
+ file name or so */
+#define ENGINE_CTRL_LOAD_SECTION 7 /* Load data from a given
+ section in the already loaded
+ configuration */
+
+/* These control commands allow an application to deal with an arbitrary engine
+ * in a dynamic way. Warn: Negative return values indicate errors FOR THESE
+ * COMMANDS because zero is used to indicate 'end-of-list'. Other commands,
+ * including ENGINE-specific command types, return zero for an error.
+ *
+ * An ENGINE can choose to implement these ctrl functions, and can internally
+ * manage things however it chooses - it does so by setting the
+ * ENGINE_FLAGS_MANUAL_CMD_CTRL flag (using ENGINE_set_flags()). Otherwise the
+ * ENGINE_ctrl() code handles this on the ENGINE's behalf using the cmd_defns
+ * data (set using ENGINE_set_cmd_defns()). This means an ENGINE's ctrl()
+ * handler need only implement its own commands - the above "meta" commands will
+ * be taken care of. */
+
+/* Returns non-zero if the supplied ENGINE has a ctrl() handler. If "not", then
+ * all the remaining control commands will return failure, so it is worth
+ * checking this first if the caller is trying to "discover" the engine's
+ * capabilities and doesn't want errors generated unnecessarily. */
+#define ENGINE_CTRL_HAS_CTRL_FUNCTION 10
+/* Returns a positive command number for the first command supported by the
+ * engine. Returns zero if no ctrl commands are supported. */
+#define ENGINE_CTRL_GET_FIRST_CMD_TYPE 11
+/* The 'long' argument specifies a command implemented by the engine, and the
+ * return value is the next command supported, or zero if there are no more. */
+#define ENGINE_CTRL_GET_NEXT_CMD_TYPE 12
+/* The 'void*' argument is a command name (cast from 'const char *'), and the
+ * return value is the command that corresponds to it. */
+#define ENGINE_CTRL_GET_CMD_FROM_NAME 13
+/* The next two allow a command to be converted into its corresponding string
+ * form. In each case, the 'long' argument supplies the command. In the NAME_LEN
+ * case, the return value is the length of the command name (not counting a
+ * trailing EOL). In the NAME case, the 'void*' argument must be a string buffer
+ * large enough, and it will be populated with the name of the command (WITH a
+ * trailing EOL). */
+#define ENGINE_CTRL_GET_NAME_LEN_FROM_CMD 14
+#define ENGINE_CTRL_GET_NAME_FROM_CMD 15
+/* The next two are similar but give a "short description" of a command. */
+#define ENGINE_CTRL_GET_DESC_LEN_FROM_CMD 16
+#define ENGINE_CTRL_GET_DESC_FROM_CMD 17
+/* With this command, the return value is the OR'd combination of
+ * ENGINE_CMD_FLAG_*** values that indicate what kind of input a given
+ * engine-specific ctrl command expects. */
+#define ENGINE_CTRL_GET_CMD_FLAGS 18
+
+/* ENGINE implementations should start the numbering of their own control
+ * commands from this value. (ie. ENGINE_CMD_BASE, ENGINE_CMD_BASE + 1, etc). */
+#define ENGINE_CMD_BASE 200
+
+/* NB: These 2 nCipher "chil" control commands are deprecated, and their
+ * functionality is now available through ENGINE-specific control commands
+ * (exposed through the above-mentioned 'CMD'-handling). Code using these 2
+ * commands should be migrated to the more general command handling before these
+ * are removed. */
+
+/* Flags specific to the nCipher "chil" engine */
+#define ENGINE_CTRL_CHIL_SET_FORKCHECK 100
+ /* Depending on the value of the (long)i argument, this sets or
+ * unsets the SimpleForkCheck flag in the CHIL API to enable or
+ * disable checking and workarounds for applications that fork().
+ */
+#define ENGINE_CTRL_CHIL_NO_LOCKING 101
+ /* This prevents the initialisation function from providing mutex
+ * callbacks to the nCipher library. */
+
+/* If an ENGINE supports its own specific control commands and wishes the
+ * framework to handle the above 'ENGINE_CMD_***'-manipulation commands on its
+ * behalf, it should supply a null-terminated array of ENGINE_CMD_DEFN entries
+ * to ENGINE_set_cmd_defns(). It should also implement a ctrl() handler that
+ * supports the stated commands (ie. the "cmd_num" entries as described by the
+ * array). NB: The array must be ordered in increasing order of cmd_num.
+ * "null-terminated" means that the last ENGINE_CMD_DEFN element has cmd_num set
+ * to zero and/or cmd_name set to NULL. */
+typedef struct ENGINE_CMD_DEFN_st
+ {
+ unsigned int cmd_num; /* The command number */
+ const char *cmd_name; /* The command name itself */
+ const char *cmd_desc; /* A short description of the command */
+ unsigned int cmd_flags; /* The input the command expects */
+ } ENGINE_CMD_DEFN;
+
+/* Generic function pointer */
+typedef int (*ENGINE_GEN_FUNC_PTR)(void);
+/* Generic function pointer taking no arguments */
+typedef int (*ENGINE_GEN_INT_FUNC_PTR)(ENGINE *);
+/* Specific control function pointer */
+typedef int (*ENGINE_CTRL_FUNC_PTR)(ENGINE *, int, long, void *, void (*f)(void));
+/* Generic load_key function pointer */
+typedef EVP_PKEY * (*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *,
+ UI_METHOD *ui_method, void *callback_data);
+typedef int (*ENGINE_SSL_CLIENT_CERT_PTR)(ENGINE *, SSL *ssl,
+ STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **pkey,
+ STACK_OF(X509) **pother, UI_METHOD *ui_method, void *callback_data);
+/* These callback types are for an ENGINE's handler for cipher and digest logic.
+ * These handlers have these prototypes;
+ * int foo(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid);
+ * int foo(ENGINE *e, const EVP_MD **digest, const int **nids, int nid);
+ * Looking at how to implement these handlers in the case of cipher support, if
+ * the framework wants the EVP_CIPHER for 'nid', it will call;
+ * foo(e, &p_evp_cipher, NULL, nid); (return zero for failure)
+ * If the framework wants a list of supported 'nid's, it will call;
+ * foo(e, NULL, &p_nids, 0); (returns number of 'nids' or -1 for error)
+ */
+/* Returns to a pointer to the array of supported cipher 'nid's. If the second
+ * parameter is non-NULL it is set to the size of the returned array. */
+typedef int (*ENGINE_CIPHERS_PTR)(ENGINE *, const EVP_CIPHER **, const int **, int);
+typedef int (*ENGINE_DIGESTS_PTR)(ENGINE *, const EVP_MD **, const int **, int);
+
+/* STRUCTURE functions ... all of these functions deal with pointers to ENGINE
+ * structures where the pointers have a "structural reference". This means that
+ * their reference is to allowed access to the structure but it does not imply
+ * that the structure is functional. To simply increment or decrement the
+ * structural reference count, use ENGINE_by_id and ENGINE_free. NB: This is not
+ * required when iterating using ENGINE_get_next as it will automatically
+ * decrement the structural reference count of the "current" ENGINE and
+ * increment the structural reference count of the ENGINE it returns (unless it
+ * is NULL). */
+
+/* Get the first/last "ENGINE" type available. */
+ENGINE *ENGINE_get_first(void);
+ENGINE *ENGINE_get_last(void);
+/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
+ENGINE *ENGINE_get_next(ENGINE *e);
+ENGINE *ENGINE_get_prev(ENGINE *e);
+/* Add another "ENGINE" type into the array. */
+int ENGINE_add(ENGINE *e);
+/* Remove an existing "ENGINE" type from the array. */
+int ENGINE_remove(ENGINE *e);
+/* Retrieve an engine from the list by its unique "id" value. */
+ENGINE *ENGINE_by_id(const char *id);
+/* Add all the built-in engines. */
+void ENGINE_load_openssl(void);
+void ENGINE_load_dynamic(void);
+#ifndef OPENSSL_NO_STATIC_ENGINE
+void ENGINE_load_4758cca(void);
+void ENGINE_load_aep(void);
+void ENGINE_load_atalla(void);
+void ENGINE_load_chil(void);
+void ENGINE_load_cswift(void);
+#ifndef OPENSSL_NO_GMP
+void ENGINE_load_gmp(void);
+#endif
+void ENGINE_load_nuron(void);
+void ENGINE_load_sureware(void);
+void ENGINE_load_ubsec(void);
+#endif
+void ENGINE_load_cryptodev(void);
+void ENGINE_load_padlock(void);
+void ENGINE_load_builtin_engines(void);
+#ifdef OPENSSL_SYS_WIN32
+#ifndef OPENSSL_NO_CAPIENG
+void ENGINE_load_capi(void);
+#endif
+#endif
+
+/* Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation
+ * "registry" handling. */
+unsigned int ENGINE_get_table_flags(void);
+void ENGINE_set_table_flags(unsigned int flags);
+
+/* Manage registration of ENGINEs per "table". For each type, there are 3
+ * functions;
+ * ENGINE_register_***(e) - registers the implementation from 'e' (if it has one)
+ * ENGINE_unregister_***(e) - unregister the implementation from 'e'
+ * ENGINE_register_all_***() - call ENGINE_register_***() for each 'e' in the list
+ * Cleanup is automatically registered from each table when required, so
+ * ENGINE_cleanup() will reverse any "register" operations. */
+
+int ENGINE_register_RSA(ENGINE *e);
+void ENGINE_unregister_RSA(ENGINE *e);
+void ENGINE_register_all_RSA(void);
+
+int ENGINE_register_DSA(ENGINE *e);
+void ENGINE_unregister_DSA(ENGINE *e);
+void ENGINE_register_all_DSA(void);
+
+int ENGINE_register_ECDH(ENGINE *e);
+void ENGINE_unregister_ECDH(ENGINE *e);
+void ENGINE_register_all_ECDH(void);
+
+int ENGINE_register_ECDSA(ENGINE *e);
+void ENGINE_unregister_ECDSA(ENGINE *e);
+void ENGINE_register_all_ECDSA(void);
+
+int ENGINE_register_DH(ENGINE *e);
+void ENGINE_unregister_DH(ENGINE *e);
+void ENGINE_register_all_DH(void);
+
+int ENGINE_register_RAND(ENGINE *e);
+void ENGINE_unregister_RAND(ENGINE *e);
+void ENGINE_register_all_RAND(void);
+
+int ENGINE_register_STORE(ENGINE *e);
+void ENGINE_unregister_STORE(ENGINE *e);
+void ENGINE_register_all_STORE(void);
+
+int ENGINE_register_ciphers(ENGINE *e);
+void ENGINE_unregister_ciphers(ENGINE *e);
+void ENGINE_register_all_ciphers(void);
+
+int ENGINE_register_digests(ENGINE *e);
+void ENGINE_unregister_digests(ENGINE *e);
+void ENGINE_register_all_digests(void);
+
+/* These functions register all support from the above categories. Note, use of
+ * these functions can result in static linkage of code your application may not
+ * need. If you only need a subset of functionality, consider using more
+ * selective initialisation. */
+int ENGINE_register_complete(ENGINE *e);
+int ENGINE_register_all_complete(void);
+
+/* Send parametrised control commands to the engine. The possibilities to send
+ * down an integer, a pointer to data or a function pointer are provided. Any of
+ * the parameters may or may not be NULL, depending on the command number. In
+ * actuality, this function only requires a structural (rather than functional)
+ * reference to an engine, but many control commands may require the engine be
+ * functional. The caller should be aware of trying commands that require an
+ * operational ENGINE, and only use functional references in such situations. */
+int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
+
+/* This function tests if an ENGINE-specific command is usable as a "setting".
+ * Eg. in an application's config file that gets processed through
+ * ENGINE_ctrl_cmd_string(). If this returns zero, it is not available to
+ * ENGINE_ctrl_cmd_string(), only ENGINE_ctrl(). */
+int ENGINE_cmd_is_executable(ENGINE *e, int cmd);
+
+/* This function works like ENGINE_ctrl() with the exception of taking a
+ * command name instead of a command number, and can handle optional commands.
+ * See the comment on ENGINE_ctrl_cmd_string() for an explanation on how to
+ * use the cmd_name and cmd_optional. */
+int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name,
+ long i, void *p, void (*f)(void), int cmd_optional);
+
+/* This function passes a command-name and argument to an ENGINE. The cmd_name
+ * is converted to a command number and the control command is called using
+ * 'arg' as an argument (unless the ENGINE doesn't support such a command, in
+ * which case no control command is called). The command is checked for input
+ * flags, and if necessary the argument will be converted to a numeric value. If
+ * cmd_optional is non-zero, then if the ENGINE doesn't support the given
+ * cmd_name the return value will be success anyway. This function is intended
+ * for applications to use so that users (or config files) can supply
+ * engine-specific config data to the ENGINE at run-time to control behaviour of
+ * specific engines. As such, it shouldn't be used for calling ENGINE_ctrl()
+ * functions that return data, deal with binary data, or that are otherwise
+ * supposed to be used directly through ENGINE_ctrl() in application code. Any
+ * "return" data from an ENGINE_ctrl() operation in this function will be lost -
+ * the return value is interpreted as failure if the return value is zero,
+ * success otherwise, and this function returns a boolean value as a result. In
+ * other words, vendors of 'ENGINE'-enabled devices should write ENGINE
+ * implementations with parameterisations that work in this scheme, so that
+ * compliant ENGINE-based applications can work consistently with the same
+ * configuration for the same ENGINE-enabled devices, across applications. */
+int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
+ int cmd_optional);
+
+/* These functions are useful for manufacturing new ENGINE structures. They
+ * don't address reference counting at all - one uses them to populate an ENGINE
+ * structure with personalised implementations of things prior to using it
+ * directly or adding it to the builtin ENGINE list in OpenSSL. These are also
+ * here so that the ENGINE structure doesn't have to be exposed and break binary
+ * compatibility! */
+ENGINE *ENGINE_new(void);
+int ENGINE_free(ENGINE *e);
+int ENGINE_up_ref(ENGINE *e);
+int ENGINE_set_id(ENGINE *e, const char *id);
+int ENGINE_set_name(ENGINE *e, const char *name);
+int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth);
+int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth);
+int ENGINE_set_ECDH(ENGINE *e, const ECDH_METHOD *ecdh_meth);
+int ENGINE_set_ECDSA(ENGINE *e, const ECDSA_METHOD *ecdsa_meth);
+int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth);
+int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth);
+int ENGINE_set_STORE(ENGINE *e, const STORE_METHOD *store_meth);
+int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f);
+int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f);
+int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f);
+int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f);
+int ENGINE_set_load_privkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpriv_f);
+int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f);
+int ENGINE_set_load_ssl_client_cert_function(ENGINE *e,
+ ENGINE_SSL_CLIENT_CERT_PTR loadssl_f);
+int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f);
+int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f);
+int ENGINE_set_flags(ENGINE *e, int flags);
+int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns);
+/* These functions allow control over any per-structure ENGINE data. */
+int ENGINE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg);
+void *ENGINE_get_ex_data(const ENGINE *e, int idx);
+
+/* This function cleans up anything that needs it. Eg. the ENGINE_add() function
+ * automatically ensures the list cleanup function is registered to be called
+ * from ENGINE_cleanup(). Similarly, all ENGINE_register_*** functions ensure
+ * ENGINE_cleanup() will clean up after them. */
+void ENGINE_cleanup(void);
+
+/* These return values from within the ENGINE structure. These can be useful
+ * with functional references as well as structural references - it depends
+ * which you obtained. Using the result for functional purposes if you only
+ * obtained a structural reference may be problematic! */
+const char *ENGINE_get_id(const ENGINE *e);
+const char *ENGINE_get_name(const ENGINE *e);
+const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e);
+const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e);
+const ECDH_METHOD *ENGINE_get_ECDH(const ENGINE *e);
+const ECDSA_METHOD *ENGINE_get_ECDSA(const ENGINE *e);
+const DH_METHOD *ENGINE_get_DH(const ENGINE *e);
+const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e);
+const STORE_METHOD *ENGINE_get_STORE(const ENGINE *e);
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e);
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e);
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e);
+ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e);
+ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e);
+ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e);
+ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE *e);
+ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e);
+ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e);
+const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid);
+const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid);
+const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e);
+int ENGINE_get_flags(const ENGINE *e);
+
+/* FUNCTIONAL functions. These functions deal with ENGINE structures
+ * that have (or will) be initialised for use. Broadly speaking, the
+ * structural functions are useful for iterating the list of available
+ * engine types, creating new engine types, and other "list" operations.
+ * These functions actually deal with ENGINEs that are to be used. As
+ * such these functions can fail (if applicable) when particular
+ * engines are unavailable - eg. if a hardware accelerator is not
+ * attached or not functioning correctly. Each ENGINE has 2 reference
+ * counts; structural and functional. Every time a functional reference
+ * is obtained or released, a corresponding structural reference is
+ * automatically obtained or released too. */
+
+/* Initialise a engine type for use (or up its reference count if it's
+ * already in use). This will fail if the engine is not currently
+ * operational and cannot initialise. */
+int ENGINE_init(ENGINE *e);
+/* Free a functional reference to a engine type. This does not require
+ * a corresponding call to ENGINE_free as it also releases a structural
+ * reference. */
+int ENGINE_finish(ENGINE *e);
+
+/* The following functions handle keys that are stored in some secondary
+ * location, handled by the engine. The storage may be on a card or
+ * whatever. */
+EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id,
+ UI_METHOD *ui_method, void *callback_data);
+EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id,
+ UI_METHOD *ui_method, void *callback_data);
+int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s,
+ STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **ppkey,
+ STACK_OF(X509) **pother,
+ UI_METHOD *ui_method, void *callback_data);
+
+/* This returns a pointer for the current ENGINE structure that
+ * is (by default) performing any RSA operations. The value returned
+ * is an incremented reference, so it should be free'd (ENGINE_finish)
+ * before it is discarded. */
+ENGINE *ENGINE_get_default_RSA(void);
+/* Same for the other "methods" */
+ENGINE *ENGINE_get_default_DSA(void);
+ENGINE *ENGINE_get_default_ECDH(void);
+ENGINE *ENGINE_get_default_ECDSA(void);
+ENGINE *ENGINE_get_default_DH(void);
+ENGINE *ENGINE_get_default_RAND(void);
+/* These functions can be used to get a functional reference to perform
+ * ciphering or digesting corresponding to "nid". */
+ENGINE *ENGINE_get_cipher_engine(int nid);
+ENGINE *ENGINE_get_digest_engine(int nid);
+
+/* This sets a new default ENGINE structure for performing RSA
+ * operations. If the result is non-zero (success) then the ENGINE
+ * structure will have had its reference count up'd so the caller
+ * should still free their own reference 'e'. */
+int ENGINE_set_default_RSA(ENGINE *e);
+int ENGINE_set_default_string(ENGINE *e, const char *def_list);
+/* Same for the other "methods" */
+int ENGINE_set_default_DSA(ENGINE *e);
+int ENGINE_set_default_ECDH(ENGINE *e);
+int ENGINE_set_default_ECDSA(ENGINE *e);
+int ENGINE_set_default_DH(ENGINE *e);
+int ENGINE_set_default_RAND(ENGINE *e);
+int ENGINE_set_default_ciphers(ENGINE *e);
+int ENGINE_set_default_digests(ENGINE *e);
+
+/* The combination "set" - the flags are bitwise "OR"d from the
+ * ENGINE_METHOD_*** defines above. As with the "ENGINE_register_complete()"
+ * function, this function can result in unnecessary static linkage. If your
+ * application requires only specific functionality, consider using more
+ * selective functions. */
+int ENGINE_set_default(ENGINE *e, unsigned int flags);
+
+void ENGINE_add_conf_module(void);
+
+/* Deprecated functions ... */
+/* int ENGINE_clear_defaults(void); */
+
+/**************************/
+/* DYNAMIC ENGINE SUPPORT */
+/**************************/
+
+/* Binary/behaviour compatibility levels */
+#define OSSL_DYNAMIC_VERSION (unsigned long)0x00020000
+/* Binary versions older than this are too old for us (whether we're a loader or
+ * a loadee) */
+#define OSSL_DYNAMIC_OLDEST (unsigned long)0x00020000
+
+/* When compiling an ENGINE entirely as an external shared library, loadable by
+ * the "dynamic" ENGINE, these types are needed. The 'dynamic_fns' structure
+ * type provides the calling application's (or library's) error functionality
+ * and memory management function pointers to the loaded library. These should
+ * be used/set in the loaded library code so that the loading application's
+ * 'state' will be used/changed in all operations. The 'static_state' pointer
+ * allows the loaded library to know if it shares the same static data as the
+ * calling application (or library), and thus whether these callbacks need to be
+ * set or not. */
+typedef void *(*dyn_MEM_malloc_cb)(size_t);
+typedef void *(*dyn_MEM_realloc_cb)(void *, size_t);
+typedef void (*dyn_MEM_free_cb)(void *);
+typedef struct st_dynamic_MEM_fns {
+ dyn_MEM_malloc_cb malloc_cb;
+ dyn_MEM_realloc_cb realloc_cb;
+ dyn_MEM_free_cb free_cb;
+ } dynamic_MEM_fns;
+/* FIXME: Perhaps the memory and locking code (crypto.h) should declare and use
+ * these types so we (and any other dependant code) can simplify a bit?? */
+typedef void (*dyn_lock_locking_cb)(int,int,const char *,int);
+typedef int (*dyn_lock_add_lock_cb)(int*,int,int,const char *,int);
+typedef struct CRYPTO_dynlock_value *(*dyn_dynlock_create_cb)(
+ const char *,int);
+typedef void (*dyn_dynlock_lock_cb)(int,struct CRYPTO_dynlock_value *,
+ const char *,int);
+typedef void (*dyn_dynlock_destroy_cb)(struct CRYPTO_dynlock_value *,
+ const char *,int);
+typedef struct st_dynamic_LOCK_fns {
+ dyn_lock_locking_cb lock_locking_cb;
+ dyn_lock_add_lock_cb lock_add_lock_cb;
+ dyn_dynlock_create_cb dynlock_create_cb;
+ dyn_dynlock_lock_cb dynlock_lock_cb;
+ dyn_dynlock_destroy_cb dynlock_destroy_cb;
+ } dynamic_LOCK_fns;
+/* The top-level structure */
+typedef struct st_dynamic_fns {
+ void *static_state;
+ const ERR_FNS *err_fns;
+ const CRYPTO_EX_DATA_IMPL *ex_data_fns;
+ dynamic_MEM_fns mem_fns;
+ dynamic_LOCK_fns lock_fns;
+ } dynamic_fns;
+
+/* The version checking function should be of this prototype. NB: The
+ * ossl_version value passed in is the OSSL_DYNAMIC_VERSION of the loading code.
+ * If this function returns zero, it indicates a (potential) version
+ * incompatibility and the loaded library doesn't believe it can proceed.
+ * Otherwise, the returned value is the (latest) version supported by the
+ * loading library. The loader may still decide that the loaded code's version
+ * is unsatisfactory and could veto the load. The function is expected to
+ * be implemented with the symbol name "v_check", and a default implementation
+ * can be fully instantiated with IMPLEMENT_DYNAMIC_CHECK_FN(). */
+typedef unsigned long (*dynamic_v_check_fn)(unsigned long ossl_version);
+#define IMPLEMENT_DYNAMIC_CHECK_FN() \
+ OPENSSL_EXPORT unsigned long v_check(unsigned long v) { \
+ if(v >= OSSL_DYNAMIC_OLDEST) return OSSL_DYNAMIC_VERSION; \
+ return 0; }
+
+/* This function is passed the ENGINE structure to initialise with its own
+ * function and command settings. It should not adjust the structural or
+ * functional reference counts. If this function returns zero, (a) the load will
+ * be aborted, (b) the previous ENGINE state will be memcpy'd back onto the
+ * structure, and (c) the shared library will be unloaded. So implementations
+ * should do their own internal cleanup in failure circumstances otherwise they
+ * could leak. The 'id' parameter, if non-NULL, represents the ENGINE id that
+ * the loader is looking for. If this is NULL, the shared library can choose to
+ * return failure or to initialise a 'default' ENGINE. If non-NULL, the shared
+ * library must initialise only an ENGINE matching the passed 'id'. The function
+ * is expected to be implemented with the symbol name "bind_engine". A standard
+ * implementation can be instantiated with IMPLEMENT_DYNAMIC_BIND_FN(fn) where
+ * the parameter 'fn' is a callback function that populates the ENGINE structure
+ * and returns an int value (zero for failure). 'fn' should have prototype;
+ * [static] int fn(ENGINE *e, const char *id); */
+typedef int (*dynamic_bind_engine)(ENGINE *e, const char *id,
+ const dynamic_fns *fns);
+#define IMPLEMENT_DYNAMIC_BIND_FN(fn) \
+ OPENSSL_EXPORT \
+ int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { \
+ if(ENGINE_get_static_state() == fns->static_state) goto skip_cbs; \
+ if(!CRYPTO_set_mem_functions(fns->mem_fns.malloc_cb, \
+ fns->mem_fns.realloc_cb, fns->mem_fns.free_cb)) \
+ return 0; \
+ CRYPTO_set_locking_callback(fns->lock_fns.lock_locking_cb); \
+ CRYPTO_set_add_lock_callback(fns->lock_fns.lock_add_lock_cb); \
+ CRYPTO_set_dynlock_create_callback(fns->lock_fns.dynlock_create_cb); \
+ CRYPTO_set_dynlock_lock_callback(fns->lock_fns.dynlock_lock_cb); \
+ CRYPTO_set_dynlock_destroy_callback(fns->lock_fns.dynlock_destroy_cb); \
+ if(!CRYPTO_set_ex_data_implementation(fns->ex_data_fns)) \
+ return 0; \
+ if(!ERR_set_implementation(fns->err_fns)) return 0; \
+ skip_cbs: \
+ if(!fn(e,id)) return 0; \
+ return 1; }
+
+/* If the loading application (or library) and the loaded ENGINE library share
+ * the same static data (eg. they're both dynamically linked to the same
+ * libcrypto.so) we need a way to avoid trying to set system callbacks - this
+ * would fail, and for the same reason that it's unnecessary to try. If the
+ * loaded ENGINE has (or gets from through the loader) its own copy of the
+ * libcrypto static data, we will need to set the callbacks. The easiest way to
+ * detect this is to have a function that returns a pointer to some static data
+ * and let the loading application and loaded ENGINE compare their respective
+ * values. */
+void *ENGINE_get_static_state(void);
+
+#if defined(__OpenBSD__) || defined(__FreeBSD__)
+void ENGINE_setup_bsd_cryptodev(void);
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ENGINE_strings(void);
+
+/* Error codes for the ENGINE functions. */
+
+/* Function codes. */
+#define ENGINE_F_DYNAMIC_CTRL 180
+#define ENGINE_F_DYNAMIC_GET_DATA_CTX 181
+#define ENGINE_F_DYNAMIC_LOAD 182
+#define ENGINE_F_DYNAMIC_SET_DATA_CTX 183
+#define ENGINE_F_ENGINE_ADD 105
+#define ENGINE_F_ENGINE_BY_ID 106
+#define ENGINE_F_ENGINE_CMD_IS_EXECUTABLE 170
+#define ENGINE_F_ENGINE_CTRL 142
+#define ENGINE_F_ENGINE_CTRL_CMD 178
+#define ENGINE_F_ENGINE_CTRL_CMD_STRING 171
+#define ENGINE_F_ENGINE_FINISH 107
+#define ENGINE_F_ENGINE_FREE_UTIL 108
+#define ENGINE_F_ENGINE_GET_CIPHER 185
+#define ENGINE_F_ENGINE_GET_DEFAULT_TYPE 177
+#define ENGINE_F_ENGINE_GET_DIGEST 186
+#define ENGINE_F_ENGINE_GET_NEXT 115
+#define ENGINE_F_ENGINE_GET_PREV 116
+#define ENGINE_F_ENGINE_INIT 119
+#define ENGINE_F_ENGINE_LIST_ADD 120
+#define ENGINE_F_ENGINE_LIST_REMOVE 121
+#define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY 150
+#define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY 151
+#define ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT 192
+#define ENGINE_F_ENGINE_NEW 122
+#define ENGINE_F_ENGINE_REMOVE 123
+#define ENGINE_F_ENGINE_SET_DEFAULT_STRING 189
+#define ENGINE_F_ENGINE_SET_DEFAULT_TYPE 126
+#define ENGINE_F_ENGINE_SET_ID 129
+#define ENGINE_F_ENGINE_SET_NAME 130
+#define ENGINE_F_ENGINE_TABLE_REGISTER 184
+#define ENGINE_F_ENGINE_UNLOAD_KEY 152
+#define ENGINE_F_ENGINE_UNLOCKED_FINISH 191
+#define ENGINE_F_ENGINE_UP_REF 190
+#define ENGINE_F_INT_CTRL_HELPER 172
+#define ENGINE_F_INT_ENGINE_CONFIGURE 188
+#define ENGINE_F_INT_ENGINE_MODULE_INIT 187
+#define ENGINE_F_LOG_MESSAGE 141
+
+/* Reason codes. */
+#define ENGINE_R_ALREADY_LOADED 100
+#define ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER 133
+#define ENGINE_R_CMD_NOT_EXECUTABLE 134
+#define ENGINE_R_COMMAND_TAKES_INPUT 135
+#define ENGINE_R_COMMAND_TAKES_NO_INPUT 136
+#define ENGINE_R_CONFLICTING_ENGINE_ID 103
+#define ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED 119
+#define ENGINE_R_DH_NOT_IMPLEMENTED 139
+#define ENGINE_R_DSA_NOT_IMPLEMENTED 140
+#define ENGINE_R_DSO_FAILURE 104
+#define ENGINE_R_DSO_NOT_FOUND 132
+#define ENGINE_R_ENGINES_SECTION_ERROR 148
+#define ENGINE_R_ENGINE_CONFIGURATION_ERROR 101
+#define ENGINE_R_ENGINE_IS_NOT_IN_LIST 105
+#define ENGINE_R_ENGINE_SECTION_ERROR 149
+#define ENGINE_R_FAILED_LOADING_PRIVATE_KEY 128
+#define ENGINE_R_FAILED_LOADING_PUBLIC_KEY 129
+#define ENGINE_R_FINISH_FAILED 106
+#define ENGINE_R_GET_HANDLE_FAILED 107
+#define ENGINE_R_ID_OR_NAME_MISSING 108
+#define ENGINE_R_INIT_FAILED 109
+#define ENGINE_R_INTERNAL_LIST_ERROR 110
+#define ENGINE_R_INVALID_ARGUMENT 143
+#define ENGINE_R_INVALID_CMD_NAME 137
+#define ENGINE_R_INVALID_CMD_NUMBER 138
+#define ENGINE_R_INVALID_INIT_VALUE 151
+#define ENGINE_R_INVALID_STRING 150
+#define ENGINE_R_NOT_INITIALISED 117
+#define ENGINE_R_NOT_LOADED 112
+#define ENGINE_R_NO_CONTROL_FUNCTION 120
+#define ENGINE_R_NO_INDEX 144
+#define ENGINE_R_NO_LOAD_FUNCTION 125
+#define ENGINE_R_NO_REFERENCE 130
+#define ENGINE_R_NO_SUCH_ENGINE 116
+#define ENGINE_R_NO_UNLOAD_FUNCTION 126
+#define ENGINE_R_PROVIDE_PARAMETERS 113
+#define ENGINE_R_RSA_NOT_IMPLEMENTED 141
+#define ENGINE_R_UNIMPLEMENTED_CIPHER 146
+#define ENGINE_R_UNIMPLEMENTED_DIGEST 147
+#define ENGINE_R_VERSION_INCOMPATIBILITY 145
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/err.h b/src/Mayaqua/win32_inc/openssl/err.h
new file mode 100644
index 00000000..1b9f733e
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/err.h
@@ -0,0 +1,330 @@
+/* crypto/err/err.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_ERR_H
+#define HEADER_ERR_H
+
+#include <openssl/e_os2.h>
+
+#ifndef OPENSSL_NO_FP_API
+#include <stdio.h>
+#include <stdlib.h>
+#endif
+
+#include <openssl/ossl_typ.h>
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#ifndef OPENSSL_NO_LHASH
+#include <openssl/lhash.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef OPENSSL_NO_ERR
+#define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,d,e)
+#else
+#define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,NULL,0)
+#endif
+
+#include <errno.h>
+
+#define ERR_TXT_MALLOCED 0x01
+#define ERR_TXT_STRING 0x02
+
+#define ERR_FLAG_MARK 0x01
+
+#define ERR_NUM_ERRORS 16
+typedef struct err_state_st
+ {
+ unsigned long pid;
+ int err_flags[ERR_NUM_ERRORS];
+ unsigned long err_buffer[ERR_NUM_ERRORS];
+ char *err_data[ERR_NUM_ERRORS];
+ int err_data_flags[ERR_NUM_ERRORS];
+ const char *err_file[ERR_NUM_ERRORS];
+ int err_line[ERR_NUM_ERRORS];
+ int top,bottom;
+ } ERR_STATE;
+
+/* library */
+#define ERR_LIB_NONE 1
+#define ERR_LIB_SYS 2
+#define ERR_LIB_BN 3
+#define ERR_LIB_RSA 4
+#define ERR_LIB_DH 5
+#define ERR_LIB_EVP 6
+#define ERR_LIB_BUF 7
+#define ERR_LIB_OBJ 8
+#define ERR_LIB_PEM 9
+#define ERR_LIB_DSA 10
+#define ERR_LIB_X509 11
+/* #define ERR_LIB_METH 12 */
+#define ERR_LIB_ASN1 13
+#define ERR_LIB_CONF 14
+#define ERR_LIB_CRYPTO 15
+#define ERR_LIB_EC 16
+#define ERR_LIB_SSL 20
+/* #define ERR_LIB_SSL23 21 */
+/* #define ERR_LIB_SSL2 22 */
+/* #define ERR_LIB_SSL3 23 */
+/* #define ERR_LIB_RSAREF 30 */
+/* #define ERR_LIB_PROXY 31 */
+#define ERR_LIB_BIO 32
+#define ERR_LIB_PKCS7 33
+#define ERR_LIB_X509V3 34
+#define ERR_LIB_PKCS12 35
+#define ERR_LIB_RAND 36
+#define ERR_LIB_DSO 37
+#define ERR_LIB_ENGINE 38
+#define ERR_LIB_OCSP 39
+#define ERR_LIB_UI 40
+#define ERR_LIB_COMP 41
+#define ERR_LIB_ECDSA 42
+#define ERR_LIB_ECDH 43
+#define ERR_LIB_STORE 44
+#define ERR_LIB_FIPS 45
+#define ERR_LIB_CMS 46
+#define ERR_LIB_JPAKE 47
+
+#define ERR_LIB_USER 128
+
+#define SYSerr(f,r) ERR_PUT_error(ERR_LIB_SYS,(f),(r),__FILE__,__LINE__)
+#define BNerr(f,r) ERR_PUT_error(ERR_LIB_BN,(f),(r),__FILE__,__LINE__)
+#define RSAerr(f,r) ERR_PUT_error(ERR_LIB_RSA,(f),(r),__FILE__,__LINE__)
+#define DHerr(f,r) ERR_PUT_error(ERR_LIB_DH,(f),(r),__FILE__,__LINE__)
+#define EVPerr(f,r) ERR_PUT_error(ERR_LIB_EVP,(f),(r),__FILE__,__LINE__)
+#define BUFerr(f,r) ERR_PUT_error(ERR_LIB_BUF,(f),(r),__FILE__,__LINE__)
+#define OBJerr(f,r) ERR_PUT_error(ERR_LIB_OBJ,(f),(r),__FILE__,__LINE__)
+#define PEMerr(f,r) ERR_PUT_error(ERR_LIB_PEM,(f),(r),__FILE__,__LINE__)
+#define DSAerr(f,r) ERR_PUT_error(ERR_LIB_DSA,(f),(r),__FILE__,__LINE__)
+#define X509err(f,r) ERR_PUT_error(ERR_LIB_X509,(f),(r),__FILE__,__LINE__)
+#define ASN1err(f,r) ERR_PUT_error(ERR_LIB_ASN1,(f),(r),__FILE__,__LINE__)
+#define CONFerr(f,r) ERR_PUT_error(ERR_LIB_CONF,(f),(r),__FILE__,__LINE__)
+#define CRYPTOerr(f,r) ERR_PUT_error(ERR_LIB_CRYPTO,(f),(r),__FILE__,__LINE__)
+#define ECerr(f,r) ERR_PUT_error(ERR_LIB_EC,(f),(r),__FILE__,__LINE__)
+#define SSLerr(f,r) ERR_PUT_error(ERR_LIB_SSL,(f),(r),__FILE__,__LINE__)
+#define BIOerr(f,r) ERR_PUT_error(ERR_LIB_BIO,(f),(r),__FILE__,__LINE__)
+#define PKCS7err(f,r) ERR_PUT_error(ERR_LIB_PKCS7,(f),(r),__FILE__,__LINE__)
+#define X509V3err(f,r) ERR_PUT_error(ERR_LIB_X509V3,(f),(r),__FILE__,__LINE__)
+#define PKCS12err(f,r) ERR_PUT_error(ERR_LIB_PKCS12,(f),(r),__FILE__,__LINE__)
+#define RANDerr(f,r) ERR_PUT_error(ERR_LIB_RAND,(f),(r),__FILE__,__LINE__)
+#define DSOerr(f,r) ERR_PUT_error(ERR_LIB_DSO,(f),(r),__FILE__,__LINE__)
+#define ENGINEerr(f,r) ERR_PUT_error(ERR_LIB_ENGINE,(f),(r),__FILE__,__LINE__)
+#define OCSPerr(f,r) ERR_PUT_error(ERR_LIB_OCSP,(f),(r),__FILE__,__LINE__)
+#define UIerr(f,r) ERR_PUT_error(ERR_LIB_UI,(f),(r),__FILE__,__LINE__)
+#define COMPerr(f,r) ERR_PUT_error(ERR_LIB_COMP,(f),(r),__FILE__,__LINE__)
+#define ECDSAerr(f,r) ERR_PUT_error(ERR_LIB_ECDSA,(f),(r),__FILE__,__LINE__)
+#define ECDHerr(f,r) ERR_PUT_error(ERR_LIB_ECDH,(f),(r),__FILE__,__LINE__)
+#define STOREerr(f,r) ERR_PUT_error(ERR_LIB_STORE,(f),(r),__FILE__,__LINE__)
+#define FIPSerr(f,r) ERR_PUT_error(ERR_LIB_FIPS,(f),(r),__FILE__,__LINE__)
+#define CMSerr(f,r) ERR_PUT_error(ERR_LIB_CMS,(f),(r),__FILE__,__LINE__)
+#define JPAKEerr(f,r) ERR_PUT_error(ERR_LIB_JPAKE,(f),(r),__FILE__,__LINE__)
+
+/* Borland C seems too stupid to be able to shift and do longs in
+ * the pre-processor :-( */
+#define ERR_PACK(l,f,r) (((((unsigned long)l)&0xffL)*0x1000000)| \
+ ((((unsigned long)f)&0xfffL)*0x1000)| \
+ ((((unsigned long)r)&0xfffL)))
+#define ERR_GET_LIB(l) (int)((((unsigned long)l)>>24L)&0xffL)
+#define ERR_GET_FUNC(l) (int)((((unsigned long)l)>>12L)&0xfffL)
+#define ERR_GET_REASON(l) (int)((l)&0xfffL)
+#define ERR_FATAL_ERROR(l) (int)((l)&ERR_R_FATAL)
+
+
+/* OS functions */
+#define SYS_F_FOPEN 1
+#define SYS_F_CONNECT 2
+#define SYS_F_GETSERVBYNAME 3
+#define SYS_F_SOCKET 4
+#define SYS_F_IOCTLSOCKET 5
+#define SYS_F_BIND 6
+#define SYS_F_LISTEN 7
+#define SYS_F_ACCEPT 8
+#define SYS_F_WSASTARTUP 9 /* Winsock stuff */
+#define SYS_F_OPENDIR 10
+#define SYS_F_FREAD 11
+
+
+/* reasons */
+#define ERR_R_SYS_LIB ERR_LIB_SYS /* 2 */
+#define ERR_R_BN_LIB ERR_LIB_BN /* 3 */
+#define ERR_R_RSA_LIB ERR_LIB_RSA /* 4 */
+#define ERR_R_DH_LIB ERR_LIB_DH /* 5 */
+#define ERR_R_EVP_LIB ERR_LIB_EVP /* 6 */
+#define ERR_R_BUF_LIB ERR_LIB_BUF /* 7 */
+#define ERR_R_OBJ_LIB ERR_LIB_OBJ /* 8 */
+#define ERR_R_PEM_LIB ERR_LIB_PEM /* 9 */
+#define ERR_R_DSA_LIB ERR_LIB_DSA /* 10 */
+#define ERR_R_X509_LIB ERR_LIB_X509 /* 11 */
+#define ERR_R_ASN1_LIB ERR_LIB_ASN1 /* 13 */
+#define ERR_R_CONF_LIB ERR_LIB_CONF /* 14 */
+#define ERR_R_CRYPTO_LIB ERR_LIB_CRYPTO /* 15 */
+#define ERR_R_EC_LIB ERR_LIB_EC /* 16 */
+#define ERR_R_SSL_LIB ERR_LIB_SSL /* 20 */
+#define ERR_R_BIO_LIB ERR_LIB_BIO /* 32 */
+#define ERR_R_PKCS7_LIB ERR_LIB_PKCS7 /* 33 */
+#define ERR_R_X509V3_LIB ERR_LIB_X509V3 /* 34 */
+#define ERR_R_PKCS12_LIB ERR_LIB_PKCS12 /* 35 */
+#define ERR_R_RAND_LIB ERR_LIB_RAND /* 36 */
+#define ERR_R_DSO_LIB ERR_LIB_DSO /* 37 */
+#define ERR_R_ENGINE_LIB ERR_LIB_ENGINE /* 38 */
+#define ERR_R_OCSP_LIB ERR_LIB_OCSP /* 39 */
+#define ERR_R_UI_LIB ERR_LIB_UI /* 40 */
+#define ERR_R_COMP_LIB ERR_LIB_COMP /* 41 */
+#define ERR_R_ECDSA_LIB ERR_LIB_ECDSA /* 42 */
+#define ERR_R_ECDH_LIB ERR_LIB_ECDH /* 43 */
+#define ERR_R_STORE_LIB ERR_LIB_STORE /* 44 */
+
+#define ERR_R_NESTED_ASN1_ERROR 58
+#define ERR_R_BAD_ASN1_OBJECT_HEADER 59
+#define ERR_R_BAD_GET_ASN1_OBJECT_CALL 60
+#define ERR_R_EXPECTING_AN_ASN1_SEQUENCE 61
+#define ERR_R_ASN1_LENGTH_MISMATCH 62
+#define ERR_R_MISSING_ASN1_EOS 63
+
+/* fatal error */
+#define ERR_R_FATAL 64
+#define ERR_R_MALLOC_FAILURE (1|ERR_R_FATAL)
+#define ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED (2|ERR_R_FATAL)
+#define ERR_R_PASSED_NULL_PARAMETER (3|ERR_R_FATAL)
+#define ERR_R_INTERNAL_ERROR (4|ERR_R_FATAL)
+#define ERR_R_DISABLED (5|ERR_R_FATAL)
+
+/* 99 is the maximum possible ERR_R_... code, higher values
+ * are reserved for the individual libraries */
+
+
+typedef struct ERR_string_data_st
+ {
+ unsigned long error;
+ const char *string;
+ } ERR_STRING_DATA;
+
+void ERR_put_error(int lib, int func,int reason,const char *file,int line);
+void ERR_set_error_data(char *data,int flags);
+
+unsigned long ERR_get_error(void);
+unsigned long ERR_get_error_line(const char **file,int *line);
+unsigned long ERR_get_error_line_data(const char **file,int *line,
+ const char **data, int *flags);
+unsigned long ERR_peek_error(void);
+unsigned long ERR_peek_error_line(const char **file,int *line);
+unsigned long ERR_peek_error_line_data(const char **file,int *line,
+ const char **data,int *flags);
+unsigned long ERR_peek_last_error(void);
+unsigned long ERR_peek_last_error_line(const char **file,int *line);
+unsigned long ERR_peek_last_error_line_data(const char **file,int *line,
+ const char **data,int *flags);
+void ERR_clear_error(void );
+char *ERR_error_string(unsigned long e,char *buf);
+void ERR_error_string_n(unsigned long e, char *buf, size_t len);
+const char *ERR_lib_error_string(unsigned long e);
+const char *ERR_func_error_string(unsigned long e);
+const char *ERR_reason_error_string(unsigned long e);
+void ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u),
+ void *u);
+#ifndef OPENSSL_NO_FP_API
+void ERR_print_errors_fp(FILE *fp);
+#endif
+#ifndef OPENSSL_NO_BIO
+void ERR_print_errors(BIO *bp);
+void ERR_add_error_data(int num, ...);
+#endif
+void ERR_load_strings(int lib,ERR_STRING_DATA str[]);
+void ERR_unload_strings(int lib,ERR_STRING_DATA str[]);
+void ERR_load_ERR_strings(void);
+void ERR_load_crypto_strings(void);
+void ERR_free_strings(void);
+
+void ERR_remove_state(unsigned long pid); /* if zero we look it up */
+ERR_STATE *ERR_get_state(void);
+
+#ifndef OPENSSL_NO_LHASH
+LHASH *ERR_get_string_table(void);
+LHASH *ERR_get_err_state_table(void);
+void ERR_release_err_state_table(LHASH **hash);
+#endif
+
+int ERR_get_next_error_library(void);
+
+int ERR_set_mark(void);
+int ERR_pop_to_mark(void);
+
+#ifdef OPENSSL_FIPS
+void int_ERR_set_state_func(ERR_STATE *(*get_func)(void),
+ void (*remove_func)(unsigned long pid));
+void int_ERR_lib_init(void);
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct st_ERR_FNS ERR_FNS; */
+/* An application can use this function and provide the return value to loaded
+ * modules that should use the application's ERR state/functionality */
+const ERR_FNS *ERR_get_implementation(void);
+/* A loaded module should call this function prior to any ERR operations using
+ * the application's "ERR_FNS". */
+int ERR_set_implementation(const ERR_FNS *fns);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/evp.h b/src/Mayaqua/win32_inc/openssl/evp.h
new file mode 100644
index 00000000..ac9ebede
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/evp.h
@@ -0,0 +1,1059 @@
+/* crypto/evp/evp.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_ENVELOPE_H
+#define HEADER_ENVELOPE_H
+
+#ifdef OPENSSL_ALGORITHM_DEFINES
+# include <openssl/opensslconf.h>
+#else
+# define OPENSSL_ALGORITHM_DEFINES
+# include <openssl/opensslconf.h>
+# undef OPENSSL_ALGORITHM_DEFINES
+#endif
+
+#include <openssl/ossl_typ.h>
+
+#include <openssl/symhacks.h>
+
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
+/*
+#define EVP_RC2_KEY_SIZE 16
+#define EVP_RC4_KEY_SIZE 16
+#define EVP_BLOWFISH_KEY_SIZE 16
+#define EVP_CAST5_KEY_SIZE 16
+#define EVP_RC5_32_12_16_KEY_SIZE 16
+*/
+#define EVP_MAX_MD_SIZE 64 /* longest known is SHA512 */
+#define EVP_MAX_KEY_LENGTH 32
+#define EVP_MAX_IV_LENGTH 16
+#define EVP_MAX_BLOCK_LENGTH 32
+
+#define PKCS5_SALT_LEN 8
+/* Default PKCS#5 iteration count */
+#define PKCS5_DEFAULT_ITER 2048
+
+#include <openssl/objects.h>
+
+#define EVP_PK_RSA 0x0001
+#define EVP_PK_DSA 0x0002
+#define EVP_PK_DH 0x0004
+#define EVP_PK_EC 0x0008
+#define EVP_PKT_SIGN 0x0010
+#define EVP_PKT_ENC 0x0020
+#define EVP_PKT_EXCH 0x0040
+#define EVP_PKS_RSA 0x0100
+#define EVP_PKS_DSA 0x0200
+#define EVP_PKS_EC 0x0400
+#define EVP_PKT_EXP 0x1000 /* <= 512 bit key */
+
+#define EVP_PKEY_NONE NID_undef
+#define EVP_PKEY_RSA NID_rsaEncryption
+#define EVP_PKEY_RSA2 NID_rsa
+#define EVP_PKEY_DSA NID_dsa
+#define EVP_PKEY_DSA1 NID_dsa_2
+#define EVP_PKEY_DSA2 NID_dsaWithSHA
+#define EVP_PKEY_DSA3 NID_dsaWithSHA1
+#define EVP_PKEY_DSA4 NID_dsaWithSHA1_2
+#define EVP_PKEY_DH NID_dhKeyAgreement
+#define EVP_PKEY_EC NID_X9_62_id_ecPublicKey
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Type needs to be a bit field
+ * Sub-type needs to be for variations on the method, as in, can it do
+ * arbitrary encryption.... */
+struct evp_pkey_st
+ {
+ int type;
+ int save_type;
+ int references;
+ union {
+ char *ptr;
+#ifndef OPENSSL_NO_RSA
+ struct rsa_st *rsa; /* RSA */
+#endif
+#ifndef OPENSSL_NO_DSA
+ struct dsa_st *dsa; /* DSA */
+#endif
+#ifndef OPENSSL_NO_DH
+ struct dh_st *dh; /* DH */
+#endif
+#ifndef OPENSSL_NO_EC
+ struct ec_key_st *ec; /* ECC */
+#endif
+ } pkey;
+ int save_parameters;
+ STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
+ } /* EVP_PKEY */;
+
+#define EVP_PKEY_MO_SIGN 0x0001
+#define EVP_PKEY_MO_VERIFY 0x0002
+#define EVP_PKEY_MO_ENCRYPT 0x0004
+#define EVP_PKEY_MO_DECRYPT 0x0008
+
+#if 0
+/* This structure is required to tie the message digest and signing together.
+ * The lookup can be done by md/pkey_method, oid, oid/pkey_method, or
+ * oid, md and pkey.
+ * This is required because for various smart-card perform the digest and
+ * signing/verification on-board. To handle this case, the specific
+ * EVP_MD and EVP_PKEY_METHODs need to be closely associated.
+ * When a PKEY is created, it will have a EVP_PKEY_METHOD associated with it.
+ * This can either be software or a token to provide the required low level
+ * routines.
+ */
+typedef struct evp_pkey_md_st
+ {
+ int oid;
+ EVP_MD *md;
+ EVP_PKEY_METHOD *pkey;
+ } EVP_PKEY_MD;
+
+#define EVP_rsa_md2() \
+ EVP_PKEY_MD_add(NID_md2WithRSAEncryption,\
+ EVP_rsa_pkcs1(),EVP_md2())
+#define EVP_rsa_md5() \
+ EVP_PKEY_MD_add(NID_md5WithRSAEncryption,\
+ EVP_rsa_pkcs1(),EVP_md5())
+#define EVP_rsa_sha0() \
+ EVP_PKEY_MD_add(NID_shaWithRSAEncryption,\
+ EVP_rsa_pkcs1(),EVP_sha())
+#define EVP_rsa_sha1() \
+ EVP_PKEY_MD_add(NID_sha1WithRSAEncryption,\
+ EVP_rsa_pkcs1(),EVP_sha1())
+#define EVP_rsa_ripemd160() \
+ EVP_PKEY_MD_add(NID_ripemd160WithRSA,\
+ EVP_rsa_pkcs1(),EVP_ripemd160())
+#define EVP_rsa_mdc2() \
+ EVP_PKEY_MD_add(NID_mdc2WithRSA,\
+ EVP_rsa_octet_string(),EVP_mdc2())
+#define EVP_dsa_sha() \
+ EVP_PKEY_MD_add(NID_dsaWithSHA,\
+ EVP_dsa(),EVP_sha())
+#define EVP_dsa_sha1() \
+ EVP_PKEY_MD_add(NID_dsaWithSHA1,\
+ EVP_dsa(),EVP_sha1())
+
+typedef struct evp_pkey_method_st
+ {
+ char *name;
+ int flags;
+ int type; /* RSA, DSA, an SSLeay specific constant */
+ int oid; /* For the pub-key type */
+ int encrypt_oid; /* pub/priv key encryption */
+
+ int (*sign)();
+ int (*verify)();
+ struct {
+ int (*set)(); /* get and/or set the underlying type */
+ int (*get)();
+ int (*encrypt)();
+ int (*decrypt)();
+ int (*i2d)();
+ int (*d2i)();
+ int (*dup)();
+ } pub,priv;
+ int (*set_asn1_parameters)();
+ int (*get_asn1_parameters)();
+ } EVP_PKEY_METHOD;
+#endif
+
+#ifndef EVP_MD
+struct env_md_st
+ {
+ int type;
+ int pkey_type;
+ int md_size;
+ unsigned long flags;
+ int (*init)(EVP_MD_CTX *ctx);
+ int (*update)(EVP_MD_CTX *ctx,const void *data,size_t count);
+ int (*final)(EVP_MD_CTX *ctx,unsigned char *md);
+ int (*copy)(EVP_MD_CTX *to,const EVP_MD_CTX *from);
+ int (*cleanup)(EVP_MD_CTX *ctx);
+
+ /* FIXME: prototype these some day */
+ int (*sign)(int type, const unsigned char *m, unsigned int m_length,
+ unsigned char *sigret, unsigned int *siglen, void *key);
+ int (*verify)(int type, const unsigned char *m, unsigned int m_length,
+ const unsigned char *sigbuf, unsigned int siglen,
+ void *key);
+ int required_pkey_type[5]; /*EVP_PKEY_xxx */
+ int block_size;
+ int ctx_size; /* how big does the ctx->md_data need to be */
+ } /* EVP_MD */;
+
+typedef int evp_sign_method(int type,const unsigned char *m,
+ unsigned int m_length,unsigned char *sigret,
+ unsigned int *siglen, void *key);
+typedef int evp_verify_method(int type,const unsigned char *m,
+ unsigned int m_length,const unsigned char *sigbuf,
+ unsigned int siglen, void *key);
+
+typedef struct
+ {
+ EVP_MD_CTX *mctx;
+ void *key;
+ } EVP_MD_SVCTX;
+
+#define EVP_MD_FLAG_ONESHOT 0x0001 /* digest can only handle a single
+ * block */
+
+#define EVP_MD_FLAG_FIPS 0x0400 /* Note if suitable for use in FIPS mode */
+
+#define EVP_MD_FLAG_SVCTX 0x0800 /* pass EVP_MD_SVCTX to sign/verify */
+
+#define EVP_PKEY_NULL_method NULL,NULL,{0,0,0,0}
+
+#ifndef OPENSSL_NO_DSA
+#define EVP_PKEY_DSA_method (evp_sign_method *)DSA_sign, \
+ (evp_verify_method *)DSA_verify, \
+ {EVP_PKEY_DSA,EVP_PKEY_DSA2,EVP_PKEY_DSA3, \
+ EVP_PKEY_DSA4,0}
+#else
+#define EVP_PKEY_DSA_method EVP_PKEY_NULL_method
+#endif
+
+#ifndef OPENSSL_NO_ECDSA
+#define EVP_PKEY_ECDSA_method (evp_sign_method *)ECDSA_sign, \
+ (evp_verify_method *)ECDSA_verify, \
+ {EVP_PKEY_EC,0,0,0}
+#else
+#define EVP_PKEY_ECDSA_method EVP_PKEY_NULL_method
+#endif
+
+#ifndef OPENSSL_NO_RSA
+#define EVP_PKEY_RSA_method (evp_sign_method *)RSA_sign, \
+ (evp_verify_method *)RSA_verify, \
+ {EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0}
+#define EVP_PKEY_RSA_ASN1_OCTET_STRING_method \
+ (evp_sign_method *)RSA_sign_ASN1_OCTET_STRING, \
+ (evp_verify_method *)RSA_verify_ASN1_OCTET_STRING, \
+ {EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0}
+#else
+#define EVP_PKEY_RSA_method EVP_PKEY_NULL_method
+#define EVP_PKEY_RSA_ASN1_OCTET_STRING_method EVP_PKEY_NULL_method
+#endif
+
+#endif /* !EVP_MD */
+
+struct env_md_ctx_st
+ {
+ const EVP_MD *digest;
+ ENGINE *engine; /* functional reference if 'digest' is ENGINE-provided */
+ unsigned long flags;
+ void *md_data;
+ } /* EVP_MD_CTX */;
+
+/* values for EVP_MD_CTX flags */
+
+#define EVP_MD_CTX_FLAG_ONESHOT 0x0001 /* digest update will be called
+ * once only */
+#define EVP_MD_CTX_FLAG_CLEANED 0x0002 /* context has already been
+ * cleaned */
+#define EVP_MD_CTX_FLAG_REUSE 0x0004 /* Don't free up ctx->md_data
+ * in EVP_MD_CTX_cleanup */
+#define EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 0x0008 /* Allow use of non FIPS digest
+ * in FIPS mode */
+
+#define EVP_MD_CTX_FLAG_PAD_MASK 0xF0 /* RSA mode to use */
+#define EVP_MD_CTX_FLAG_PAD_PKCS1 0x00 /* PKCS#1 v1.5 mode */
+#define EVP_MD_CTX_FLAG_PAD_X931 0x10 /* X9.31 mode */
+#define EVP_MD_CTX_FLAG_PAD_PSS 0x20 /* PSS mode */
+#define M_EVP_MD_CTX_FLAG_PSS_SALT(ctx) \
+ ((ctx->flags>>16) &0xFFFF) /* seed length */
+#define EVP_MD_CTX_FLAG_PSS_MDLEN 0xFFFF /* salt len same as digest */
+#define EVP_MD_CTX_FLAG_PSS_MREC 0xFFFE /* salt max or auto recovered */
+
+struct evp_cipher_st
+ {
+ int nid;
+ int block_size;
+ int key_len; /* Default value for variable length ciphers */
+ int iv_len;
+ unsigned long flags; /* Various flags */
+ int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc); /* init key */
+ int (*do_cipher)(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, unsigned int inl);/* encrypt/decrypt data */
+ int (*cleanup)(EVP_CIPHER_CTX *); /* cleanup ctx */
+ int ctx_size; /* how big ctx->cipher_data needs to be */
+ int (*set_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Populate a ASN1_TYPE with parameters */
+ int (*get_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Get parameters from a ASN1_TYPE */
+ int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr); /* Miscellaneous operations */
+ void *app_data; /* Application data */
+ } /* EVP_CIPHER */;
+
+/* Values for cipher flags */
+
+/* Modes for ciphers */
+
+#define EVP_CIPH_STREAM_CIPHER 0x0
+#define EVP_CIPH_ECB_MODE 0x1
+#define EVP_CIPH_CBC_MODE 0x2
+#define EVP_CIPH_CFB_MODE 0x3
+#define EVP_CIPH_OFB_MODE 0x4
+#define EVP_CIPH_MODE 0x7
+/* Set if variable length cipher */
+#define EVP_CIPH_VARIABLE_LENGTH 0x8
+/* Set if the iv handling should be done by the cipher itself */
+#define EVP_CIPH_CUSTOM_IV 0x10
+/* Set if the cipher's init() function should be called if key is NULL */
+#define EVP_CIPH_ALWAYS_CALL_INIT 0x20
+/* Call ctrl() to init cipher parameters */
+#define EVP_CIPH_CTRL_INIT 0x40
+/* Don't use standard key length function */
+#define EVP_CIPH_CUSTOM_KEY_LENGTH 0x80
+/* Don't use standard block padding */
+#define EVP_CIPH_NO_PADDING 0x100
+/* cipher handles random key generation */
+#define EVP_CIPH_RAND_KEY 0x200
+/* Note if suitable for use in FIPS mode */
+#define EVP_CIPH_FLAG_FIPS 0x400
+/* Allow non FIPS cipher in FIPS mode */
+#define EVP_CIPH_FLAG_NON_FIPS_ALLOW 0x800
+/* Allow use default ASN1 get/set iv */
+#define EVP_CIPH_FLAG_DEFAULT_ASN1 0x1000
+/* Buffer length in bits not bytes: CFB1 mode only */
+#define EVP_CIPH_FLAG_LENGTH_BITS 0x2000
+
+/* ctrl() values */
+
+#define EVP_CTRL_INIT 0x0
+#define EVP_CTRL_SET_KEY_LENGTH 0x1
+#define EVP_CTRL_GET_RC2_KEY_BITS 0x2
+#define EVP_CTRL_SET_RC2_KEY_BITS 0x3
+#define EVP_CTRL_GET_RC5_ROUNDS 0x4
+#define EVP_CTRL_SET_RC5_ROUNDS 0x5
+#define EVP_CTRL_RAND_KEY 0x6
+
+typedef struct evp_cipher_info_st
+ {
+ const EVP_CIPHER *cipher;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+ } EVP_CIPHER_INFO;
+
+struct evp_cipher_ctx_st
+ {
+ const EVP_CIPHER *cipher;
+ ENGINE *engine; /* functional reference if 'cipher' is ENGINE-provided */
+ int encrypt; /* encrypt or decrypt */
+ int buf_len; /* number we have left */
+
+ unsigned char oiv[EVP_MAX_IV_LENGTH]; /* original iv */
+ unsigned char iv[EVP_MAX_IV_LENGTH]; /* working iv */
+ unsigned char buf[EVP_MAX_BLOCK_LENGTH];/* saved partial block */
+ int num; /* used by cfb/ofb mode */
+
+ void *app_data; /* application stuff */
+ int key_len; /* May change for variable length cipher */
+ unsigned long flags; /* Various flags */
+ void *cipher_data; /* per EVP data */
+ int final_used;
+ int block_mask;
+ unsigned char final[EVP_MAX_BLOCK_LENGTH];/* possible final block */
+ } /* EVP_CIPHER_CTX */;
+
+typedef struct evp_Encode_Ctx_st
+ {
+ int num; /* number saved in a partial encode/decode */
+ int length; /* The length is either the output line length
+ * (in input bytes) or the shortest input line
+ * length that is ok. Once decoding begins,
+ * the length is adjusted up each time a longer
+ * line is decoded */
+ unsigned char enc_data[80]; /* data to encode */
+ int line_num; /* number read on current line */
+ int expect_nl;
+ } EVP_ENCODE_CTX;
+
+/* Password based encryption function */
+typedef int (EVP_PBE_KEYGEN)(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de);
+
+#ifndef OPENSSL_NO_RSA
+#define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\
+ (char *)(rsa))
+#endif
+
+#ifndef OPENSSL_NO_DSA
+#define EVP_PKEY_assign_DSA(pkey,dsa) EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\
+ (char *)(dsa))
+#endif
+
+#ifndef OPENSSL_NO_DH
+#define EVP_PKEY_assign_DH(pkey,dh) EVP_PKEY_assign((pkey),EVP_PKEY_DH,\
+ (char *)(dh))
+#endif
+
+#ifndef OPENSSL_NO_EC
+#define EVP_PKEY_assign_EC_KEY(pkey,eckey) EVP_PKEY_assign((pkey),EVP_PKEY_EC,\
+ (char *)(eckey))
+#endif
+
+/* Add some extra combinations */
+#define EVP_get_digestbynid(a) EVP_get_digestbyname(OBJ_nid2sn(a))
+#define EVP_get_digestbyobj(a) EVP_get_digestbynid(OBJ_obj2nid(a))
+#define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a))
+#define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a))
+
+/* Macros to reduce FIPS dependencies: do NOT use in applications */
+#define M_EVP_MD_size(e) ((e)->md_size)
+#define M_EVP_MD_block_size(e) ((e)->block_size)
+#define M_EVP_MD_CTX_set_flags(ctx,flgs) ((ctx)->flags|=(flgs))
+#define M_EVP_MD_CTX_clear_flags(ctx,flgs) ((ctx)->flags&=~(flgs))
+#define M_EVP_MD_CTX_test_flags(ctx,flgs) ((ctx)->flags&(flgs))
+#define M_EVP_MD_type(e) ((e)->type)
+#define M_EVP_MD_CTX_type(e) M_EVP_MD_type(M_EVP_MD_CTX_md(e))
+#define M_EVP_MD_CTX_md(e) ((e)->digest)
+
+#define M_EVP_CIPHER_CTX_set_flags(ctx,flgs) ((ctx)->flags|=(flgs))
+
+int EVP_MD_type(const EVP_MD *md);
+#define EVP_MD_nid(e) EVP_MD_type(e)
+#define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_nid(e))
+int EVP_MD_pkey_type(const EVP_MD *md);
+int EVP_MD_size(const EVP_MD *md);
+int EVP_MD_block_size(const EVP_MD *md);
+
+const EVP_MD * EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
+#define EVP_MD_CTX_size(e) EVP_MD_size(EVP_MD_CTX_md(e))
+#define EVP_MD_CTX_block_size(e) EVP_MD_block_size(EVP_MD_CTX_md(e))
+#define EVP_MD_CTX_type(e) EVP_MD_type(EVP_MD_CTX_md(e))
+
+int EVP_CIPHER_nid(const EVP_CIPHER *cipher);
+#define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e))
+int EVP_CIPHER_block_size(const EVP_CIPHER *cipher);
+int EVP_CIPHER_key_length(const EVP_CIPHER *cipher);
+int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher);
+unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher);
+#define EVP_CIPHER_mode(e) (EVP_CIPHER_flags(e) & EVP_CIPH_MODE)
+
+const EVP_CIPHER * EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx);
+int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx);
+void * EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx);
+void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data);
+#define EVP_CIPHER_CTX_type(c) EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c))
+unsigned long EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx);
+#define EVP_CIPHER_CTX_mode(e) (EVP_CIPHER_CTX_flags(e) & EVP_CIPH_MODE)
+
+#define EVP_ENCODE_LENGTH(l) (((l+2)/3*4)+(l/48+1)*2+80)
+#define EVP_DECODE_LENGTH(l) ((l+3)/4*3+80)
+
+#define EVP_SignInit_ex(a,b,c) EVP_DigestInit_ex(a,b,c)
+#define EVP_SignInit(a,b) EVP_DigestInit(a,b)
+#define EVP_SignUpdate(a,b,c) EVP_DigestUpdate(a,b,c)
+#define EVP_VerifyInit_ex(a,b,c) EVP_DigestInit_ex(a,b,c)
+#define EVP_VerifyInit(a,b) EVP_DigestInit(a,b)
+#define EVP_VerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c)
+#define EVP_OpenUpdate(a,b,c,d,e) EVP_DecryptUpdate(a,b,c,d,e)
+#define EVP_SealUpdate(a,b,c,d,e) EVP_EncryptUpdate(a,b,c,d,e)
+
+#ifdef CONST_STRICT
+void BIO_set_md(BIO *,const EVP_MD *md);
+#else
+# define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,0,(char *)md)
+#endif
+#define BIO_get_md(b,mdp) BIO_ctrl(b,BIO_C_GET_MD,0,(char *)mdp)
+#define BIO_get_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_GET_MD_CTX,0,(char *)mdcp)
+#define BIO_set_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_SET_MD_CTX,0,(char *)mdcp)
+#define BIO_get_cipher_status(b) BIO_ctrl(b,BIO_C_GET_CIPHER_STATUS,0,NULL)
+#define BIO_get_cipher_ctx(b,c_pp) BIO_ctrl(b,BIO_C_GET_CIPHER_CTX,0,(char *)c_pp)
+
+int EVP_Cipher(EVP_CIPHER_CTX *c,
+ unsigned char *out,
+ const unsigned char *in,
+ unsigned int inl);
+
+#define EVP_add_cipher_alias(n,alias) \
+ OBJ_NAME_add((alias),OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS,(n))
+#define EVP_add_digest_alias(n,alias) \
+ OBJ_NAME_add((alias),OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,(n))
+#define EVP_delete_cipher_alias(alias) \
+ OBJ_NAME_remove(alias,OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS);
+#define EVP_delete_digest_alias(alias) \
+ OBJ_NAME_remove(alias,OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS);
+
+void EVP_MD_CTX_init(EVP_MD_CTX *ctx);
+int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx);
+EVP_MD_CTX *EVP_MD_CTX_create(void);
+void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
+int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out,const EVP_MD_CTX *in);
+void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags);
+void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags);
+int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx,int flags);
+int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
+int EVP_DigestUpdate(EVP_MD_CTX *ctx,const void *d,
+ size_t cnt);
+int EVP_DigestFinal_ex(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s);
+int EVP_Digest(const void *data, size_t count,
+ unsigned char *md, unsigned int *size, const EVP_MD *type, ENGINE *impl);
+
+int EVP_MD_CTX_copy(EVP_MD_CTX *out,const EVP_MD_CTX *in);
+int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);
+int EVP_DigestFinal(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s);
+
+int EVP_read_pw_string(char *buf,int length,const char *prompt,int verify);
+void EVP_set_pw_prompt(const char *prompt);
+char * EVP_get_pw_prompt(void);
+
+int EVP_BytesToKey(const EVP_CIPHER *type,const EVP_MD *md,
+ const unsigned char *salt, const unsigned char *data,
+ int datal, int count, unsigned char *key,unsigned char *iv);
+
+void EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags);
+void EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags);
+int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx,int flags);
+
+int EVP_EncryptInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher,
+ const unsigned char *key, const unsigned char *iv);
+int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl,
+ const unsigned char *key, const unsigned char *iv);
+int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ int *outl, const unsigned char *in, int inl);
+int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+
+int EVP_DecryptInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher,
+ const unsigned char *key, const unsigned char *iv);
+int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl,
+ const unsigned char *key, const unsigned char *iv);
+int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ int *outl, const unsigned char *in, int inl);
+int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+
+int EVP_CipherInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher,
+ const unsigned char *key,const unsigned char *iv,
+ int enc);
+int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl,
+ const unsigned char *key,const unsigned char *iv,
+ int enc);
+int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ int *outl, const unsigned char *in, int inl);
+int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
+
+int EVP_SignFinal(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s,
+ EVP_PKEY *pkey);
+
+int EVP_VerifyFinal(EVP_MD_CTX *ctx,const unsigned char *sigbuf,
+ unsigned int siglen,EVP_PKEY *pkey);
+
+int EVP_OpenInit(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *type,
+ const unsigned char *ek, int ekl, const unsigned char *iv,
+ EVP_PKEY *priv);
+int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+
+int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
+ unsigned char **ek, int *ekl, unsigned char *iv,
+ EVP_PKEY **pubk, int npubk);
+int EVP_SealFinal(EVP_CIPHER_CTX *ctx,unsigned char *out,int *outl);
+
+void EVP_EncodeInit(EVP_ENCODE_CTX *ctx);
+void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl,
+ const unsigned char *in,int inl);
+void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl);
+int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int n);
+
+void EVP_DecodeInit(EVP_ENCODE_CTX *ctx);
+int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl,
+ const unsigned char *in, int inl);
+int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned
+ char *out, int *outl);
+int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n);
+
+void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
+int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
+EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
+void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a);
+int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
+int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad);
+int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
+int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key);
+
+#ifndef OPENSSL_NO_BIO
+BIO_METHOD *BIO_f_md(void);
+BIO_METHOD *BIO_f_base64(void);
+BIO_METHOD *BIO_f_cipher(void);
+BIO_METHOD *BIO_f_reliable(void);
+void BIO_set_cipher(BIO *b,const EVP_CIPHER *c,const unsigned char *k,
+ const unsigned char *i, int enc);
+#endif
+
+const EVP_MD *EVP_md_null(void);
+#ifndef OPENSSL_NO_MD2
+const EVP_MD *EVP_md2(void);
+#endif
+#ifndef OPENSSL_NO_MD4
+const EVP_MD *EVP_md4(void);
+#endif
+#ifndef OPENSSL_NO_MD5
+const EVP_MD *EVP_md5(void);
+#endif
+#ifndef OPENSSL_NO_SHA
+const EVP_MD *EVP_sha(void);
+const EVP_MD *EVP_sha1(void);
+const EVP_MD *EVP_dss(void);
+const EVP_MD *EVP_dss1(void);
+const EVP_MD *EVP_ecdsa(void);
+#endif
+#ifndef OPENSSL_NO_SHA256
+const EVP_MD *EVP_sha224(void);
+const EVP_MD *EVP_sha256(void);
+#endif
+#ifndef OPENSSL_NO_SHA512
+const EVP_MD *EVP_sha384(void);
+const EVP_MD *EVP_sha512(void);
+#endif
+#ifndef OPENSSL_NO_MDC2
+const EVP_MD *EVP_mdc2(void);
+#endif
+#ifndef OPENSSL_NO_RIPEMD
+const EVP_MD *EVP_ripemd160(void);
+#endif
+const EVP_CIPHER *EVP_enc_null(void); /* does nothing :-) */
+#ifndef OPENSSL_NO_DES
+const EVP_CIPHER *EVP_des_ecb(void);
+const EVP_CIPHER *EVP_des_ede(void);
+const EVP_CIPHER *EVP_des_ede3(void);
+const EVP_CIPHER *EVP_des_ede_ecb(void);
+const EVP_CIPHER *EVP_des_ede3_ecb(void);
+const EVP_CIPHER *EVP_des_cfb64(void);
+# define EVP_des_cfb EVP_des_cfb64
+const EVP_CIPHER *EVP_des_cfb1(void);
+const EVP_CIPHER *EVP_des_cfb8(void);
+const EVP_CIPHER *EVP_des_ede_cfb64(void);
+# define EVP_des_ede_cfb EVP_des_ede_cfb64
+#if 0
+const EVP_CIPHER *EVP_des_ede_cfb1(void);
+const EVP_CIPHER *EVP_des_ede_cfb8(void);
+#endif
+const EVP_CIPHER *EVP_des_ede3_cfb64(void);
+# define EVP_des_ede3_cfb EVP_des_ede3_cfb64
+const EVP_CIPHER *EVP_des_ede3_cfb1(void);
+const EVP_CIPHER *EVP_des_ede3_cfb8(void);
+const EVP_CIPHER *EVP_des_ofb(void);
+const EVP_CIPHER *EVP_des_ede_ofb(void);
+const EVP_CIPHER *EVP_des_ede3_ofb(void);
+const EVP_CIPHER *EVP_des_cbc(void);
+const EVP_CIPHER *EVP_des_ede_cbc(void);
+const EVP_CIPHER *EVP_des_ede3_cbc(void);
+const EVP_CIPHER *EVP_desx_cbc(void);
+/* This should now be supported through the dev_crypto ENGINE. But also, why are
+ * rc4 and md5 declarations made here inside a "NO_DES" precompiler branch? */
+#if 0
+# ifdef OPENSSL_OPENBSD_DEV_CRYPTO
+const EVP_CIPHER *EVP_dev_crypto_des_ede3_cbc(void);
+const EVP_CIPHER *EVP_dev_crypto_rc4(void);
+const EVP_MD *EVP_dev_crypto_md5(void);
+# endif
+#endif
+#endif
+#ifndef OPENSSL_NO_RC4
+const EVP_CIPHER *EVP_rc4(void);
+const EVP_CIPHER *EVP_rc4_40(void);
+#endif
+#ifndef OPENSSL_NO_IDEA
+const EVP_CIPHER *EVP_idea_ecb(void);
+const EVP_CIPHER *EVP_idea_cfb64(void);
+# define EVP_idea_cfb EVP_idea_cfb64
+const EVP_CIPHER *EVP_idea_ofb(void);
+const EVP_CIPHER *EVP_idea_cbc(void);
+#endif
+#ifndef OPENSSL_NO_RC2
+const EVP_CIPHER *EVP_rc2_ecb(void);
+const EVP_CIPHER *EVP_rc2_cbc(void);
+const EVP_CIPHER *EVP_rc2_40_cbc(void);
+const EVP_CIPHER *EVP_rc2_64_cbc(void);
+const EVP_CIPHER *EVP_rc2_cfb64(void);
+# define EVP_rc2_cfb EVP_rc2_cfb64
+const EVP_CIPHER *EVP_rc2_ofb(void);
+#endif
+#ifndef OPENSSL_NO_BF
+const EVP_CIPHER *EVP_bf_ecb(void);
+const EVP_CIPHER *EVP_bf_cbc(void);
+const EVP_CIPHER *EVP_bf_cfb64(void);
+# define EVP_bf_cfb EVP_bf_cfb64
+const EVP_CIPHER *EVP_bf_ofb(void);
+#endif
+#ifndef OPENSSL_NO_CAST
+const EVP_CIPHER *EVP_cast5_ecb(void);
+const EVP_CIPHER *EVP_cast5_cbc(void);
+const EVP_CIPHER *EVP_cast5_cfb64(void);
+# define EVP_cast5_cfb EVP_cast5_cfb64
+const EVP_CIPHER *EVP_cast5_ofb(void);
+#endif
+#ifndef OPENSSL_NO_RC5
+const EVP_CIPHER *EVP_rc5_32_12_16_cbc(void);
+const EVP_CIPHER *EVP_rc5_32_12_16_ecb(void);
+const EVP_CIPHER *EVP_rc5_32_12_16_cfb64(void);
+# define EVP_rc5_32_12_16_cfb EVP_rc5_32_12_16_cfb64
+const EVP_CIPHER *EVP_rc5_32_12_16_ofb(void);
+#endif
+#ifndef OPENSSL_NO_AES
+const EVP_CIPHER *EVP_aes_128_ecb(void);
+const EVP_CIPHER *EVP_aes_128_cbc(void);
+const EVP_CIPHER *EVP_aes_128_cfb1(void);
+const EVP_CIPHER *EVP_aes_128_cfb8(void);
+const EVP_CIPHER *EVP_aes_128_cfb128(void);
+# define EVP_aes_128_cfb EVP_aes_128_cfb128
+const EVP_CIPHER *EVP_aes_128_ofb(void);
+#if 0
+const EVP_CIPHER *EVP_aes_128_ctr(void);
+#endif
+const EVP_CIPHER *EVP_aes_192_ecb(void);
+const EVP_CIPHER *EVP_aes_192_cbc(void);
+const EVP_CIPHER *EVP_aes_192_cfb1(void);
+const EVP_CIPHER *EVP_aes_192_cfb8(void);
+const EVP_CIPHER *EVP_aes_192_cfb128(void);
+# define EVP_aes_192_cfb EVP_aes_192_cfb128
+const EVP_CIPHER *EVP_aes_192_ofb(void);
+#if 0
+const EVP_CIPHER *EVP_aes_192_ctr(void);
+#endif
+const EVP_CIPHER *EVP_aes_256_ecb(void);
+const EVP_CIPHER *EVP_aes_256_cbc(void);
+const EVP_CIPHER *EVP_aes_256_cfb1(void);
+const EVP_CIPHER *EVP_aes_256_cfb8(void);
+const EVP_CIPHER *EVP_aes_256_cfb128(void);
+# define EVP_aes_256_cfb EVP_aes_256_cfb128
+const EVP_CIPHER *EVP_aes_256_ofb(void);
+#if 0
+const EVP_CIPHER *EVP_aes_256_ctr(void);
+#endif
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+const EVP_CIPHER *EVP_camellia_128_ecb(void);
+const EVP_CIPHER *EVP_camellia_128_cbc(void);
+const EVP_CIPHER *EVP_camellia_128_cfb1(void);
+const EVP_CIPHER *EVP_camellia_128_cfb8(void);
+const EVP_CIPHER *EVP_camellia_128_cfb128(void);
+# define EVP_camellia_128_cfb EVP_camellia_128_cfb128
+const EVP_CIPHER *EVP_camellia_128_ofb(void);
+const EVP_CIPHER *EVP_camellia_192_ecb(void);
+const EVP_CIPHER *EVP_camellia_192_cbc(void);
+const EVP_CIPHER *EVP_camellia_192_cfb1(void);
+const EVP_CIPHER *EVP_camellia_192_cfb8(void);
+const EVP_CIPHER *EVP_camellia_192_cfb128(void);
+# define EVP_camellia_192_cfb EVP_camellia_192_cfb128
+const EVP_CIPHER *EVP_camellia_192_ofb(void);
+const EVP_CIPHER *EVP_camellia_256_ecb(void);
+const EVP_CIPHER *EVP_camellia_256_cbc(void);
+const EVP_CIPHER *EVP_camellia_256_cfb1(void);
+const EVP_CIPHER *EVP_camellia_256_cfb8(void);
+const EVP_CIPHER *EVP_camellia_256_cfb128(void);
+# define EVP_camellia_256_cfb EVP_camellia_256_cfb128
+const EVP_CIPHER *EVP_camellia_256_ofb(void);
+#endif
+
+#ifndef OPENSSL_NO_SEED
+const EVP_CIPHER *EVP_seed_ecb(void);
+const EVP_CIPHER *EVP_seed_cbc(void);
+const EVP_CIPHER *EVP_seed_cfb128(void);
+# define EVP_seed_cfb EVP_seed_cfb128
+const EVP_CIPHER *EVP_seed_ofb(void);
+#endif
+
+void OPENSSL_add_all_algorithms_noconf(void);
+void OPENSSL_add_all_algorithms_conf(void);
+
+#ifdef OPENSSL_LOAD_CONF
+#define OpenSSL_add_all_algorithms() \
+ OPENSSL_add_all_algorithms_conf()
+#else
+#define OpenSSL_add_all_algorithms() \
+ OPENSSL_add_all_algorithms_noconf()
+#endif
+
+void OpenSSL_add_all_ciphers(void);
+void OpenSSL_add_all_digests(void);
+#define SSLeay_add_all_algorithms() OpenSSL_add_all_algorithms()
+#define SSLeay_add_all_ciphers() OpenSSL_add_all_ciphers()
+#define SSLeay_add_all_digests() OpenSSL_add_all_digests()
+
+int EVP_add_cipher(const EVP_CIPHER *cipher);
+int EVP_add_digest(const EVP_MD *digest);
+
+const EVP_CIPHER *EVP_get_cipherbyname(const char *name);
+const EVP_MD *EVP_get_digestbyname(const char *name);
+void EVP_cleanup(void);
+
+int EVP_PKEY_decrypt(unsigned char *dec_key,
+ const unsigned char *enc_key,int enc_key_len,
+ EVP_PKEY *private_key);
+int EVP_PKEY_encrypt(unsigned char *enc_key,
+ const unsigned char *key,int key_len,
+ EVP_PKEY *pub_key);
+int EVP_PKEY_type(int type);
+int EVP_PKEY_bits(EVP_PKEY *pkey);
+int EVP_PKEY_size(EVP_PKEY *pkey);
+int EVP_PKEY_assign(EVP_PKEY *pkey,int type,char *key);
+
+#ifndef OPENSSL_NO_RSA
+struct rsa_st;
+int EVP_PKEY_set1_RSA(EVP_PKEY *pkey,struct rsa_st *key);
+struct rsa_st *EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
+#endif
+#ifndef OPENSSL_NO_DSA
+struct dsa_st;
+int EVP_PKEY_set1_DSA(EVP_PKEY *pkey,struct dsa_st *key);
+struct dsa_st *EVP_PKEY_get1_DSA(EVP_PKEY *pkey);
+#endif
+#ifndef OPENSSL_NO_DH
+struct dh_st;
+int EVP_PKEY_set1_DH(EVP_PKEY *pkey,struct dh_st *key);
+struct dh_st *EVP_PKEY_get1_DH(EVP_PKEY *pkey);
+#endif
+#ifndef OPENSSL_NO_EC
+struct ec_key_st;
+int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey,struct ec_key_st *key);
+struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey);
+#endif
+
+EVP_PKEY * EVP_PKEY_new(void);
+void EVP_PKEY_free(EVP_PKEY *pkey);
+
+EVP_PKEY * d2i_PublicKey(int type,EVP_PKEY **a, const unsigned char **pp,
+ long length);
+int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp);
+
+EVP_PKEY * d2i_PrivateKey(int type,EVP_PKEY **a, const unsigned char **pp,
+ long length);
+EVP_PKEY * d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
+ long length);
+int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp);
+
+int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from);
+int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey);
+int EVP_PKEY_save_parameters(EVP_PKEY *pkey,int mode);
+int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b);
+
+int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b);
+
+int EVP_CIPHER_type(const EVP_CIPHER *ctx);
+
+/* calls methods */
+int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+
+/* These are used by EVP_CIPHER methods */
+int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c,ASN1_TYPE *type);
+int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c,ASN1_TYPE *type);
+
+/* PKCS5 password based encryption */
+int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md,
+ int en_de);
+int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
+ const unsigned char *salt, int saltlen, int iter,
+ int keylen, unsigned char *out);
+int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md,
+ int en_de);
+
+void PKCS5_PBE_add(void);
+
+int EVP_PBE_CipherInit (ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
+ ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de);
+int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
+ EVP_PBE_KEYGEN *keygen);
+void EVP_PBE_cleanup(void);
+
+#ifdef OPENSSL_FIPS
+#ifndef OPENSSL_NO_ENGINE
+void int_EVP_MD_set_engine_callbacks(
+ int (*eng_md_init)(ENGINE *impl),
+ int (*eng_md_fin)(ENGINE *impl),
+ int (*eng_md_evp)
+ (EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl));
+void int_EVP_MD_init_engine_callbacks(void);
+void int_EVP_CIPHER_set_engine_callbacks(
+ int (*eng_ciph_fin)(ENGINE *impl),
+ int (*eng_ciph_evp)
+ (EVP_CIPHER_CTX *ctx, const EVP_CIPHER **pciph, ENGINE *impl));
+void int_EVP_CIPHER_init_engine_callbacks(void);
+#endif
+#endif
+
+void EVP_add_alg_module(void);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_EVP_strings(void);
+
+/* Error codes for the EVP functions. */
+
+/* Function codes. */
+#define EVP_F_AES_INIT_KEY 133
+#define EVP_F_ALG_MODULE_INIT 138
+#define EVP_F_CAMELLIA_INIT_KEY 159
+#define EVP_F_D2I_PKEY 100
+#define EVP_F_DO_EVP_ENC_ENGINE 140
+#define EVP_F_DO_EVP_ENC_ENGINE_FULL 141
+#define EVP_F_DO_EVP_MD_ENGINE 139
+#define EVP_F_DO_EVP_MD_ENGINE_FULL 142
+#define EVP_F_DSAPKEY2PKCS8 134
+#define EVP_F_DSA_PKEY2PKCS8 135
+#define EVP_F_ECDSA_PKEY2PKCS8 129
+#define EVP_F_ECKEY_PKEY2PKCS8 132
+#define EVP_F_EVP_CIPHERINIT 137
+#define EVP_F_EVP_CIPHERINIT_EX 123
+#define EVP_F_EVP_CIPHER_CTX_CTRL 124
+#define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH 122
+#define EVP_F_EVP_DECRYPTFINAL_EX 101
+#define EVP_F_EVP_DIGESTINIT 136
+#define EVP_F_EVP_DIGESTINIT_EX 128
+#define EVP_F_EVP_ENCRYPTFINAL_EX 127
+#define EVP_F_EVP_MD_CTX_COPY_EX 110
+#define EVP_F_EVP_OPENINIT 102
+#define EVP_F_EVP_PBE_ALG_ADD 115
+#define EVP_F_EVP_PBE_CIPHERINIT 116
+#define EVP_F_EVP_PKCS82PKEY 111
+#define EVP_F_EVP_PKEY2PKCS8_BROKEN 113
+#define EVP_F_EVP_PKEY_COPY_PARAMETERS 103
+#define EVP_F_EVP_PKEY_DECRYPT 104
+#define EVP_F_EVP_PKEY_ENCRYPT 105
+#define EVP_F_EVP_PKEY_GET1_DH 119
+#define EVP_F_EVP_PKEY_GET1_DSA 120
+#define EVP_F_EVP_PKEY_GET1_ECDSA 130
+#define EVP_F_EVP_PKEY_GET1_EC_KEY 131
+#define EVP_F_EVP_PKEY_GET1_RSA 121
+#define EVP_F_EVP_PKEY_NEW 106
+#define EVP_F_EVP_RIJNDAEL 126
+#define EVP_F_EVP_SIGNFINAL 107
+#define EVP_F_EVP_VERIFYFINAL 108
+#define EVP_F_PKCS5_PBE_KEYIVGEN 117
+#define EVP_F_PKCS5_V2_PBE_KEYIVGEN 118
+#define EVP_F_PKCS8_SET_BROKEN 112
+#define EVP_F_RC2_MAGIC_TO_METH 109
+#define EVP_F_RC5_CTRL 125
+
+/* Reason codes. */
+#define EVP_R_AES_KEY_SETUP_FAILED 143
+#define EVP_R_ASN1_LIB 140
+#define EVP_R_BAD_BLOCK_LENGTH 136
+#define EVP_R_BAD_DECRYPT 100
+#define EVP_R_BAD_KEY_LENGTH 137
+#define EVP_R_BN_DECODE_ERROR 112
+#define EVP_R_BN_PUBKEY_ERROR 113
+#define EVP_R_CAMELLIA_KEY_SETUP_FAILED 157
+#define EVP_R_CIPHER_PARAMETER_ERROR 122
+#define EVP_R_CTRL_NOT_IMPLEMENTED 132
+#define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED 133
+#define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH 138
+#define EVP_R_DECODE_ERROR 114
+#define EVP_R_DIFFERENT_KEY_TYPES 101
+#define EVP_R_DISABLED_FOR_FIPS 144
+#define EVP_R_ENCODE_ERROR 115
+#define EVP_R_ERROR_LOADING_SECTION 145
+#define EVP_R_ERROR_SETTING_FIPS_MODE 146
+#define EVP_R_EVP_PBE_CIPHERINIT_ERROR 119
+#define EVP_R_EXPECTING_AN_RSA_KEY 127
+#define EVP_R_EXPECTING_A_DH_KEY 128
+#define EVP_R_EXPECTING_A_DSA_KEY 129
+#define EVP_R_EXPECTING_A_ECDSA_KEY 141
+#define EVP_R_EXPECTING_A_EC_KEY 142
+#define EVP_R_FIPS_MODE_NOT_SUPPORTED 147
+#define EVP_R_INITIALIZATION_ERROR 134
+#define EVP_R_INPUT_NOT_INITIALIZED 111
+#define EVP_R_INVALID_FIPS_MODE 148
+#define EVP_R_INVALID_KEY_LENGTH 130
+#define EVP_R_IV_TOO_LARGE 102
+#define EVP_R_KEYGEN_FAILURE 120
+#define EVP_R_MISSING_PARAMETERS 103
+#define EVP_R_NO_CIPHER_SET 131
+#define EVP_R_NO_DIGEST_SET 139
+#define EVP_R_NO_DSA_PARAMETERS 116
+#define EVP_R_NO_SIGN_FUNCTION_CONFIGURED 104
+#define EVP_R_NO_VERIFY_FUNCTION_CONFIGURED 105
+#define EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE 117
+#define EVP_R_PUBLIC_KEY_NOT_RSA 106
+#define EVP_R_UNKNOWN_OPTION 149
+#define EVP_R_UNKNOWN_PBE_ALGORITHM 121
+#define EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS 135
+#define EVP_R_UNSUPPORTED_CIPHER 107
+#define EVP_R_UNSUPPORTED_KEYLENGTH 123
+#define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION 124
+#define EVP_R_UNSUPPORTED_KEY_SIZE 108
+#define EVP_R_UNSUPPORTED_PRF 125
+#define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM 118
+#define EVP_R_UNSUPPORTED_SALT_TYPE 126
+#define EVP_R_WRONG_FINAL_BLOCK_LENGTH 109
+#define EVP_R_WRONG_PUBLIC_KEY_TYPE 110
+#define EVP_R_SEED_KEY_SETUP_FAILED 162
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/fips.h b/src/Mayaqua/win32_inc/openssl/fips.h
new file mode 100644
index 00000000..3af03253
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/fips.h
@@ -0,0 +1,126 @@
+/* ====================================================================
+ * Copyright (c) 2003 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_FIPS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Note that these are defined in crypto/cryptlib.c so they're
+ * available even without -lfips.
+ */
+struct dsa_st;
+
+int FIPS_mode_set(int onoff,const char *path);
+void FIPS_allow_md5(int onoff);
+int FIPS_md5_allowed(void);
+int FIPS_selftest_failed(void);
+int FIPS_dsa_check(struct dsa_st *dsa);
+void FIPS_corrupt_sha1(void);
+int FIPS_selftest_sha1(void);
+void FIPS_corrupt_aes(void);
+int FIPS_selftest_aes(void);
+void FIPS_corrupt_des(void);
+int FIPS_selftest_des(void);
+void FIPS_corrupt_rsa(void);
+int FIPS_selftest_rsa(void);
+void FIPS_corrupt_dsa(void);
+int FIPS_selftest_dsa(void);
+
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_FIPS_strings(void);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_FIPS_strings(void);
+
+/* Error codes for the FIPS functions. */
+
+/* Function codes. */
+#define FIPS_F_DSA_DO_SIGN 111
+#define FIPS_F_DSA_DO_VERIFY 112
+#define FIPS_F_DSA_GENERATE_PARAMETERS 110
+#define FIPS_F_FIPS_CHECK_DSA 116
+#define FIPS_F_FIPS_CHECK_EXE 106
+#define FIPS_F_FIPS_CHECK_RSA 115
+#define FIPS_F_FIPS_DSA_CHECK 102
+#define FIPS_F_FIPS_MODE_SET 105
+#define FIPS_F_FIPS_SELFTEST_AES 104
+#define FIPS_F_FIPS_SELFTEST_DES 107
+#define FIPS_F_FIPS_SELFTEST_DSA 109
+#define FIPS_F_FIPS_SELFTEST_RSA 108
+#define FIPS_F_FIPS_SELFTEST_SHA1 103
+#define FIPS_F_HASH_FINAL 100
+#define FIPS_F_DH_GENERATE_PARAMETERS 117
+#define FIPS_F_RSA_EAY_PUBLIC_ENCRYPT 114
+#define FIPS_F_RSA_GENERATE_KEY 113
+#define FIPS_F_SSLEAY_RAND_BYTES 101
+
+/* Reason codes. */
+#define FIPS_R_CANNOT_READ_EXE 103
+#define FIPS_R_CANNOT_READ_EXE_DIGEST 104
+#define FIPS_R_EXE_DIGEST_DOES_NOT_MATCH 105
+#define FIPS_R_FIPS_MODE_ALREADY_SET 102
+#define FIPS_R_FIPS_SELFTEST_FAILED 106
+#define FIPS_R_NON_FIPS_METHOD 100
+#define FIPS_R_PAIRWISE_TEST_FAILED 107
+#define FIPS_R_SELFTEST_FAILED 101
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/fips_rand.h b/src/Mayaqua/win32_inc/openssl/fips_rand.h
new file mode 100644
index 00000000..07a925d4
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/fips_rand.h
@@ -0,0 +1,74 @@
+/* ====================================================================
+ * Copyright (c) 2003 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef HEADER_FIPS_RAND_H
+#define HEADER_FIPS_RAND_H
+
+#include "des.h"
+
+#ifdef OPENSSL_FIPS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void FIPS_set_prng_key(const unsigned char k1[8],const unsigned char k2[8]);
+void FIPS_test_mode(int test,const unsigned char faketime[8]);
+void FIPS_rand_seed(const void *buf, FIPS_RAND_SIZE_T num);
+/* NB: this returns true if _partially_ seeded */
+int FIPS_rand_seeded(void);
+
+RAND_METHOD *FIPS_rand_method(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/hmac.h b/src/Mayaqua/win32_inc/openssl/hmac.h
new file mode 100644
index 00000000..4bbf8b57
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/hmac.h
@@ -0,0 +1,109 @@
+/* crypto/hmac/hmac.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+#ifndef HEADER_HMAC_H
+#define HEADER_HMAC_H
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_HMAC
+#error HMAC is disabled.
+#endif
+
+#include <openssl/evp.h>
+
+#define HMAC_MAX_MD_CBLOCK 128 /* largest known is SHA512 */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct hmac_ctx_st
+ {
+ const EVP_MD *md;
+ EVP_MD_CTX md_ctx;
+ EVP_MD_CTX i_ctx;
+ EVP_MD_CTX o_ctx;
+ unsigned int key_length;
+ unsigned char key[HMAC_MAX_MD_CBLOCK];
+ } HMAC_CTX;
+
+#define HMAC_size(e) (EVP_MD_size((e)->md))
+
+
+void HMAC_CTX_init(HMAC_CTX *ctx);
+void HMAC_CTX_cleanup(HMAC_CTX *ctx);
+
+#define HMAC_cleanup(ctx) HMAC_CTX_cleanup(ctx) /* deprecated */
+
+void HMAC_Init(HMAC_CTX *ctx, const void *key, int len,
+ const EVP_MD *md); /* deprecated */
+void HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
+ const EVP_MD *md, ENGINE *impl);
+void HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len);
+void HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len);
+unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
+ const unsigned char *d, size_t n, unsigned char *md,
+ unsigned int *md_len);
+
+void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/idea.h b/src/Mayaqua/win32_inc/openssl/idea.h
new file mode 100644
index 00000000..f52d21fa
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/idea.h
@@ -0,0 +1,103 @@
+/* crypto/idea/idea.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_IDEA_H
+#define HEADER_IDEA_H
+
+#include <openssl/opensslconf.h> /* IDEA_INT, OPENSSL_NO_IDEA */
+
+#ifdef OPENSSL_NO_IDEA
+#error IDEA is disabled.
+#endif
+
+#define IDEA_ENCRYPT 1
+#define IDEA_DECRYPT 0
+
+#define IDEA_BLOCK 8
+#define IDEA_KEY_LENGTH 16
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct idea_key_st
+ {
+ IDEA_INT data[9][6];
+ } IDEA_KEY_SCHEDULE;
+
+const char *idea_options(void);
+void idea_ecb_encrypt(const unsigned char *in, unsigned char *out,
+ IDEA_KEY_SCHEDULE *ks);
+#ifdef OPENSSL_FIPS
+void private_idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks);
+#endif
+void idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks);
+void idea_set_decrypt_key(const IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk);
+void idea_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,int enc);
+void idea_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,
+ int *num,int enc);
+void idea_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, int *num);
+void idea_encrypt(unsigned long *in, IDEA_KEY_SCHEDULE *ks);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/krb5_asn.h b/src/Mayaqua/win32_inc/openssl/krb5_asn.h
new file mode 100644
index 00000000..fa08967f
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/krb5_asn.h
@@ -0,0 +1,256 @@
+/* krb5_asn.h */
+/* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project,
+** using ocsp/{*.h,*asn*.c} as a starting point
+*/
+
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_KRB5_ASN_H
+#define HEADER_KRB5_ASN_H
+
+/*
+#include <krb5.h>
+*/
+#include <openssl/safestack.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* ASN.1 from Kerberos RFC 1510
+*/
+
+/* EncryptedData ::= SEQUENCE {
+** etype[0] INTEGER, -- EncryptionType
+** kvno[1] INTEGER OPTIONAL,
+** cipher[2] OCTET STRING -- ciphertext
+** }
+*/
+typedef struct krb5_encdata_st
+ {
+ ASN1_INTEGER *etype;
+ ASN1_INTEGER *kvno;
+ ASN1_OCTET_STRING *cipher;
+ } KRB5_ENCDATA;
+
+DECLARE_STACK_OF(KRB5_ENCDATA)
+
+/* PrincipalName ::= SEQUENCE {
+** name-type[0] INTEGER,
+** name-string[1] SEQUENCE OF GeneralString
+** }
+*/
+typedef struct krb5_princname_st
+ {
+ ASN1_INTEGER *nametype;
+ STACK_OF(ASN1_GENERALSTRING) *namestring;
+ } KRB5_PRINCNAME;
+
+DECLARE_STACK_OF(KRB5_PRINCNAME)
+
+
+/* Ticket ::= [APPLICATION 1] SEQUENCE {
+** tkt-vno[0] INTEGER,
+** realm[1] Realm,
+** sname[2] PrincipalName,
+** enc-part[3] EncryptedData
+** }
+*/
+typedef struct krb5_tktbody_st
+ {
+ ASN1_INTEGER *tktvno;
+ ASN1_GENERALSTRING *realm;
+ KRB5_PRINCNAME *sname;
+ KRB5_ENCDATA *encdata;
+ } KRB5_TKTBODY;
+
+typedef STACK_OF(KRB5_TKTBODY) KRB5_TICKET;
+DECLARE_STACK_OF(KRB5_TKTBODY)
+
+
+/* AP-REQ ::= [APPLICATION 14] SEQUENCE {
+** pvno[0] INTEGER,
+** msg-type[1] INTEGER,
+** ap-options[2] APOptions,
+** ticket[3] Ticket,
+** authenticator[4] EncryptedData
+** }
+**
+** APOptions ::= BIT STRING {
+** reserved(0), use-session-key(1), mutual-required(2) }
+*/
+typedef struct krb5_ap_req_st
+ {
+ ASN1_INTEGER *pvno;
+ ASN1_INTEGER *msgtype;
+ ASN1_BIT_STRING *apoptions;
+ KRB5_TICKET *ticket;
+ KRB5_ENCDATA *authenticator;
+ } KRB5_APREQBODY;
+
+typedef STACK_OF(KRB5_APREQBODY) KRB5_APREQ;
+DECLARE_STACK_OF(KRB5_APREQBODY)
+
+
+/* Authenticator Stuff */
+
+
+/* Checksum ::= SEQUENCE {
+** cksumtype[0] INTEGER,
+** checksum[1] OCTET STRING
+** }
+*/
+typedef struct krb5_checksum_st
+ {
+ ASN1_INTEGER *ctype;
+ ASN1_OCTET_STRING *checksum;
+ } KRB5_CHECKSUM;
+
+DECLARE_STACK_OF(KRB5_CHECKSUM)
+
+
+/* EncryptionKey ::= SEQUENCE {
+** keytype[0] INTEGER,
+** keyvalue[1] OCTET STRING
+** }
+*/
+typedef struct krb5_encryptionkey_st
+ {
+ ASN1_INTEGER *ktype;
+ ASN1_OCTET_STRING *keyvalue;
+ } KRB5_ENCKEY;
+
+DECLARE_STACK_OF(KRB5_ENCKEY)
+
+
+/* AuthorizationData ::= SEQUENCE OF SEQUENCE {
+** ad-type[0] INTEGER,
+** ad-data[1] OCTET STRING
+** }
+*/
+typedef struct krb5_authorization_st
+ {
+ ASN1_INTEGER *adtype;
+ ASN1_OCTET_STRING *addata;
+ } KRB5_AUTHDATA;
+
+DECLARE_STACK_OF(KRB5_AUTHDATA)
+
+
+/* -- Unencrypted authenticator
+** Authenticator ::= [APPLICATION 2] SEQUENCE {
+** authenticator-vno[0] INTEGER,
+** crealm[1] Realm,
+** cname[2] PrincipalName,
+** cksum[3] Checksum OPTIONAL,
+** cusec[4] INTEGER,
+** ctime[5] KerberosTime,
+** subkey[6] EncryptionKey OPTIONAL,
+** seq-number[7] INTEGER OPTIONAL,
+** authorization-data[8] AuthorizationData OPTIONAL
+** }
+*/
+typedef struct krb5_authenticator_st
+ {
+ ASN1_INTEGER *avno;
+ ASN1_GENERALSTRING *crealm;
+ KRB5_PRINCNAME *cname;
+ KRB5_CHECKSUM *cksum;
+ ASN1_INTEGER *cusec;
+ ASN1_GENERALIZEDTIME *ctime;
+ KRB5_ENCKEY *subkey;
+ ASN1_INTEGER *seqnum;
+ KRB5_AUTHDATA *authorization;
+ } KRB5_AUTHENTBODY;
+
+typedef STACK_OF(KRB5_AUTHENTBODY) KRB5_AUTHENT;
+DECLARE_STACK_OF(KRB5_AUTHENTBODY)
+
+
+/* DECLARE_ASN1_FUNCTIONS(type) = DECLARE_ASN1_FUNCTIONS_name(type, type) =
+** type *name##_new(void);
+** void name##_free(type *a);
+** DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name) =
+** DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) =
+** type *d2i_##name(type **a, const unsigned char **in, long len);
+** int i2d_##name(type *a, unsigned char **out);
+** DECLARE_ASN1_ITEM(itname) = OPENSSL_EXTERN const ASN1_ITEM itname##_it
+*/
+
+DECLARE_ASN1_FUNCTIONS(KRB5_ENCDATA)
+DECLARE_ASN1_FUNCTIONS(KRB5_PRINCNAME)
+DECLARE_ASN1_FUNCTIONS(KRB5_TKTBODY)
+DECLARE_ASN1_FUNCTIONS(KRB5_APREQBODY)
+DECLARE_ASN1_FUNCTIONS(KRB5_TICKET)
+DECLARE_ASN1_FUNCTIONS(KRB5_APREQ)
+
+DECLARE_ASN1_FUNCTIONS(KRB5_CHECKSUM)
+DECLARE_ASN1_FUNCTIONS(KRB5_ENCKEY)
+DECLARE_ASN1_FUNCTIONS(KRB5_AUTHDATA)
+DECLARE_ASN1_FUNCTIONS(KRB5_AUTHENTBODY)
+DECLARE_ASN1_FUNCTIONS(KRB5_AUTHENT)
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/kssl.h b/src/Mayaqua/win32_inc/openssl/kssl.h
new file mode 100644
index 00000000..c84820f5
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/kssl.h
@@ -0,0 +1,179 @@
+/* ssl/kssl.h -*- mode: C; c-file-style: "eay" -*- */
+/* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project 2000.
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/*
+** 19990701 VRS Started.
+*/
+
+#ifndef KSSL_H
+#define KSSL_H
+
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_NO_KRB5
+
+#include <stdio.h>
+#include <ctype.h>
+#include <krb5.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Depending on which KRB5 implementation used, some types from
+** the other may be missing. Resolve that here and now
+*/
+#ifdef KRB5_HEIMDAL
+typedef unsigned char krb5_octet;
+#define FAR
+#else
+
+#ifndef FAR
+#define FAR
+#endif
+
+#endif
+
+/* Uncomment this to debug kssl problems or
+** to trace usage of the Kerberos session key
+**
+** #define KSSL_DEBUG
+*/
+
+#ifndef KRB5SVC
+#define KRB5SVC "host"
+#endif
+
+#ifndef KRB5KEYTAB
+#define KRB5KEYTAB "/etc/krb5.keytab"
+#endif
+
+#ifndef KRB5SENDAUTH
+#define KRB5SENDAUTH 1
+#endif
+
+#ifndef KRB5CHECKAUTH
+#define KRB5CHECKAUTH 1
+#endif
+
+#ifndef KSSL_CLOCKSKEW
+#define KSSL_CLOCKSKEW 300;
+#endif
+
+#define KSSL_ERR_MAX 255
+typedef struct kssl_err_st {
+ int reason;
+ char text[KSSL_ERR_MAX+1];
+ } KSSL_ERR;
+
+
+/* Context for passing
+** (1) Kerberos session key to SSL, and
+** (2) Config data between application and SSL lib
+*/
+typedef struct kssl_ctx_st
+ {
+ /* used by: disposition: */
+ char *service_name; /* C,S default ok (kssl) */
+ char *service_host; /* C input, REQUIRED */
+ char *client_princ; /* S output from krb5 ticket */
+ char *keytab_file; /* S NULL (/etc/krb5.keytab) */
+ char *cred_cache; /* C NULL (default) */
+ krb5_enctype enctype;
+ int length;
+ krb5_octet FAR *key;
+ } KSSL_CTX;
+
+#define KSSL_CLIENT 1
+#define KSSL_SERVER 2
+#define KSSL_SERVICE 3
+#define KSSL_KEYTAB 4
+
+#define KSSL_CTX_OK 0
+#define KSSL_CTX_ERR 1
+#define KSSL_NOMEM 2
+
+/* Public (for use by applications that use OpenSSL with Kerberos 5 support */
+krb5_error_code kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text);
+KSSL_CTX *kssl_ctx_new(void);
+KSSL_CTX *kssl_ctx_free(KSSL_CTX *kssl_ctx);
+void kssl_ctx_show(KSSL_CTX *kssl_ctx);
+krb5_error_code kssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which,
+ krb5_data *realm, krb5_data *entity, int nentities);
+krb5_error_code kssl_cget_tkt(KSSL_CTX *kssl_ctx, krb5_data **enc_tktp,
+ krb5_data *authenp, KSSL_ERR *kssl_err);
+krb5_error_code kssl_sget_tkt(KSSL_CTX *kssl_ctx, krb5_data *indata,
+ krb5_ticket_times *ttimes, KSSL_ERR *kssl_err);
+krb5_error_code kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session);
+void kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text);
+void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data);
+krb5_error_code kssl_build_principal_2(krb5_context context,
+ krb5_principal *princ, int rlen, const char *realm,
+ int slen, const char *svc, int hlen, const char *host);
+krb5_error_code kssl_validate_times(krb5_timestamp atime,
+ krb5_ticket_times *ttimes);
+krb5_error_code kssl_check_authent(KSSL_CTX *kssl_ctx, krb5_data *authentp,
+ krb5_timestamp *atimep, KSSL_ERR *kssl_err);
+unsigned char *kssl_skip_confound(krb5_enctype enctype, unsigned char *authn);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* OPENSSL_NO_KRB5 */
+#endif /* KSSL_H */
diff --git a/src/Mayaqua/win32_inc/openssl/lhash.h b/src/Mayaqua/win32_inc/openssl/lhash.h
new file mode 100644
index 00000000..d0b1daf6
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/lhash.h
@@ -0,0 +1,200 @@
+/* crypto/lhash/lhash.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* Header for dynamic hash table routines
+ * Author - Eric Young
+ */
+
+#ifndef HEADER_LHASH_H
+#define HEADER_LHASH_H
+
+#include <openssl/e_os2.h>
+#ifndef OPENSSL_NO_FP_API
+#include <stdio.h>
+#endif
+
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct lhash_node_st
+ {
+ void *data;
+ struct lhash_node_st *next;
+#ifndef OPENSSL_NO_HASH_COMP
+ unsigned long hash;
+#endif
+ } LHASH_NODE;
+
+typedef int (*LHASH_COMP_FN_TYPE)(const void *, const void *);
+typedef unsigned long (*LHASH_HASH_FN_TYPE)(const void *);
+typedef void (*LHASH_DOALL_FN_TYPE)(void *);
+typedef void (*LHASH_DOALL_ARG_FN_TYPE)(void *, void *);
+
+/* Macros for declaring and implementing type-safe wrappers for LHASH callbacks.
+ * This way, callbacks can be provided to LHASH structures without function
+ * pointer casting and the macro-defined callbacks provide per-variable casting
+ * before deferring to the underlying type-specific callbacks. NB: It is
+ * possible to place a "static" in front of both the DECLARE and IMPLEMENT
+ * macros if the functions are strictly internal. */
+
+/* First: "hash" functions */
+#define DECLARE_LHASH_HASH_FN(f_name,o_type) \
+ unsigned long f_name##_LHASH_HASH(const void *);
+#define IMPLEMENT_LHASH_HASH_FN(f_name,o_type) \
+ unsigned long f_name##_LHASH_HASH(const void *arg) { \
+ o_type a = (o_type)arg; \
+ return f_name(a); }
+#define LHASH_HASH_FN(f_name) f_name##_LHASH_HASH
+
+/* Second: "compare" functions */
+#define DECLARE_LHASH_COMP_FN(f_name,o_type) \
+ int f_name##_LHASH_COMP(const void *, const void *);
+#define IMPLEMENT_LHASH_COMP_FN(f_name,o_type) \
+ int f_name##_LHASH_COMP(const void *arg1, const void *arg2) { \
+ o_type a = (o_type)arg1; \
+ o_type b = (o_type)arg2; \
+ return f_name(a,b); }
+#define LHASH_COMP_FN(f_name) f_name##_LHASH_COMP
+
+/* Third: "doall" functions */
+#define DECLARE_LHASH_DOALL_FN(f_name,o_type) \
+ void f_name##_LHASH_DOALL(void *);
+#define IMPLEMENT_LHASH_DOALL_FN(f_name,o_type) \
+ void f_name##_LHASH_DOALL(void *arg) { \
+ o_type a = (o_type)arg; \
+ f_name(a); }
+#define LHASH_DOALL_FN(f_name) f_name##_LHASH_DOALL
+
+/* Fourth: "doall_arg" functions */
+#define DECLARE_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \
+ void f_name##_LHASH_DOALL_ARG(void *, void *);
+#define IMPLEMENT_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \
+ void f_name##_LHASH_DOALL_ARG(void *arg1, void *arg2) { \
+ o_type a = (o_type)arg1; \
+ a_type b = (a_type)arg2; \
+ f_name(a,b); }
+#define LHASH_DOALL_ARG_FN(f_name) f_name##_LHASH_DOALL_ARG
+
+typedef struct lhash_st
+ {
+ LHASH_NODE **b;
+ LHASH_COMP_FN_TYPE comp;
+ LHASH_HASH_FN_TYPE hash;
+ unsigned int num_nodes;
+ unsigned int num_alloc_nodes;
+ unsigned int p;
+ unsigned int pmax;
+ unsigned long up_load; /* load times 256 */
+ unsigned long down_load; /* load times 256 */
+ unsigned long num_items;
+
+ unsigned long num_expands;
+ unsigned long num_expand_reallocs;
+ unsigned long num_contracts;
+ unsigned long num_contract_reallocs;
+ unsigned long num_hash_calls;
+ unsigned long num_comp_calls;
+ unsigned long num_insert;
+ unsigned long num_replace;
+ unsigned long num_delete;
+ unsigned long num_no_delete;
+ unsigned long num_retrieve;
+ unsigned long num_retrieve_miss;
+ unsigned long num_hash_comps;
+
+ int error;
+ } LHASH;
+
+#define LH_LOAD_MULT 256
+
+/* Indicates a malloc() error in the last call, this is only bad
+ * in lh_insert(). */
+#define lh_error(lh) ((lh)->error)
+
+LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c);
+void lh_free(LHASH *lh);
+void *lh_insert(LHASH *lh, void *data);
+void *lh_delete(LHASH *lh, const void *data);
+void *lh_retrieve(LHASH *lh, const void *data);
+void lh_doall(LHASH *lh, LHASH_DOALL_FN_TYPE func);
+void lh_doall_arg(LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg);
+unsigned long lh_strhash(const char *c);
+unsigned long lh_num_items(const LHASH *lh);
+
+#ifndef OPENSSL_NO_FP_API
+void lh_stats(const LHASH *lh, FILE *out);
+void lh_node_stats(const LHASH *lh, FILE *out);
+void lh_node_usage_stats(const LHASH *lh, FILE *out);
+#endif
+
+#ifndef OPENSSL_NO_BIO
+void lh_stats_bio(const LHASH *lh, BIO *out);
+void lh_node_stats_bio(const LHASH *lh, BIO *out);
+void lh_node_usage_stats_bio(const LHASH *lh, BIO *out);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/md2.h b/src/Mayaqua/win32_inc/openssl/md2.h
new file mode 100644
index 00000000..f06843e1
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/md2.h
@@ -0,0 +1,95 @@
+/* crypto/md/md2.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MD2_H
+#define HEADER_MD2_H
+
+#include <openssl/opensslconf.h> /* OPENSSL_NO_MD2, MD2_INT */
+#ifdef OPENSSL_NO_MD2
+#error MD2 is disabled.
+#endif
+#include <stddef.h>
+
+#define MD2_DIGEST_LENGTH 16
+#define MD2_BLOCK 16
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct MD2state_st
+ {
+ unsigned int num;
+ unsigned char data[MD2_BLOCK];
+ MD2_INT cksm[MD2_BLOCK];
+ MD2_INT state[MD2_BLOCK];
+ } MD2_CTX;
+
+const char *MD2_options(void);
+#ifdef OPENSSL_FIPS
+int private_MD2_Init(MD2_CTX *c);
+#endif
+int MD2_Init(MD2_CTX *c);
+int MD2_Update(MD2_CTX *c, const unsigned char *data, size_t len);
+int MD2_Final(unsigned char *md, MD2_CTX *c);
+unsigned char *MD2(const unsigned char *d, size_t n,unsigned char *md);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/md4.h b/src/Mayaqua/win32_inc/openssl/md4.h
new file mode 100644
index 00000000..b316d87d
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/md4.h
@@ -0,0 +1,120 @@
+/* crypto/md4/md4.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MD4_H
+#define HEADER_MD4_H
+
+#include <openssl/e_os2.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_MD4
+#error MD4 is disabled.
+#endif
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! MD4_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! MD4_LONG_LOG2 has to be defined along. !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define MD4_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define MD4_LONG unsigned long
+#define MD4_LONG_LOG2 3
+/*
+ * _CRAY note. I could declare short, but I have no idea what impact
+ * does it have on performance on none-T3E machines. I could declare
+ * int, but at least on C90 sizeof(int) can be chosen at compile time.
+ * So I've chosen long...
+ * <appro@fy.chalmers.se>
+ */
+#else
+#define MD4_LONG unsigned int
+#endif
+
+#define MD4_CBLOCK 64
+#define MD4_LBLOCK (MD4_CBLOCK/4)
+#define MD4_DIGEST_LENGTH 16
+
+typedef struct MD4state_st
+ {
+ MD4_LONG A,B,C,D;
+ MD4_LONG Nl,Nh;
+ MD4_LONG data[MD4_LBLOCK];
+ unsigned int num;
+ } MD4_CTX;
+
+#ifdef OPENSSL_FIPS
+int private_MD4_Init(MD4_CTX *c);
+#endif
+int MD4_Init(MD4_CTX *c);
+int MD4_Update(MD4_CTX *c, const void *data, size_t len);
+int MD4_Final(unsigned char *md, MD4_CTX *c);
+unsigned char *MD4(const unsigned char *d, size_t n, unsigned char *md);
+void MD4_Transform(MD4_CTX *c, const unsigned char *b);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/md5.h b/src/Mayaqua/win32_inc/openssl/md5.h
new file mode 100644
index 00000000..f84cc762
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/md5.h
@@ -0,0 +1,120 @@
+/* crypto/md5/md5.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MD5_H
+#define HEADER_MD5_H
+
+#include <openssl/e_os2.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_MD5
+#error MD5 is disabled.
+#endif
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! MD5_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! MD5_LONG_LOG2 has to be defined along. !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define MD5_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define MD5_LONG unsigned long
+#define MD5_LONG_LOG2 3
+/*
+ * _CRAY note. I could declare short, but I have no idea what impact
+ * does it have on performance on none-T3E machines. I could declare
+ * int, but at least on C90 sizeof(int) can be chosen at compile time.
+ * So I've chosen long...
+ * <appro@fy.chalmers.se>
+ */
+#else
+#define MD5_LONG unsigned int
+#endif
+
+#define MD5_CBLOCK 64
+#define MD5_LBLOCK (MD5_CBLOCK/4)
+#define MD5_DIGEST_LENGTH 16
+
+typedef struct MD5state_st
+ {
+ MD5_LONG A,B,C,D;
+ MD5_LONG Nl,Nh;
+ MD5_LONG data[MD5_LBLOCK];
+ unsigned int num;
+ } MD5_CTX;
+
+#ifdef OPENSSL_FIPS
+int private_MD5_Init(MD5_CTX *c);
+#endif
+int MD5_Init(MD5_CTX *c);
+int MD5_Update(MD5_CTX *c, const void *data, size_t len);
+int MD5_Final(unsigned char *md, MD5_CTX *c);
+unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md);
+void MD5_Transform(MD5_CTX *c, const unsigned char *b);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/mdc2.h b/src/Mayaqua/win32_inc/openssl/mdc2.h
new file mode 100644
index 00000000..48320c42
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/mdc2.h
@@ -0,0 +1,98 @@
+/* crypto/mdc2/mdc2.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_MDC2_H
+#define HEADER_MDC2_H
+
+#include <openssl/des.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_MDC2
+#error MDC2 is disabled.
+#endif
+
+#define MDC2_BLOCK 8
+#define MDC2_DIGEST_LENGTH 16
+
+typedef struct mdc2_ctx_st
+ {
+ int num;
+ unsigned char data[MDC2_BLOCK];
+ DES_cblock h,hh;
+ int pad_type; /* either 1 or 2, default 1 */
+ } MDC2_CTX;
+
+#ifdef OPENSSL_FIPS
+int private_MDC2_Init(MDC2_CTX *c);
+#endif
+int MDC2_Init(MDC2_CTX *c);
+int MDC2_Update(MDC2_CTX *c, const unsigned char *data, unsigned long len);
+int MDC2_Final(unsigned char *md, MDC2_CTX *c);
+unsigned char *MDC2(const unsigned char *d, unsigned long n,
+ unsigned char *md);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/src/Mayaqua/win32_inc/openssl/obj_mac.h b/src/Mayaqua/win32_inc/openssl/obj_mac.h
new file mode 100644
index 00000000..b402e896
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/obj_mac.h
@@ -0,0 +1,3914 @@
+/* crypto/objects/obj_mac.h */
+
+/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the
+ * following command:
+ * perl objects.pl objects.txt obj_mac.num obj_mac.h
+ */
+
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#define SN_undef "UNDEF"
+#define LN_undef "undefined"
+#define NID_undef 0
+#define OBJ_undef 0L
+
+#define SN_itu_t "ITU-T"
+#define LN_itu_t "itu-t"
+#define NID_itu_t 645
+#define OBJ_itu_t 0L
+
+#define NID_ccitt 404
+#define OBJ_ccitt OBJ_itu_t
+
+#define SN_iso "ISO"
+#define LN_iso "iso"
+#define NID_iso 181
+#define OBJ_iso 1L
+
+#define SN_joint_iso_itu_t "JOINT-ISO-ITU-T"
+#define LN_joint_iso_itu_t "joint-iso-itu-t"
+#define NID_joint_iso_itu_t 646
+#define OBJ_joint_iso_itu_t 2L
+
+#define NID_joint_iso_ccitt 393
+#define OBJ_joint_iso_ccitt OBJ_joint_iso_itu_t
+
+#define SN_member_body "member-body"
+#define LN_member_body "ISO Member Body"
+#define NID_member_body 182
+#define OBJ_member_body OBJ_iso,2L
+
+#define SN_identified_organization "identified-organization"
+#define NID_identified_organization 676
+#define OBJ_identified_organization OBJ_iso,3L
+
+#define SN_hmac_md5 "HMAC-MD5"
+#define LN_hmac_md5 "hmac-md5"
+#define NID_hmac_md5 780
+#define OBJ_hmac_md5 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,1L
+
+#define SN_hmac_sha1 "HMAC-SHA1"
+#define LN_hmac_sha1 "hmac-sha1"
+#define NID_hmac_sha1 781
+#define OBJ_hmac_sha1 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,2L
+
+#define SN_certicom_arc "certicom-arc"
+#define NID_certicom_arc 677
+#define OBJ_certicom_arc OBJ_identified_organization,132L
+
+#define SN_international_organizations "international-organizations"
+#define LN_international_organizations "International Organizations"
+#define NID_international_organizations 647
+#define OBJ_international_organizations OBJ_joint_iso_itu_t,23L
+
+#define SN_wap "wap"
+#define NID_wap 678
+#define OBJ_wap OBJ_international_organizations,43L
+
+#define SN_wap_wsg "wap-wsg"
+#define NID_wap_wsg 679
+#define OBJ_wap_wsg OBJ_wap,1L
+
+#define SN_selected_attribute_types "selected-attribute-types"
+#define LN_selected_attribute_types "Selected Attribute Types"
+#define NID_selected_attribute_types 394
+#define OBJ_selected_attribute_types OBJ_joint_iso_itu_t,5L,1L,5L
+
+#define SN_clearance "clearance"
+#define NID_clearance 395
+#define OBJ_clearance OBJ_selected_attribute_types,55L
+
+#define SN_ISO_US "ISO-US"
+#define LN_ISO_US "ISO US Member Body"
+#define NID_ISO_US 183
+#define OBJ_ISO_US OBJ_member_body,840L
+
+#define SN_X9_57 "X9-57"
+#define LN_X9_57 "X9.57"
+#define NID_X9_57 184
+#define OBJ_X9_57 OBJ_ISO_US,10040L
+
+#define SN_X9cm "X9cm"
+#define LN_X9cm "X9.57 CM ?"
+#define NID_X9cm 185
+#define OBJ_X9cm OBJ_X9_57,4L
+
+#define SN_dsa "DSA"
+#define LN_dsa "dsaEncryption"
+#define NID_dsa 116
+#define OBJ_dsa OBJ_X9cm,1L
+
+#define SN_dsaWithSHA1 "DSA-SHA1"
+#define LN_dsaWithSHA1 "dsaWithSHA1"
+#define NID_dsaWithSHA1 113
+#define OBJ_dsaWithSHA1 OBJ_X9cm,3L
+
+#define SN_ansi_X9_62 "ansi-X9-62"
+#define LN_ansi_X9_62 "ANSI X9.62"
+#define NID_ansi_X9_62 405
+#define OBJ_ansi_X9_62 OBJ_ISO_US,10045L
+
+#define OBJ_X9_62_id_fieldType OBJ_ansi_X9_62,1L
+
+#define SN_X9_62_prime_field "prime-field"
+#define NID_X9_62_prime_field 406
+#define OBJ_X9_62_prime_field OBJ_X9_62_id_fieldType,1L
+
+#define SN_X9_62_characteristic_two_field "characteristic-two-field"
+#define NID_X9_62_characteristic_two_field 407
+#define OBJ_X9_62_characteristic_two_field OBJ_X9_62_id_fieldType,2L
+
+#define SN_X9_62_id_characteristic_two_basis "id-characteristic-two-basis"
+#define NID_X9_62_id_characteristic_two_basis 680
+#define OBJ_X9_62_id_characteristic_two_basis OBJ_X9_62_characteristic_two_field,3L
+
+#define SN_X9_62_onBasis "onBasis"
+#define NID_X9_62_onBasis 681
+#define OBJ_X9_62_onBasis OBJ_X9_62_id_characteristic_two_basis,1L
+
+#define SN_X9_62_tpBasis "tpBasis"
+#define NID_X9_62_tpBasis 682
+#define OBJ_X9_62_tpBasis OBJ_X9_62_id_characteristic_two_basis,2L
+
+#define SN_X9_62_ppBasis "ppBasis"
+#define NID_X9_62_ppBasis 683
+#define OBJ_X9_62_ppBasis OBJ_X9_62_id_characteristic_two_basis,3L
+
+#define OBJ_X9_62_id_publicKeyType OBJ_ansi_X9_62,2L
+
+#define SN_X9_62_id_ecPublicKey "id-ecPublicKey"
+#define NID_X9_62_id_ecPublicKey 408
+#define OBJ_X9_62_id_ecPublicKey OBJ_X9_62_id_publicKeyType,1L
+
+#define OBJ_X9_62_ellipticCurve OBJ_ansi_X9_62,3L
+
+#define OBJ_X9_62_c_TwoCurve OBJ_X9_62_ellipticCurve,0L
+
+#define SN_X9_62_c2pnb163v1 "c2pnb163v1"
+#define NID_X9_62_c2pnb163v1 684
+#define OBJ_X9_62_c2pnb163v1 OBJ_X9_62_c_TwoCurve,1L
+
+#define SN_X9_62_c2pnb163v2 "c2pnb163v2"
+#define NID_X9_62_c2pnb163v2 685
+#define OBJ_X9_62_c2pnb163v2 OBJ_X9_62_c_TwoCurve,2L
+
+#define SN_X9_62_c2pnb163v3 "c2pnb163v3"
+#define NID_X9_62_c2pnb163v3 686
+#define OBJ_X9_62_c2pnb163v3 OBJ_X9_62_c_TwoCurve,3L
+
+#define SN_X9_62_c2pnb176v1 "c2pnb176v1"
+#define NID_X9_62_c2pnb176v1 687
+#define OBJ_X9_62_c2pnb176v1 OBJ_X9_62_c_TwoCurve,4L
+
+#define SN_X9_62_c2tnb191v1 "c2tnb191v1"
+#define NID_X9_62_c2tnb191v1 688
+#define OBJ_X9_62_c2tnb191v1 OBJ_X9_62_c_TwoCurve,5L
+
+#define SN_X9_62_c2tnb191v2 "c2tnb191v2"
+#define NID_X9_62_c2tnb191v2 689
+#define OBJ_X9_62_c2tnb191v2 OBJ_X9_62_c_TwoCurve,6L
+
+#define SN_X9_62_c2tnb191v3 "c2tnb191v3"
+#define NID_X9_62_c2tnb191v3 690
+#define OBJ_X9_62_c2tnb191v3 OBJ_X9_62_c_TwoCurve,7L
+
+#define SN_X9_62_c2onb191v4 "c2onb191v4"
+#define NID_X9_62_c2onb191v4 691
+#define OBJ_X9_62_c2onb191v4 OBJ_X9_62_c_TwoCurve,8L
+
+#define SN_X9_62_c2onb191v5 "c2onb191v5"
+#define NID_X9_62_c2onb191v5 692
+#define OBJ_X9_62_c2onb191v5 OBJ_X9_62_c_TwoCurve,9L
+
+#define SN_X9_62_c2pnb208w1 "c2pnb208w1"
+#define NID_X9_62_c2pnb208w1 693
+#define OBJ_X9_62_c2pnb208w1 OBJ_X9_62_c_TwoCurve,10L
+
+#define SN_X9_62_c2tnb239v1 "c2tnb239v1"
+#define NID_X9_62_c2tnb239v1 694
+#define OBJ_X9_62_c2tnb239v1 OBJ_X9_62_c_TwoCurve,11L
+
+#define SN_X9_62_c2tnb239v2 "c2tnb239v2"
+#define NID_X9_62_c2tnb239v2 695
+#define OBJ_X9_62_c2tnb239v2 OBJ_X9_62_c_TwoCurve,12L
+
+#define SN_X9_62_c2tnb239v3 "c2tnb239v3"
+#define NID_X9_62_c2tnb239v3 696
+#define OBJ_X9_62_c2tnb239v3 OBJ_X9_62_c_TwoCurve,13L
+
+#define SN_X9_62_c2onb239v4 "c2onb239v4"
+#define NID_X9_62_c2onb239v4 697
+#define OBJ_X9_62_c2onb239v4 OBJ_X9_62_c_TwoCurve,14L
+
+#define SN_X9_62_c2onb239v5 "c2onb239v5"
+#define NID_X9_62_c2onb239v5 698
+#define OBJ_X9_62_c2onb239v5 OBJ_X9_62_c_TwoCurve,15L
+
+#define SN_X9_62_c2pnb272w1 "c2pnb272w1"
+#define NID_X9_62_c2pnb272w1 699
+#define OBJ_X9_62_c2pnb272w1 OBJ_X9_62_c_TwoCurve,16L
+
+#define SN_X9_62_c2pnb304w1 "c2pnb304w1"
+#define NID_X9_62_c2pnb304w1 700
+#define OBJ_X9_62_c2pnb304w1 OBJ_X9_62_c_TwoCurve,17L
+
+#define SN_X9_62_c2tnb359v1 "c2tnb359v1"
+#define NID_X9_62_c2tnb359v1 701
+#define OBJ_X9_62_c2tnb359v1 OBJ_X9_62_c_TwoCurve,18L
+
+#define SN_X9_62_c2pnb368w1 "c2pnb368w1"
+#define NID_X9_62_c2pnb368w1 702
+#define OBJ_X9_62_c2pnb368w1 OBJ_X9_62_c_TwoCurve,19L
+
+#define SN_X9_62_c2tnb431r1 "c2tnb431r1"
+#define NID_X9_62_c2tnb431r1 703
+#define OBJ_X9_62_c2tnb431r1 OBJ_X9_62_c_TwoCurve,20L
+
+#define OBJ_X9_62_primeCurve OBJ_X9_62_ellipticCurve,1L
+
+#define SN_X9_62_prime192v1 "prime192v1"
+#define NID_X9_62_prime192v1 409
+#define OBJ_X9_62_prime192v1 OBJ_X9_62_primeCurve,1L
+
+#define SN_X9_62_prime192v2 "prime192v2"
+#define NID_X9_62_prime192v2 410
+#define OBJ_X9_62_prime192v2 OBJ_X9_62_primeCurve,2L
+
+#define SN_X9_62_prime192v3 "prime192v3"
+#define NID_X9_62_prime192v3 411
+#define OBJ_X9_62_prime192v3 OBJ_X9_62_primeCurve,3L
+
+#define SN_X9_62_prime239v1 "prime239v1"
+#define NID_X9_62_prime239v1 412
+#define OBJ_X9_62_prime239v1 OBJ_X9_62_primeCurve,4L
+
+#define SN_X9_62_prime239v2 "prime239v2"
+#define NID_X9_62_prime239v2 413
+#define OBJ_X9_62_prime239v2 OBJ_X9_62_primeCurve,5L
+
+#define SN_X9_62_prime239v3 "prime239v3"
+#define NID_X9_62_prime239v3 414
+#define OBJ_X9_62_prime239v3 OBJ_X9_62_primeCurve,6L
+
+#define SN_X9_62_prime256v1 "prime256v1"
+#define NID_X9_62_prime256v1 415
+#define OBJ_X9_62_prime256v1 OBJ_X9_62_primeCurve,7L
+
+#define OBJ_X9_62_id_ecSigType OBJ_ansi_X9_62,4L
+
+#define SN_ecdsa_with_SHA1 "ecdsa-with-SHA1"
+#define NID_ecdsa_with_SHA1 416
+#define OBJ_ecdsa_with_SHA1 OBJ_X9_62_id_ecSigType,1L
+
+#define SN_ecdsa_with_Recommended "ecdsa-with-Recommended"
+#define NID_ecdsa_with_Recommended 791
+#define OBJ_ecdsa_with_Recommended OBJ_X9_62_id_ecSigType,2L
+
+#define SN_ecdsa_with_Specified "ecdsa-with-Specified"
+#define NID_ecdsa_with_Specified 792
+#define OBJ_ecdsa_with_Specified OBJ_X9_62_id_ecSigType,3L
+
+#define SN_ecdsa_with_SHA224 "ecdsa-with-SHA224"
+#define NID_ecdsa_with_SHA224 793
+#define OBJ_ecdsa_with_SHA224 OBJ_ecdsa_with_Specified,1L
+
+#define SN_ecdsa_with_SHA256 "ecdsa-with-SHA256"
+#define NID_ecdsa_with_SHA256 794
+#define OBJ_ecdsa_with_SHA256 OBJ_ecdsa_with_Specified,2L
+
+#define SN_ecdsa_with_SHA384 "ecdsa-with-SHA384"
+#define NID_ecdsa_with_SHA384 795
+#define OBJ_ecdsa_with_SHA384 OBJ_ecdsa_with_Specified,3L
+
+#define SN_ecdsa_with_SHA512 "ecdsa-with-SHA512"
+#define NID_ecdsa_with_SHA512 796
+#define OBJ_ecdsa_with_SHA512 OBJ_ecdsa_with_Specified,4L
+
+#define OBJ_secg_ellipticCurve OBJ_certicom_arc,0L
+
+#define SN_secp112r1 "secp112r1"
+#define NID_secp112r1 704
+#define OBJ_secp112r1 OBJ_secg_ellipticCurve,6L
+
+#define SN_secp112r2 "secp112r2"
+#define NID_secp112r2 705
+#define OBJ_secp112r2 OBJ_secg_ellipticCurve,7L
+
+#define SN_secp128r1 "secp128r1"
+#define NID_secp128r1 706
+#define OBJ_secp128r1 OBJ_secg_ellipticCurve,28L
+
+#define SN_secp128r2 "secp128r2"
+#define NID_secp128r2 707
+#define OBJ_secp128r2 OBJ_secg_ellipticCurve,29L
+
+#define SN_secp160k1 "secp160k1"
+#define NID_secp160k1 708
+#define OBJ_secp160k1 OBJ_secg_ellipticCurve,9L
+
+#define SN_secp160r1 "secp160r1"
+#define NID_secp160r1 709
+#define OBJ_secp160r1 OBJ_secg_ellipticCurve,8L
+
+#define SN_secp160r2 "secp160r2"
+#define NID_secp160r2 710
+#define OBJ_secp160r2 OBJ_secg_ellipticCurve,30L
+
+#define SN_secp192k1 "secp192k1"
+#define NID_secp192k1 711
+#define OBJ_secp192k1 OBJ_secg_ellipticCurve,31L
+
+#define SN_secp224k1 "secp224k1"
+#define NID_secp224k1 712
+#define OBJ_secp224k1 OBJ_secg_ellipticCurve,32L
+
+#define SN_secp224r1 "secp224r1"
+#define NID_secp224r1 713
+#define OBJ_secp224r1 OBJ_secg_ellipticCurve,33L
+
+#define SN_secp256k1 "secp256k1"
+#define NID_secp256k1 714
+#define OBJ_secp256k1 OBJ_secg_ellipticCurve,10L
+
+#define SN_secp384r1 "secp384r1"
+#define NID_secp384r1 715
+#define OBJ_secp384r1 OBJ_secg_ellipticCurve,34L
+
+#define SN_secp521r1 "secp521r1"
+#define NID_secp521r1 716
+#define OBJ_secp521r1 OBJ_secg_ellipticCurve,35L
+
+#define SN_sect113r1 "sect113r1"
+#define NID_sect113r1 717
+#define OBJ_sect113r1 OBJ_secg_ellipticCurve,4L
+
+#define SN_sect113r2 "sect113r2"
+#define NID_sect113r2 718
+#define OBJ_sect113r2 OBJ_secg_ellipticCurve,5L
+
+#define SN_sect131r1 "sect131r1"
+#define NID_sect131r1 719
+#define OBJ_sect131r1 OBJ_secg_ellipticCurve,22L
+
+#define SN_sect131r2 "sect131r2"
+#define NID_sect131r2 720
+#define OBJ_sect131r2 OBJ_secg_ellipticCurve,23L
+
+#define SN_sect163k1 "sect163k1"
+#define NID_sect163k1 721
+#define OBJ_sect163k1 OBJ_secg_ellipticCurve,1L
+
+#define SN_sect163r1 "sect163r1"
+#define NID_sect163r1 722
+#define OBJ_sect163r1 OBJ_secg_ellipticCurve,2L
+
+#define SN_sect163r2 "sect163r2"
+#define NID_sect163r2 723
+#define OBJ_sect163r2 OBJ_secg_ellipticCurve,15L
+
+#define SN_sect193r1 "sect193r1"
+#define NID_sect193r1 724
+#define OBJ_sect193r1 OBJ_secg_ellipticCurve,24L
+
+#define SN_sect193r2 "sect193r2"
+#define NID_sect193r2 725
+#define OBJ_sect193r2 OBJ_secg_ellipticCurve,25L
+
+#define SN_sect233k1 "sect233k1"
+#define NID_sect233k1 726
+#define OBJ_sect233k1 OBJ_secg_ellipticCurve,26L
+
+#define SN_sect233r1 "sect233r1"
+#define NID_sect233r1 727
+#define OBJ_sect233r1 OBJ_secg_ellipticCurve,27L
+
+#define SN_sect239k1 "sect239k1"
+#define NID_sect239k1 728
+#define OBJ_sect239k1 OBJ_secg_ellipticCurve,3L
+
+#define SN_sect283k1 "sect283k1"
+#define NID_sect283k1 729
+#define OBJ_sect283k1 OBJ_secg_ellipticCurve,16L
+
+#define SN_sect283r1 "sect283r1"
+#define NID_sect283r1 730
+#define OBJ_sect283r1 OBJ_secg_ellipticCurve,17L
+
+#define SN_sect409k1 "sect409k1"
+#define NID_sect409k1 731
+#define OBJ_sect409k1 OBJ_secg_ellipticCurve,36L
+
+#define SN_sect409r1 "sect409r1"
+#define NID_sect409r1 732
+#define OBJ_sect409r1 OBJ_secg_ellipticCurve,37L
+
+#define SN_sect571k1 "sect571k1"
+#define NID_sect571k1 733
+#define OBJ_sect571k1 OBJ_secg_ellipticCurve,38L
+
+#define SN_sect571r1 "sect571r1"
+#define NID_sect571r1 734
+#define OBJ_sect571r1 OBJ_secg_ellipticCurve,39L
+
+#define OBJ_wap_wsg_idm_ecid OBJ_wap_wsg,4L
+
+#define SN_wap_wsg_idm_ecid_wtls1 "wap-wsg-idm-ecid-wtls1"
+#define NID_wap_wsg_idm_ecid_wtls1 735
+#define OBJ_wap_wsg_idm_ecid_wtls1 OBJ_wap_wsg_idm_ecid,1L
+
+#define SN_wap_wsg_idm_ecid_wtls3 "wap-wsg-idm-ecid-wtls3"
+#define NID_wap_wsg_idm_ecid_wtls3 736
+#define OBJ_wap_wsg_idm_ecid_wtls3 OBJ_wap_wsg_idm_ecid,3L
+
+#define SN_wap_wsg_idm_ecid_wtls4 "wap-wsg-idm-ecid-wtls4"
+#define NID_wap_wsg_idm_ecid_wtls4 737
+#define OBJ_wap_wsg_idm_ecid_wtls4 OBJ_wap_wsg_idm_ecid,4L
+
+#define SN_wap_wsg_idm_ecid_wtls5 "wap-wsg-idm-ecid-wtls5"
+#define NID_wap_wsg_idm_ecid_wtls5 738
+#define OBJ_wap_wsg_idm_ecid_wtls5 OBJ_wap_wsg_idm_ecid,5L
+
+#define SN_wap_wsg_idm_ecid_wtls6 "wap-wsg-idm-ecid-wtls6"
+#define NID_wap_wsg_idm_ecid_wtls6 739
+#define OBJ_wap_wsg_idm_ecid_wtls6 OBJ_wap_wsg_idm_ecid,6L
+
+#define SN_wap_wsg_idm_ecid_wtls7 "wap-wsg-idm-ecid-wtls7"
+#define NID_wap_wsg_idm_ecid_wtls7 740
+#define OBJ_wap_wsg_idm_ecid_wtls7 OBJ_wap_wsg_idm_ecid,7L
+
+#define SN_wap_wsg_idm_ecid_wtls8 "wap-wsg-idm-ecid-wtls8"
+#define NID_wap_wsg_idm_ecid_wtls8 741
+#define OBJ_wap_wsg_idm_ecid_wtls8 OBJ_wap_wsg_idm_ecid,8L
+
+#define SN_wap_wsg_idm_ecid_wtls9 "wap-wsg-idm-ecid-wtls9"
+#define NID_wap_wsg_idm_ecid_wtls9 742
+#define OBJ_wap_wsg_idm_ecid_wtls9 OBJ_wap_wsg_idm_ecid,9L
+
+#define SN_wap_wsg_idm_ecid_wtls10 "wap-wsg-idm-ecid-wtls10"
+#define NID_wap_wsg_idm_ecid_wtls10 743
+#define OBJ_wap_wsg_idm_ecid_wtls10 OBJ_wap_wsg_idm_ecid,10L
+
+#define SN_wap_wsg_idm_ecid_wtls11 "wap-wsg-idm-ecid-wtls11"
+#define NID_wap_wsg_idm_ecid_wtls11 744
+#define OBJ_wap_wsg_idm_ecid_wtls11 OBJ_wap_wsg_idm_ecid,11L
+
+#define SN_wap_wsg_idm_ecid_wtls12 "wap-wsg-idm-ecid-wtls12"
+#define NID_wap_wsg_idm_ecid_wtls12 745
+#define OBJ_wap_wsg_idm_ecid_wtls12 OBJ_wap_wsg_idm_ecid,12L
+
+#define SN_cast5_cbc "CAST5-CBC"
+#define LN_cast5_cbc "cast5-cbc"
+#define NID_cast5_cbc 108
+#define OBJ_cast5_cbc OBJ_ISO_US,113533L,7L,66L,10L
+
+#define SN_cast5_ecb "CAST5-ECB"
+#define LN_cast5_ecb "cast5-ecb"
+#define NID_cast5_ecb 109
+
+#define SN_cast5_cfb64 "CAST5-CFB"
+#define LN_cast5_cfb64 "cast5-cfb"
+#define NID_cast5_cfb64 110
+
+#define SN_cast5_ofb64 "CAST5-OFB"
+#define LN_cast5_ofb64 "cast5-ofb"
+#define NID_cast5_ofb64 111
+
+#define LN_pbeWithMD5AndCast5_CBC "pbeWithMD5AndCast5CBC"
+#define NID_pbeWithMD5AndCast5_CBC 112
+#define OBJ_pbeWithMD5AndCast5_CBC OBJ_ISO_US,113533L,7L,66L,12L
+
+#define SN_id_PasswordBasedMAC "id-PasswordBasedMAC"
+#define LN_id_PasswordBasedMAC "password based MAC"
+#define NID_id_PasswordBasedMAC 782
+#define OBJ_id_PasswordBasedMAC OBJ_ISO_US,113533L,7L,66L,13L
+
+#define SN_id_DHBasedMac "id-DHBasedMac"
+#define LN_id_DHBasedMac "Diffie-Hellman based MAC"
+#define NID_id_DHBasedMac 783
+#define OBJ_id_DHBasedMac OBJ_ISO_US,113533L,7L,66L,30L
+
+#define SN_rsadsi "rsadsi"
+#define LN_rsadsi "RSA Data Security, Inc."
+#define NID_rsadsi 1
+#define OBJ_rsadsi OBJ_ISO_US,113549L
+
+#define SN_pkcs "pkcs"
+#define LN_pkcs "RSA Data Security, Inc. PKCS"
+#define NID_pkcs 2
+#define OBJ_pkcs OBJ_rsadsi,1L
+
+#define SN_pkcs1 "pkcs1"
+#define NID_pkcs1 186
+#define OBJ_pkcs1 OBJ_pkcs,1L
+
+#define LN_rsaEncryption "rsaEncryption"
+#define NID_rsaEncryption 6
+#define OBJ_rsaEncryption OBJ_pkcs1,1L
+
+#define SN_md2WithRSAEncryption "RSA-MD2"
+#define LN_md2WithRSAEncryption "md2WithRSAEncryption"
+#define NID_md2WithRSAEncryption 7
+#define OBJ_md2WithRSAEncryption OBJ_pkcs1,2L
+
+#define SN_md4WithRSAEncryption "RSA-MD4"
+#define LN_md4WithRSAEncryption "md4WithRSAEncryption"
+#define NID_md4WithRSAEncryption 396
+#define OBJ_md4WithRSAEncryption OBJ_pkcs1,3L
+
+#define SN_md5WithRSAEncryption "RSA-MD5"
+#define LN_md5WithRSAEncryption "md5WithRSAEncryption"
+#define NID_md5WithRSAEncryption 8
+#define OBJ_md5WithRSAEncryption OBJ_pkcs1,4L
+
+#define SN_sha1WithRSAEncryption "RSA-SHA1"
+#define LN_sha1WithRSAEncryption "sha1WithRSAEncryption"
+#define NID_sha1WithRSAEncryption 65
+#define OBJ_sha1WithRSAEncryption OBJ_pkcs1,5L
+
+#define SN_sha256WithRSAEncryption "RSA-SHA256"
+#define LN_sha256WithRSAEncryption "sha256WithRSAEncryption"
+#define NID_sha256WithRSAEncryption 668
+#define OBJ_sha256WithRSAEncryption OBJ_pkcs1,11L
+
+#define SN_sha384WithRSAEncryption "RSA-SHA384"
+#define LN_sha384WithRSAEncryption "sha384WithRSAEncryption"
+#define NID_sha384WithRSAEncryption 669
+#define OBJ_sha384WithRSAEncryption OBJ_pkcs1,12L
+
+#define SN_sha512WithRSAEncryption "RSA-SHA512"
+#define LN_sha512WithRSAEncryption "sha512WithRSAEncryption"
+#define NID_sha512WithRSAEncryption 670
+#define OBJ_sha512WithRSAEncryption OBJ_pkcs1,13L
+
+#define SN_sha224WithRSAEncryption "RSA-SHA224"
+#define LN_sha224WithRSAEncryption "sha224WithRSAEncryption"
+#define NID_sha224WithRSAEncryption 671
+#define OBJ_sha224WithRSAEncryption OBJ_pkcs1,14L
+
+#define SN_pkcs3 "pkcs3"
+#define NID_pkcs3 27
+#define OBJ_pkcs3 OBJ_pkcs,3L
+
+#define LN_dhKeyAgreement "dhKeyAgreement"
+#define NID_dhKeyAgreement 28
+#define OBJ_dhKeyAgreement OBJ_pkcs3,1L
+
+#define SN_pkcs5 "pkcs5"
+#define NID_pkcs5 187
+#define OBJ_pkcs5 OBJ_pkcs,5L
+
+#define SN_pbeWithMD2AndDES_CBC "PBE-MD2-DES"
+#define LN_pbeWithMD2AndDES_CBC "pbeWithMD2AndDES-CBC"
+#define NID_pbeWithMD2AndDES_CBC 9
+#define OBJ_pbeWithMD2AndDES_CBC OBJ_pkcs5,1L
+
+#define SN_pbeWithMD5AndDES_CBC "PBE-MD5-DES"
+#define LN_pbeWithMD5AndDES_CBC "pbeWithMD5AndDES-CBC"
+#define NID_pbeWithMD5AndDES_CBC 10
+#define OBJ_pbeWithMD5AndDES_CBC OBJ_pkcs5,3L
+
+#define SN_pbeWithMD2AndRC2_CBC "PBE-MD2-RC2-64"
+#define LN_pbeWithMD2AndRC2_CBC "pbeWithMD2AndRC2-CBC"
+#define NID_pbeWithMD2AndRC2_CBC 168
+#define OBJ_pbeWithMD2AndRC2_CBC OBJ_pkcs5,4L
+
+#define SN_pbeWithMD5AndRC2_CBC "PBE-MD5-RC2-64"
+#define LN_pbeWithMD5AndRC2_CBC "pbeWithMD5AndRC2-CBC"
+#define NID_pbeWithMD5AndRC2_CBC 169
+#define OBJ_pbeWithMD5AndRC2_CBC OBJ_pkcs5,6L
+
+#define SN_pbeWithSHA1AndDES_CBC "PBE-SHA1-DES"
+#define LN_pbeWithSHA1AndDES_CBC "pbeWithSHA1AndDES-CBC"
+#define NID_pbeWithSHA1AndDES_CBC 170
+#define OBJ_pbeWithSHA1AndDES_CBC OBJ_pkcs5,10L
+
+#define SN_pbeWithSHA1AndRC2_CBC "PBE-SHA1-RC2-64"
+#define LN_pbeWithSHA1AndRC2_CBC "pbeWithSHA1AndRC2-CBC"
+#define NID_pbeWithSHA1AndRC2_CBC 68
+#define OBJ_pbeWithSHA1AndRC2_CBC OBJ_pkcs5,11L
+
+#define LN_id_pbkdf2 "PBKDF2"
+#define NID_id_pbkdf2 69
+#define OBJ_id_pbkdf2 OBJ_pkcs5,12L
+
+#define LN_pbes2 "PBES2"
+#define NID_pbes2 161
+#define OBJ_pbes2 OBJ_pkcs5,13L
+
+#define LN_pbmac1 "PBMAC1"
+#define NID_pbmac1 162
+#define OBJ_pbmac1 OBJ_pkcs5,14L
+
+#define SN_pkcs7 "pkcs7"
+#define NID_pkcs7 20
+#define OBJ_pkcs7 OBJ_pkcs,7L
+
+#define LN_pkcs7_data "pkcs7-data"
+#define NID_pkcs7_data 21
+#define OBJ_pkcs7_data OBJ_pkcs7,1L
+
+#define LN_pkcs7_signed "pkcs7-signedData"
+#define NID_pkcs7_signed 22
+#define OBJ_pkcs7_signed OBJ_pkcs7,2L
+
+#define LN_pkcs7_enveloped "pkcs7-envelopedData"
+#define NID_pkcs7_enveloped 23
+#define OBJ_pkcs7_enveloped OBJ_pkcs7,3L
+
+#define LN_pkcs7_signedAndEnveloped "pkcs7-signedAndEnvelopedData"
+#define NID_pkcs7_signedAndEnveloped 24
+#define OBJ_pkcs7_signedAndEnveloped OBJ_pkcs7,4L
+
+#define LN_pkcs7_digest "pkcs7-digestData"
+#define NID_pkcs7_digest 25
+#define OBJ_pkcs7_digest OBJ_pkcs7,5L
+
+#define LN_pkcs7_encrypted "pkcs7-encryptedData"
+#define NID_pkcs7_encrypted 26
+#define OBJ_pkcs7_encrypted OBJ_pkcs7,6L
+
+#define SN_pkcs9 "pkcs9"
+#define NID_pkcs9 47
+#define OBJ_pkcs9 OBJ_pkcs,9L
+
+#define LN_pkcs9_emailAddress "emailAddress"
+#define NID_pkcs9_emailAddress 48
+#define OBJ_pkcs9_emailAddress OBJ_pkcs9,1L
+
+#define LN_pkcs9_unstructuredName "unstructuredName"
+#define NID_pkcs9_unstructuredName 49
+#define OBJ_pkcs9_unstructuredName OBJ_pkcs9,2L
+
+#define LN_pkcs9_contentType "contentType"
+#define NID_pkcs9_contentType 50
+#define OBJ_pkcs9_contentType OBJ_pkcs9,3L
+
+#define LN_pkcs9_messageDigest "messageDigest"
+#define NID_pkcs9_messageDigest 51
+#define OBJ_pkcs9_messageDigest OBJ_pkcs9,4L
+
+#define LN_pkcs9_signingTime "signingTime"
+#define NID_pkcs9_signingTime 52
+#define OBJ_pkcs9_signingTime OBJ_pkcs9,5L
+
+#define LN_pkcs9_countersignature "countersignature"
+#define NID_pkcs9_countersignature 53
+#define OBJ_pkcs9_countersignature OBJ_pkcs9,6L
+
+#define LN_pkcs9_challengePassword "challengePassword"
+#define NID_pkcs9_challengePassword 54
+#define OBJ_pkcs9_challengePassword OBJ_pkcs9,7L
+
+#define LN_pkcs9_unstructuredAddress "unstructuredAddress"
+#define NID_pkcs9_unstructuredAddress 55
+#define OBJ_pkcs9_unstructuredAddress OBJ_pkcs9,8L
+
+#define LN_pkcs9_extCertAttributes "extendedCertificateAttributes"
+#define NID_pkcs9_extCertAttributes 56
+#define OBJ_pkcs9_extCertAttributes OBJ_pkcs9,9L
+
+#define SN_ext_req "extReq"
+#define LN_ext_req "Extension Request"
+#define NID_ext_req 172
+#define OBJ_ext_req OBJ_pkcs9,14L
+
+#define SN_SMIMECapabilities "SMIME-CAPS"
+#define LN_SMIMECapabilities "S/MIME Capabilities"
+#define NID_SMIMECapabilities 167
+#define OBJ_SMIMECapabilities OBJ_pkcs9,15L
+
+#define SN_SMIME "SMIME"
+#define LN_SMIME "S/MIME"
+#define NID_SMIME 188
+#define OBJ_SMIME OBJ_pkcs9,16L
+
+#define SN_id_smime_mod "id-smime-mod"
+#define NID_id_smime_mod 189
+#define OBJ_id_smime_mod OBJ_SMIME,0L
+
+#define SN_id_smime_ct "id-smime-ct"
+#define NID_id_smime_ct 190
+#define OBJ_id_smime_ct OBJ_SMIME,1L
+
+#define SN_id_smime_aa "id-smime-aa"
+#define NID_id_smime_aa 191
+#define OBJ_id_smime_aa OBJ_SMIME,2L
+
+#define SN_id_smime_alg "id-smime-alg"
+#define NID_id_smime_alg 192
+#define OBJ_id_smime_alg OBJ_SMIME,3L
+
+#define SN_id_smime_cd "id-smime-cd"
+#define NID_id_smime_cd 193
+#define OBJ_id_smime_cd OBJ_SMIME,4L
+
+#define SN_id_smime_spq "id-smime-spq"
+#define NID_id_smime_spq 194
+#define OBJ_id_smime_spq OBJ_SMIME,5L
+
+#define SN_id_smime_cti "id-smime-cti"
+#define NID_id_smime_cti 195
+#define OBJ_id_smime_cti OBJ_SMIME,6L
+
+#define SN_id_smime_mod_cms "id-smime-mod-cms"
+#define NID_id_smime_mod_cms 196
+#define OBJ_id_smime_mod_cms OBJ_id_smime_mod,1L
+
+#define SN_id_smime_mod_ess "id-smime-mod-ess"
+#define NID_id_smime_mod_ess 197
+#define OBJ_id_smime_mod_ess OBJ_id_smime_mod,2L
+
+#define SN_id_smime_mod_oid "id-smime-mod-oid"
+#define NID_id_smime_mod_oid 198
+#define OBJ_id_smime_mod_oid OBJ_id_smime_mod,3L
+
+#define SN_id_smime_mod_msg_v3 "id-smime-mod-msg-v3"
+#define NID_id_smime_mod_msg_v3 199
+#define OBJ_id_smime_mod_msg_v3 OBJ_id_smime_mod,4L
+
+#define SN_id_smime_mod_ets_eSignature_88 "id-smime-mod-ets-eSignature-88"
+#define NID_id_smime_mod_ets_eSignature_88 200
+#define OBJ_id_smime_mod_ets_eSignature_88 OBJ_id_smime_mod,5L
+
+#define SN_id_smime_mod_ets_eSignature_97 "id-smime-mod-ets-eSignature-97"
+#define NID_id_smime_mod_ets_eSignature_97 201
+#define OBJ_id_smime_mod_ets_eSignature_97 OBJ_id_smime_mod,6L
+
+#define SN_id_smime_mod_ets_eSigPolicy_88 "id-smime-mod-ets-eSigPolicy-88"
+#define NID_id_smime_mod_ets_eSigPolicy_88 202
+#define OBJ_id_smime_mod_ets_eSigPolicy_88 OBJ_id_smime_mod,7L
+
+#define SN_id_smime_mod_ets_eSigPolicy_97 "id-smime-mod-ets-eSigPolicy-97"
+#define NID_id_smime_mod_ets_eSigPolicy_97 203
+#define OBJ_id_smime_mod_ets_eSigPolicy_97 OBJ_id_smime_mod,8L
+
+#define SN_id_smime_ct_receipt "id-smime-ct-receipt"
+#define NID_id_smime_ct_receipt 204
+#define OBJ_id_smime_ct_receipt OBJ_id_smime_ct,1L
+
+#define SN_id_smime_ct_authData "id-smime-ct-authData"
+#define NID_id_smime_ct_authData 205
+#define OBJ_id_smime_ct_authData OBJ_id_smime_ct,2L
+
+#define SN_id_smime_ct_publishCert "id-smime-ct-publishCert"
+#define NID_id_smime_ct_publishCert 206
+#define OBJ_id_smime_ct_publishCert OBJ_id_smime_ct,3L
+
+#define SN_id_smime_ct_TSTInfo "id-smime-ct-TSTInfo"
+#define NID_id_smime_ct_TSTInfo 207
+#define OBJ_id_smime_ct_TSTInfo OBJ_id_smime_ct,4L
+
+#define SN_id_smime_ct_TDTInfo "id-smime-ct-TDTInfo"
+#define NID_id_smime_ct_TDTInfo 208
+#define OBJ_id_smime_ct_TDTInfo OBJ_id_smime_ct,5L
+
+#define SN_id_smime_ct_contentInfo "id-smime-ct-contentInfo"
+#define NID_id_smime_ct_contentInfo 209
+#define OBJ_id_smime_ct_contentInfo OBJ_id_smime_ct,6L
+
+#define SN_id_smime_ct_DVCSRequestData "id-smime-ct-DVCSRequestData"
+#define NID_id_smime_ct_DVCSRequestData 210
+#define OBJ_id_smime_ct_DVCSRequestData OBJ_id_smime_ct,7L
+
+#define SN_id_smime_ct_DVCSResponseData "id-smime-ct-DVCSResponseData"
+#define NID_id_smime_ct_DVCSResponseData 211
+#define OBJ_id_smime_ct_DVCSResponseData OBJ_id_smime_ct,8L
+
+#define SN_id_smime_ct_compressedData "id-smime-ct-compressedData"
+#define NID_id_smime_ct_compressedData 786
+#define OBJ_id_smime_ct_compressedData OBJ_id_smime_ct,9L
+
+#define SN_id_ct_asciiTextWithCRLF "id-ct-asciiTextWithCRLF"
+#define NID_id_ct_asciiTextWithCRLF 787
+#define OBJ_id_ct_asciiTextWithCRLF OBJ_id_smime_ct,27L
+
+#define SN_id_smime_aa_receiptRequest "id-smime-aa-receiptRequest"
+#define NID_id_smime_aa_receiptRequest 212
+#define OBJ_id_smime_aa_receiptRequest OBJ_id_smime_aa,1L
+
+#define SN_id_smime_aa_securityLabel "id-smime-aa-securityLabel"
+#define NID_id_smime_aa_securityLabel 213
+#define OBJ_id_smime_aa_securityLabel OBJ_id_smime_aa,2L
+
+#define SN_id_smime_aa_mlExpandHistory "id-smime-aa-mlExpandHistory"
+#define NID_id_smime_aa_mlExpandHistory 214
+#define OBJ_id_smime_aa_mlExpandHistory OBJ_id_smime_aa,3L
+
+#define SN_id_smime_aa_contentHint "id-smime-aa-contentHint"
+#define NID_id_smime_aa_contentHint 215
+#define OBJ_id_smime_aa_contentHint OBJ_id_smime_aa,4L
+
+#define SN_id_smime_aa_msgSigDigest "id-smime-aa-msgSigDigest"
+#define NID_id_smime_aa_msgSigDigest 216
+#define OBJ_id_smime_aa_msgSigDigest OBJ_id_smime_aa,5L
+
+#define SN_id_smime_aa_encapContentType "id-smime-aa-encapContentType"
+#define NID_id_smime_aa_encapContentType 217
+#define OBJ_id_smime_aa_encapContentType OBJ_id_smime_aa,6L
+
+#define SN_id_smime_aa_contentIdentifier "id-smime-aa-contentIdentifier"
+#define NID_id_smime_aa_contentIdentifier 218
+#define OBJ_id_smime_aa_contentIdentifier OBJ_id_smime_aa,7L
+
+#define SN_id_smime_aa_macValue "id-smime-aa-macValue"
+#define NID_id_smime_aa_macValue 219
+#define OBJ_id_smime_aa_macValue OBJ_id_smime_aa,8L
+
+#define SN_id_smime_aa_equivalentLabels "id-smime-aa-equivalentLabels"
+#define NID_id_smime_aa_equivalentLabels 220
+#define OBJ_id_smime_aa_equivalentLabels OBJ_id_smime_aa,9L
+
+#define SN_id_smime_aa_contentReference "id-smime-aa-contentReference"
+#define NID_id_smime_aa_contentReference 221
+#define OBJ_id_smime_aa_contentReference OBJ_id_smime_aa,10L
+
+#define SN_id_smime_aa_encrypKeyPref "id-smime-aa-encrypKeyPref"
+#define NID_id_smime_aa_encrypKeyPref 222
+#define OBJ_id_smime_aa_encrypKeyPref OBJ_id_smime_aa,11L
+
+#define SN_id_smime_aa_signingCertificate "id-smime-aa-signingCertificate"
+#define NID_id_smime_aa_signingCertificate 223
+#define OBJ_id_smime_aa_signingCertificate OBJ_id_smime_aa,12L
+
+#define SN_id_smime_aa_smimeEncryptCerts "id-smime-aa-smimeEncryptCerts"
+#define NID_id_smime_aa_smimeEncryptCerts 224
+#define OBJ_id_smime_aa_smimeEncryptCerts OBJ_id_smime_aa,13L
+
+#define SN_id_smime_aa_timeStampToken "id-smime-aa-timeStampToken"
+#define NID_id_smime_aa_timeStampToken 225
+#define OBJ_id_smime_aa_timeStampToken OBJ_id_smime_aa,14L
+
+#define SN_id_smime_aa_ets_sigPolicyId "id-smime-aa-ets-sigPolicyId"
+#define NID_id_smime_aa_ets_sigPolicyId 226
+#define OBJ_id_smime_aa_ets_sigPolicyId OBJ_id_smime_aa,15L
+
+#define SN_id_smime_aa_ets_commitmentType "id-smime-aa-ets-commitmentType"
+#define NID_id_smime_aa_ets_commitmentType 227
+#define OBJ_id_smime_aa_ets_commitmentType OBJ_id_smime_aa,16L
+
+#define SN_id_smime_aa_ets_signerLocation "id-smime-aa-ets-signerLocation"
+#define NID_id_smime_aa_ets_signerLocation 228
+#define OBJ_id_smime_aa_ets_signerLocation OBJ_id_smime_aa,17L
+
+#define SN_id_smime_aa_ets_signerAttr "id-smime-aa-ets-signerAttr"
+#define NID_id_smime_aa_ets_signerAttr 229
+#define OBJ_id_smime_aa_ets_signerAttr OBJ_id_smime_aa,18L
+
+#define SN_id_smime_aa_ets_otherSigCert "id-smime-aa-ets-otherSigCert"
+#define NID_id_smime_aa_ets_otherSigCert 230
+#define OBJ_id_smime_aa_ets_otherSigCert OBJ_id_smime_aa,19L
+
+#define SN_id_smime_aa_ets_contentTimestamp "id-smime-aa-ets-contentTimestamp"
+#define NID_id_smime_aa_ets_contentTimestamp 231
+#define OBJ_id_smime_aa_ets_contentTimestamp OBJ_id_smime_aa,20L
+
+#define SN_id_smime_aa_ets_CertificateRefs "id-smime-aa-ets-CertificateRefs"
+#define NID_id_smime_aa_ets_CertificateRefs 232
+#define OBJ_id_smime_aa_ets_CertificateRefs OBJ_id_smime_aa,21L
+
+#define SN_id_smime_aa_ets_RevocationRefs "id-smime-aa-ets-RevocationRefs"
+#define NID_id_smime_aa_ets_RevocationRefs 233
+#define OBJ_id_smime_aa_ets_RevocationRefs OBJ_id_smime_aa,22L
+
+#define SN_id_smime_aa_ets_certValues "id-smime-aa-ets-certValues"
+#define NID_id_smime_aa_ets_certValues 234
+#define OBJ_id_smime_aa_ets_certValues OBJ_id_smime_aa,23L
+
+#define SN_id_smime_aa_ets_revocationValues "id-smime-aa-ets-revocationValues"
+#define NID_id_smime_aa_ets_revocationValues 235
+#define OBJ_id_smime_aa_ets_revocationValues OBJ_id_smime_aa,24L
+
+#define SN_id_smime_aa_ets_escTimeStamp "id-smime-aa-ets-escTimeStamp"
+#define NID_id_smime_aa_ets_escTimeStamp 236
+#define OBJ_id_smime_aa_ets_escTimeStamp OBJ_id_smime_aa,25L
+
+#define SN_id_smime_aa_ets_certCRLTimestamp "id-smime-aa-ets-certCRLTimestamp"
+#define NID_id_smime_aa_ets_certCRLTimestamp 237
+#define OBJ_id_smime_aa_ets_certCRLTimestamp OBJ_id_smime_aa,26L
+
+#define SN_id_smime_aa_ets_archiveTimeStamp "id-smime-aa-ets-archiveTimeStamp"
+#define NID_id_smime_aa_ets_archiveTimeStamp 238
+#define OBJ_id_smime_aa_ets_archiveTimeStamp OBJ_id_smime_aa,27L
+
+#define SN_id_smime_aa_signatureType "id-smime-aa-signatureType"
+#define NID_id_smime_aa_signatureType 239
+#define OBJ_id_smime_aa_signatureType OBJ_id_smime_aa,28L
+
+#define SN_id_smime_aa_dvcs_dvc "id-smime-aa-dvcs-dvc"
+#define NID_id_smime_aa_dvcs_dvc 240
+#define OBJ_id_smime_aa_dvcs_dvc OBJ_id_smime_aa,29L
+
+#define SN_id_smime_alg_ESDHwith3DES "id-smime-alg-ESDHwith3DES"
+#define NID_id_smime_alg_ESDHwith3DES 241
+#define OBJ_id_smime_alg_ESDHwith3DES OBJ_id_smime_alg,1L
+
+#define SN_id_smime_alg_ESDHwithRC2 "id-smime-alg-ESDHwithRC2"
+#define NID_id_smime_alg_ESDHwithRC2 242
+#define OBJ_id_smime_alg_ESDHwithRC2 OBJ_id_smime_alg,2L
+
+#define SN_id_smime_alg_3DESwrap "id-smime-alg-3DESwrap"
+#define NID_id_smime_alg_3DESwrap 243
+#define OBJ_id_smime_alg_3DESwrap OBJ_id_smime_alg,3L
+
+#define SN_id_smime_alg_RC2wrap "id-smime-alg-RC2wrap"
+#define NID_id_smime_alg_RC2wrap 244
+#define OBJ_id_smime_alg_RC2wrap OBJ_id_smime_alg,4L
+
+#define SN_id_smime_alg_ESDH "id-smime-alg-ESDH"
+#define NID_id_smime_alg_ESDH 245
+#define OBJ_id_smime_alg_ESDH OBJ_id_smime_alg,5L
+
+#define SN_id_smime_alg_CMS3DESwrap "id-smime-alg-CMS3DESwrap"
+#define NID_id_smime_alg_CMS3DESwrap 246
+#define OBJ_id_smime_alg_CMS3DESwrap OBJ_id_smime_alg,6L
+
+#define SN_id_smime_alg_CMSRC2wrap "id-smime-alg-CMSRC2wrap"
+#define NID_id_smime_alg_CMSRC2wrap 247
+#define OBJ_id_smime_alg_CMSRC2wrap OBJ_id_smime_alg,7L
+
+#define SN_id_smime_cd_ldap "id-smime-cd-ldap"
+#define NID_id_smime_cd_ldap 248
+#define OBJ_id_smime_cd_ldap OBJ_id_smime_cd,1L
+
+#define SN_id_smime_spq_ets_sqt_uri "id-smime-spq-ets-sqt-uri"
+#define NID_id_smime_spq_ets_sqt_uri 249
+#define OBJ_id_smime_spq_ets_sqt_uri OBJ_id_smime_spq,1L
+
+#define SN_id_smime_spq_ets_sqt_unotice "id-smime-spq-ets-sqt-unotice"
+#define NID_id_smime_spq_ets_sqt_unotice 250
+#define OBJ_id_smime_spq_ets_sqt_unotice OBJ_id_smime_spq,2L
+
+#define SN_id_smime_cti_ets_proofOfOrigin "id-smime-cti-ets-proofOfOrigin"
+#define NID_id_smime_cti_ets_proofOfOrigin 251
+#define OBJ_id_smime_cti_ets_proofOfOrigin OBJ_id_smime_cti,1L
+
+#define SN_id_smime_cti_ets_proofOfReceipt "id-smime-cti-ets-proofOfReceipt"
+#define NID_id_smime_cti_ets_proofOfReceipt 252
+#define OBJ_id_smime_cti_ets_proofOfReceipt OBJ_id_smime_cti,2L
+
+#define SN_id_smime_cti_ets_proofOfDelivery "id-smime-cti-ets-proofOfDelivery"
+#define NID_id_smime_cti_ets_proofOfDelivery 253
+#define OBJ_id_smime_cti_ets_proofOfDelivery OBJ_id_smime_cti,3L
+
+#define SN_id_smime_cti_ets_proofOfSender "id-smime-cti-ets-proofOfSender"
+#define NID_id_smime_cti_ets_proofOfSender 254
+#define OBJ_id_smime_cti_ets_proofOfSender OBJ_id_smime_cti,4L
+
+#define SN_id_smime_cti_ets_proofOfApproval "id-smime-cti-ets-proofOfApproval"
+#define NID_id_smime_cti_ets_proofOfApproval 255
+#define OBJ_id_smime_cti_ets_proofOfApproval OBJ_id_smime_cti,5L
+
+#define SN_id_smime_cti_ets_proofOfCreation "id-smime-cti-ets-proofOfCreation"
+#define NID_id_smime_cti_ets_proofOfCreation 256
+#define OBJ_id_smime_cti_ets_proofOfCreation OBJ_id_smime_cti,6L
+
+#define LN_friendlyName "friendlyName"
+#define NID_friendlyName 156
+#define OBJ_friendlyName OBJ_pkcs9,20L
+
+#define LN_localKeyID "localKeyID"
+#define NID_localKeyID 157
+#define OBJ_localKeyID OBJ_pkcs9,21L
+
+#define SN_ms_csp_name "CSPName"
+#define LN_ms_csp_name "Microsoft CSP Name"
+#define NID_ms_csp_name 417
+#define OBJ_ms_csp_name 1L,3L,6L,1L,4L,1L,311L,17L,1L
+
+#define SN_LocalKeySet "LocalKeySet"
+#define LN_LocalKeySet "Microsoft Local Key set"
+#define NID_LocalKeySet 856
+#define OBJ_LocalKeySet 1L,3L,6L,1L,4L,1L,311L,17L,2L
+
+#define OBJ_certTypes OBJ_pkcs9,22L
+
+#define LN_x509Certificate "x509Certificate"
+#define NID_x509Certificate 158
+#define OBJ_x509Certificate OBJ_certTypes,1L
+
+#define LN_sdsiCertificate "sdsiCertificate"
+#define NID_sdsiCertificate 159
+#define OBJ_sdsiCertificate OBJ_certTypes,2L
+
+#define OBJ_crlTypes OBJ_pkcs9,23L
+
+#define LN_x509Crl "x509Crl"
+#define NID_x509Crl 160
+#define OBJ_x509Crl OBJ_crlTypes,1L
+
+#define OBJ_pkcs12 OBJ_pkcs,12L
+
+#define OBJ_pkcs12_pbeids OBJ_pkcs12,1L
+
+#define SN_pbe_WithSHA1And128BitRC4 "PBE-SHA1-RC4-128"
+#define LN_pbe_WithSHA1And128BitRC4 "pbeWithSHA1And128BitRC4"
+#define NID_pbe_WithSHA1And128BitRC4 144
+#define OBJ_pbe_WithSHA1And128BitRC4 OBJ_pkcs12_pbeids,1L
+
+#define SN_pbe_WithSHA1And40BitRC4 "PBE-SHA1-RC4-40"
+#define LN_pbe_WithSHA1And40BitRC4 "pbeWithSHA1And40BitRC4"
+#define NID_pbe_WithSHA1And40BitRC4 145
+#define OBJ_pbe_WithSHA1And40BitRC4 OBJ_pkcs12_pbeids,2L
+
+#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC "PBE-SHA1-3DES"
+#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC "pbeWithSHA1And3-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146
+#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC OBJ_pkcs12_pbeids,3L
+
+#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC "PBE-SHA1-2DES"
+#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC "pbeWithSHA1And2-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147
+#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC OBJ_pkcs12_pbeids,4L
+
+#define SN_pbe_WithSHA1And128BitRC2_CBC "PBE-SHA1-RC2-128"
+#define LN_pbe_WithSHA1And128BitRC2_CBC "pbeWithSHA1And128BitRC2-CBC"
+#define NID_pbe_WithSHA1And128BitRC2_CBC 148
+#define OBJ_pbe_WithSHA1And128BitRC2_CBC OBJ_pkcs12_pbeids,5L
+
+#define SN_pbe_WithSHA1And40BitRC2_CBC "PBE-SHA1-RC2-40"
+#define LN_pbe_WithSHA1And40BitRC2_CBC "pbeWithSHA1And40BitRC2-CBC"
+#define NID_pbe_WithSHA1And40BitRC2_CBC 149
+#define OBJ_pbe_WithSHA1And40BitRC2_CBC OBJ_pkcs12_pbeids,6L
+
+#define OBJ_pkcs12_Version1 OBJ_pkcs12,10L
+
+#define OBJ_pkcs12_BagIds OBJ_pkcs12_Version1,1L
+
+#define LN_keyBag "keyBag"
+#define NID_keyBag 150
+#define OBJ_keyBag OBJ_pkcs12_BagIds,1L
+
+#define LN_pkcs8ShroudedKeyBag "pkcs8ShroudedKeyBag"
+#define NID_pkcs8ShroudedKeyBag 151
+#define OBJ_pkcs8ShroudedKeyBag OBJ_pkcs12_BagIds,2L
+
+#define LN_certBag "certBag"
+#define NID_certBag 152
+#define OBJ_certBag OBJ_pkcs12_BagIds,3L
+
+#define LN_crlBag "crlBag"
+#define NID_crlBag 153
+#define OBJ_crlBag OBJ_pkcs12_BagIds,4L
+
+#define LN_secretBag "secretBag"
+#define NID_secretBag 154
+#define OBJ_secretBag OBJ_pkcs12_BagIds,5L
+
+#define LN_safeContentsBag "safeContentsBag"
+#define NID_safeContentsBag 155
+#define OBJ_safeContentsBag OBJ_pkcs12_BagIds,6L
+
+#define SN_md2 "MD2"
+#define LN_md2 "md2"
+#define NID_md2 3
+#define OBJ_md2 OBJ_rsadsi,2L,2L
+
+#define SN_md4 "MD4"
+#define LN_md4 "md4"
+#define NID_md4 257
+#define OBJ_md4 OBJ_rsadsi,2L,4L
+
+#define SN_md5 "MD5"
+#define LN_md5 "md5"
+#define NID_md5 4
+#define OBJ_md5 OBJ_rsadsi,2L,5L
+
+#define SN_md5_sha1 "MD5-SHA1"
+#define LN_md5_sha1 "md5-sha1"
+#define NID_md5_sha1 114
+
+#define LN_hmacWithMD5 "hmacWithMD5"
+#define NID_hmacWithMD5 797
+#define OBJ_hmacWithMD5 OBJ_rsadsi,2L,6L
+
+#define LN_hmacWithSHA1 "hmacWithSHA1"
+#define NID_hmacWithSHA1 163
+#define OBJ_hmacWithSHA1 OBJ_rsadsi,2L,7L
+
+#define LN_hmacWithSHA224 "hmacWithSHA224"
+#define NID_hmacWithSHA224 798
+#define OBJ_hmacWithSHA224 OBJ_rsadsi,2L,8L
+
+#define LN_hmacWithSHA256 "hmacWithSHA256"
+#define NID_hmacWithSHA256 799
+#define OBJ_hmacWithSHA256 OBJ_rsadsi,2L,9L
+
+#define LN_hmacWithSHA384 "hmacWithSHA384"
+#define NID_hmacWithSHA384 800
+#define OBJ_hmacWithSHA384 OBJ_rsadsi,2L,10L
+
+#define LN_hmacWithSHA512 "hmacWithSHA512"
+#define NID_hmacWithSHA512 801
+#define OBJ_hmacWithSHA512 OBJ_rsadsi,2L,11L
+
+#define SN_rc2_cbc "RC2-CBC"
+#define LN_rc2_cbc "rc2-cbc"
+#define NID_rc2_cbc 37
+#define OBJ_rc2_cbc OBJ_rsadsi,3L,2L
+
+#define SN_rc2_ecb "RC2-ECB"
+#define LN_rc2_ecb "rc2-ecb"
+#define NID_rc2_ecb 38
+
+#define SN_rc2_cfb64 "RC2-CFB"
+#define LN_rc2_cfb64 "rc2-cfb"
+#define NID_rc2_cfb64 39
+
+#define SN_rc2_ofb64 "RC2-OFB"
+#define LN_rc2_ofb64 "rc2-ofb"
+#define NID_rc2_ofb64 40
+
+#define SN_rc2_40_cbc "RC2-40-CBC"
+#define LN_rc2_40_cbc "rc2-40-cbc"
+#define NID_rc2_40_cbc 98
+
+#define SN_rc2_64_cbc "RC2-64-CBC"
+#define LN_rc2_64_cbc "rc2-64-cbc"
+#define NID_rc2_64_cbc 166
+
+#define SN_rc4 "RC4"
+#define LN_rc4 "rc4"
+#define NID_rc4 5
+#define OBJ_rc4 OBJ_rsadsi,3L,4L
+
+#define SN_rc4_40 "RC4-40"
+#define LN_rc4_40 "rc4-40"
+#define NID_rc4_40 97
+
+#define SN_des_ede3_cbc "DES-EDE3-CBC"
+#define LN_des_ede3_cbc "des-ede3-cbc"
+#define NID_des_ede3_cbc 44
+#define OBJ_des_ede3_cbc OBJ_rsadsi,3L,7L
+
+#define SN_rc5_cbc "RC5-CBC"
+#define LN_rc5_cbc "rc5-cbc"
+#define NID_rc5_cbc 120
+#define OBJ_rc5_cbc OBJ_rsadsi,3L,8L
+
+#define SN_rc5_ecb "RC5-ECB"
+#define LN_rc5_ecb "rc5-ecb"
+#define NID_rc5_ecb 121
+
+#define SN_rc5_cfb64 "RC5-CFB"
+#define LN_rc5_cfb64 "rc5-cfb"
+#define NID_rc5_cfb64 122
+
+#define SN_rc5_ofb64 "RC5-OFB"
+#define LN_rc5_ofb64 "rc5-ofb"
+#define NID_rc5_ofb64 123
+
+#define SN_ms_ext_req "msExtReq"
+#define LN_ms_ext_req "Microsoft Extension Request"
+#define NID_ms_ext_req 171
+#define OBJ_ms_ext_req 1L,3L,6L,1L,4L,1L,311L,2L,1L,14L
+
+#define SN_ms_code_ind "msCodeInd"
+#define LN_ms_code_ind "Microsoft Individual Code Signing"
+#define NID_ms_code_ind 134
+#define OBJ_ms_code_ind 1L,3L,6L,1L,4L,1L,311L,2L,1L,21L
+
+#define SN_ms_code_com "msCodeCom"
+#define LN_ms_code_com "Microsoft Commercial Code Signing"
+#define NID_ms_code_com 135
+#define OBJ_ms_code_com 1L,3L,6L,1L,4L,1L,311L,2L,1L,22L
+
+#define SN_ms_ctl_sign "msCTLSign"
+#define LN_ms_ctl_sign "Microsoft Trust List Signing"
+#define NID_ms_ctl_sign 136
+#define OBJ_ms_ctl_sign 1L,3L,6L,1L,4L,1L,311L,10L,3L,1L
+
+#define SN_ms_sgc "msSGC"
+#define LN_ms_sgc "Microsoft Server Gated Crypto"
+#define NID_ms_sgc 137
+#define OBJ_ms_sgc 1L,3L,6L,1L,4L,1L,311L,10L,3L,3L
+
+#define SN_ms_efs "msEFS"
+#define LN_ms_efs "Microsoft Encrypted File System"
+#define NID_ms_efs 138
+#define OBJ_ms_efs 1L,3L,6L,1L,4L,1L,311L,10L,3L,4L
+
+#define SN_ms_smartcard_login "msSmartcardLogin"
+#define LN_ms_smartcard_login "Microsoft Smartcardlogin"
+#define NID_ms_smartcard_login 648
+#define OBJ_ms_smartcard_login 1L,3L,6L,1L,4L,1L,311L,20L,2L,2L
+
+#define SN_ms_upn "msUPN"
+#define LN_ms_upn "Microsoft Universal Principal Name"
+#define NID_ms_upn 649
+#define OBJ_ms_upn 1L,3L,6L,1L,4L,1L,311L,20L,2L,3L
+
+#define SN_idea_cbc "IDEA-CBC"
+#define LN_idea_cbc "idea-cbc"
+#define NID_idea_cbc 34
+#define OBJ_idea_cbc 1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L
+
+#define SN_idea_ecb "IDEA-ECB"
+#define LN_idea_ecb "idea-ecb"
+#define NID_idea_ecb 36
+
+#define SN_idea_cfb64 "IDEA-CFB"
+#define LN_idea_cfb64 "idea-cfb"
+#define NID_idea_cfb64 35
+
+#define SN_idea_ofb64 "IDEA-OFB"
+#define LN_idea_ofb64 "idea-ofb"
+#define NID_idea_ofb64 46
+
+#define SN_bf_cbc "BF-CBC"
+#define LN_bf_cbc "bf-cbc"
+#define NID_bf_cbc 91
+#define OBJ_bf_cbc 1L,3L,6L,1L,4L,1L,3029L,1L,2L
+
+#define SN_bf_ecb "BF-ECB"
+#define LN_bf_ecb "bf-ecb"
+#define NID_bf_ecb 92
+
+#define SN_bf_cfb64 "BF-CFB"
+#define LN_bf_cfb64 "bf-cfb"
+#define NID_bf_cfb64 93
+
+#define SN_bf_ofb64 "BF-OFB"
+#define LN_bf_ofb64 "bf-ofb"
+#define NID_bf_ofb64 94
+
+#define SN_id_pkix "PKIX"
+#define NID_id_pkix 127
+#define OBJ_id_pkix 1L,3L,6L,1L,5L,5L,7L
+
+#define SN_id_pkix_mod "id-pkix-mod"
+#define NID_id_pkix_mod 258
+#define OBJ_id_pkix_mod OBJ_id_pkix,0L
+
+#define SN_id_pe "id-pe"
+#define NID_id_pe 175
+#define OBJ_id_pe OBJ_id_pkix,1L
+
+#define SN_id_qt "id-qt"
+#define NID_id_qt 259
+#define OBJ_id_qt OBJ_id_pkix,2L
+
+#define SN_id_kp "id-kp"
+#define NID_id_kp 128
+#define OBJ_id_kp OBJ_id_pkix,3L
+
+#define SN_id_it "id-it"
+#define NID_id_it 260
+#define OBJ_id_it OBJ_id_pkix,4L
+
+#define SN_id_pkip "id-pkip"
+#define NID_id_pkip 261
+#define OBJ_id_pkip OBJ_id_pkix,5L
+
+#define SN_id_alg "id-alg"
+#define NID_id_alg 262
+#define OBJ_id_alg OBJ_id_pkix,6L
+
+#define SN_id_cmc "id-cmc"
+#define NID_id_cmc 263
+#define OBJ_id_cmc OBJ_id_pkix,7L
+
+#define SN_id_on "id-on"
+#define NID_id_on 264
+#define OBJ_id_on OBJ_id_pkix,8L
+
+#define SN_id_pda "id-pda"
+#define NID_id_pda 265
+#define OBJ_id_pda OBJ_id_pkix,9L
+
+#define SN_id_aca "id-aca"
+#define NID_id_aca 266
+#define OBJ_id_aca OBJ_id_pkix,10L
+
+#define SN_id_qcs "id-qcs"
+#define NID_id_qcs 267
+#define OBJ_id_qcs OBJ_id_pkix,11L
+
+#define SN_id_cct "id-cct"
+#define NID_id_cct 268
+#define OBJ_id_cct OBJ_id_pkix,12L
+
+#define SN_id_ppl "id-ppl"
+#define NID_id_ppl 662
+#define OBJ_id_ppl OBJ_id_pkix,21L
+
+#define SN_id_ad "id-ad"
+#define NID_id_ad 176
+#define OBJ_id_ad OBJ_id_pkix,48L
+
+#define SN_id_pkix1_explicit_88 "id-pkix1-explicit-88"
+#define NID_id_pkix1_explicit_88 269
+#define OBJ_id_pkix1_explicit_88 OBJ_id_pkix_mod,1L
+
+#define SN_id_pkix1_implicit_88 "id-pkix1-implicit-88"
+#define NID_id_pkix1_implicit_88 270
+#define OBJ_id_pkix1_implicit_88 OBJ_id_pkix_mod,2L
+
+#define SN_id_pkix1_explicit_93 "id-pkix1-explicit-93"
+#define NID_id_pkix1_explicit_93 271
+#define OBJ_id_pkix1_explicit_93 OBJ_id_pkix_mod,3L
+
+#define SN_id_pkix1_implicit_93 "id-pkix1-implicit-93"
+#define NID_id_pkix1_implicit_93 272
+#define OBJ_id_pkix1_implicit_93 OBJ_id_pkix_mod,4L
+
+#define SN_id_mod_crmf "id-mod-crmf"
+#define NID_id_mod_crmf 273
+#define OBJ_id_mod_crmf OBJ_id_pkix_mod,5L
+
+#define SN_id_mod_cmc "id-mod-cmc"
+#define NID_id_mod_cmc 274
+#define OBJ_id_mod_cmc OBJ_id_pkix_mod,6L
+
+#define SN_id_mod_kea_profile_88 "id-mod-kea-profile-88"
+#define NID_id_mod_kea_profile_88 275
+#define OBJ_id_mod_kea_profile_88 OBJ_id_pkix_mod,7L
+
+#define SN_id_mod_kea_profile_93 "id-mod-kea-profile-93"
+#define NID_id_mod_kea_profile_93 276
+#define OBJ_id_mod_kea_profile_93 OBJ_id_pkix_mod,8L
+
+#define SN_id_mod_cmp "id-mod-cmp"
+#define NID_id_mod_cmp 277
+#define OBJ_id_mod_cmp OBJ_id_pkix_mod,9L
+
+#define SN_id_mod_qualified_cert_88 "id-mod-qualified-cert-88"
+#define NID_id_mod_qualified_cert_88 278
+#define OBJ_id_mod_qualified_cert_88 OBJ_id_pkix_mod,10L
+
+#define SN_id_mod_qualified_cert_93 "id-mod-qualified-cert-93"
+#define NID_id_mod_qualified_cert_93 279
+#define OBJ_id_mod_qualified_cert_93 OBJ_id_pkix_mod,11L
+
+#define SN_id_mod_attribute_cert "id-mod-attribute-cert"
+#define NID_id_mod_attribute_cert 280
+#define OBJ_id_mod_attribute_cert OBJ_id_pkix_mod,12L
+
+#define SN_id_mod_timestamp_protocol "id-mod-timestamp-protocol"
+#define NID_id_mod_timestamp_protocol 281
+#define OBJ_id_mod_timestamp_protocol OBJ_id_pkix_mod,13L
+
+#define SN_id_mod_ocsp "id-mod-ocsp"
+#define NID_id_mod_ocsp 282
+#define OBJ_id_mod_ocsp OBJ_id_pkix_mod,14L
+
+#define SN_id_mod_dvcs "id-mod-dvcs"
+#define NID_id_mod_dvcs 283
+#define OBJ_id_mod_dvcs OBJ_id_pkix_mod,15L
+
+#define SN_id_mod_cmp2000 "id-mod-cmp2000"
+#define NID_id_mod_cmp2000 284
+#define OBJ_id_mod_cmp2000 OBJ_id_pkix_mod,16L
+
+#define SN_info_access "authorityInfoAccess"
+#define LN_info_access "Authority Information Access"
+#define NID_info_access 177
+#define OBJ_info_access OBJ_id_pe,1L
+
+#define SN_biometricInfo "biometricInfo"
+#define LN_biometricInfo "Biometric Info"
+#define NID_biometricInfo 285
+#define OBJ_biometricInfo OBJ_id_pe,2L
+
+#define SN_qcStatements "qcStatements"
+#define NID_qcStatements 286
+#define OBJ_qcStatements OBJ_id_pe,3L
+
+#define SN_ac_auditEntity "ac-auditEntity"
+#define NID_ac_auditEntity 287
+#define OBJ_ac_auditEntity OBJ_id_pe,4L
+
+#define SN_ac_targeting "ac-targeting"
+#define NID_ac_targeting 288
+#define OBJ_ac_targeting OBJ_id_pe,5L
+
+#define SN_aaControls "aaControls"
+#define NID_aaControls 289
+#define OBJ_aaControls OBJ_id_pe,6L
+
+#define SN_sbgp_ipAddrBlock "sbgp-ipAddrBlock"
+#define NID_sbgp_ipAddrBlock 290
+#define OBJ_sbgp_ipAddrBlock OBJ_id_pe,7L
+
+#define SN_sbgp_autonomousSysNum "sbgp-autonomousSysNum"
+#define NID_sbgp_autonomousSysNum 291
+#define OBJ_sbgp_autonomousSysNum OBJ_id_pe,8L
+
+#define SN_sbgp_routerIdentifier "sbgp-routerIdentifier"
+#define NID_sbgp_routerIdentifier 292
+#define OBJ_sbgp_routerIdentifier OBJ_id_pe,9L
+
+#define SN_ac_proxying "ac-proxying"
+#define NID_ac_proxying 397
+#define OBJ_ac_proxying OBJ_id_pe,10L
+
+#define SN_sinfo_access "subjectInfoAccess"
+#define LN_sinfo_access "Subject Information Access"
+#define NID_sinfo_access 398
+#define OBJ_sinfo_access OBJ_id_pe,11L
+
+#define SN_proxyCertInfo "proxyCertInfo"
+#define LN_proxyCertInfo "Proxy Certificate Information"
+#define NID_proxyCertInfo 663
+#define OBJ_proxyCertInfo OBJ_id_pe,14L
+
+#define SN_id_qt_cps "id-qt-cps"
+#define LN_id_qt_cps "Policy Qualifier CPS"
+#define NID_id_qt_cps 164
+#define OBJ_id_qt_cps OBJ_id_qt,1L
+
+#define SN_id_qt_unotice "id-qt-unotice"
+#define LN_id_qt_unotice "Policy Qualifier User Notice"
+#define NID_id_qt_unotice 165
+#define OBJ_id_qt_unotice OBJ_id_qt,2L
+
+#define SN_textNotice "textNotice"
+#define NID_textNotice 293
+#define OBJ_textNotice OBJ_id_qt,3L
+
+#define SN_server_auth "serverAuth"
+#define LN_server_auth "TLS Web Server Authentication"
+#define NID_server_auth 129
+#define OBJ_server_auth OBJ_id_kp,1L
+
+#define SN_client_auth "clientAuth"
+#define LN_client_auth "TLS Web Client Authentication"
+#define NID_client_auth 130
+#define OBJ_client_auth OBJ_id_kp,2L
+
+#define SN_code_sign "codeSigning"
+#define LN_code_sign "Code Signing"
+#define NID_code_sign 131
+#define OBJ_code_sign OBJ_id_kp,3L
+
+#define SN_email_protect "emailProtection"
+#define LN_email_protect "E-mail Protection"
+#define NID_email_protect 132
+#define OBJ_email_protect OBJ_id_kp,4L
+
+#define SN_ipsecEndSystem "ipsecEndSystem"
+#define LN_ipsecEndSystem "IPSec End System"
+#define NID_ipsecEndSystem 294
+#define OBJ_ipsecEndSystem OBJ_id_kp,5L
+
+#define SN_ipsecTunnel "ipsecTunnel"
+#define LN_ipsecTunnel "IPSec Tunnel"
+#define NID_ipsecTunnel 295
+#define OBJ_ipsecTunnel OBJ_id_kp,6L
+
+#define SN_ipsecUser "ipsecUser"
+#define LN_ipsecUser "IPSec User"
+#define NID_ipsecUser 296
+#define OBJ_ipsecUser OBJ_id_kp,7L
+
+#define SN_time_stamp "timeStamping"
+#define LN_time_stamp "Time Stamping"
+#define NID_time_stamp 133
+#define OBJ_time_stamp OBJ_id_kp,8L
+
+#define SN_OCSP_sign "OCSPSigning"
+#define LN_OCSP_sign "OCSP Signing"
+#define NID_OCSP_sign 180
+#define OBJ_OCSP_sign OBJ_id_kp,9L
+
+#define SN_dvcs "DVCS"
+#define LN_dvcs "dvcs"
+#define NID_dvcs 297
+#define OBJ_dvcs OBJ_id_kp,10L
+
+#define SN_id_it_caProtEncCert "id-it-caProtEncCert"
+#define NID_id_it_caProtEncCert 298
+#define OBJ_id_it_caProtEncCert OBJ_id_it,1L
+
+#define SN_id_it_signKeyPairTypes "id-it-signKeyPairTypes"
+#define NID_id_it_signKeyPairTypes 299
+#define OBJ_id_it_signKeyPairTypes OBJ_id_it,2L
+
+#define SN_id_it_encKeyPairTypes "id-it-encKeyPairTypes"
+#define NID_id_it_encKeyPairTypes 300
+#define OBJ_id_it_encKeyPairTypes OBJ_id_it,3L
+
+#define SN_id_it_preferredSymmAlg "id-it-preferredSymmAlg"
+#define NID_id_it_preferredSymmAlg 301
+#define OBJ_id_it_preferredSymmAlg OBJ_id_it,4L
+
+#define SN_id_it_caKeyUpdateInfo "id-it-caKeyUpdateInfo"
+#define NID_id_it_caKeyUpdateInfo 302
+#define OBJ_id_it_caKeyUpdateInfo OBJ_id_it,5L
+
+#define SN_id_it_currentCRL "id-it-currentCRL"
+#define NID_id_it_currentCRL 303
+#define OBJ_id_it_currentCRL OBJ_id_it,6L
+
+#define SN_id_it_unsupportedOIDs "id-it-unsupportedOIDs"
+#define NID_id_it_unsupportedOIDs 304
+#define OBJ_id_it_unsupportedOIDs OBJ_id_it,7L
+
+#define SN_id_it_subscriptionRequest "id-it-subscriptionRequest"
+#define NID_id_it_subscriptionRequest 305
+#define OBJ_id_it_subscriptionRequest OBJ_id_it,8L
+
+#define SN_id_it_subscriptionResponse "id-it-subscriptionResponse"
+#define NID_id_it_subscriptionResponse 306
+#define OBJ_id_it_subscriptionResponse OBJ_id_it,9L
+
+#define SN_id_it_keyPairParamReq "id-it-keyPairParamReq"
+#define NID_id_it_keyPairParamReq 307
+#define OBJ_id_it_keyPairParamReq OBJ_id_it,10L
+
+#define SN_id_it_keyPairParamRep "id-it-keyPairParamRep"
+#define NID_id_it_keyPairParamRep 308
+#define OBJ_id_it_keyPairParamRep OBJ_id_it,11L
+
+#define SN_id_it_revPassphrase "id-it-revPassphrase"
+#define NID_id_it_revPassphrase 309
+#define OBJ_id_it_revPassphrase OBJ_id_it,12L
+
+#define SN_id_it_implicitConfirm "id-it-implicitConfirm"
+#define NID_id_it_implicitConfirm 310
+#define OBJ_id_it_implicitConfirm OBJ_id_it,13L
+
+#define SN_id_it_confirmWaitTime "id-it-confirmWaitTime"
+#define NID_id_it_confirmWaitTime 311
+#define OBJ_id_it_confirmWaitTime OBJ_id_it,14L
+
+#define SN_id_it_origPKIMessage "id-it-origPKIMessage"
+#define NID_id_it_origPKIMessage 312
+#define OBJ_id_it_origPKIMessage OBJ_id_it,15L
+
+#define SN_id_it_suppLangTags "id-it-suppLangTags"
+#define NID_id_it_suppLangTags 784
+#define OBJ_id_it_suppLangTags OBJ_id_it,16L
+
+#define SN_id_regCtrl "id-regCtrl"
+#define NID_id_regCtrl 313
+#define OBJ_id_regCtrl OBJ_id_pkip,1L
+
+#define SN_id_regInfo "id-regInfo"
+#define NID_id_regInfo 314
+#define OBJ_id_regInfo OBJ_id_pkip,2L
+
+#define SN_id_regCtrl_regToken "id-regCtrl-regToken"
+#define NID_id_regCtrl_regToken 315
+#define OBJ_id_regCtrl_regToken OBJ_id_regCtrl,1L
+
+#define SN_id_regCtrl_authenticator "id-regCtrl-authenticator"
+#define NID_id_regCtrl_authenticator 316
+#define OBJ_id_regCtrl_authenticator OBJ_id_regCtrl,2L
+
+#define SN_id_regCtrl_pkiPublicationInfo "id-regCtrl-pkiPublicationInfo"
+#define NID_id_regCtrl_pkiPublicationInfo 317
+#define OBJ_id_regCtrl_pkiPublicationInfo OBJ_id_regCtrl,3L
+
+#define SN_id_regCtrl_pkiArchiveOptions "id-regCtrl-pkiArchiveOptions"
+#define NID_id_regCtrl_pkiArchiveOptions 318
+#define OBJ_id_regCtrl_pkiArchiveOptions OBJ_id_regCtrl,4L
+
+#define SN_id_regCtrl_oldCertID "id-regCtrl-oldCertID"
+#define NID_id_regCtrl_oldCertID 319
+#define OBJ_id_regCtrl_oldCertID OBJ_id_regCtrl,5L
+
+#define SN_id_regCtrl_protocolEncrKey "id-regCtrl-protocolEncrKey"
+#define NID_id_regCtrl_protocolEncrKey 320
+#define OBJ_id_regCtrl_protocolEncrKey OBJ_id_regCtrl,6L
+
+#define SN_id_regInfo_utf8Pairs "id-regInfo-utf8Pairs"
+#define NID_id_regInfo_utf8Pairs 321
+#define OBJ_id_regInfo_utf8Pairs OBJ_id_regInfo,1L
+
+#define SN_id_regInfo_certReq "id-regInfo-certReq"
+#define NID_id_regInfo_certReq 322
+#define OBJ_id_regInfo_certReq OBJ_id_regInfo,2L
+
+#define SN_id_alg_des40 "id-alg-des40"
+#define NID_id_alg_des40 323
+#define OBJ_id_alg_des40 OBJ_id_alg,1L
+
+#define SN_id_alg_noSignature "id-alg-noSignature"
+#define NID_id_alg_noSignature 324
+#define OBJ_id_alg_noSignature OBJ_id_alg,2L
+
+#define SN_id_alg_dh_sig_hmac_sha1 "id-alg-dh-sig-hmac-sha1"
+#define NID_id_alg_dh_sig_hmac_sha1 325
+#define OBJ_id_alg_dh_sig_hmac_sha1 OBJ_id_alg,3L
+
+#define SN_id_alg_dh_pop "id-alg-dh-pop"
+#define NID_id_alg_dh_pop 326
+#define OBJ_id_alg_dh_pop OBJ_id_alg,4L
+
+#define SN_id_cmc_statusInfo "id-cmc-statusInfo"
+#define NID_id_cmc_statusInfo 327
+#define OBJ_id_cmc_statusInfo OBJ_id_cmc,1L
+
+#define SN_id_cmc_identification "id-cmc-identification"
+#define NID_id_cmc_identification 328
+#define OBJ_id_cmc_identification OBJ_id_cmc,2L
+
+#define SN_id_cmc_identityProof "id-cmc-identityProof"
+#define NID_id_cmc_identityProof 329
+#define OBJ_id_cmc_identityProof OBJ_id_cmc,3L
+
+#define SN_id_cmc_dataReturn "id-cmc-dataReturn"
+#define NID_id_cmc_dataReturn 330
+#define OBJ_id_cmc_dataReturn OBJ_id_cmc,4L
+
+#define SN_id_cmc_transactionId "id-cmc-transactionId"
+#define NID_id_cmc_transactionId 331
+#define OBJ_id_cmc_transactionId OBJ_id_cmc,5L
+
+#define SN_id_cmc_senderNonce "id-cmc-senderNonce"
+#define NID_id_cmc_senderNonce 332
+#define OBJ_id_cmc_senderNonce OBJ_id_cmc,6L
+
+#define SN_id_cmc_recipientNonce "id-cmc-recipientNonce"
+#define NID_id_cmc_recipientNonce 333
+#define OBJ_id_cmc_recipientNonce OBJ_id_cmc,7L
+
+#define SN_id_cmc_addExtensions "id-cmc-addExtensions"
+#define NID_id_cmc_addExtensions 334
+#define OBJ_id_cmc_addExtensions OBJ_id_cmc,8L
+
+#define SN_id_cmc_encryptedPOP "id-cmc-encryptedPOP"
+#define NID_id_cmc_encryptedPOP 335
+#define OBJ_id_cmc_encryptedPOP OBJ_id_cmc,9L
+
+#define SN_id_cmc_decryptedPOP "id-cmc-decryptedPOP"
+#define NID_id_cmc_decryptedPOP 336
+#define OBJ_id_cmc_decryptedPOP OBJ_id_cmc,10L
+
+#define SN_id_cmc_lraPOPWitness "id-cmc-lraPOPWitness"
+#define NID_id_cmc_lraPOPWitness 337
+#define OBJ_id_cmc_lraPOPWitness OBJ_id_cmc,11L
+
+#define SN_id_cmc_getCert "id-cmc-getCert"
+#define NID_id_cmc_getCert 338
+#define OBJ_id_cmc_getCert OBJ_id_cmc,15L
+
+#define SN_id_cmc_getCRL "id-cmc-getCRL"
+#define NID_id_cmc_getCRL 339
+#define OBJ_id_cmc_getCRL OBJ_id_cmc,16L
+
+#define SN_id_cmc_revokeRequest "id-cmc-revokeRequest"
+#define NID_id_cmc_revokeRequest 340
+#define OBJ_id_cmc_revokeRequest OBJ_id_cmc,17L
+
+#define SN_id_cmc_regInfo "id-cmc-regInfo"
+#define NID_id_cmc_regInfo 341
+#define OBJ_id_cmc_regInfo OBJ_id_cmc,18L
+
+#define SN_id_cmc_responseInfo "id-cmc-responseInfo"
+#define NID_id_cmc_responseInfo 342
+#define OBJ_id_cmc_responseInfo OBJ_id_cmc,19L
+
+#define SN_id_cmc_queryPending "id-cmc-queryPending"
+#define NID_id_cmc_queryPending 343
+#define OBJ_id_cmc_queryPending OBJ_id_cmc,21L
+
+#define SN_id_cmc_popLinkRandom "id-cmc-popLinkRandom"
+#define NID_id_cmc_popLinkRandom 344
+#define OBJ_id_cmc_popLinkRandom OBJ_id_cmc,22L
+
+#define SN_id_cmc_popLinkWitness "id-cmc-popLinkWitness"
+#define NID_id_cmc_popLinkWitness 345
+#define OBJ_id_cmc_popLinkWitness OBJ_id_cmc,23L
+
+#define SN_id_cmc_confirmCertAcceptance "id-cmc-confirmCertAcceptance"
+#define NID_id_cmc_confirmCertAcceptance 346
+#define OBJ_id_cmc_confirmCertAcceptance OBJ_id_cmc,24L
+
+#define SN_id_on_personalData "id-on-personalData"
+#define NID_id_on_personalData 347
+#define OBJ_id_on_personalData OBJ_id_on,1L
+
+#define SN_id_on_permanentIdentifier "id-on-permanentIdentifier"
+#define LN_id_on_permanentIdentifier "Permanent Identifier"
+#define NID_id_on_permanentIdentifier 858
+#define OBJ_id_on_permanentIdentifier OBJ_id_on,3L
+
+#define SN_id_pda_dateOfBirth "id-pda-dateOfBirth"
+#define NID_id_pda_dateOfBirth 348
+#define OBJ_id_pda_dateOfBirth OBJ_id_pda,1L
+
+#define SN_id_pda_placeOfBirth "id-pda-placeOfBirth"
+#define NID_id_pda_placeOfBirth 349
+#define OBJ_id_pda_placeOfBirth OBJ_id_pda,2L
+
+#define SN_id_pda_gender "id-pda-gender"
+#define NID_id_pda_gender 351
+#define OBJ_id_pda_gender OBJ_id_pda,3L
+
+#define SN_id_pda_countryOfCitizenship "id-pda-countryOfCitizenship"
+#define NID_id_pda_countryOfCitizenship 352
+#define OBJ_id_pda_countryOfCitizenship OBJ_id_pda,4L
+
+#define SN_id_pda_countryOfResidence "id-pda-countryOfResidence"
+#define NID_id_pda_countryOfResidence 353
+#define OBJ_id_pda_countryOfResidence OBJ_id_pda,5L
+
+#define SN_id_aca_authenticationInfo "id-aca-authenticationInfo"
+#define NID_id_aca_authenticationInfo 354
+#define OBJ_id_aca_authenticationInfo OBJ_id_aca,1L
+
+#define SN_id_aca_accessIdentity "id-aca-accessIdentity"
+#define NID_id_aca_accessIdentity 355
+#define OBJ_id_aca_accessIdentity OBJ_id_aca,2L
+
+#define SN_id_aca_chargingIdentity "id-aca-chargingIdentity"
+#define NID_id_aca_chargingIdentity 356
+#define OBJ_id_aca_chargingIdentity OBJ_id_aca,3L
+
+#define SN_id_aca_group "id-aca-group"
+#define NID_id_aca_group 357
+#define OBJ_id_aca_group OBJ_id_aca,4L
+
+#define SN_id_aca_role "id-aca-role"
+#define NID_id_aca_role 358
+#define OBJ_id_aca_role OBJ_id_aca,5L
+
+#define SN_id_aca_encAttrs "id-aca-encAttrs"
+#define NID_id_aca_encAttrs 399
+#define OBJ_id_aca_encAttrs OBJ_id_aca,6L
+
+#define SN_id_qcs_pkixQCSyntax_v1 "id-qcs-pkixQCSyntax-v1"
+#define NID_id_qcs_pkixQCSyntax_v1 359
+#define OBJ_id_qcs_pkixQCSyntax_v1 OBJ_id_qcs,1L
+
+#define SN_id_cct_crs "id-cct-crs"
+#define NID_id_cct_crs 360
+#define OBJ_id_cct_crs OBJ_id_cct,1L
+
+#define SN_id_cct_PKIData "id-cct-PKIData"
+#define NID_id_cct_PKIData 361
+#define OBJ_id_cct_PKIData OBJ_id_cct,2L
+
+#define SN_id_cct_PKIResponse "id-cct-PKIResponse"
+#define NID_id_cct_PKIResponse 362
+#define OBJ_id_cct_PKIResponse OBJ_id_cct,3L
+
+#define SN_id_ppl_anyLanguage "id-ppl-anyLanguage"
+#define LN_id_ppl_anyLanguage "Any language"
+#define NID_id_ppl_anyLanguage 664
+#define OBJ_id_ppl_anyLanguage OBJ_id_ppl,0L
+
+#define SN_id_ppl_inheritAll "id-ppl-inheritAll"
+#define LN_id_ppl_inheritAll "Inherit all"
+#define NID_id_ppl_inheritAll 665
+#define OBJ_id_ppl_inheritAll OBJ_id_ppl,1L
+
+#define SN_Independent "id-ppl-independent"
+#define LN_Independent "Independent"
+#define NID_Independent 667
+#define OBJ_Independent OBJ_id_ppl,2L
+
+#define SN_ad_OCSP "OCSP"
+#define LN_ad_OCSP "OCSP"
+#define NID_ad_OCSP 178
+#define OBJ_ad_OCSP OBJ_id_ad,1L
+
+#define SN_ad_ca_issuers "caIssuers"
+#define LN_ad_ca_issuers "CA Issuers"
+#define NID_ad_ca_issuers 179
+#define OBJ_ad_ca_issuers OBJ_id_ad,2L
+
+#define SN_ad_timeStamping "ad_timestamping"
+#define LN_ad_timeStamping "AD Time Stamping"
+#define NID_ad_timeStamping 363
+#define OBJ_ad_timeStamping OBJ_id_ad,3L
+
+#define SN_ad_dvcs "AD_DVCS"
+#define LN_ad_dvcs "ad dvcs"
+#define NID_ad_dvcs 364
+#define OBJ_ad_dvcs OBJ_id_ad,4L
+
+#define SN_caRepository "caRepository"
+#define LN_caRepository "CA Repository"
+#define NID_caRepository 785
+#define OBJ_caRepository OBJ_id_ad,5L
+
+#define OBJ_id_pkix_OCSP OBJ_ad_OCSP
+
+#define SN_id_pkix_OCSP_basic "basicOCSPResponse"
+#define LN_id_pkix_OCSP_basic "Basic OCSP Response"
+#define NID_id_pkix_OCSP_basic 365
+#define OBJ_id_pkix_OCSP_basic OBJ_id_pkix_OCSP,1L
+
+#define SN_id_pkix_OCSP_Nonce "Nonce"
+#define LN_id_pkix_OCSP_Nonce "OCSP Nonce"
+#define NID_id_pkix_OCSP_Nonce 366
+#define OBJ_id_pkix_OCSP_Nonce OBJ_id_pkix_OCSP,2L
+
+#define SN_id_pkix_OCSP_CrlID "CrlID"
+#define LN_id_pkix_OCSP_CrlID "OCSP CRL ID"
+#define NID_id_pkix_OCSP_CrlID 367
+#define OBJ_id_pkix_OCSP_CrlID OBJ_id_pkix_OCSP,3L
+
+#define SN_id_pkix_OCSP_acceptableResponses "acceptableResponses"
+#define LN_id_pkix_OCSP_acceptableResponses "Acceptable OCSP Responses"
+#define NID_id_pkix_OCSP_acceptableResponses 368
+#define OBJ_id_pkix_OCSP_acceptableResponses OBJ_id_pkix_OCSP,4L
+
+#define SN_id_pkix_OCSP_noCheck "noCheck"
+#define LN_id_pkix_OCSP_noCheck "OCSP No Check"
+#define NID_id_pkix_OCSP_noCheck 369
+#define OBJ_id_pkix_OCSP_noCheck OBJ_id_pkix_OCSP,5L
+
+#define SN_id_pkix_OCSP_archiveCutoff "archiveCutoff"
+#define LN_id_pkix_OCSP_archiveCutoff "OCSP Archive Cutoff"
+#define NID_id_pkix_OCSP_archiveCutoff 370
+#define OBJ_id_pkix_OCSP_archiveCutoff OBJ_id_pkix_OCSP,6L
+
+#define SN_id_pkix_OCSP_serviceLocator "serviceLocator"
+#define LN_id_pkix_OCSP_serviceLocator "OCSP Service Locator"
+#define NID_id_pkix_OCSP_serviceLocator 371
+#define OBJ_id_pkix_OCSP_serviceLocator OBJ_id_pkix_OCSP,7L
+
+#define SN_id_pkix_OCSP_extendedStatus "extendedStatus"
+#define LN_id_pkix_OCSP_extendedStatus "Extended OCSP Status"
+#define NID_id_pkix_OCSP_extendedStatus 372
+#define OBJ_id_pkix_OCSP_extendedStatus OBJ_id_pkix_OCSP,8L
+
+#define SN_id_pkix_OCSP_valid "valid"
+#define NID_id_pkix_OCSP_valid 373
+#define OBJ_id_pkix_OCSP_valid OBJ_id_pkix_OCSP,9L
+
+#define SN_id_pkix_OCSP_path "path"
+#define NID_id_pkix_OCSP_path 374
+#define OBJ_id_pkix_OCSP_path OBJ_id_pkix_OCSP,10L
+
+#define SN_id_pkix_OCSP_trustRoot "trustRoot"
+#define LN_id_pkix_OCSP_trustRoot "Trust Root"
+#define NID_id_pkix_OCSP_trustRoot 375
+#define OBJ_id_pkix_OCSP_trustRoot OBJ_id_pkix_OCSP,11L
+
+#define SN_algorithm "algorithm"
+#define LN_algorithm "algorithm"
+#define NID_algorithm 376
+#define OBJ_algorithm 1L,3L,14L,3L,2L
+
+#define SN_md5WithRSA "RSA-NP-MD5"
+#define LN_md5WithRSA "md5WithRSA"
+#define NID_md5WithRSA 104
+#define OBJ_md5WithRSA OBJ_algorithm,3L
+
+#define SN_des_ecb "DES-ECB"
+#define LN_des_ecb "des-ecb"
+#define NID_des_ecb 29
+#define OBJ_des_ecb OBJ_algorithm,6L
+
+#define SN_des_cbc "DES-CBC"
+#define LN_des_cbc "des-cbc"
+#define NID_des_cbc 31
+#define OBJ_des_cbc OBJ_algorithm,7L
+
+#define SN_des_ofb64 "DES-OFB"
+#define LN_des_ofb64 "des-ofb"
+#define NID_des_ofb64 45
+#define OBJ_des_ofb64 OBJ_algorithm,8L
+
+#define SN_des_cfb64 "DES-CFB"
+#define LN_des_cfb64 "des-cfb"
+#define NID_des_cfb64 30
+#define OBJ_des_cfb64 OBJ_algorithm,9L
+
+#define SN_rsaSignature "rsaSignature"
+#define NID_rsaSignature 377
+#define OBJ_rsaSignature OBJ_algorithm,11L
+
+#define SN_dsa_2 "DSA-old"
+#define LN_dsa_2 "dsaEncryption-old"
+#define NID_dsa_2 67
+#define OBJ_dsa_2 OBJ_algorithm,12L
+
+#define SN_dsaWithSHA "DSA-SHA"
+#define LN_dsaWithSHA "dsaWithSHA"
+#define NID_dsaWithSHA 66
+#define OBJ_dsaWithSHA OBJ_algorithm,13L
+
+#define SN_shaWithRSAEncryption "RSA-SHA"
+#define LN_shaWithRSAEncryption "shaWithRSAEncryption"
+#define NID_shaWithRSAEncryption 42
+#define OBJ_shaWithRSAEncryption OBJ_algorithm,15L
+
+#define SN_des_ede_ecb "DES-EDE"
+#define LN_des_ede_ecb "des-ede"
+#define NID_des_ede_ecb 32
+#define OBJ_des_ede_ecb OBJ_algorithm,17L
+
+#define SN_des_ede3_ecb "DES-EDE3"
+#define LN_des_ede3_ecb "des-ede3"
+#define NID_des_ede3_ecb 33
+
+#define SN_des_ede_cbc "DES-EDE-CBC"
+#define LN_des_ede_cbc "des-ede-cbc"
+#define NID_des_ede_cbc 43
+
+#define SN_des_ede_cfb64 "DES-EDE-CFB"
+#define LN_des_ede_cfb64 "des-ede-cfb"
+#define NID_des_ede_cfb64 60
+
+#define SN_des_ede3_cfb64 "DES-EDE3-CFB"
+#define LN_des_ede3_cfb64 "des-ede3-cfb"
+#define NID_des_ede3_cfb64 61
+
+#define SN_des_ede_ofb64 "DES-EDE-OFB"
+#define LN_des_ede_ofb64 "des-ede-ofb"
+#define NID_des_ede_ofb64 62
+
+#define SN_des_ede3_ofb64 "DES-EDE3-OFB"
+#define LN_des_ede3_ofb64 "des-ede3-ofb"
+#define NID_des_ede3_ofb64 63
+
+#define SN_desx_cbc "DESX-CBC"
+#define LN_desx_cbc "desx-cbc"
+#define NID_desx_cbc 80
+
+#define SN_sha "SHA"
+#define LN_sha "sha"
+#define NID_sha 41
+#define OBJ_sha OBJ_algorithm,18L
+
+#define SN_sha1 "SHA1"
+#define LN_sha1 "sha1"
+#define NID_sha1 64
+#define OBJ_sha1 OBJ_algorithm,26L
+
+#define SN_dsaWithSHA1_2 "DSA-SHA1-old"
+#define LN_dsaWithSHA1_2 "dsaWithSHA1-old"
+#define NID_dsaWithSHA1_2 70
+#define OBJ_dsaWithSHA1_2 OBJ_algorithm,27L
+
+#define SN_sha1WithRSA "RSA-SHA1-2"
+#define LN_sha1WithRSA "sha1WithRSA"
+#define NID_sha1WithRSA 115
+#define OBJ_sha1WithRSA OBJ_algorithm,29L
+
+#define SN_ripemd160 "RIPEMD160"
+#define LN_ripemd160 "ripemd160"
+#define NID_ripemd160 117
+#define OBJ_ripemd160 1L,3L,36L,3L,2L,1L
+
+#define SN_ripemd160WithRSA "RSA-RIPEMD160"
+#define LN_ripemd160WithRSA "ripemd160WithRSA"
+#define NID_ripemd160WithRSA 119
+#define OBJ_ripemd160WithRSA 1L,3L,36L,3L,3L,1L,2L
+
+#define SN_sxnet "SXNetID"
+#define LN_sxnet "Strong Extranet ID"
+#define NID_sxnet 143
+#define OBJ_sxnet 1L,3L,101L,1L,4L,1L
+
+#define SN_X500 "X500"
+#define LN_X500 "directory services (X.500)"
+#define NID_X500 11
+#define OBJ_X500 2L,5L
+
+#define SN_X509 "X509"
+#define NID_X509 12
+#define OBJ_X509 OBJ_X500,4L
+
+#define SN_commonName "CN"
+#define LN_commonName "commonName"
+#define NID_commonName 13
+#define OBJ_commonName OBJ_X509,3L
+
+#define SN_surname "SN"
+#define LN_surname "surname"
+#define NID_surname 100
+#define OBJ_surname OBJ_X509,4L
+
+#define LN_serialNumber "serialNumber"
+#define NID_serialNumber 105
+#define OBJ_serialNumber OBJ_X509,5L
+
+#define SN_countryName "C"
+#define LN_countryName "countryName"
+#define NID_countryName 14
+#define OBJ_countryName OBJ_X509,6L
+
+#define SN_localityName "L"
+#define LN_localityName "localityName"
+#define NID_localityName 15
+#define OBJ_localityName OBJ_X509,7L
+
+#define SN_stateOrProvinceName "ST"
+#define LN_stateOrProvinceName "stateOrProvinceName"
+#define NID_stateOrProvinceName 16
+#define OBJ_stateOrProvinceName OBJ_X509,8L
+
+#define SN_streetAddress "street"
+#define LN_streetAddress "streetAddress"
+#define NID_streetAddress 660
+#define OBJ_streetAddress OBJ_X509,9L
+
+#define SN_organizationName "O"
+#define LN_organizationName "organizationName"
+#define NID_organizationName 17
+#define OBJ_organizationName OBJ_X509,10L
+
+#define SN_organizationalUnitName "OU"
+#define LN_organizationalUnitName "organizationalUnitName"
+#define NID_organizationalUnitName 18
+#define OBJ_organizationalUnitName OBJ_X509,11L
+
+#define SN_title "title"
+#define LN_title "title"
+#define NID_title 106
+#define OBJ_title OBJ_X509,12L
+
+#define LN_description "description"
+#define NID_description 107
+#define OBJ_description OBJ_X509,13L
+
+#define LN_searchGuide "searchGuide"
+#define NID_searchGuide 859
+#define OBJ_searchGuide OBJ_X509,14L
+
+#define LN_businessCategory "businessCategory"
+#define NID_businessCategory 860
+#define OBJ_businessCategory OBJ_X509,15L
+
+#define LN_postalAddress "postalAddress"
+#define NID_postalAddress 861
+#define OBJ_postalAddress OBJ_X509,16L
+
+#define LN_postalCode "postalCode"
+#define NID_postalCode 661
+#define OBJ_postalCode OBJ_X509,17L
+
+#define LN_postOfficeBox "postOfficeBox"
+#define NID_postOfficeBox 862
+#define OBJ_postOfficeBox OBJ_X509,18L
+
+#define LN_physicalDeliveryOfficeName "physicalDeliveryOfficeName"
+#define NID_physicalDeliveryOfficeName 863
+#define OBJ_physicalDeliveryOfficeName OBJ_X509,19L
+
+#define LN_telephoneNumber "telephoneNumber"
+#define NID_telephoneNumber 864
+#define OBJ_telephoneNumber OBJ_X509,20L
+
+#define LN_telexNumber "telexNumber"
+#define NID_telexNumber 865
+#define OBJ_telexNumber OBJ_X509,21L
+
+#define LN_teletexTerminalIdentifier "teletexTerminalIdentifier"
+#define NID_teletexTerminalIdentifier 866
+#define OBJ_teletexTerminalIdentifier OBJ_X509,22L
+
+#define LN_facsimileTelephoneNumber "facsimileTelephoneNumber"
+#define NID_facsimileTelephoneNumber 867
+#define OBJ_facsimileTelephoneNumber OBJ_X509,23L
+
+#define LN_x121Address "x121Address"
+#define NID_x121Address 868
+#define OBJ_x121Address OBJ_X509,24L
+
+#define LN_internationaliSDNNumber "internationaliSDNNumber"
+#define NID_internationaliSDNNumber 869
+#define OBJ_internationaliSDNNumber OBJ_X509,25L
+
+#define LN_registeredAddress "registeredAddress"
+#define NID_registeredAddress 870
+#define OBJ_registeredAddress OBJ_X509,26L
+
+#define LN_destinationIndicator "destinationIndicator"
+#define NID_destinationIndicator 871
+#define OBJ_destinationIndicator OBJ_X509,27L
+
+#define LN_preferredDeliveryMethod "preferredDeliveryMethod"
+#define NID_preferredDeliveryMethod 872
+#define OBJ_preferredDeliveryMethod OBJ_X509,28L
+
+#define LN_presentationAddress "presentationAddress"
+#define NID_presentationAddress 873
+#define OBJ_presentationAddress OBJ_X509,29L
+
+#define LN_supportedApplicationContext "supportedApplicationContext"
+#define NID_supportedApplicationContext 874
+#define OBJ_supportedApplicationContext OBJ_X509,30L
+
+#define SN_member "member"
+#define NID_member 875
+#define OBJ_member OBJ_X509,31L
+
+#define SN_owner "owner"
+#define NID_owner 876
+#define OBJ_owner OBJ_X509,32L
+
+#define LN_roleOccupant "roleOccupant"
+#define NID_roleOccupant 877
+#define OBJ_roleOccupant OBJ_X509,33L
+
+#define SN_seeAlso "seeAlso"
+#define NID_seeAlso 878
+#define OBJ_seeAlso OBJ_X509,34L
+
+#define LN_userPassword "userPassword"
+#define NID_userPassword 879
+#define OBJ_userPassword OBJ_X509,35L
+
+#define LN_userCertificate "userCertificate"
+#define NID_userCertificate 880
+#define OBJ_userCertificate OBJ_X509,36L
+
+#define LN_cACertificate "cACertificate"
+#define NID_cACertificate 881
+#define OBJ_cACertificate OBJ_X509,37L
+
+#define LN_authorityRevocationList "authorityRevocationList"
+#define NID_authorityRevocationList 882
+#define OBJ_authorityRevocationList OBJ_X509,38L
+
+#define LN_certificateRevocationList "certificateRevocationList"
+#define NID_certificateRevocationList 883
+#define OBJ_certificateRevocationList OBJ_X509,39L
+
+#define LN_crossCertificatePair "crossCertificatePair"
+#define NID_crossCertificatePair 884
+#define OBJ_crossCertificatePair OBJ_X509,40L
+
+#define SN_name "name"
+#define LN_name "name"
+#define NID_name 173
+#define OBJ_name OBJ_X509,41L
+
+#define SN_givenName "GN"
+#define LN_givenName "givenName"
+#define NID_givenName 99
+#define OBJ_givenName OBJ_X509,42L
+
+#define SN_initials "initials"
+#define LN_initials "initials"
+#define NID_initials 101
+#define OBJ_initials OBJ_X509,43L
+
+#define LN_generationQualifier "generationQualifier"
+#define NID_generationQualifier 509
+#define OBJ_generationQualifier OBJ_X509,44L
+
+#define LN_x500UniqueIdentifier "x500UniqueIdentifier"
+#define NID_x500UniqueIdentifier 503
+#define OBJ_x500UniqueIdentifier OBJ_X509,45L
+
+#define SN_dnQualifier "dnQualifier"
+#define LN_dnQualifier "dnQualifier"
+#define NID_dnQualifier 174
+#define OBJ_dnQualifier OBJ_X509,46L
+
+#define LN_enhancedSearchGuide "enhancedSearchGuide"
+#define NID_enhancedSearchGuide 885
+#define OBJ_enhancedSearchGuide OBJ_X509,47L
+
+#define LN_protocolInformation "protocolInformation"
+#define NID_protocolInformation 886
+#define OBJ_protocolInformation OBJ_X509,48L
+
+#define LN_distinguishedName "distinguishedName"
+#define NID_distinguishedName 887
+#define OBJ_distinguishedName OBJ_X509,49L
+
+#define LN_uniqueMember "uniqueMember"
+#define NID_uniqueMember 888
+#define OBJ_uniqueMember OBJ_X509,50L
+
+#define LN_houseIdentifier "houseIdentifier"
+#define NID_houseIdentifier 889
+#define OBJ_houseIdentifier OBJ_X509,51L
+
+#define LN_supportedAlgorithms "supportedAlgorithms"
+#define NID_supportedAlgorithms 890
+#define OBJ_supportedAlgorithms OBJ_X509,52L
+
+#define LN_deltaRevocationList "deltaRevocationList"
+#define NID_deltaRevocationList 891
+#define OBJ_deltaRevocationList OBJ_X509,53L
+
+#define SN_dmdName "dmdName"
+#define NID_dmdName 892
+#define OBJ_dmdName OBJ_X509,54L
+
+#define LN_pseudonym "pseudonym"
+#define NID_pseudonym 510
+#define OBJ_pseudonym OBJ_X509,65L
+
+#define SN_role "role"
+#define LN_role "role"
+#define NID_role 400
+#define OBJ_role OBJ_X509,72L
+
+#define SN_X500algorithms "X500algorithms"
+#define LN_X500algorithms "directory services - algorithms"
+#define NID_X500algorithms 378
+#define OBJ_X500algorithms OBJ_X500,8L
+
+#define SN_rsa "RSA"
+#define LN_rsa "rsa"
+#define NID_rsa 19
+#define OBJ_rsa OBJ_X500algorithms,1L,1L
+
+#define SN_mdc2WithRSA "RSA-MDC2"
+#define LN_mdc2WithRSA "mdc2WithRSA"
+#define NID_mdc2WithRSA 96
+#define OBJ_mdc2WithRSA OBJ_X500algorithms,3L,100L
+
+#define SN_mdc2 "MDC2"
+#define LN_mdc2 "mdc2"
+#define NID_mdc2 95
+#define OBJ_mdc2 OBJ_X500algorithms,3L,101L
+
+#define SN_id_ce "id-ce"
+#define NID_id_ce 81
+#define OBJ_id_ce OBJ_X500,29L
+
+#define SN_subject_directory_attributes "subjectDirectoryAttributes"
+#define LN_subject_directory_attributes "X509v3 Subject Directory Attributes"
+#define NID_subject_directory_attributes 769
+#define OBJ_subject_directory_attributes OBJ_id_ce,9L
+
+#define SN_subject_key_identifier "subjectKeyIdentifier"
+#define LN_subject_key_identifier "X509v3 Subject Key Identifier"
+#define NID_subject_key_identifier 82
+#define OBJ_subject_key_identifier OBJ_id_ce,14L
+
+#define SN_key_usage "keyUsage"
+#define LN_key_usage "X509v3 Key Usage"
+#define NID_key_usage 83
+#define OBJ_key_usage OBJ_id_ce,15L
+
+#define SN_private_key_usage_period "privateKeyUsagePeriod"
+#define LN_private_key_usage_period "X509v3 Private Key Usage Period"
+#define NID_private_key_usage_period 84
+#define OBJ_private_key_usage_period OBJ_id_ce,16L
+
+#define SN_subject_alt_name "subjectAltName"
+#define LN_subject_alt_name "X509v3 Subject Alternative Name"
+#define NID_subject_alt_name 85
+#define OBJ_subject_alt_name OBJ_id_ce,17L
+
+#define SN_issuer_alt_name "issuerAltName"
+#define LN_issuer_alt_name "X509v3 Issuer Alternative Name"
+#define NID_issuer_alt_name 86
+#define OBJ_issuer_alt_name OBJ_id_ce,18L
+
+#define SN_basic_constraints "basicConstraints"
+#define LN_basic_constraints "X509v3 Basic Constraints"
+#define NID_basic_constraints 87
+#define OBJ_basic_constraints OBJ_id_ce,19L
+
+#define SN_crl_number "crlNumber"
+#define LN_crl_number "X509v3 CRL Number"
+#define NID_crl_number 88
+#define OBJ_crl_number OBJ_id_ce,20L
+
+#define SN_crl_reason "CRLReason"
+#define LN_crl_reason "X509v3 CRL Reason Code"
+#define NID_crl_reason 141
+#define OBJ_crl_reason OBJ_id_ce,21L
+
+#define SN_invalidity_date "invalidityDate"
+#define LN_invalidity_date "Invalidity Date"
+#define NID_invalidity_date 142
+#define OBJ_invalidity_date OBJ_id_ce,24L
+
+#define SN_delta_crl "deltaCRL"
+#define LN_delta_crl "X509v3 Delta CRL Indicator"
+#define NID_delta_crl 140
+#define OBJ_delta_crl OBJ_id_ce,27L
+
+#define SN_issuing_distribution_point "issuingDistributionPoint"
+#define LN_issuing_distribution_point "X509v3 Issuing Distrubution Point"
+#define NID_issuing_distribution_point 770
+#define OBJ_issuing_distribution_point OBJ_id_ce,28L
+
+#define SN_certificate_issuer "certificateIssuer"
+#define LN_certificate_issuer "X509v3 Certificate Issuer"
+#define NID_certificate_issuer 771
+#define OBJ_certificate_issuer OBJ_id_ce,29L
+
+#define SN_name_constraints "nameConstraints"
+#define LN_name_constraints "X509v3 Name Constraints"
+#define NID_name_constraints 666
+#define OBJ_name_constraints OBJ_id_ce,30L
+
+#define SN_crl_distribution_points "crlDistributionPoints"
+#define LN_crl_distribution_points "X509v3 CRL Distribution Points"
+#define NID_crl_distribution_points 103
+#define OBJ_crl_distribution_points OBJ_id_ce,31L
+
+#define SN_certificate_policies "certificatePolicies"
+#define LN_certificate_policies "X509v3 Certificate Policies"
+#define NID_certificate_policies 89
+#define OBJ_certificate_policies OBJ_id_ce,32L
+
+#define SN_any_policy "anyPolicy"
+#define LN_any_policy "X509v3 Any Policy"
+#define NID_any_policy 746
+#define OBJ_any_policy OBJ_certificate_policies,0L
+
+#define SN_policy_mappings "policyMappings"
+#define LN_policy_mappings "X509v3 Policy Mappings"
+#define NID_policy_mappings 747
+#define OBJ_policy_mappings OBJ_id_ce,33L
+
+#define SN_authority_key_identifier "authorityKeyIdentifier"
+#define LN_authority_key_identifier "X509v3 Authority Key Identifier"
+#define NID_authority_key_identifier 90
+#define OBJ_authority_key_identifier OBJ_id_ce,35L
+
+#define SN_policy_constraints "policyConstraints"
+#define LN_policy_constraints "X509v3 Policy Constraints"
+#define NID_policy_constraints 401
+#define OBJ_policy_constraints OBJ_id_ce,36L
+
+#define SN_ext_key_usage "extendedKeyUsage"
+#define LN_ext_key_usage "X509v3 Extended Key Usage"
+#define NID_ext_key_usage 126
+#define OBJ_ext_key_usage OBJ_id_ce,37L
+
+#define SN_freshest_crl "freshestCRL"
+#define LN_freshest_crl "X509v3 Freshest CRL"
+#define NID_freshest_crl 857
+#define OBJ_freshest_crl OBJ_id_ce,46L
+
+#define SN_inhibit_any_policy "inhibitAnyPolicy"
+#define LN_inhibit_any_policy "X509v3 Inhibit Any Policy"
+#define NID_inhibit_any_policy 748
+#define OBJ_inhibit_any_policy OBJ_id_ce,54L
+
+#define SN_target_information "targetInformation"
+#define LN_target_information "X509v3 AC Targeting"
+#define NID_target_information 402
+#define OBJ_target_information OBJ_id_ce,55L
+
+#define SN_no_rev_avail "noRevAvail"
+#define LN_no_rev_avail "X509v3 No Revocation Available"
+#define NID_no_rev_avail 403
+#define OBJ_no_rev_avail OBJ_id_ce,56L
+
+#define SN_netscape "Netscape"
+#define LN_netscape "Netscape Communications Corp."
+#define NID_netscape 57
+#define OBJ_netscape 2L,16L,840L,1L,113730L
+
+#define SN_netscape_cert_extension "nsCertExt"
+#define LN_netscape_cert_extension "Netscape Certificate Extension"
+#define NID_netscape_cert_extension 58
+#define OBJ_netscape_cert_extension OBJ_netscape,1L
+
+#define SN_netscape_data_type "nsDataType"
+#define LN_netscape_data_type "Netscape Data Type"
+#define NID_netscape_data_type 59
+#define OBJ_netscape_data_type OBJ_netscape,2L
+
+#define SN_netscape_cert_type "nsCertType"
+#define LN_netscape_cert_type "Netscape Cert Type"
+#define NID_netscape_cert_type 71
+#define OBJ_netscape_cert_type OBJ_netscape_cert_extension,1L
+
+#define SN_netscape_base_url "nsBaseUrl"
+#define LN_netscape_base_url "Netscape Base Url"
+#define NID_netscape_base_url 72
+#define OBJ_netscape_base_url OBJ_netscape_cert_extension,2L
+
+#define SN_netscape_revocation_url "nsRevocationUrl"
+#define LN_netscape_revocation_url "Netscape Revocation Url"
+#define NID_netscape_revocation_url 73
+#define OBJ_netscape_revocation_url OBJ_netscape_cert_extension,3L
+
+#define SN_netscape_ca_revocation_url "nsCaRevocationUrl"
+#define LN_netscape_ca_revocation_url "Netscape CA Revocation Url"
+#define NID_netscape_ca_revocation_url 74
+#define OBJ_netscape_ca_revocation_url OBJ_netscape_cert_extension,4L
+
+#define SN_netscape_renewal_url "nsRenewalUrl"
+#define LN_netscape_renewal_url "Netscape Renewal Url"
+#define NID_netscape_renewal_url 75
+#define OBJ_netscape_renewal_url OBJ_netscape_cert_extension,7L
+
+#define SN_netscape_ca_policy_url "nsCaPolicyUrl"
+#define LN_netscape_ca_policy_url "Netscape CA Policy Url"
+#define NID_netscape_ca_policy_url 76
+#define OBJ_netscape_ca_policy_url OBJ_netscape_cert_extension,8L
+
+#define SN_netscape_ssl_server_name "nsSslServerName"
+#define LN_netscape_ssl_server_name "Netscape SSL Server Name"
+#define NID_netscape_ssl_server_name 77
+#define OBJ_netscape_ssl_server_name OBJ_netscape_cert_extension,12L
+
+#define SN_netscape_comment "nsComment"
+#define LN_netscape_comment "Netscape Comment"
+#define NID_netscape_comment 78
+#define OBJ_netscape_comment OBJ_netscape_cert_extension,13L
+
+#define SN_netscape_cert_sequence "nsCertSequence"
+#define LN_netscape_cert_sequence "Netscape Certificate Sequence"
+#define NID_netscape_cert_sequence 79
+#define OBJ_netscape_cert_sequence OBJ_netscape_data_type,5L
+
+#define SN_ns_sgc "nsSGC"
+#define LN_ns_sgc "Netscape Server Gated Crypto"
+#define NID_ns_sgc 139
+#define OBJ_ns_sgc OBJ_netscape,4L,1L
+
+#define SN_org "ORG"
+#define LN_org "org"
+#define NID_org 379
+#define OBJ_org OBJ_iso,3L
+
+#define SN_dod "DOD"
+#define LN_dod "dod"
+#define NID_dod 380
+#define OBJ_dod OBJ_org,6L
+
+#define SN_iana "IANA"
+#define LN_iana "iana"
+#define NID_iana 381
+#define OBJ_iana OBJ_dod,1L
+
+#define OBJ_internet OBJ_iana
+
+#define SN_Directory "directory"
+#define LN_Directory "Directory"
+#define NID_Directory 382
+#define OBJ_Directory OBJ_internet,1L
+
+#define SN_Management "mgmt"
+#define LN_Management "Management"
+#define NID_Management 383
+#define OBJ_Management OBJ_internet,2L
+
+#define SN_Experimental "experimental"
+#define LN_Experimental "Experimental"
+#define NID_Experimental 384
+#define OBJ_Experimental OBJ_internet,3L
+
+#define SN_Private "private"
+#define LN_Private "Private"
+#define NID_Private 385
+#define OBJ_Private OBJ_internet,4L
+
+#define SN_Security "security"
+#define LN_Security "Security"
+#define NID_Security 386
+#define OBJ_Security OBJ_internet,5L
+
+#define SN_SNMPv2 "snmpv2"
+#define LN_SNMPv2 "SNMPv2"
+#define NID_SNMPv2 387
+#define OBJ_SNMPv2 OBJ_internet,6L
+
+#define LN_Mail "Mail"
+#define NID_Mail 388
+#define OBJ_Mail OBJ_internet,7L
+
+#define SN_Enterprises "enterprises"
+#define LN_Enterprises "Enterprises"
+#define NID_Enterprises 389
+#define OBJ_Enterprises OBJ_Private,1L
+
+#define SN_dcObject "dcobject"
+#define LN_dcObject "dcObject"
+#define NID_dcObject 390
+#define OBJ_dcObject OBJ_Enterprises,1466L,344L
+
+#define SN_mime_mhs "mime-mhs"
+#define LN_mime_mhs "MIME MHS"
+#define NID_mime_mhs 504
+#define OBJ_mime_mhs OBJ_Mail,1L
+
+#define SN_mime_mhs_headings "mime-mhs-headings"
+#define LN_mime_mhs_headings "mime-mhs-headings"
+#define NID_mime_mhs_headings 505
+#define OBJ_mime_mhs_headings OBJ_mime_mhs,1L
+
+#define SN_mime_mhs_bodies "mime-mhs-bodies"
+#define LN_mime_mhs_bodies "mime-mhs-bodies"
+#define NID_mime_mhs_bodies 506
+#define OBJ_mime_mhs_bodies OBJ_mime_mhs,2L
+
+#define SN_id_hex_partial_message "id-hex-partial-message"
+#define LN_id_hex_partial_message "id-hex-partial-message"
+#define NID_id_hex_partial_message 507
+#define OBJ_id_hex_partial_message OBJ_mime_mhs_headings,1L
+
+#define SN_id_hex_multipart_message "id-hex-multipart-message"
+#define LN_id_hex_multipart_message "id-hex-multipart-message"
+#define NID_id_hex_multipart_message 508
+#define OBJ_id_hex_multipart_message OBJ_mime_mhs_headings,2L
+
+#define SN_rle_compression "RLE"
+#define LN_rle_compression "run length compression"
+#define NID_rle_compression 124
+#define OBJ_rle_compression 1L,1L,1L,1L,666L,1L
+
+#define SN_zlib_compression "ZLIB"
+#define LN_zlib_compression "zlib compression"
+#define NID_zlib_compression 125
+#define OBJ_zlib_compression OBJ_id_smime_alg,8L
+
+#define OBJ_csor 2L,16L,840L,1L,101L,3L
+
+#define OBJ_nistAlgorithms OBJ_csor,4L
+
+#define OBJ_aes OBJ_nistAlgorithms,1L
+
+#define SN_aes_128_ecb "AES-128-ECB"
+#define LN_aes_128_ecb "aes-128-ecb"
+#define NID_aes_128_ecb 418
+#define OBJ_aes_128_ecb OBJ_aes,1L
+
+#define SN_aes_128_cbc "AES-128-CBC"
+#define LN_aes_128_cbc "aes-128-cbc"
+#define NID_aes_128_cbc 419
+#define OBJ_aes_128_cbc OBJ_aes,2L
+
+#define SN_aes_128_ofb128 "AES-128-OFB"
+#define LN_aes_128_ofb128 "aes-128-ofb"
+#define NID_aes_128_ofb128 420
+#define OBJ_aes_128_ofb128 OBJ_aes,3L
+
+#define SN_aes_128_cfb128 "AES-128-CFB"
+#define LN_aes_128_cfb128 "aes-128-cfb"
+#define NID_aes_128_cfb128 421
+#define OBJ_aes_128_cfb128 OBJ_aes,4L
+
+#define SN_aes_192_ecb "AES-192-ECB"
+#define LN_aes_192_ecb "aes-192-ecb"
+#define NID_aes_192_ecb 422
+#define OBJ_aes_192_ecb OBJ_aes,21L
+
+#define SN_aes_192_cbc "AES-192-CBC"
+#define LN_aes_192_cbc "aes-192-cbc"
+#define NID_aes_192_cbc 423
+#define OBJ_aes_192_cbc OBJ_aes,22L
+
+#define SN_aes_192_ofb128 "AES-192-OFB"
+#define LN_aes_192_ofb128 "aes-192-ofb"
+#define NID_aes_192_ofb128 424
+#define OBJ_aes_192_ofb128 OBJ_aes,23L
+
+#define SN_aes_192_cfb128 "AES-192-CFB"
+#define LN_aes_192_cfb128 "aes-192-cfb"
+#define NID_aes_192_cfb128 425
+#define OBJ_aes_192_cfb128 OBJ_aes,24L
+
+#define SN_aes_256_ecb "AES-256-ECB"
+#define LN_aes_256_ecb "aes-256-ecb"
+#define NID_aes_256_ecb 426
+#define OBJ_aes_256_ecb OBJ_aes,41L
+
+#define SN_aes_256_cbc "AES-256-CBC"
+#define LN_aes_256_cbc "aes-256-cbc"
+#define NID_aes_256_cbc 427
+#define OBJ_aes_256_cbc OBJ_aes,42L
+
+#define SN_aes_256_ofb128 "AES-256-OFB"
+#define LN_aes_256_ofb128 "aes-256-ofb"
+#define NID_aes_256_ofb128 428
+#define OBJ_aes_256_ofb128 OBJ_aes,43L
+
+#define SN_aes_256_cfb128 "AES-256-CFB"
+#define LN_aes_256_cfb128 "aes-256-cfb"
+#define NID_aes_256_cfb128 429
+#define OBJ_aes_256_cfb128 OBJ_aes,44L
+
+#define SN_aes_128_cfb1 "AES-128-CFB1"
+#define LN_aes_128_cfb1 "aes-128-cfb1"
+#define NID_aes_128_cfb1 650
+
+#define SN_aes_192_cfb1 "AES-192-CFB1"
+#define LN_aes_192_cfb1 "aes-192-cfb1"
+#define NID_aes_192_cfb1 651
+
+#define SN_aes_256_cfb1 "AES-256-CFB1"
+#define LN_aes_256_cfb1 "aes-256-cfb1"
+#define NID_aes_256_cfb1 652
+
+#define SN_aes_128_cfb8 "AES-128-CFB8"
+#define LN_aes_128_cfb8 "aes-128-cfb8"
+#define NID_aes_128_cfb8 653
+
+#define SN_aes_192_cfb8 "AES-192-CFB8"
+#define LN_aes_192_cfb8 "aes-192-cfb8"
+#define NID_aes_192_cfb8 654
+
+#define SN_aes_256_cfb8 "AES-256-CFB8"
+#define LN_aes_256_cfb8 "aes-256-cfb8"
+#define NID_aes_256_cfb8 655
+
+#define SN_des_cfb1 "DES-CFB1"
+#define LN_des_cfb1 "des-cfb1"
+#define NID_des_cfb1 656
+
+#define SN_des_cfb8 "DES-CFB8"
+#define LN_des_cfb8 "des-cfb8"
+#define NID_des_cfb8 657
+
+#define SN_des_ede3_cfb1 "DES-EDE3-CFB1"
+#define LN_des_ede3_cfb1 "des-ede3-cfb1"
+#define NID_des_ede3_cfb1 658
+
+#define SN_des_ede3_cfb8 "DES-EDE3-CFB8"
+#define LN_des_ede3_cfb8 "des-ede3-cfb8"
+#define NID_des_ede3_cfb8 659
+
+#define SN_id_aes128_wrap "id-aes128-wrap"
+#define NID_id_aes128_wrap 788
+#define OBJ_id_aes128_wrap OBJ_aes,5L
+
+#define SN_id_aes192_wrap "id-aes192-wrap"
+#define NID_id_aes192_wrap 789
+#define OBJ_id_aes192_wrap OBJ_aes,25L
+
+#define SN_id_aes256_wrap "id-aes256-wrap"
+#define NID_id_aes256_wrap 790
+#define OBJ_id_aes256_wrap OBJ_aes,45L
+
+#define OBJ_nist_hashalgs OBJ_nistAlgorithms,2L
+
+#define SN_sha256 "SHA256"
+#define LN_sha256 "sha256"
+#define NID_sha256 672
+#define OBJ_sha256 OBJ_nist_hashalgs,1L
+
+#define SN_sha384 "SHA384"
+#define LN_sha384 "sha384"
+#define NID_sha384 673
+#define OBJ_sha384 OBJ_nist_hashalgs,2L
+
+#define SN_sha512 "SHA512"
+#define LN_sha512 "sha512"
+#define NID_sha512 674
+#define OBJ_sha512 OBJ_nist_hashalgs,3L
+
+#define SN_sha224 "SHA224"
+#define LN_sha224 "sha224"
+#define NID_sha224 675
+#define OBJ_sha224 OBJ_nist_hashalgs,4L
+
+#define OBJ_dsa_with_sha2 OBJ_nistAlgorithms,3L
+
+#define SN_dsa_with_SHA224 "dsa_with_SHA224"
+#define NID_dsa_with_SHA224 802
+#define OBJ_dsa_with_SHA224 OBJ_dsa_with_sha2,1L
+
+#define SN_dsa_with_SHA256 "dsa_with_SHA256"
+#define NID_dsa_with_SHA256 803
+#define OBJ_dsa_with_SHA256 OBJ_dsa_with_sha2,2L
+
+#define SN_hold_instruction_code "holdInstructionCode"
+#define LN_hold_instruction_code "Hold Instruction Code"
+#define NID_hold_instruction_code 430
+#define OBJ_hold_instruction_code OBJ_id_ce,23L
+
+#define OBJ_holdInstruction OBJ_X9_57,2L
+
+#define SN_hold_instruction_none "holdInstructionNone"
+#define LN_hold_instruction_none "Hold Instruction None"
+#define NID_hold_instruction_none 431
+#define OBJ_hold_instruction_none OBJ_holdInstruction,1L
+
+#define SN_hold_instruction_call_issuer "holdInstructionCallIssuer"
+#define LN_hold_instruction_call_issuer "Hold Instruction Call Issuer"
+#define NID_hold_instruction_call_issuer 432
+#define OBJ_hold_instruction_call_issuer OBJ_holdInstruction,2L
+
+#define SN_hold_instruction_reject "holdInstructionReject"
+#define LN_hold_instruction_reject "Hold Instruction Reject"
+#define NID_hold_instruction_reject 433
+#define OBJ_hold_instruction_reject OBJ_holdInstruction,3L
+
+#define SN_data "data"
+#define NID_data 434
+#define OBJ_data OBJ_itu_t,9L
+
+#define SN_pss "pss"
+#define NID_pss 435
+#define OBJ_pss OBJ_data,2342L
+
+#define SN_ucl "ucl"
+#define NID_ucl 436
+#define OBJ_ucl OBJ_pss,19200300L
+
+#define SN_pilot "pilot"
+#define NID_pilot 437
+#define OBJ_pilot OBJ_ucl,100L
+
+#define LN_pilotAttributeType "pilotAttributeType"
+#define NID_pilotAttributeType 438
+#define OBJ_pilotAttributeType OBJ_pilot,1L
+
+#define LN_pilotAttributeSyntax "pilotAttributeSyntax"
+#define NID_pilotAttributeSyntax 439
+#define OBJ_pilotAttributeSyntax OBJ_pilot,3L
+
+#define LN_pilotObjectClass "pilotObjectClass"
+#define NID_pilotObjectClass 440
+#define OBJ_pilotObjectClass OBJ_pilot,4L
+
+#define LN_pilotGroups "pilotGroups"
+#define NID_pilotGroups 441
+#define OBJ_pilotGroups OBJ_pilot,10L
+
+#define LN_iA5StringSyntax "iA5StringSyntax"
+#define NID_iA5StringSyntax 442
+#define OBJ_iA5StringSyntax OBJ_pilotAttributeSyntax,4L
+
+#define LN_caseIgnoreIA5StringSyntax "caseIgnoreIA5StringSyntax"
+#define NID_caseIgnoreIA5StringSyntax 443
+#define OBJ_caseIgnoreIA5StringSyntax OBJ_pilotAttributeSyntax,5L
+
+#define LN_pilotObject "pilotObject"
+#define NID_pilotObject 444
+#define OBJ_pilotObject OBJ_pilotObjectClass,3L
+
+#define LN_pilotPerson "pilotPerson"
+#define NID_pilotPerson 445
+#define OBJ_pilotPerson OBJ_pilotObjectClass,4L
+
+#define SN_account "account"
+#define NID_account 446
+#define OBJ_account OBJ_pilotObjectClass,5L
+
+#define SN_document "document"
+#define NID_document 447
+#define OBJ_document OBJ_pilotObjectClass,6L
+
+#define SN_room "room"
+#define NID_room 448
+#define OBJ_room OBJ_pilotObjectClass,7L
+
+#define LN_documentSeries "documentSeries"
+#define NID_documentSeries 449
+#define OBJ_documentSeries OBJ_pilotObjectClass,9L
+
+#define SN_Domain "domain"
+#define LN_Domain "Domain"
+#define NID_Domain 392
+#define OBJ_Domain OBJ_pilotObjectClass,13L
+
+#define LN_rFC822localPart "rFC822localPart"
+#define NID_rFC822localPart 450
+#define OBJ_rFC822localPart OBJ_pilotObjectClass,14L
+
+#define LN_dNSDomain "dNSDomain"
+#define NID_dNSDomain 451
+#define OBJ_dNSDomain OBJ_pilotObjectClass,15L
+
+#define LN_domainRelatedObject "domainRelatedObject"
+#define NID_domainRelatedObject 452
+#define OBJ_domainRelatedObject OBJ_pilotObjectClass,17L
+
+#define LN_friendlyCountry "friendlyCountry"
+#define NID_friendlyCountry 453
+#define OBJ_friendlyCountry OBJ_pilotObjectClass,18L
+
+#define LN_simpleSecurityObject "simpleSecurityObject"
+#define NID_simpleSecurityObject 454
+#define OBJ_simpleSecurityObject OBJ_pilotObjectClass,19L
+
+#define LN_pilotOrganization "pilotOrganization"
+#define NID_pilotOrganization 455
+#define OBJ_pilotOrganization OBJ_pilotObjectClass,20L
+
+#define LN_pilotDSA "pilotDSA"
+#define NID_pilotDSA 456
+#define OBJ_pilotDSA OBJ_pilotObjectClass,21L
+
+#define LN_qualityLabelledData "qualityLabelledData"
+#define NID_qualityLabelledData 457
+#define OBJ_qualityLabelledData OBJ_pilotObjectClass,22L
+
+#define SN_userId "UID"
+#define LN_userId "userId"
+#define NID_userId 458
+#define OBJ_userId OBJ_pilotAttributeType,1L
+
+#define LN_textEncodedORAddress "textEncodedORAddress"
+#define NID_textEncodedORAddress 459
+#define OBJ_textEncodedORAddress OBJ_pilotAttributeType,2L
+
+#define SN_rfc822Mailbox "mail"
+#define LN_rfc822Mailbox "rfc822Mailbox"
+#define NID_rfc822Mailbox 460
+#define OBJ_rfc822Mailbox OBJ_pilotAttributeType,3L
+
+#define SN_info "info"
+#define NID_info 461
+#define OBJ_info OBJ_pilotAttributeType,4L
+
+#define LN_favouriteDrink "favouriteDrink"
+#define NID_favouriteDrink 462
+#define OBJ_favouriteDrink OBJ_pilotAttributeType,5L
+
+#define LN_roomNumber "roomNumber"
+#define NID_roomNumber 463
+#define OBJ_roomNumber OBJ_pilotAttributeType,6L
+
+#define SN_photo "photo"
+#define NID_photo 464
+#define OBJ_photo OBJ_pilotAttributeType,7L
+
+#define LN_userClass "userClass"
+#define NID_userClass 465
+#define OBJ_userClass OBJ_pilotAttributeType,8L
+
+#define SN_host "host"
+#define NID_host 466
+#define OBJ_host OBJ_pilotAttributeType,9L
+
+#define SN_manager "manager"
+#define NID_manager 467
+#define OBJ_manager OBJ_pilotAttributeType,10L
+
+#define LN_documentIdentifier "documentIdentifier"
+#define NID_documentIdentifier 468
+#define OBJ_documentIdentifier OBJ_pilotAttributeType,11L
+
+#define LN_documentTitle "documentTitle"
+#define NID_documentTitle 469
+#define OBJ_documentTitle OBJ_pilotAttributeType,12L
+
+#define LN_documentVersion "documentVersion"
+#define NID_documentVersion 470
+#define OBJ_documentVersion OBJ_pilotAttributeType,13L
+
+#define LN_documentAuthor "documentAuthor"
+#define NID_documentAuthor 471
+#define OBJ_documentAuthor OBJ_pilotAttributeType,14L
+
+#define LN_documentLocation "documentLocation"
+#define NID_documentLocation 472
+#define OBJ_documentLocation OBJ_pilotAttributeType,15L
+
+#define LN_homeTelephoneNumber "homeTelephoneNumber"
+#define NID_homeTelephoneNumber 473
+#define OBJ_homeTelephoneNumber OBJ_pilotAttributeType,20L
+
+#define SN_secretary "secretary"
+#define NID_secretary 474
+#define OBJ_secretary OBJ_pilotAttributeType,21L
+
+#define LN_otherMailbox "otherMailbox"
+#define NID_otherMailbox 475
+#define OBJ_otherMailbox OBJ_pilotAttributeType,22L
+
+#define LN_lastModifiedTime "lastModifiedTime"
+#define NID_lastModifiedTime 476
+#define OBJ_lastModifiedTime OBJ_pilotAttributeType,23L
+
+#define LN_lastModifiedBy "lastModifiedBy"
+#define NID_lastModifiedBy 477
+#define OBJ_lastModifiedBy OBJ_pilotAttributeType,24L
+
+#define SN_domainComponent "DC"
+#define LN_domainComponent "domainComponent"
+#define NID_domainComponent 391
+#define OBJ_domainComponent OBJ_pilotAttributeType,25L
+
+#define LN_aRecord "aRecord"
+#define NID_aRecord 478
+#define OBJ_aRecord OBJ_pilotAttributeType,26L
+
+#define LN_pilotAttributeType27 "pilotAttributeType27"
+#define NID_pilotAttributeType27 479
+#define OBJ_pilotAttributeType27 OBJ_pilotAttributeType,27L
+
+#define LN_mXRecord "mXRecord"
+#define NID_mXRecord 480
+#define OBJ_mXRecord OBJ_pilotAttributeType,28L
+
+#define LN_nSRecord "nSRecord"
+#define NID_nSRecord 481
+#define OBJ_nSRecord OBJ_pilotAttributeType,29L
+
+#define LN_sOARecord "sOARecord"
+#define NID_sOARecord 482
+#define OBJ_sOARecord OBJ_pilotAttributeType,30L
+
+#define LN_cNAMERecord "cNAMERecord"
+#define NID_cNAMERecord 483
+#define OBJ_cNAMERecord OBJ_pilotAttributeType,31L
+
+#define LN_associatedDomain "associatedDomain"
+#define NID_associatedDomain 484
+#define OBJ_associatedDomain OBJ_pilotAttributeType,37L
+
+#define LN_associatedName "associatedName"
+#define NID_associatedName 485
+#define OBJ_associatedName OBJ_pilotAttributeType,38L
+
+#define LN_homePostalAddress "homePostalAddress"
+#define NID_homePostalAddress 486
+#define OBJ_homePostalAddress OBJ_pilotAttributeType,39L
+
+#define LN_personalTitle "personalTitle"
+#define NID_personalTitle 487
+#define OBJ_personalTitle OBJ_pilotAttributeType,40L
+
+#define LN_mobileTelephoneNumber "mobileTelephoneNumber"
+#define NID_mobileTelephoneNumber 488
+#define OBJ_mobileTelephoneNumber OBJ_pilotAttributeType,41L
+
+#define LN_pagerTelephoneNumber "pagerTelephoneNumber"
+#define NID_pagerTelephoneNumber 489
+#define OBJ_pagerTelephoneNumber OBJ_pilotAttributeType,42L
+
+#define LN_friendlyCountryName "friendlyCountryName"
+#define NID_friendlyCountryName 490
+#define OBJ_friendlyCountryName OBJ_pilotAttributeType,43L
+
+#define LN_organizationalStatus "organizationalStatus"
+#define NID_organizationalStatus 491
+#define OBJ_organizationalStatus OBJ_pilotAttributeType,45L
+
+#define LN_janetMailbox "janetMailbox"
+#define NID_janetMailbox 492
+#define OBJ_janetMailbox OBJ_pilotAttributeType,46L
+
+#define LN_mailPreferenceOption "mailPreferenceOption"
+#define NID_mailPreferenceOption 493
+#define OBJ_mailPreferenceOption OBJ_pilotAttributeType,47L
+
+#define LN_buildingName "buildingName"
+#define NID_buildingName 494
+#define OBJ_buildingName OBJ_pilotAttributeType,48L
+
+#define LN_dSAQuality "dSAQuality"
+#define NID_dSAQuality 495
+#define OBJ_dSAQuality OBJ_pilotAttributeType,49L
+
+#define LN_singleLevelQuality "singleLevelQuality"
+#define NID_singleLevelQuality 496
+#define OBJ_singleLevelQuality OBJ_pilotAttributeType,50L
+
+#define LN_subtreeMinimumQuality "subtreeMinimumQuality"
+#define NID_subtreeMinimumQuality 497
+#define OBJ_subtreeMinimumQuality OBJ_pilotAttributeType,51L
+
+#define LN_subtreeMaximumQuality "subtreeMaximumQuality"
+#define NID_subtreeMaximumQuality 498
+#define OBJ_subtreeMaximumQuality OBJ_pilotAttributeType,52L
+
+#define LN_personalSignature "personalSignature"
+#define NID_personalSignature 499
+#define OBJ_personalSignature OBJ_pilotAttributeType,53L
+
+#define LN_dITRedirect "dITRedirect"
+#define NID_dITRedirect 500
+#define OBJ_dITRedirect OBJ_pilotAttributeType,54L
+
+#define SN_audio "audio"
+#define NID_audio 501
+#define OBJ_audio OBJ_pilotAttributeType,55L
+
+#define LN_documentPublisher "documentPublisher"
+#define NID_documentPublisher 502
+#define OBJ_documentPublisher OBJ_pilotAttributeType,56L
+
+#define SN_id_set "id-set"
+#define LN_id_set "Secure Electronic Transactions"
+#define NID_id_set 512
+#define OBJ_id_set OBJ_international_organizations,42L
+
+#define SN_set_ctype "set-ctype"
+#define LN_set_ctype "content types"
+#define NID_set_ctype 513
+#define OBJ_set_ctype OBJ_id_set,0L
+
+#define SN_set_msgExt "set-msgExt"
+#define LN_set_msgExt "message extensions"
+#define NID_set_msgExt 514
+#define OBJ_set_msgExt OBJ_id_set,1L
+
+#define SN_set_attr "set-attr"
+#define NID_set_attr 515
+#define OBJ_set_attr OBJ_id_set,3L
+
+#define SN_set_policy "set-policy"
+#define NID_set_policy 516
+#define OBJ_set_policy OBJ_id_set,5L
+
+#define SN_set_certExt "set-certExt"
+#define LN_set_certExt "certificate extensions"
+#define NID_set_certExt 517
+#define OBJ_set_certExt OBJ_id_set,7L
+
+#define SN_set_brand "set-brand"
+#define NID_set_brand 518
+#define OBJ_set_brand OBJ_id_set,8L
+
+#define SN_setct_PANData "setct-PANData"
+#define NID_setct_PANData 519
+#define OBJ_setct_PANData OBJ_set_ctype,0L
+
+#define SN_setct_PANToken "setct-PANToken"
+#define NID_setct_PANToken 520
+#define OBJ_setct_PANToken OBJ_set_ctype,1L
+
+#define SN_setct_PANOnly "setct-PANOnly"
+#define NID_setct_PANOnly 521
+#define OBJ_setct_PANOnly OBJ_set_ctype,2L
+
+#define SN_setct_OIData "setct-OIData"
+#define NID_setct_OIData 522
+#define OBJ_setct_OIData OBJ_set_ctype,3L
+
+#define SN_setct_PI "setct-PI"
+#define NID_setct_PI 523
+#define OBJ_setct_PI OBJ_set_ctype,4L
+
+#define SN_setct_PIData "setct-PIData"
+#define NID_setct_PIData 524
+#define OBJ_setct_PIData OBJ_set_ctype,5L
+
+#define SN_setct_PIDataUnsigned "setct-PIDataUnsigned"
+#define NID_setct_PIDataUnsigned 525
+#define OBJ_setct_PIDataUnsigned OBJ_set_ctype,6L
+
+#define SN_setct_HODInput "setct-HODInput"
+#define NID_setct_HODInput 526
+#define OBJ_setct_HODInput OBJ_set_ctype,7L
+
+#define SN_setct_AuthResBaggage "setct-AuthResBaggage"
+#define NID_setct_AuthResBaggage 527
+#define OBJ_setct_AuthResBaggage OBJ_set_ctype,8L
+
+#define SN_setct_AuthRevReqBaggage "setct-AuthRevReqBaggage"
+#define NID_setct_AuthRevReqBaggage 528
+#define OBJ_setct_AuthRevReqBaggage OBJ_set_ctype,9L
+
+#define SN_setct_AuthRevResBaggage "setct-AuthRevResBaggage"
+#define NID_setct_AuthRevResBaggage 529
+#define OBJ_setct_AuthRevResBaggage OBJ_set_ctype,10L
+
+#define SN_setct_CapTokenSeq "setct-CapTokenSeq"
+#define NID_setct_CapTokenSeq 530
+#define OBJ_setct_CapTokenSeq OBJ_set_ctype,11L
+
+#define SN_setct_PInitResData "setct-PInitResData"
+#define NID_setct_PInitResData 531
+#define OBJ_setct_PInitResData OBJ_set_ctype,12L
+
+#define SN_setct_PI_TBS "setct-PI-TBS"
+#define NID_setct_PI_TBS 532
+#define OBJ_setct_PI_TBS OBJ_set_ctype,13L
+
+#define SN_setct_PResData "setct-PResData"
+#define NID_setct_PResData 533
+#define OBJ_setct_PResData OBJ_set_ctype,14L
+
+#define SN_setct_AuthReqTBS "setct-AuthReqTBS"
+#define NID_setct_AuthReqTBS 534
+#define OBJ_setct_AuthReqTBS OBJ_set_ctype,16L
+
+#define SN_setct_AuthResTBS "setct-AuthResTBS"
+#define NID_setct_AuthResTBS 535
+#define OBJ_setct_AuthResTBS OBJ_set_ctype,17L
+
+#define SN_setct_AuthResTBSX "setct-AuthResTBSX"
+#define NID_setct_AuthResTBSX 536
+#define OBJ_setct_AuthResTBSX OBJ_set_ctype,18L
+
+#define SN_setct_AuthTokenTBS "setct-AuthTokenTBS"
+#define NID_setct_AuthTokenTBS 537
+#define OBJ_setct_AuthTokenTBS OBJ_set_ctype,19L
+
+#define SN_setct_CapTokenData "setct-CapTokenData"
+#define NID_setct_CapTokenData 538
+#define OBJ_setct_CapTokenData OBJ_set_ctype,20L
+
+#define SN_setct_CapTokenTBS "setct-CapTokenTBS"
+#define NID_setct_CapTokenTBS 539
+#define OBJ_setct_CapTokenTBS OBJ_set_ctype,21L
+
+#define SN_setct_AcqCardCodeMsg "setct-AcqCardCodeMsg"
+#define NID_setct_AcqCardCodeMsg 540
+#define OBJ_setct_AcqCardCodeMsg OBJ_set_ctype,22L
+
+#define SN_setct_AuthRevReqTBS "setct-AuthRevReqTBS"
+#define NID_setct_AuthRevReqTBS 541
+#define OBJ_setct_AuthRevReqTBS OBJ_set_ctype,23L
+
+#define SN_setct_AuthRevResData "setct-AuthRevResData"
+#define NID_setct_AuthRevResData 542
+#define OBJ_setct_AuthRevResData OBJ_set_ctype,24L
+
+#define SN_setct_AuthRevResTBS "setct-AuthRevResTBS"
+#define NID_setct_AuthRevResTBS 543
+#define OBJ_setct_AuthRevResTBS OBJ_set_ctype,25L
+
+#define SN_setct_CapReqTBS "setct-CapReqTBS"
+#define NID_setct_CapReqTBS 544
+#define OBJ_setct_CapReqTBS OBJ_set_ctype,26L
+
+#define SN_setct_CapReqTBSX "setct-CapReqTBSX"
+#define NID_setct_CapReqTBSX 545
+#define OBJ_setct_CapReqTBSX OBJ_set_ctype,27L
+
+#define SN_setct_CapResData "setct-CapResData"
+#define NID_setct_CapResData 546
+#define OBJ_setct_CapResData OBJ_set_ctype,28L
+
+#define SN_setct_CapRevReqTBS "setct-CapRevReqTBS"
+#define NID_setct_CapRevReqTBS 547
+#define OBJ_setct_CapRevReqTBS OBJ_set_ctype,29L
+
+#define SN_setct_CapRevReqTBSX "setct-CapRevReqTBSX"
+#define NID_setct_CapRevReqTBSX 548
+#define OBJ_setct_CapRevReqTBSX OBJ_set_ctype,30L
+
+#define SN_setct_CapRevResData "setct-CapRevResData"
+#define NID_setct_CapRevResData 549
+#define OBJ_setct_CapRevResData OBJ_set_ctype,31L
+
+#define SN_setct_CredReqTBS "setct-CredReqTBS"
+#define NID_setct_CredReqTBS 550
+#define OBJ_setct_CredReqTBS OBJ_set_ctype,32L
+
+#define SN_setct_CredReqTBSX "setct-CredReqTBSX"
+#define NID_setct_CredReqTBSX 551
+#define OBJ_setct_CredReqTBSX OBJ_set_ctype,33L
+
+#define SN_setct_CredResData "setct-CredResData"
+#define NID_setct_CredResData 552
+#define OBJ_setct_CredResData OBJ_set_ctype,34L
+
+#define SN_setct_CredRevReqTBS "setct-CredRevReqTBS"
+#define NID_setct_CredRevReqTBS 553
+#define OBJ_setct_CredRevReqTBS OBJ_set_ctype,35L
+
+#define SN_setct_CredRevReqTBSX "setct-CredRevReqTBSX"
+#define NID_setct_CredRevReqTBSX 554
+#define OBJ_setct_CredRevReqTBSX OBJ_set_ctype,36L
+
+#define SN_setct_CredRevResData "setct-CredRevResData"
+#define NID_setct_CredRevResData 555
+#define OBJ_setct_CredRevResData OBJ_set_ctype,37L
+
+#define SN_setct_PCertReqData "setct-PCertReqData"
+#define NID_setct_PCertReqData 556
+#define OBJ_setct_PCertReqData OBJ_set_ctype,38L
+
+#define SN_setct_PCertResTBS "setct-PCertResTBS"
+#define NID_setct_PCertResTBS 557
+#define OBJ_setct_PCertResTBS OBJ_set_ctype,39L
+
+#define SN_setct_BatchAdminReqData "setct-BatchAdminReqData"
+#define NID_setct_BatchAdminReqData 558
+#define OBJ_setct_BatchAdminReqData OBJ_set_ctype,40L
+
+#define SN_setct_BatchAdminResData "setct-BatchAdminResData"
+#define NID_setct_BatchAdminResData 559
+#define OBJ_setct_BatchAdminResData OBJ_set_ctype,41L
+
+#define SN_setct_CardCInitResTBS "setct-CardCInitResTBS"
+#define NID_setct_CardCInitResTBS 560
+#define OBJ_setct_CardCInitResTBS OBJ_set_ctype,42L
+
+#define SN_setct_MeAqCInitResTBS "setct-MeAqCInitResTBS"
+#define NID_setct_MeAqCInitResTBS 561
+#define OBJ_setct_MeAqCInitResTBS OBJ_set_ctype,43L
+
+#define SN_setct_RegFormResTBS "setct-RegFormResTBS"
+#define NID_setct_RegFormResTBS 562
+#define OBJ_setct_RegFormResTBS OBJ_set_ctype,44L
+
+#define SN_setct_CertReqData "setct-CertReqData"
+#define NID_setct_CertReqData 563
+#define OBJ_setct_CertReqData OBJ_set_ctype,45L
+
+#define SN_setct_CertReqTBS "setct-CertReqTBS"
+#define NID_setct_CertReqTBS 564
+#define OBJ_setct_CertReqTBS OBJ_set_ctype,46L
+
+#define SN_setct_CertResData "setct-CertResData"
+#define NID_setct_CertResData 565
+#define OBJ_setct_CertResData OBJ_set_ctype,47L
+
+#define SN_setct_CertInqReqTBS "setct-CertInqReqTBS"
+#define NID_setct_CertInqReqTBS 566
+#define OBJ_setct_CertInqReqTBS OBJ_set_ctype,48L
+
+#define SN_setct_ErrorTBS "setct-ErrorTBS"
+#define NID_setct_ErrorTBS 567
+#define OBJ_setct_ErrorTBS OBJ_set_ctype,49L
+
+#define SN_setct_PIDualSignedTBE "setct-PIDualSignedTBE"
+#define NID_setct_PIDualSignedTBE 568
+#define OBJ_setct_PIDualSignedTBE OBJ_set_ctype,50L
+
+#define SN_setct_PIUnsignedTBE "setct-PIUnsignedTBE"
+#define NID_setct_PIUnsignedTBE 569
+#define OBJ_setct_PIUnsignedTBE OBJ_set_ctype,51L
+
+#define SN_setct_AuthReqTBE "setct-AuthReqTBE"
+#define NID_setct_AuthReqTBE 570
+#define OBJ_setct_AuthReqTBE OBJ_set_ctype,52L
+
+#define SN_setct_AuthResTBE "setct-AuthResTBE"
+#define NID_setct_AuthResTBE 571
+#define OBJ_setct_AuthResTBE OBJ_set_ctype,53L
+
+#define SN_setct_AuthResTBEX "setct-AuthResTBEX"
+#define NID_setct_AuthResTBEX 572
+#define OBJ_setct_AuthResTBEX OBJ_set_ctype,54L
+
+#define SN_setct_AuthTokenTBE "setct-AuthTokenTBE"
+#define NID_setct_AuthTokenTBE 573
+#define OBJ_setct_AuthTokenTBE OBJ_set_ctype,55L
+
+#define SN_setct_CapTokenTBE "setct-CapTokenTBE"
+#define NID_setct_CapTokenTBE 574
+#define OBJ_setct_CapTokenTBE OBJ_set_ctype,56L
+
+#define SN_setct_CapTokenTBEX "setct-CapTokenTBEX"
+#define NID_setct_CapTokenTBEX 575
+#define OBJ_setct_CapTokenTBEX OBJ_set_ctype,57L
+
+#define SN_setct_AcqCardCodeMsgTBE "setct-AcqCardCodeMsgTBE"
+#define NID_setct_AcqCardCodeMsgTBE 576
+#define OBJ_setct_AcqCardCodeMsgTBE OBJ_set_ctype,58L
+
+#define SN_setct_AuthRevReqTBE "setct-AuthRevReqTBE"
+#define NID_setct_AuthRevReqTBE 577
+#define OBJ_setct_AuthRevReqTBE OBJ_set_ctype,59L
+
+#define SN_setct_AuthRevResTBE "setct-AuthRevResTBE"
+#define NID_setct_AuthRevResTBE 578
+#define OBJ_setct_AuthRevResTBE OBJ_set_ctype,60L
+
+#define SN_setct_AuthRevResTBEB "setct-AuthRevResTBEB"
+#define NID_setct_AuthRevResTBEB 579
+#define OBJ_setct_AuthRevResTBEB OBJ_set_ctype,61L
+
+#define SN_setct_CapReqTBE "setct-CapReqTBE"
+#define NID_setct_CapReqTBE 580
+#define OBJ_setct_CapReqTBE OBJ_set_ctype,62L
+
+#define SN_setct_CapReqTBEX "setct-CapReqTBEX"
+#define NID_setct_CapReqTBEX 581
+#define OBJ_setct_CapReqTBEX OBJ_set_ctype,63L
+
+#define SN_setct_CapResTBE "setct-CapResTBE"
+#define NID_setct_CapResTBE 582
+#define OBJ_setct_CapResTBE OBJ_set_ctype,64L
+
+#define SN_setct_CapRevReqTBE "setct-CapRevReqTBE"
+#define NID_setct_CapRevReqTBE 583
+#define OBJ_setct_CapRevReqTBE OBJ_set_ctype,65L
+
+#define SN_setct_CapRevReqTBEX "setct-CapRevReqTBEX"
+#define NID_setct_CapRevReqTBEX 584
+#define OBJ_setct_CapRevReqTBEX OBJ_set_ctype,66L
+
+#define SN_setct_CapRevResTBE "setct-CapRevResTBE"
+#define NID_setct_CapRevResTBE 585
+#define OBJ_setct_CapRevResTBE OBJ_set_ctype,67L
+
+#define SN_setct_CredReqTBE "setct-CredReqTBE"
+#define NID_setct_CredReqTBE 586
+#define OBJ_setct_CredReqTBE OBJ_set_ctype,68L
+
+#define SN_setct_CredReqTBEX "setct-CredReqTBEX"
+#define NID_setct_CredReqTBEX 587
+#define OBJ_setct_CredReqTBEX OBJ_set_ctype,69L
+
+#define SN_setct_CredResTBE "setct-CredResTBE"
+#define NID_setct_CredResTBE 588
+#define OBJ_setct_CredResTBE OBJ_set_ctype,70L
+
+#define SN_setct_CredRevReqTBE "setct-CredRevReqTBE"
+#define NID_setct_CredRevReqTBE 589
+#define OBJ_setct_CredRevReqTBE OBJ_set_ctype,71L
+
+#define SN_setct_CredRevReqTBEX "setct-CredRevReqTBEX"
+#define NID_setct_CredRevReqTBEX 590
+#define OBJ_setct_CredRevReqTBEX OBJ_set_ctype,72L
+
+#define SN_setct_CredRevResTBE "setct-CredRevResTBE"
+#define NID_setct_CredRevResTBE 591
+#define OBJ_setct_CredRevResTBE OBJ_set_ctype,73L
+
+#define SN_setct_BatchAdminReqTBE "setct-BatchAdminReqTBE"
+#define NID_setct_BatchAdminReqTBE 592
+#define OBJ_setct_BatchAdminReqTBE OBJ_set_ctype,74L
+
+#define SN_setct_BatchAdminResTBE "setct-BatchAdminResTBE"
+#define NID_setct_BatchAdminResTBE 593
+#define OBJ_setct_BatchAdminResTBE OBJ_set_ctype,75L
+
+#define SN_setct_RegFormReqTBE "setct-RegFormReqTBE"
+#define NID_setct_RegFormReqTBE 594
+#define OBJ_setct_RegFormReqTBE OBJ_set_ctype,76L
+
+#define SN_setct_CertReqTBE "setct-CertReqTBE"
+#define NID_setct_CertReqTBE 595
+#define OBJ_setct_CertReqTBE OBJ_set_ctype,77L
+
+#define SN_setct_CertReqTBEX "setct-CertReqTBEX"
+#define NID_setct_CertReqTBEX 596
+#define OBJ_setct_CertReqTBEX OBJ_set_ctype,78L
+
+#define SN_setct_CertResTBE "setct-CertResTBE"
+#define NID_setct_CertResTBE 597
+#define OBJ_setct_CertResTBE OBJ_set_ctype,79L
+
+#define SN_setct_CRLNotificationTBS "setct-CRLNotificationTBS"
+#define NID_setct_CRLNotificationTBS 598
+#define OBJ_setct_CRLNotificationTBS OBJ_set_ctype,80L
+
+#define SN_setct_CRLNotificationResTBS "setct-CRLNotificationResTBS"
+#define NID_setct_CRLNotificationResTBS 599
+#define OBJ_setct_CRLNotificationResTBS OBJ_set_ctype,81L
+
+#define SN_setct_BCIDistributionTBS "setct-BCIDistributionTBS"
+#define NID_setct_BCIDistributionTBS 600
+#define OBJ_setct_BCIDistributionTBS OBJ_set_ctype,82L
+
+#define SN_setext_genCrypt "setext-genCrypt"
+#define LN_setext_genCrypt "generic cryptogram"
+#define NID_setext_genCrypt 601
+#define OBJ_setext_genCrypt OBJ_set_msgExt,1L
+
+#define SN_setext_miAuth "setext-miAuth"
+#define LN_setext_miAuth "merchant initiated auth"
+#define NID_setext_miAuth 602
+#define OBJ_setext_miAuth OBJ_set_msgExt,3L
+
+#define SN_setext_pinSecure "setext-pinSecure"
+#define NID_setext_pinSecure 603
+#define OBJ_setext_pinSecure OBJ_set_msgExt,4L
+
+#define SN_setext_pinAny "setext-pinAny"
+#define NID_setext_pinAny 604
+#define OBJ_setext_pinAny OBJ_set_msgExt,5L
+
+#define SN_setext_track2 "setext-track2"
+#define NID_setext_track2 605
+#define OBJ_setext_track2 OBJ_set_msgExt,7L
+
+#define SN_setext_cv "setext-cv"
+#define LN_setext_cv "additional verification"
+#define NID_setext_cv 606
+#define OBJ_setext_cv OBJ_set_msgExt,8L
+
+#define SN_set_policy_root "set-policy-root"
+#define NID_set_policy_root 607
+#define OBJ_set_policy_root OBJ_set_policy,0L
+
+#define SN_setCext_hashedRoot "setCext-hashedRoot"
+#define NID_setCext_hashedRoot 608
+#define OBJ_setCext_hashedRoot OBJ_set_certExt,0L
+
+#define SN_setCext_certType "setCext-certType"
+#define NID_setCext_certType 609
+#define OBJ_setCext_certType OBJ_set_certExt,1L
+
+#define SN_setCext_merchData "setCext-merchData"
+#define NID_setCext_merchData 610
+#define OBJ_setCext_merchData OBJ_set_certExt,2L
+
+#define SN_setCext_cCertRequired "setCext-cCertRequired"
+#define NID_setCext_cCertRequired 611
+#define OBJ_setCext_cCertRequired OBJ_set_certExt,3L
+
+#define SN_setCext_tunneling "setCext-tunneling"
+#define NID_setCext_tunneling 612
+#define OBJ_setCext_tunneling OBJ_set_certExt,4L
+
+#define SN_setCext_setExt "setCext-setExt"
+#define NID_setCext_setExt 613
+#define OBJ_setCext_setExt OBJ_set_certExt,5L
+
+#define SN_setCext_setQualf "setCext-setQualf"
+#define NID_setCext_setQualf 614
+#define OBJ_setCext_setQualf OBJ_set_certExt,6L
+
+#define SN_setCext_PGWYcapabilities "setCext-PGWYcapabilities"
+#define NID_setCext_PGWYcapabilities 615
+#define OBJ_setCext_PGWYcapabilities OBJ_set_certExt,7L
+
+#define SN_setCext_TokenIdentifier "setCext-TokenIdentifier"
+#define NID_setCext_TokenIdentifier 616
+#define OBJ_setCext_TokenIdentifier OBJ_set_certExt,8L
+
+#define SN_setCext_Track2Data "setCext-Track2Data"
+#define NID_setCext_Track2Data 617
+#define OBJ_setCext_Track2Data OBJ_set_certExt,9L
+
+#define SN_setCext_TokenType "setCext-TokenType"
+#define NID_setCext_TokenType 618
+#define OBJ_setCext_TokenType OBJ_set_certExt,10L
+
+#define SN_setCext_IssuerCapabilities "setCext-IssuerCapabilities"
+#define NID_setCext_IssuerCapabilities 619
+#define OBJ_setCext_IssuerCapabilities OBJ_set_certExt,11L
+
+#define SN_setAttr_Cert "setAttr-Cert"
+#define NID_setAttr_Cert 620
+#define OBJ_setAttr_Cert OBJ_set_attr,0L
+
+#define SN_setAttr_PGWYcap "setAttr-PGWYcap"
+#define LN_setAttr_PGWYcap "payment gateway capabilities"
+#define NID_setAttr_PGWYcap 621
+#define OBJ_setAttr_PGWYcap OBJ_set_attr,1L
+
+#define SN_setAttr_TokenType "setAttr-TokenType"
+#define NID_setAttr_TokenType 622
+#define OBJ_setAttr_TokenType OBJ_set_attr,2L
+
+#define SN_setAttr_IssCap "setAttr-IssCap"
+#define LN_setAttr_IssCap "issuer capabilities"
+#define NID_setAttr_IssCap 623
+#define OBJ_setAttr_IssCap OBJ_set_attr,3L
+
+#define SN_set_rootKeyThumb "set-rootKeyThumb"
+#define NID_set_rootKeyThumb 624
+#define OBJ_set_rootKeyThumb OBJ_setAttr_Cert,0L
+
+#define SN_set_addPolicy "set-addPolicy"
+#define NID_set_addPolicy 625
+#define OBJ_set_addPolicy OBJ_setAttr_Cert,1L
+
+#define SN_setAttr_Token_EMV "setAttr-Token-EMV"
+#define NID_setAttr_Token_EMV 626
+#define OBJ_setAttr_Token_EMV OBJ_setAttr_TokenType,1L
+
+#define SN_setAttr_Token_B0Prime "setAttr-Token-B0Prime"
+#define NID_setAttr_Token_B0Prime 627
+#define OBJ_setAttr_Token_B0Prime OBJ_setAttr_TokenType,2L
+
+#define SN_setAttr_IssCap_CVM "setAttr-IssCap-CVM"
+#define NID_setAttr_IssCap_CVM 628
+#define OBJ_setAttr_IssCap_CVM OBJ_setAttr_IssCap,3L
+
+#define SN_setAttr_IssCap_T2 "setAttr-IssCap-T2"
+#define NID_setAttr_IssCap_T2 629
+#define OBJ_setAttr_IssCap_T2 OBJ_setAttr_IssCap,4L
+
+#define SN_setAttr_IssCap_Sig "setAttr-IssCap-Sig"
+#define NID_setAttr_IssCap_Sig 630
+#define OBJ_setAttr_IssCap_Sig OBJ_setAttr_IssCap,5L
+
+#define SN_setAttr_GenCryptgrm "setAttr-GenCryptgrm"
+#define LN_setAttr_GenCryptgrm "generate cryptogram"
+#define NID_setAttr_GenCryptgrm 631
+#define OBJ_setAttr_GenCryptgrm OBJ_setAttr_IssCap_CVM,1L
+
+#define SN_setAttr_T2Enc "setAttr-T2Enc"
+#define LN_setAttr_T2Enc "encrypted track 2"
+#define NID_setAttr_T2Enc 632
+#define OBJ_setAttr_T2Enc OBJ_setAttr_IssCap_T2,1L
+
+#define SN_setAttr_T2cleartxt "setAttr-T2cleartxt"
+#define LN_setAttr_T2cleartxt "cleartext track 2"
+#define NID_setAttr_T2cleartxt 633
+#define OBJ_setAttr_T2cleartxt OBJ_setAttr_IssCap_T2,2L
+
+#define SN_setAttr_TokICCsig "setAttr-TokICCsig"
+#define LN_setAttr_TokICCsig "ICC or token signature"
+#define NID_setAttr_TokICCsig 634
+#define OBJ_setAttr_TokICCsig OBJ_setAttr_IssCap_Sig,1L
+
+#define SN_setAttr_SecDevSig "setAttr-SecDevSig"
+#define LN_setAttr_SecDevSig "secure device signature"
+#define NID_setAttr_SecDevSig 635
+#define OBJ_setAttr_SecDevSig OBJ_setAttr_IssCap_Sig,2L
+
+#define SN_set_brand_IATA_ATA "set-brand-IATA-ATA"
+#define NID_set_brand_IATA_ATA 636
+#define OBJ_set_brand_IATA_ATA OBJ_set_brand,1L
+
+#define SN_set_brand_Diners "set-brand-Diners"
+#define NID_set_brand_Diners 637
+#define OBJ_set_brand_Diners OBJ_set_brand,30L
+
+#define SN_set_brand_AmericanExpress "set-brand-AmericanExpress"
+#define NID_set_brand_AmericanExpress 638
+#define OBJ_set_brand_AmericanExpress OBJ_set_brand,34L
+
+#define SN_set_brand_JCB "set-brand-JCB"
+#define NID_set_brand_JCB 639
+#define OBJ_set_brand_JCB OBJ_set_brand,35L
+
+#define SN_set_brand_Visa "set-brand-Visa"
+#define NID_set_brand_Visa 640
+#define OBJ_set_brand_Visa OBJ_set_brand,4L
+
+#define SN_set_brand_MasterCard "set-brand-MasterCard"
+#define NID_set_brand_MasterCard 641
+#define OBJ_set_brand_MasterCard OBJ_set_brand,5L
+
+#define SN_set_brand_Novus "set-brand-Novus"
+#define NID_set_brand_Novus 642
+#define OBJ_set_brand_Novus OBJ_set_brand,6011L
+
+#define SN_des_cdmf "DES-CDMF"
+#define LN_des_cdmf "des-cdmf"
+#define NID_des_cdmf 643
+#define OBJ_des_cdmf OBJ_rsadsi,3L,10L
+
+#define SN_rsaOAEPEncryptionSET "rsaOAEPEncryptionSET"
+#define NID_rsaOAEPEncryptionSET 644
+#define OBJ_rsaOAEPEncryptionSET OBJ_rsadsi,1L,1L,6L
+
+#define SN_ipsec3 "Oakley-EC2N-3"
+#define LN_ipsec3 "ipsec3"
+#define NID_ipsec3 749
+
+#define SN_ipsec4 "Oakley-EC2N-4"
+#define LN_ipsec4 "ipsec4"
+#define NID_ipsec4 750
+
+#define SN_whirlpool "whirlpool"
+#define NID_whirlpool 804
+#define OBJ_whirlpool OBJ_iso,0L,10118L,3L,0L,55L
+
+#define SN_cryptopro "cryptopro"
+#define NID_cryptopro 805
+#define OBJ_cryptopro OBJ_member_body,643L,2L,2L
+
+#define SN_cryptocom "cryptocom"
+#define NID_cryptocom 806
+#define OBJ_cryptocom OBJ_member_body,643L,2L,9L
+
+#define SN_id_GostR3411_94_with_GostR3410_2001 "id-GostR3411-94-with-GostR3410-2001"
+#define LN_id_GostR3411_94_with_GostR3410_2001 "GOST R 34.11-94 with GOST R 34.10-2001"
+#define NID_id_GostR3411_94_with_GostR3410_2001 807
+#define OBJ_id_GostR3411_94_with_GostR3410_2001 OBJ_cryptopro,3L
+
+#define SN_id_GostR3411_94_with_GostR3410_94 "id-GostR3411-94-with-GostR3410-94"
+#define LN_id_GostR3411_94_with_GostR3410_94 "GOST R 34.11-94 with GOST R 34.10-94"
+#define NID_id_GostR3411_94_with_GostR3410_94 808
+#define OBJ_id_GostR3411_94_with_GostR3410_94 OBJ_cryptopro,4L
+
+#define SN_id_GostR3411_94 "md_gost94"
+#define LN_id_GostR3411_94 "GOST R 34.11-94"
+#define NID_id_GostR3411_94 809
+#define OBJ_id_GostR3411_94 OBJ_cryptopro,9L
+
+#define SN_id_HMACGostR3411_94 "id-HMACGostR3411-94"
+#define LN_id_HMACGostR3411_94 "HMAC GOST 34.11-94"
+#define NID_id_HMACGostR3411_94 810
+#define OBJ_id_HMACGostR3411_94 OBJ_cryptopro,10L
+
+#define SN_id_GostR3410_2001 "gost2001"
+#define LN_id_GostR3410_2001 "GOST R 34.10-2001"
+#define NID_id_GostR3410_2001 811
+#define OBJ_id_GostR3410_2001 OBJ_cryptopro,19L
+
+#define SN_id_GostR3410_94 "gost94"
+#define LN_id_GostR3410_94 "GOST R 34.10-94"
+#define NID_id_GostR3410_94 812
+#define OBJ_id_GostR3410_94 OBJ_cryptopro,20L
+
+#define SN_id_Gost28147_89 "gost89"
+#define LN_id_Gost28147_89 "GOST 28147-89"
+#define NID_id_Gost28147_89 813
+#define OBJ_id_Gost28147_89 OBJ_cryptopro,21L
+
+#define SN_gost89_cnt "gost89-cnt"
+#define NID_gost89_cnt 814
+
+#define SN_id_Gost28147_89_MAC "gost-mac"
+#define LN_id_Gost28147_89_MAC "GOST 28147-89 MAC"
+#define NID_id_Gost28147_89_MAC 815
+#define OBJ_id_Gost28147_89_MAC OBJ_cryptopro,22L
+
+#define SN_id_GostR3411_94_prf "prf-gostr3411-94"
+#define LN_id_GostR3411_94_prf "GOST R 34.11-94 PRF"
+#define NID_id_GostR3411_94_prf 816
+#define OBJ_id_GostR3411_94_prf OBJ_cryptopro,23L
+
+#define SN_id_GostR3410_2001DH "id-GostR3410-2001DH"
+#define LN_id_GostR3410_2001DH "GOST R 34.10-2001 DH"
+#define NID_id_GostR3410_2001DH 817
+#define OBJ_id_GostR3410_2001DH OBJ_cryptopro,98L
+
+#define SN_id_GostR3410_94DH "id-GostR3410-94DH"
+#define LN_id_GostR3410_94DH "GOST R 34.10-94 DH"
+#define NID_id_GostR3410_94DH 818
+#define OBJ_id_GostR3410_94DH OBJ_cryptopro,99L
+
+#define SN_id_Gost28147_89_CryptoPro_KeyMeshing "id-Gost28147-89-CryptoPro-KeyMeshing"
+#define NID_id_Gost28147_89_CryptoPro_KeyMeshing 819
+#define OBJ_id_Gost28147_89_CryptoPro_KeyMeshing OBJ_cryptopro,14L,1L
+
+#define SN_id_Gost28147_89_None_KeyMeshing "id-Gost28147-89-None-KeyMeshing"
+#define NID_id_Gost28147_89_None_KeyMeshing 820
+#define OBJ_id_Gost28147_89_None_KeyMeshing OBJ_cryptopro,14L,0L
+
+#define SN_id_GostR3411_94_TestParamSet "id-GostR3411-94-TestParamSet"
+#define NID_id_GostR3411_94_TestParamSet 821
+#define OBJ_id_GostR3411_94_TestParamSet OBJ_cryptopro,30L,0L
+
+#define SN_id_GostR3411_94_CryptoProParamSet "id-GostR3411-94-CryptoProParamSet"
+#define NID_id_GostR3411_94_CryptoProParamSet 822
+#define OBJ_id_GostR3411_94_CryptoProParamSet OBJ_cryptopro,30L,1L
+
+#define SN_id_Gost28147_89_TestParamSet "id-Gost28147-89-TestParamSet"
+#define NID_id_Gost28147_89_TestParamSet 823
+#define OBJ_id_Gost28147_89_TestParamSet OBJ_cryptopro,31L,0L
+
+#define SN_id_Gost28147_89_CryptoPro_A_ParamSet "id-Gost28147-89-CryptoPro-A-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_A_ParamSet 824
+#define OBJ_id_Gost28147_89_CryptoPro_A_ParamSet OBJ_cryptopro,31L,1L
+
+#define SN_id_Gost28147_89_CryptoPro_B_ParamSet "id-Gost28147-89-CryptoPro-B-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_B_ParamSet 825
+#define OBJ_id_Gost28147_89_CryptoPro_B_ParamSet OBJ_cryptopro,31L,2L
+
+#define SN_id_Gost28147_89_CryptoPro_C_ParamSet "id-Gost28147-89-CryptoPro-C-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_C_ParamSet 826
+#define OBJ_id_Gost28147_89_CryptoPro_C_ParamSet OBJ_cryptopro,31L,3L
+
+#define SN_id_Gost28147_89_CryptoPro_D_ParamSet "id-Gost28147-89-CryptoPro-D-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_D_ParamSet 827
+#define OBJ_id_Gost28147_89_CryptoPro_D_ParamSet OBJ_cryptopro,31L,4L
+
+#define SN_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 828
+#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet OBJ_cryptopro,31L,5L
+
+#define SN_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 829
+#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet OBJ_cryptopro,31L,6L
+
+#define SN_id_Gost28147_89_CryptoPro_RIC_1_ParamSet "id-Gost28147-89-CryptoPro-RIC-1-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet 830
+#define OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet OBJ_cryptopro,31L,7L
+
+#define SN_id_GostR3410_94_TestParamSet "id-GostR3410-94-TestParamSet"
+#define NID_id_GostR3410_94_TestParamSet 831
+#define OBJ_id_GostR3410_94_TestParamSet OBJ_cryptopro,32L,0L
+
+#define SN_id_GostR3410_94_CryptoPro_A_ParamSet "id-GostR3410-94-CryptoPro-A-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_A_ParamSet 832
+#define OBJ_id_GostR3410_94_CryptoPro_A_ParamSet OBJ_cryptopro,32L,2L
+
+#define SN_id_GostR3410_94_CryptoPro_B_ParamSet "id-GostR3410-94-CryptoPro-B-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_B_ParamSet 833
+#define OBJ_id_GostR3410_94_CryptoPro_B_ParamSet OBJ_cryptopro,32L,3L
+
+#define SN_id_GostR3410_94_CryptoPro_C_ParamSet "id-GostR3410-94-CryptoPro-C-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_C_ParamSet 834
+#define OBJ_id_GostR3410_94_CryptoPro_C_ParamSet OBJ_cryptopro,32L,4L
+
+#define SN_id_GostR3410_94_CryptoPro_D_ParamSet "id-GostR3410-94-CryptoPro-D-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_D_ParamSet 835
+#define OBJ_id_GostR3410_94_CryptoPro_D_ParamSet OBJ_cryptopro,32L,5L
+
+#define SN_id_GostR3410_94_CryptoPro_XchA_ParamSet "id-GostR3410-94-CryptoPro-XchA-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_XchA_ParamSet 836
+#define OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet OBJ_cryptopro,33L,1L
+
+#define SN_id_GostR3410_94_CryptoPro_XchB_ParamSet "id-GostR3410-94-CryptoPro-XchB-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_XchB_ParamSet 837
+#define OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet OBJ_cryptopro,33L,2L
+
+#define SN_id_GostR3410_94_CryptoPro_XchC_ParamSet "id-GostR3410-94-CryptoPro-XchC-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_XchC_ParamSet 838
+#define OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet OBJ_cryptopro,33L,3L
+
+#define SN_id_GostR3410_2001_TestParamSet "id-GostR3410-2001-TestParamSet"
+#define NID_id_GostR3410_2001_TestParamSet 839
+#define OBJ_id_GostR3410_2001_TestParamSet OBJ_cryptopro,35L,0L
+
+#define SN_id_GostR3410_2001_CryptoPro_A_ParamSet "id-GostR3410-2001-CryptoPro-A-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_A_ParamSet 840
+#define OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet OBJ_cryptopro,35L,1L
+
+#define SN_id_GostR3410_2001_CryptoPro_B_ParamSet "id-GostR3410-2001-CryptoPro-B-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_B_ParamSet 841
+#define OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet OBJ_cryptopro,35L,2L
+
+#define SN_id_GostR3410_2001_CryptoPro_C_ParamSet "id-GostR3410-2001-CryptoPro-C-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_C_ParamSet 842
+#define OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet OBJ_cryptopro,35L,3L
+
+#define SN_id_GostR3410_2001_CryptoPro_XchA_ParamSet "id-GostR3410-2001-CryptoPro-XchA-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet 843
+#define OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet OBJ_cryptopro,36L,0L
+
+#define SN_id_GostR3410_2001_CryptoPro_XchB_ParamSet "id-GostR3410-2001-CryptoPro-XchB-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet 844
+#define OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet OBJ_cryptopro,36L,1L
+
+#define SN_id_GostR3410_94_a "id-GostR3410-94-a"
+#define NID_id_GostR3410_94_a 845
+#define OBJ_id_GostR3410_94_a OBJ_id_GostR3410_94,1L
+
+#define SN_id_GostR3410_94_aBis "id-GostR3410-94-aBis"
+#define NID_id_GostR3410_94_aBis 846
+#define OBJ_id_GostR3410_94_aBis OBJ_id_GostR3410_94,2L
+
+#define SN_id_GostR3410_94_b "id-GostR3410-94-b"
+#define NID_id_GostR3410_94_b 847
+#define OBJ_id_GostR3410_94_b OBJ_id_GostR3410_94,3L
+
+#define SN_id_GostR3410_94_bBis "id-GostR3410-94-bBis"
+#define NID_id_GostR3410_94_bBis 848
+#define OBJ_id_GostR3410_94_bBis OBJ_id_GostR3410_94,4L
+
+#define SN_id_Gost28147_89_cc "id-Gost28147-89-cc"
+#define LN_id_Gost28147_89_cc "GOST 28147-89 Cryptocom ParamSet"
+#define NID_id_Gost28147_89_cc 849
+#define OBJ_id_Gost28147_89_cc OBJ_cryptocom,1L,6L,1L
+
+#define SN_id_GostR3410_94_cc "gost94cc"
+#define LN_id_GostR3410_94_cc "GOST 34.10-94 Cryptocom"
+#define NID_id_GostR3410_94_cc 850
+#define OBJ_id_GostR3410_94_cc OBJ_cryptocom,1L,5L,3L
+
+#define SN_id_GostR3410_2001_cc "gost2001cc"
+#define LN_id_GostR3410_2001_cc "GOST 34.10-2001 Cryptocom"
+#define NID_id_GostR3410_2001_cc 851
+#define OBJ_id_GostR3410_2001_cc OBJ_cryptocom,1L,5L,4L
+
+#define SN_id_GostR3411_94_with_GostR3410_94_cc "id-GostR3411-94-with-GostR3410-94-cc"
+#define LN_id_GostR3411_94_with_GostR3410_94_cc "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom"
+#define NID_id_GostR3411_94_with_GostR3410_94_cc 852
+#define OBJ_id_GostR3411_94_with_GostR3410_94_cc OBJ_cryptocom,1L,3L,3L
+
+#define SN_id_GostR3411_94_with_GostR3410_2001_cc "id-GostR3411-94-with-GostR3410-2001-cc"
+#define LN_id_GostR3411_94_with_GostR3410_2001_cc "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom"
+#define NID_id_GostR3411_94_with_GostR3410_2001_cc 853
+#define OBJ_id_GostR3411_94_with_GostR3410_2001_cc OBJ_cryptocom,1L,3L,4L
+
+#define SN_id_GostR3410_2001_ParamSet_cc "id-GostR3410-2001-ParamSet-cc"
+#define LN_id_GostR3410_2001_ParamSet_cc "GOST R 3410-2001 Parameter Set Cryptocom"
+#define NID_id_GostR3410_2001_ParamSet_cc 854
+#define OBJ_id_GostR3410_2001_ParamSet_cc OBJ_cryptocom,1L,8L,1L
+
+#define SN_camellia_128_cbc "CAMELLIA-128-CBC"
+#define LN_camellia_128_cbc "camellia-128-cbc"
+#define NID_camellia_128_cbc 751
+#define OBJ_camellia_128_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,2L
+
+#define SN_camellia_192_cbc "CAMELLIA-192-CBC"
+#define LN_camellia_192_cbc "camellia-192-cbc"
+#define NID_camellia_192_cbc 752
+#define OBJ_camellia_192_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,3L
+
+#define SN_camellia_256_cbc "CAMELLIA-256-CBC"
+#define LN_camellia_256_cbc "camellia-256-cbc"
+#define NID_camellia_256_cbc 753
+#define OBJ_camellia_256_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,4L
+
+#define OBJ_ntt_ds 0L,3L,4401L,5L
+
+#define OBJ_camellia OBJ_ntt_ds,3L,1L,9L
+
+#define SN_camellia_128_ecb "CAMELLIA-128-ECB"
+#define LN_camellia_128_ecb "camellia-128-ecb"
+#define NID_camellia_128_ecb 754
+#define OBJ_camellia_128_ecb OBJ_camellia,1L
+
+#define SN_camellia_128_ofb128 "CAMELLIA-128-OFB"
+#define LN_camellia_128_ofb128 "camellia-128-ofb"
+#define NID_camellia_128_ofb128 766
+#define OBJ_camellia_128_ofb128 OBJ_camellia,3L
+
+#define SN_camellia_128_cfb128 "CAMELLIA-128-CFB"
+#define LN_camellia_128_cfb128 "camellia-128-cfb"
+#define NID_camellia_128_cfb128 757
+#define OBJ_camellia_128_cfb128 OBJ_camellia,4L
+
+#define SN_camellia_192_ecb "CAMELLIA-192-ECB"
+#define LN_camellia_192_ecb "camellia-192-ecb"
+#define NID_camellia_192_ecb 755
+#define OBJ_camellia_192_ecb OBJ_camellia,21L
+
+#define SN_camellia_192_ofb128 "CAMELLIA-192-OFB"
+#define LN_camellia_192_ofb128 "camellia-192-ofb"
+#define NID_camellia_192_ofb128 767
+#define OBJ_camellia_192_ofb128 OBJ_camellia,23L
+
+#define SN_camellia_192_cfb128 "CAMELLIA-192-CFB"
+#define LN_camellia_192_cfb128 "camellia-192-cfb"
+#define NID_camellia_192_cfb128 758
+#define OBJ_camellia_192_cfb128 OBJ_camellia,24L
+
+#define SN_camellia_256_ecb "CAMELLIA-256-ECB"
+#define LN_camellia_256_ecb "camellia-256-ecb"
+#define NID_camellia_256_ecb 756
+#define OBJ_camellia_256_ecb OBJ_camellia,41L
+
+#define SN_camellia_256_ofb128 "CAMELLIA-256-OFB"
+#define LN_camellia_256_ofb128 "camellia-256-ofb"
+#define NID_camellia_256_ofb128 768
+#define OBJ_camellia_256_ofb128 OBJ_camellia,43L
+
+#define SN_camellia_256_cfb128 "CAMELLIA-256-CFB"
+#define LN_camellia_256_cfb128 "camellia-256-cfb"
+#define NID_camellia_256_cfb128 759
+#define OBJ_camellia_256_cfb128 OBJ_camellia,44L
+
+#define SN_camellia_128_cfb1 "CAMELLIA-128-CFB1"
+#define LN_camellia_128_cfb1 "camellia-128-cfb1"
+#define NID_camellia_128_cfb1 760
+
+#define SN_camellia_192_cfb1 "CAMELLIA-192-CFB1"
+#define LN_camellia_192_cfb1 "camellia-192-cfb1"
+#define NID_camellia_192_cfb1 761
+
+#define SN_camellia_256_cfb1 "CAMELLIA-256-CFB1"
+#define LN_camellia_256_cfb1 "camellia-256-cfb1"
+#define NID_camellia_256_cfb1 762
+
+#define SN_camellia_128_cfb8 "CAMELLIA-128-CFB8"
+#define LN_camellia_128_cfb8 "camellia-128-cfb8"
+#define NID_camellia_128_cfb8 763
+
+#define SN_camellia_192_cfb8 "CAMELLIA-192-CFB8"
+#define LN_camellia_192_cfb8 "camellia-192-cfb8"
+#define NID_camellia_192_cfb8 764
+
+#define SN_camellia_256_cfb8 "CAMELLIA-256-CFB8"
+#define LN_camellia_256_cfb8 "camellia-256-cfb8"
+#define NID_camellia_256_cfb8 765
+
+#define SN_kisa "KISA"
+#define LN_kisa "kisa"
+#define NID_kisa 773
+#define OBJ_kisa OBJ_member_body,410L,200004L
+
+#define SN_seed_ecb "SEED-ECB"
+#define LN_seed_ecb "seed-ecb"
+#define NID_seed_ecb 776
+#define OBJ_seed_ecb OBJ_kisa,1L,3L
+
+#define SN_seed_cbc "SEED-CBC"
+#define LN_seed_cbc "seed-cbc"
+#define NID_seed_cbc 777
+#define OBJ_seed_cbc OBJ_kisa,1L,4L
+
+#define SN_seed_cfb128 "SEED-CFB"
+#define LN_seed_cfb128 "seed-cfb"
+#define NID_seed_cfb128 779
+#define OBJ_seed_cfb128 OBJ_kisa,1L,5L
+
+#define SN_seed_ofb128 "SEED-OFB"
+#define LN_seed_ofb128 "seed-ofb"
+#define NID_seed_ofb128 778
+#define OBJ_seed_ofb128 OBJ_kisa,1L,6L
+
+#define SN_hmac "HMAC"
+#define LN_hmac "hmac"
+#define NID_hmac 855
+
diff --git a/src/Mayaqua/win32_inc/openssl/objects.h b/src/Mayaqua/win32_inc/openssl/objects.h
new file mode 100644
index 00000000..77008942
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/objects.h
@@ -0,0 +1,1049 @@
+/* crypto/objects/objects.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_OBJECTS_H
+#define HEADER_OBJECTS_H
+
+#define USE_OBJ_MAC
+
+#ifdef USE_OBJ_MAC
+#include <openssl/obj_mac.h>
+#else
+#define SN_undef "UNDEF"
+#define LN_undef "undefined"
+#define NID_undef 0
+#define OBJ_undef 0L
+
+#define SN_Algorithm "Algorithm"
+#define LN_algorithm "algorithm"
+#define NID_algorithm 38
+#define OBJ_algorithm 1L,3L,14L,3L,2L
+
+#define LN_rsadsi "rsadsi"
+#define NID_rsadsi 1
+#define OBJ_rsadsi 1L,2L,840L,113549L
+
+#define LN_pkcs "pkcs"
+#define NID_pkcs 2
+#define OBJ_pkcs OBJ_rsadsi,1L
+
+#define SN_md2 "MD2"
+#define LN_md2 "md2"
+#define NID_md2 3
+#define OBJ_md2 OBJ_rsadsi,2L,2L
+
+#define SN_md5 "MD5"
+#define LN_md5 "md5"
+#define NID_md5 4
+#define OBJ_md5 OBJ_rsadsi,2L,5L
+
+#define SN_rc4 "RC4"
+#define LN_rc4 "rc4"
+#define NID_rc4 5
+#define OBJ_rc4 OBJ_rsadsi,3L,4L
+
+#define LN_rsaEncryption "rsaEncryption"
+#define NID_rsaEncryption 6
+#define OBJ_rsaEncryption OBJ_pkcs,1L,1L
+
+#define SN_md2WithRSAEncryption "RSA-MD2"
+#define LN_md2WithRSAEncryption "md2WithRSAEncryption"
+#define NID_md2WithRSAEncryption 7
+#define OBJ_md2WithRSAEncryption OBJ_pkcs,1L,2L
+
+#define SN_md5WithRSAEncryption "RSA-MD5"
+#define LN_md5WithRSAEncryption "md5WithRSAEncryption"
+#define NID_md5WithRSAEncryption 8
+#define OBJ_md5WithRSAEncryption OBJ_pkcs,1L,4L
+
+#define SN_pbeWithMD2AndDES_CBC "PBE-MD2-DES"
+#define LN_pbeWithMD2AndDES_CBC "pbeWithMD2AndDES-CBC"
+#define NID_pbeWithMD2AndDES_CBC 9
+#define OBJ_pbeWithMD2AndDES_CBC OBJ_pkcs,5L,1L
+
+#define SN_pbeWithMD5AndDES_CBC "PBE-MD5-DES"
+#define LN_pbeWithMD5AndDES_CBC "pbeWithMD5AndDES-CBC"
+#define NID_pbeWithMD5AndDES_CBC 10
+#define OBJ_pbeWithMD5AndDES_CBC OBJ_pkcs,5L,3L
+
+#define LN_X500 "X500"
+#define NID_X500 11
+#define OBJ_X500 2L,5L
+
+#define LN_X509 "X509"
+#define NID_X509 12
+#define OBJ_X509 OBJ_X500,4L
+
+#define SN_commonName "CN"
+#define LN_commonName "commonName"
+#define NID_commonName 13
+#define OBJ_commonName OBJ_X509,3L
+
+#define SN_countryName "C"
+#define LN_countryName "countryName"
+#define NID_countryName 14
+#define OBJ_countryName OBJ_X509,6L
+
+#define SN_localityName "L"
+#define LN_localityName "localityName"
+#define NID_localityName 15
+#define OBJ_localityName OBJ_X509,7L
+
+/* Postal Address? PA */
+
+/* should be "ST" (rfc1327) but MS uses 'S' */
+#define SN_stateOrProvinceName "ST"
+#define LN_stateOrProvinceName "stateOrProvinceName"
+#define NID_stateOrProvinceName 16
+#define OBJ_stateOrProvinceName OBJ_X509,8L
+
+#define SN_organizationName "O"
+#define LN_organizationName "organizationName"
+#define NID_organizationName 17
+#define OBJ_organizationName OBJ_X509,10L
+
+#define SN_organizationalUnitName "OU"
+#define LN_organizationalUnitName "organizationalUnitName"
+#define NID_organizationalUnitName 18
+#define OBJ_organizationalUnitName OBJ_X509,11L
+
+#define SN_rsa "RSA"
+#define LN_rsa "rsa"
+#define NID_rsa 19
+#define OBJ_rsa OBJ_X500,8L,1L,1L
+
+#define LN_pkcs7 "pkcs7"
+#define NID_pkcs7 20
+#define OBJ_pkcs7 OBJ_pkcs,7L
+
+#define LN_pkcs7_data "pkcs7-data"
+#define NID_pkcs7_data 21
+#define OBJ_pkcs7_data OBJ_pkcs7,1L
+
+#define LN_pkcs7_signed "pkcs7-signedData"
+#define NID_pkcs7_signed 22
+#define OBJ_pkcs7_signed OBJ_pkcs7,2L
+
+#define LN_pkcs7_enveloped "pkcs7-envelopedData"
+#define NID_pkcs7_enveloped 23
+#define OBJ_pkcs7_enveloped OBJ_pkcs7,3L
+
+#define LN_pkcs7_signedAndEnveloped "pkcs7-signedAndEnvelopedData"
+#define NID_pkcs7_signedAndEnveloped 24
+#define OBJ_pkcs7_signedAndEnveloped OBJ_pkcs7,4L
+
+#define LN_pkcs7_digest "pkcs7-digestData"
+#define NID_pkcs7_digest 25
+#define OBJ_pkcs7_digest OBJ_pkcs7,5L
+
+#define LN_pkcs7_encrypted "pkcs7-encryptedData"
+#define NID_pkcs7_encrypted 26
+#define OBJ_pkcs7_encrypted OBJ_pkcs7,6L
+
+#define LN_pkcs3 "pkcs3"
+#define NID_pkcs3 27
+#define OBJ_pkcs3 OBJ_pkcs,3L
+
+#define LN_dhKeyAgreement "dhKeyAgreement"
+#define NID_dhKeyAgreement 28
+#define OBJ_dhKeyAgreement OBJ_pkcs3,1L
+
+#define SN_des_ecb "DES-ECB"
+#define LN_des_ecb "des-ecb"
+#define NID_des_ecb 29
+#define OBJ_des_ecb OBJ_algorithm,6L
+
+#define SN_des_cfb64 "DES-CFB"
+#define LN_des_cfb64 "des-cfb"
+#define NID_des_cfb64 30
+/* IV + num */
+#define OBJ_des_cfb64 OBJ_algorithm,9L
+
+#define SN_des_cbc "DES-CBC"
+#define LN_des_cbc "des-cbc"
+#define NID_des_cbc 31
+/* IV */
+#define OBJ_des_cbc OBJ_algorithm,7L
+
+#define SN_des_ede "DES-EDE"
+#define LN_des_ede "des-ede"
+#define NID_des_ede 32
+/* ?? */
+#define OBJ_des_ede OBJ_algorithm,17L
+
+#define SN_des_ede3 "DES-EDE3"
+#define LN_des_ede3 "des-ede3"
+#define NID_des_ede3 33
+
+#define SN_idea_cbc "IDEA-CBC"
+#define LN_idea_cbc "idea-cbc"
+#define NID_idea_cbc 34
+#define OBJ_idea_cbc 1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L
+
+#define SN_idea_cfb64 "IDEA-CFB"
+#define LN_idea_cfb64 "idea-cfb"
+#define NID_idea_cfb64 35
+
+#define SN_idea_ecb "IDEA-ECB"
+#define LN_idea_ecb "idea-ecb"
+#define NID_idea_ecb 36
+
+#define SN_rc2_cbc "RC2-CBC"
+#define LN_rc2_cbc "rc2-cbc"
+#define NID_rc2_cbc 37
+#define OBJ_rc2_cbc OBJ_rsadsi,3L,2L
+
+#define SN_rc2_ecb "RC2-ECB"
+#define LN_rc2_ecb "rc2-ecb"
+#define NID_rc2_ecb 38
+
+#define SN_rc2_cfb64 "RC2-CFB"
+#define LN_rc2_cfb64 "rc2-cfb"
+#define NID_rc2_cfb64 39
+
+#define SN_rc2_ofb64 "RC2-OFB"
+#define LN_rc2_ofb64 "rc2-ofb"
+#define NID_rc2_ofb64 40
+
+#define SN_sha "SHA"
+#define LN_sha "sha"
+#define NID_sha 41
+#define OBJ_sha OBJ_algorithm,18L
+
+#define SN_shaWithRSAEncryption "RSA-SHA"
+#define LN_shaWithRSAEncryption "shaWithRSAEncryption"
+#define NID_shaWithRSAEncryption 42
+#define OBJ_shaWithRSAEncryption OBJ_algorithm,15L
+
+#define SN_des_ede_cbc "DES-EDE-CBC"
+#define LN_des_ede_cbc "des-ede-cbc"
+#define NID_des_ede_cbc 43
+
+#define SN_des_ede3_cbc "DES-EDE3-CBC"
+#define LN_des_ede3_cbc "des-ede3-cbc"
+#define NID_des_ede3_cbc 44
+#define OBJ_des_ede3_cbc OBJ_rsadsi,3L,7L
+
+#define SN_des_ofb64 "DES-OFB"
+#define LN_des_ofb64 "des-ofb"
+#define NID_des_ofb64 45
+#define OBJ_des_ofb64 OBJ_algorithm,8L
+
+#define SN_idea_ofb64 "IDEA-OFB"
+#define LN_idea_ofb64 "idea-ofb"
+#define NID_idea_ofb64 46
+
+#define LN_pkcs9 "pkcs9"
+#define NID_pkcs9 47
+#define OBJ_pkcs9 OBJ_pkcs,9L
+
+#define SN_pkcs9_emailAddress "Email"
+#define LN_pkcs9_emailAddress "emailAddress"
+#define NID_pkcs9_emailAddress 48
+#define OBJ_pkcs9_emailAddress OBJ_pkcs9,1L
+
+#define LN_pkcs9_unstructuredName "unstructuredName"
+#define NID_pkcs9_unstructuredName 49
+#define OBJ_pkcs9_unstructuredName OBJ_pkcs9,2L
+
+#define LN_pkcs9_contentType "contentType"
+#define NID_pkcs9_contentType 50
+#define OBJ_pkcs9_contentType OBJ_pkcs9,3L
+
+#define LN_pkcs9_messageDigest "messageDigest"
+#define NID_pkcs9_messageDigest 51
+#define OBJ_pkcs9_messageDigest OBJ_pkcs9,4L
+
+#define LN_pkcs9_signingTime "signingTime"
+#define NID_pkcs9_signingTime 52
+#define OBJ_pkcs9_signingTime OBJ_pkcs9,5L
+
+#define LN_pkcs9_countersignature "countersignature"
+#define NID_pkcs9_countersignature 53
+#define OBJ_pkcs9_countersignature OBJ_pkcs9,6L
+
+#define LN_pkcs9_challengePassword "challengePassword"
+#define NID_pkcs9_challengePassword 54
+#define OBJ_pkcs9_challengePassword OBJ_pkcs9,7L
+
+#define LN_pkcs9_unstructuredAddress "unstructuredAddress"
+#define NID_pkcs9_unstructuredAddress 55
+#define OBJ_pkcs9_unstructuredAddress OBJ_pkcs9,8L
+
+#define LN_pkcs9_extCertAttributes "extendedCertificateAttributes"
+#define NID_pkcs9_extCertAttributes 56
+#define OBJ_pkcs9_extCertAttributes OBJ_pkcs9,9L
+
+#define SN_netscape "Netscape"
+#define LN_netscape "Netscape Communications Corp."
+#define NID_netscape 57
+#define OBJ_netscape 2L,16L,840L,1L,113730L
+
+#define SN_netscape_cert_extension "nsCertExt"
+#define LN_netscape_cert_extension "Netscape Certificate Extension"
+#define NID_netscape_cert_extension 58
+#define OBJ_netscape_cert_extension OBJ_netscape,1L
+
+#define SN_netscape_data_type "nsDataType"
+#define LN_netscape_data_type "Netscape Data Type"
+#define NID_netscape_data_type 59
+#define OBJ_netscape_data_type OBJ_netscape,2L
+
+#define SN_des_ede_cfb64 "DES-EDE-CFB"
+#define LN_des_ede_cfb64 "des-ede-cfb"
+#define NID_des_ede_cfb64 60
+
+#define SN_des_ede3_cfb64 "DES-EDE3-CFB"
+#define LN_des_ede3_cfb64 "des-ede3-cfb"
+#define NID_des_ede3_cfb64 61
+
+#define SN_des_ede_ofb64 "DES-EDE-OFB"
+#define LN_des_ede_ofb64 "des-ede-ofb"
+#define NID_des_ede_ofb64 62
+
+#define SN_des_ede3_ofb64 "DES-EDE3-OFB"
+#define LN_des_ede3_ofb64 "des-ede3-ofb"
+#define NID_des_ede3_ofb64 63
+
+/* I'm not sure about the object ID */
+#define SN_sha1 "SHA1"
+#define LN_sha1 "sha1"
+#define NID_sha1 64
+#define OBJ_sha1 OBJ_algorithm,26L
+/* 28 Jun 1996 - eay */
+/* #define OBJ_sha1 1L,3L,14L,2L,26L,05L <- wrong */
+
+#define SN_sha1WithRSAEncryption "RSA-SHA1"
+#define LN_sha1WithRSAEncryption "sha1WithRSAEncryption"
+#define NID_sha1WithRSAEncryption 65
+#define OBJ_sha1WithRSAEncryption OBJ_pkcs,1L,5L
+
+#define SN_dsaWithSHA "DSA-SHA"
+#define LN_dsaWithSHA "dsaWithSHA"
+#define NID_dsaWithSHA 66
+#define OBJ_dsaWithSHA OBJ_algorithm,13L
+
+#define SN_dsa_2 "DSA-old"
+#define LN_dsa_2 "dsaEncryption-old"
+#define NID_dsa_2 67
+#define OBJ_dsa_2 OBJ_algorithm,12L
+
+/* proposed by microsoft to RSA */
+#define SN_pbeWithSHA1AndRC2_CBC "PBE-SHA1-RC2-64"
+#define LN_pbeWithSHA1AndRC2_CBC "pbeWithSHA1AndRC2-CBC"
+#define NID_pbeWithSHA1AndRC2_CBC 68
+#define OBJ_pbeWithSHA1AndRC2_CBC OBJ_pkcs,5L,11L
+
+/* proposed by microsoft to RSA as pbeWithSHA1AndRC4: it is now
+ * defined explicitly in PKCS#5 v2.0 as id-PBKDF2 which is something
+ * completely different.
+ */
+#define LN_id_pbkdf2 "PBKDF2"
+#define NID_id_pbkdf2 69
+#define OBJ_id_pbkdf2 OBJ_pkcs,5L,12L
+
+#define SN_dsaWithSHA1_2 "DSA-SHA1-old"
+#define LN_dsaWithSHA1_2 "dsaWithSHA1-old"
+#define NID_dsaWithSHA1_2 70
+/* Got this one from 'sdn706r20.pdf' which is actually an NSA document :-) */
+#define OBJ_dsaWithSHA1_2 OBJ_algorithm,27L
+
+#define SN_netscape_cert_type "nsCertType"
+#define LN_netscape_cert_type "Netscape Cert Type"
+#define NID_netscape_cert_type 71
+#define OBJ_netscape_cert_type OBJ_netscape_cert_extension,1L
+
+#define SN_netscape_base_url "nsBaseUrl"
+#define LN_netscape_base_url "Netscape Base Url"
+#define NID_netscape_base_url 72
+#define OBJ_netscape_base_url OBJ_netscape_cert_extension,2L
+
+#define SN_netscape_revocation_url "nsRevocationUrl"
+#define LN_netscape_revocation_url "Netscape Revocation Url"
+#define NID_netscape_revocation_url 73
+#define OBJ_netscape_revocation_url OBJ_netscape_cert_extension,3L
+
+#define SN_netscape_ca_revocation_url "nsCaRevocationUrl"
+#define LN_netscape_ca_revocation_url "Netscape CA Revocation Url"
+#define NID_netscape_ca_revocation_url 74
+#define OBJ_netscape_ca_revocation_url OBJ_netscape_cert_extension,4L
+
+#define SN_netscape_renewal_url "nsRenewalUrl"
+#define LN_netscape_renewal_url "Netscape Renewal Url"
+#define NID_netscape_renewal_url 75
+#define OBJ_netscape_renewal_url OBJ_netscape_cert_extension,7L
+
+#define SN_netscape_ca_policy_url "nsCaPolicyUrl"
+#define LN_netscape_ca_policy_url "Netscape CA Policy Url"
+#define NID_netscape_ca_policy_url 76
+#define OBJ_netscape_ca_policy_url OBJ_netscape_cert_extension,8L
+
+#define SN_netscape_ssl_server_name "nsSslServerName"
+#define LN_netscape_ssl_server_name "Netscape SSL Server Name"
+#define NID_netscape_ssl_server_name 77
+#define OBJ_netscape_ssl_server_name OBJ_netscape_cert_extension,12L
+
+#define SN_netscape_comment "nsComment"
+#define LN_netscape_comment "Netscape Comment"
+#define NID_netscape_comment 78
+#define OBJ_netscape_comment OBJ_netscape_cert_extension,13L
+
+#define SN_netscape_cert_sequence "nsCertSequence"
+#define LN_netscape_cert_sequence "Netscape Certificate Sequence"
+#define NID_netscape_cert_sequence 79
+#define OBJ_netscape_cert_sequence OBJ_netscape_data_type,5L
+
+#define SN_desx_cbc "DESX-CBC"
+#define LN_desx_cbc "desx-cbc"
+#define NID_desx_cbc 80
+
+#define SN_id_ce "id-ce"
+#define NID_id_ce 81
+#define OBJ_id_ce 2L,5L,29L
+
+#define SN_subject_key_identifier "subjectKeyIdentifier"
+#define LN_subject_key_identifier "X509v3 Subject Key Identifier"
+#define NID_subject_key_identifier 82
+#define OBJ_subject_key_identifier OBJ_id_ce,14L
+
+#define SN_key_usage "keyUsage"
+#define LN_key_usage "X509v3 Key Usage"
+#define NID_key_usage 83
+#define OBJ_key_usage OBJ_id_ce,15L
+
+#define SN_private_key_usage_period "privateKeyUsagePeriod"
+#define LN_private_key_usage_period "X509v3 Private Key Usage Period"
+#define NID_private_key_usage_period 84
+#define OBJ_private_key_usage_period OBJ_id_ce,16L
+
+#define SN_subject_alt_name "subjectAltName"
+#define LN_subject_alt_name "X509v3 Subject Alternative Name"
+#define NID_subject_alt_name 85
+#define OBJ_subject_alt_name OBJ_id_ce,17L
+
+#define SN_issuer_alt_name "issuerAltName"
+#define LN_issuer_alt_name "X509v3 Issuer Alternative Name"
+#define NID_issuer_alt_name 86
+#define OBJ_issuer_alt_name OBJ_id_ce,18L
+
+#define SN_basic_constraints "basicConstraints"
+#define LN_basic_constraints "X509v3 Basic Constraints"
+#define NID_basic_constraints 87
+#define OBJ_basic_constraints OBJ_id_ce,19L
+
+#define SN_crl_number "crlNumber"
+#define LN_crl_number "X509v3 CRL Number"
+#define NID_crl_number 88
+#define OBJ_crl_number OBJ_id_ce,20L
+
+#define SN_certificate_policies "certificatePolicies"
+#define LN_certificate_policies "X509v3 Certificate Policies"
+#define NID_certificate_policies 89
+#define OBJ_certificate_policies OBJ_id_ce,32L
+
+#define SN_authority_key_identifier "authorityKeyIdentifier"
+#define LN_authority_key_identifier "X509v3 Authority Key Identifier"
+#define NID_authority_key_identifier 90
+#define OBJ_authority_key_identifier OBJ_id_ce,35L
+
+#define SN_bf_cbc "BF-CBC"
+#define LN_bf_cbc "bf-cbc"
+#define NID_bf_cbc 91
+#define OBJ_bf_cbc 1L,3L,6L,1L,4L,1L,3029L,1L,2L
+
+#define SN_bf_ecb "BF-ECB"
+#define LN_bf_ecb "bf-ecb"
+#define NID_bf_ecb 92
+
+#define SN_bf_cfb64 "BF-CFB"
+#define LN_bf_cfb64 "bf-cfb"
+#define NID_bf_cfb64 93
+
+#define SN_bf_ofb64 "BF-OFB"
+#define LN_bf_ofb64 "bf-ofb"
+#define NID_bf_ofb64 94
+
+#define SN_mdc2 "MDC2"
+#define LN_mdc2 "mdc2"
+#define NID_mdc2 95
+#define OBJ_mdc2 2L,5L,8L,3L,101L
+/* An alternative? 1L,3L,14L,3L,2L,19L */
+
+#define SN_mdc2WithRSA "RSA-MDC2"
+#define LN_mdc2WithRSA "mdc2withRSA"
+#define NID_mdc2WithRSA 96
+#define OBJ_mdc2WithRSA 2L,5L,8L,3L,100L
+
+#define SN_rc4_40 "RC4-40"
+#define LN_rc4_40 "rc4-40"
+#define NID_rc4_40 97
+
+#define SN_rc2_40_cbc "RC2-40-CBC"
+#define LN_rc2_40_cbc "rc2-40-cbc"
+#define NID_rc2_40_cbc 98
+
+#define SN_givenName "G"
+#define LN_givenName "givenName"
+#define NID_givenName 99
+#define OBJ_givenName OBJ_X509,42L
+
+#define SN_surname "S"
+#define LN_surname "surname"
+#define NID_surname 100
+#define OBJ_surname OBJ_X509,4L
+
+#define SN_initials "I"
+#define LN_initials "initials"
+#define NID_initials 101
+#define OBJ_initials OBJ_X509,43L
+
+#define SN_uniqueIdentifier "UID"
+#define LN_uniqueIdentifier "uniqueIdentifier"
+#define NID_uniqueIdentifier 102
+#define OBJ_uniqueIdentifier OBJ_X509,45L
+
+#define SN_crl_distribution_points "crlDistributionPoints"
+#define LN_crl_distribution_points "X509v3 CRL Distribution Points"
+#define NID_crl_distribution_points 103
+#define OBJ_crl_distribution_points OBJ_id_ce,31L
+
+#define SN_md5WithRSA "RSA-NP-MD5"
+#define LN_md5WithRSA "md5WithRSA"
+#define NID_md5WithRSA 104
+#define OBJ_md5WithRSA OBJ_algorithm,3L
+
+#define SN_serialNumber "SN"
+#define LN_serialNumber "serialNumber"
+#define NID_serialNumber 105
+#define OBJ_serialNumber OBJ_X509,5L
+
+#define SN_title "T"
+#define LN_title "title"
+#define NID_title 106
+#define OBJ_title OBJ_X509,12L
+
+#define SN_description "D"
+#define LN_description "description"
+#define NID_description 107
+#define OBJ_description OBJ_X509,13L
+
+/* CAST5 is CAST-128, I'm just sticking with the documentation */
+#define SN_cast5_cbc "CAST5-CBC"
+#define LN_cast5_cbc "cast5-cbc"
+#define NID_cast5_cbc 108
+#define OBJ_cast5_cbc 1L,2L,840L,113533L,7L,66L,10L
+
+#define SN_cast5_ecb "CAST5-ECB"
+#define LN_cast5_ecb "cast5-ecb"
+#define NID_cast5_ecb 109
+
+#define SN_cast5_cfb64 "CAST5-CFB"
+#define LN_cast5_cfb64 "cast5-cfb"
+#define NID_cast5_cfb64 110
+
+#define SN_cast5_ofb64 "CAST5-OFB"
+#define LN_cast5_ofb64 "cast5-ofb"
+#define NID_cast5_ofb64 111
+
+#define LN_pbeWithMD5AndCast5_CBC "pbeWithMD5AndCast5CBC"
+#define NID_pbeWithMD5AndCast5_CBC 112
+#define OBJ_pbeWithMD5AndCast5_CBC 1L,2L,840L,113533L,7L,66L,12L
+
+/* This is one sun will soon be using :-(
+ * id-dsa-with-sha1 ID ::= {
+ * iso(1) member-body(2) us(840) x9-57 (10040) x9cm(4) 3 }
+ */
+#define SN_dsaWithSHA1 "DSA-SHA1"
+#define LN_dsaWithSHA1 "dsaWithSHA1"
+#define NID_dsaWithSHA1 113
+#define OBJ_dsaWithSHA1 1L,2L,840L,10040L,4L,3L
+
+#define NID_md5_sha1 114
+#define SN_md5_sha1 "MD5-SHA1"
+#define LN_md5_sha1 "md5-sha1"
+
+#define SN_sha1WithRSA "RSA-SHA1-2"
+#define LN_sha1WithRSA "sha1WithRSA"
+#define NID_sha1WithRSA 115
+#define OBJ_sha1WithRSA OBJ_algorithm,29L
+
+#define SN_dsa "DSA"
+#define LN_dsa "dsaEncryption"
+#define NID_dsa 116
+#define OBJ_dsa 1L,2L,840L,10040L,4L,1L
+
+#define SN_ripemd160 "RIPEMD160"
+#define LN_ripemd160 "ripemd160"
+#define NID_ripemd160 117
+#define OBJ_ripemd160 1L,3L,36L,3L,2L,1L
+
+/* The name should actually be rsaSignatureWithripemd160, but I'm going
+ * to continue using the convention I'm using with the other ciphers */
+#define SN_ripemd160WithRSA "RSA-RIPEMD160"
+#define LN_ripemd160WithRSA "ripemd160WithRSA"
+#define NID_ripemd160WithRSA 119
+#define OBJ_ripemd160WithRSA 1L,3L,36L,3L,3L,1L,2L
+
+/* Taken from rfc2040
+ * RC5_CBC_Parameters ::= SEQUENCE {
+ * version INTEGER (v1_0(16)),
+ * rounds INTEGER (8..127),
+ * blockSizeInBits INTEGER (64, 128),
+ * iv OCTET STRING OPTIONAL
+ * }
+ */
+#define SN_rc5_cbc "RC5-CBC"
+#define LN_rc5_cbc "rc5-cbc"
+#define NID_rc5_cbc 120
+#define OBJ_rc5_cbc OBJ_rsadsi,3L,8L
+
+#define SN_rc5_ecb "RC5-ECB"
+#define LN_rc5_ecb "rc5-ecb"
+#define NID_rc5_ecb 121
+
+#define SN_rc5_cfb64 "RC5-CFB"
+#define LN_rc5_cfb64 "rc5-cfb"
+#define NID_rc5_cfb64 122
+
+#define SN_rc5_ofb64 "RC5-OFB"
+#define LN_rc5_ofb64 "rc5-ofb"
+#define NID_rc5_ofb64 123
+
+#define SN_rle_compression "RLE"
+#define LN_rle_compression "run length compression"
+#define NID_rle_compression 124
+#define OBJ_rle_compression 1L,1L,1L,1L,666L,1L
+
+#define SN_zlib_compression "ZLIB"
+#define LN_zlib_compression "zlib compression"
+#define NID_zlib_compression 125
+#define OBJ_zlib_compression 1L,1L,1L,1L,666L,2L
+
+#define SN_ext_key_usage "extendedKeyUsage"
+#define LN_ext_key_usage "X509v3 Extended Key Usage"
+#define NID_ext_key_usage 126
+#define OBJ_ext_key_usage OBJ_id_ce,37
+
+#define SN_id_pkix "PKIX"
+#define NID_id_pkix 127
+#define OBJ_id_pkix 1L,3L,6L,1L,5L,5L,7L
+
+#define SN_id_kp "id-kp"
+#define NID_id_kp 128
+#define OBJ_id_kp OBJ_id_pkix,3L
+
+/* PKIX extended key usage OIDs */
+
+#define SN_server_auth "serverAuth"
+#define LN_server_auth "TLS Web Server Authentication"
+#define NID_server_auth 129
+#define OBJ_server_auth OBJ_id_kp,1L
+
+#define SN_client_auth "clientAuth"
+#define LN_client_auth "TLS Web Client Authentication"
+#define NID_client_auth 130
+#define OBJ_client_auth OBJ_id_kp,2L
+
+#define SN_code_sign "codeSigning"
+#define LN_code_sign "Code Signing"
+#define NID_code_sign 131
+#define OBJ_code_sign OBJ_id_kp,3L
+
+#define SN_email_protect "emailProtection"
+#define LN_email_protect "E-mail Protection"
+#define NID_email_protect 132
+#define OBJ_email_protect OBJ_id_kp,4L
+
+#define SN_time_stamp "timeStamping"
+#define LN_time_stamp "Time Stamping"
+#define NID_time_stamp 133
+#define OBJ_time_stamp OBJ_id_kp,8L
+
+/* Additional extended key usage OIDs: Microsoft */
+
+#define SN_ms_code_ind "msCodeInd"
+#define LN_ms_code_ind "Microsoft Individual Code Signing"
+#define NID_ms_code_ind 134
+#define OBJ_ms_code_ind 1L,3L,6L,1L,4L,1L,311L,2L,1L,21L
+
+#define SN_ms_code_com "msCodeCom"
+#define LN_ms_code_com "Microsoft Commercial Code Signing"
+#define NID_ms_code_com 135
+#define OBJ_ms_code_com 1L,3L,6L,1L,4L,1L,311L,2L,1L,22L
+
+#define SN_ms_ctl_sign "msCTLSign"
+#define LN_ms_ctl_sign "Microsoft Trust List Signing"
+#define NID_ms_ctl_sign 136
+#define OBJ_ms_ctl_sign 1L,3L,6L,1L,4L,1L,311L,10L,3L,1L
+
+#define SN_ms_sgc "msSGC"
+#define LN_ms_sgc "Microsoft Server Gated Crypto"
+#define NID_ms_sgc 137
+#define OBJ_ms_sgc 1L,3L,6L,1L,4L,1L,311L,10L,3L,3L
+
+#define SN_ms_efs "msEFS"
+#define LN_ms_efs "Microsoft Encrypted File System"
+#define NID_ms_efs 138
+#define OBJ_ms_efs 1L,3L,6L,1L,4L,1L,311L,10L,3L,4L
+
+/* Additional usage: Netscape */
+
+#define SN_ns_sgc "nsSGC"
+#define LN_ns_sgc "Netscape Server Gated Crypto"
+#define NID_ns_sgc 139
+#define OBJ_ns_sgc OBJ_netscape,4L,1L
+
+#define SN_delta_crl "deltaCRL"
+#define LN_delta_crl "X509v3 Delta CRL Indicator"
+#define NID_delta_crl 140
+#define OBJ_delta_crl OBJ_id_ce,27L
+
+#define SN_crl_reason "CRLReason"
+#define LN_crl_reason "CRL Reason Code"
+#define NID_crl_reason 141
+#define OBJ_crl_reason OBJ_id_ce,21L
+
+#define SN_invalidity_date "invalidityDate"
+#define LN_invalidity_date "Invalidity Date"
+#define NID_invalidity_date 142
+#define OBJ_invalidity_date OBJ_id_ce,24L
+
+#define SN_sxnet "SXNetID"
+#define LN_sxnet "Strong Extranet ID"
+#define NID_sxnet 143
+#define OBJ_sxnet 1L,3L,101L,1L,4L,1L
+
+/* PKCS12 and related OBJECT IDENTIFIERS */
+
+#define OBJ_pkcs12 OBJ_pkcs,12L
+#define OBJ_pkcs12_pbeids OBJ_pkcs12, 1
+
+#define SN_pbe_WithSHA1And128BitRC4 "PBE-SHA1-RC4-128"
+#define LN_pbe_WithSHA1And128BitRC4 "pbeWithSHA1And128BitRC4"
+#define NID_pbe_WithSHA1And128BitRC4 144
+#define OBJ_pbe_WithSHA1And128BitRC4 OBJ_pkcs12_pbeids, 1L
+
+#define SN_pbe_WithSHA1And40BitRC4 "PBE-SHA1-RC4-40"
+#define LN_pbe_WithSHA1And40BitRC4 "pbeWithSHA1And40BitRC4"
+#define NID_pbe_WithSHA1And40BitRC4 145
+#define OBJ_pbe_WithSHA1And40BitRC4 OBJ_pkcs12_pbeids, 2L
+
+#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC "PBE-SHA1-3DES"
+#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC "pbeWithSHA1And3-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146
+#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC OBJ_pkcs12_pbeids, 3L
+
+#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC "PBE-SHA1-2DES"
+#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC "pbeWithSHA1And2-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147
+#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC OBJ_pkcs12_pbeids, 4L
+
+#define SN_pbe_WithSHA1And128BitRC2_CBC "PBE-SHA1-RC2-128"
+#define LN_pbe_WithSHA1And128BitRC2_CBC "pbeWithSHA1And128BitRC2-CBC"
+#define NID_pbe_WithSHA1And128BitRC2_CBC 148
+#define OBJ_pbe_WithSHA1And128BitRC2_CBC OBJ_pkcs12_pbeids, 5L
+
+#define SN_pbe_WithSHA1And40BitRC2_CBC "PBE-SHA1-RC2-40"
+#define LN_pbe_WithSHA1And40BitRC2_CBC "pbeWithSHA1And40BitRC2-CBC"
+#define NID_pbe_WithSHA1And40BitRC2_CBC 149
+#define OBJ_pbe_WithSHA1And40BitRC2_CBC OBJ_pkcs12_pbeids, 6L
+
+#define OBJ_pkcs12_Version1 OBJ_pkcs12, 10L
+
+#define OBJ_pkcs12_BagIds OBJ_pkcs12_Version1, 1L
+
+#define LN_keyBag "keyBag"
+#define NID_keyBag 150
+#define OBJ_keyBag OBJ_pkcs12_BagIds, 1L
+
+#define LN_pkcs8ShroudedKeyBag "pkcs8ShroudedKeyBag"
+#define NID_pkcs8ShroudedKeyBag 151
+#define OBJ_pkcs8ShroudedKeyBag OBJ_pkcs12_BagIds, 2L
+
+#define LN_certBag "certBag"
+#define NID_certBag 152
+#define OBJ_certBag OBJ_pkcs12_BagIds, 3L
+
+#define LN_crlBag "crlBag"
+#define NID_crlBag 153
+#define OBJ_crlBag OBJ_pkcs12_BagIds, 4L
+
+#define LN_secretBag "secretBag"
+#define NID_secretBag 154
+#define OBJ_secretBag OBJ_pkcs12_BagIds, 5L
+
+#define LN_safeContentsBag "safeContentsBag"
+#define NID_safeContentsBag 155
+#define OBJ_safeContentsBag OBJ_pkcs12_BagIds, 6L
+
+#define LN_friendlyName "friendlyName"
+#define NID_friendlyName 156
+#define OBJ_friendlyName OBJ_pkcs9, 20L
+
+#define LN_localKeyID "localKeyID"
+#define NID_localKeyID 157
+#define OBJ_localKeyID OBJ_pkcs9, 21L
+
+#define OBJ_certTypes OBJ_pkcs9, 22L
+
+#define LN_x509Certificate "x509Certificate"
+#define NID_x509Certificate 158
+#define OBJ_x509Certificate OBJ_certTypes, 1L
+
+#define LN_sdsiCertificate "sdsiCertificate"
+#define NID_sdsiCertificate 159
+#define OBJ_sdsiCertificate OBJ_certTypes, 2L
+
+#define OBJ_crlTypes OBJ_pkcs9, 23L
+
+#define LN_x509Crl "x509Crl"
+#define NID_x509Crl 160
+#define OBJ_x509Crl OBJ_crlTypes, 1L
+
+/* PKCS#5 v2 OIDs */
+
+#define LN_pbes2 "PBES2"
+#define NID_pbes2 161
+#define OBJ_pbes2 OBJ_pkcs,5L,13L
+
+#define LN_pbmac1 "PBMAC1"
+#define NID_pbmac1 162
+#define OBJ_pbmac1 OBJ_pkcs,5L,14L
+
+#define LN_hmacWithSHA1 "hmacWithSHA1"
+#define NID_hmacWithSHA1 163
+#define OBJ_hmacWithSHA1 OBJ_rsadsi,2L,7L
+
+/* Policy Qualifier Ids */
+
+#define LN_id_qt_cps "Policy Qualifier CPS"
+#define SN_id_qt_cps "id-qt-cps"
+#define NID_id_qt_cps 164
+#define OBJ_id_qt_cps OBJ_id_pkix,2L,1L
+
+#define LN_id_qt_unotice "Policy Qualifier User Notice"
+#define SN_id_qt_unotice "id-qt-unotice"
+#define NID_id_qt_unotice 165
+#define OBJ_id_qt_unotice OBJ_id_pkix,2L,2L
+
+#define SN_rc2_64_cbc "RC2-64-CBC"
+#define LN_rc2_64_cbc "rc2-64-cbc"
+#define NID_rc2_64_cbc 166
+
+#define SN_SMIMECapabilities "SMIME-CAPS"
+#define LN_SMIMECapabilities "S/MIME Capabilities"
+#define NID_SMIMECapabilities 167
+#define OBJ_SMIMECapabilities OBJ_pkcs9,15L
+
+#define SN_pbeWithMD2AndRC2_CBC "PBE-MD2-RC2-64"
+#define LN_pbeWithMD2AndRC2_CBC "pbeWithMD2AndRC2-CBC"
+#define NID_pbeWithMD2AndRC2_CBC 168
+#define OBJ_pbeWithMD2AndRC2_CBC OBJ_pkcs,5L,4L
+
+#define SN_pbeWithMD5AndRC2_CBC "PBE-MD5-RC2-64"
+#define LN_pbeWithMD5AndRC2_CBC "pbeWithMD5AndRC2-CBC"
+#define NID_pbeWithMD5AndRC2_CBC 169
+#define OBJ_pbeWithMD5AndRC2_CBC OBJ_pkcs,5L,6L
+
+#define SN_pbeWithSHA1AndDES_CBC "PBE-SHA1-DES"
+#define LN_pbeWithSHA1AndDES_CBC "pbeWithSHA1AndDES-CBC"
+#define NID_pbeWithSHA1AndDES_CBC 170
+#define OBJ_pbeWithSHA1AndDES_CBC OBJ_pkcs,5L,10L
+
+/* Extension request OIDs */
+
+#define LN_ms_ext_req "Microsoft Extension Request"
+#define SN_ms_ext_req "msExtReq"
+#define NID_ms_ext_req 171
+#define OBJ_ms_ext_req 1L,3L,6L,1L,4L,1L,311L,2L,1L,14L
+
+#define LN_ext_req "Extension Request"
+#define SN_ext_req "extReq"
+#define NID_ext_req 172
+#define OBJ_ext_req OBJ_pkcs9,14L
+
+#define SN_name "name"
+#define LN_name "name"
+#define NID_name 173
+#define OBJ_name OBJ_X509,41L
+
+#define SN_dnQualifier "dnQualifier"
+#define LN_dnQualifier "dnQualifier"
+#define NID_dnQualifier 174
+#define OBJ_dnQualifier OBJ_X509,46L
+
+#define SN_id_pe "id-pe"
+#define NID_id_pe 175
+#define OBJ_id_pe OBJ_id_pkix,1L
+
+#define SN_id_ad "id-ad"
+#define NID_id_ad 176
+#define OBJ_id_ad OBJ_id_pkix,48L
+
+#define SN_info_access "authorityInfoAccess"
+#define LN_info_access "Authority Information Access"
+#define NID_info_access 177
+#define OBJ_info_access OBJ_id_pe,1L
+
+#define SN_ad_OCSP "OCSP"
+#define LN_ad_OCSP "OCSP"
+#define NID_ad_OCSP 178
+#define OBJ_ad_OCSP OBJ_id_ad,1L
+
+#define SN_ad_ca_issuers "caIssuers"
+#define LN_ad_ca_issuers "CA Issuers"
+#define NID_ad_ca_issuers 179
+#define OBJ_ad_ca_issuers OBJ_id_ad,2L
+
+#define SN_OCSP_sign "OCSPSigning"
+#define LN_OCSP_sign "OCSP Signing"
+#define NID_OCSP_sign 180
+#define OBJ_OCSP_sign OBJ_id_kp,9L
+#endif /* USE_OBJ_MAC */
+
+#include <openssl/bio.h>
+#include <openssl/asn1.h>
+
+#define OBJ_NAME_TYPE_UNDEF 0x00
+#define OBJ_NAME_TYPE_MD_METH 0x01
+#define OBJ_NAME_TYPE_CIPHER_METH 0x02
+#define OBJ_NAME_TYPE_PKEY_METH 0x03
+#define OBJ_NAME_TYPE_COMP_METH 0x04
+#define OBJ_NAME_TYPE_NUM 0x05
+
+#define OBJ_NAME_ALIAS 0x8000
+
+#define OBJ_BSEARCH_VALUE_ON_NOMATCH 0x01
+#define OBJ_BSEARCH_FIRST_VALUE_ON_MATCH 0x02
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct obj_name_st
+ {
+ int type;
+ int alias;
+ const char *name;
+ const char *data;
+ } OBJ_NAME;
+
+#define OBJ_create_and_add_object(a,b,c) OBJ_create(a,b,c)
+
+
+int OBJ_NAME_init(void);
+int OBJ_NAME_new_index(unsigned long (*hash_func)(const char *),
+ int (*cmp_func)(const char *, const char *),
+ void (*free_func)(const char *, int, const char *));
+const char *OBJ_NAME_get(const char *name,int type);
+int OBJ_NAME_add(const char *name,int type,const char *data);
+int OBJ_NAME_remove(const char *name,int type);
+void OBJ_NAME_cleanup(int type); /* -1 for everything */
+void OBJ_NAME_do_all(int type,void (*fn)(const OBJ_NAME *,void *arg),
+ void *arg);
+void OBJ_NAME_do_all_sorted(int type,void (*fn)(const OBJ_NAME *,void *arg),
+ void *arg);
+
+ASN1_OBJECT * OBJ_dup(const ASN1_OBJECT *o);
+ASN1_OBJECT * OBJ_nid2obj(int n);
+const char * OBJ_nid2ln(int n);
+const char * OBJ_nid2sn(int n);
+int OBJ_obj2nid(const ASN1_OBJECT *o);
+ASN1_OBJECT * OBJ_txt2obj(const char *s, int no_name);
+int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name);
+int OBJ_txt2nid(const char *s);
+int OBJ_ln2nid(const char *s);
+int OBJ_sn2nid(const char *s);
+int OBJ_cmp(const ASN1_OBJECT *a,const ASN1_OBJECT *b);
+const char * OBJ_bsearch(const char *key,const char *base,int num,int size,
+ int (*cmp)(const void *, const void *));
+const char * OBJ_bsearch_ex(const char *key,const char *base,int num,
+ int size, int (*cmp)(const void *, const void *), int flags);
+
+int OBJ_new_nid(int num);
+int OBJ_add_object(const ASN1_OBJECT *obj);
+int OBJ_create(const char *oid,const char *sn,const char *ln);
+void OBJ_cleanup(void );
+int OBJ_create_objects(BIO *in);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_OBJ_strings(void);
+
+/* Error codes for the OBJ functions. */
+
+/* Function codes. */
+#define OBJ_F_OBJ_ADD_OBJECT 105
+#define OBJ_F_OBJ_CREATE 100
+#define OBJ_F_OBJ_DUP 101
+#define OBJ_F_OBJ_NAME_NEW_INDEX 106
+#define OBJ_F_OBJ_NID2LN 102
+#define OBJ_F_OBJ_NID2OBJ 103
+#define OBJ_F_OBJ_NID2SN 104
+
+/* Reason codes. */
+#define OBJ_R_MALLOC_FAILURE 100
+#define OBJ_R_UNKNOWN_NID 101
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ocsp.h b/src/Mayaqua/win32_inc/openssl/ocsp.h
new file mode 100644
index 00000000..a9b7160a
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ocsp.h
@@ -0,0 +1,623 @@
+/* ocsp.h */
+/* Written by Tom Titchener <Tom_Titchener@groove.net> for the OpenSSL
+ * project. */
+
+/* History:
+ This file was transfered to Richard Levitte from CertCo by Kathy
+ Weinhold in mid-spring 2000 to be included in OpenSSL or released
+ as a patch kit. */
+
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_OCSP_H
+#define HEADER_OCSP_H
+
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/safestack.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Various flags and values */
+
+#define OCSP_DEFAULT_NONCE_LENGTH 16
+
+#define OCSP_NOCERTS 0x1
+#define OCSP_NOINTERN 0x2
+#define OCSP_NOSIGS 0x4
+#define OCSP_NOCHAIN 0x8
+#define OCSP_NOVERIFY 0x10
+#define OCSP_NOEXPLICIT 0x20
+#define OCSP_NOCASIGN 0x40
+#define OCSP_NODELEGATED 0x80
+#define OCSP_NOCHECKS 0x100
+#define OCSP_TRUSTOTHER 0x200
+#define OCSP_RESPID_KEY 0x400
+#define OCSP_NOTIME 0x800
+
+/* CertID ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * issuerNameHash OCTET STRING, -- Hash of Issuer's DN
+ * issuerKeyHash OCTET STRING, -- Hash of Issuers public key (excluding the tag & length fields)
+ * serialNumber CertificateSerialNumber }
+ */
+typedef struct ocsp_cert_id_st
+ {
+ X509_ALGOR *hashAlgorithm;
+ ASN1_OCTET_STRING *issuerNameHash;
+ ASN1_OCTET_STRING *issuerKeyHash;
+ ASN1_INTEGER *serialNumber;
+ } OCSP_CERTID;
+
+DECLARE_STACK_OF(OCSP_CERTID)
+
+/* Request ::= SEQUENCE {
+ * reqCert CertID,
+ * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_one_request_st
+ {
+ OCSP_CERTID *reqCert;
+ STACK_OF(X509_EXTENSION) *singleRequestExtensions;
+ } OCSP_ONEREQ;
+
+DECLARE_STACK_OF(OCSP_ONEREQ)
+DECLARE_ASN1_SET_OF(OCSP_ONEREQ)
+
+
+/* TBSRequest ::= SEQUENCE {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * requestorName [1] EXPLICIT GeneralName OPTIONAL,
+ * requestList SEQUENCE OF Request,
+ * requestExtensions [2] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_req_info_st
+ {
+ ASN1_INTEGER *version;
+ GENERAL_NAME *requestorName;
+ STACK_OF(OCSP_ONEREQ) *requestList;
+ STACK_OF(X509_EXTENSION) *requestExtensions;
+ } OCSP_REQINFO;
+
+/* Signature ::= SEQUENCE {
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING,
+ * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ */
+typedef struct ocsp_signature_st
+ {
+ X509_ALGOR *signatureAlgorithm;
+ ASN1_BIT_STRING *signature;
+ STACK_OF(X509) *certs;
+ } OCSP_SIGNATURE;
+
+/* OCSPRequest ::= SEQUENCE {
+ * tbsRequest TBSRequest,
+ * optionalSignature [0] EXPLICIT Signature OPTIONAL }
+ */
+typedef struct ocsp_request_st
+ {
+ OCSP_REQINFO *tbsRequest;
+ OCSP_SIGNATURE *optionalSignature; /* OPTIONAL */
+ } OCSP_REQUEST;
+
+/* OCSPResponseStatus ::= ENUMERATED {
+ * successful (0), --Response has valid confirmations
+ * malformedRequest (1), --Illegal confirmation request
+ * internalError (2), --Internal error in issuer
+ * tryLater (3), --Try again later
+ * --(4) is not used
+ * sigRequired (5), --Must sign the request
+ * unauthorized (6) --Request unauthorized
+ * }
+ */
+#define OCSP_RESPONSE_STATUS_SUCCESSFUL 0
+#define OCSP_RESPONSE_STATUS_MALFORMEDREQUEST 1
+#define OCSP_RESPONSE_STATUS_INTERNALERROR 2
+#define OCSP_RESPONSE_STATUS_TRYLATER 3
+#define OCSP_RESPONSE_STATUS_SIGREQUIRED 5
+#define OCSP_RESPONSE_STATUS_UNAUTHORIZED 6
+
+/* ResponseBytes ::= SEQUENCE {
+ * responseType OBJECT IDENTIFIER,
+ * response OCTET STRING }
+ */
+typedef struct ocsp_resp_bytes_st
+ {
+ ASN1_OBJECT *responseType;
+ ASN1_OCTET_STRING *response;
+ } OCSP_RESPBYTES;
+
+/* OCSPResponse ::= SEQUENCE {
+ * responseStatus OCSPResponseStatus,
+ * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
+ */
+struct ocsp_response_st
+ {
+ ASN1_ENUMERATED *responseStatus;
+ OCSP_RESPBYTES *responseBytes;
+ };
+
+/* ResponderID ::= CHOICE {
+ * byName [1] Name,
+ * byKey [2] KeyHash }
+ */
+#define V_OCSP_RESPID_NAME 0
+#define V_OCSP_RESPID_KEY 1
+struct ocsp_responder_id_st
+ {
+ int type;
+ union {
+ X509_NAME* byName;
+ ASN1_OCTET_STRING *byKey;
+ } value;
+ };
+
+DECLARE_STACK_OF(OCSP_RESPID)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPID)
+
+/* KeyHash ::= OCTET STRING --SHA-1 hash of responder's public key
+ * --(excluding the tag and length fields)
+ */
+
+/* RevokedInfo ::= SEQUENCE {
+ * revocationTime GeneralizedTime,
+ * revocationReason [0] EXPLICIT CRLReason OPTIONAL }
+ */
+typedef struct ocsp_revoked_info_st
+ {
+ ASN1_GENERALIZEDTIME *revocationTime;
+ ASN1_ENUMERATED *revocationReason;
+ } OCSP_REVOKEDINFO;
+
+/* CertStatus ::= CHOICE {
+ * good [0] IMPLICIT NULL,
+ * revoked [1] IMPLICIT RevokedInfo,
+ * unknown [2] IMPLICIT UnknownInfo }
+ */
+#define V_OCSP_CERTSTATUS_GOOD 0
+#define V_OCSP_CERTSTATUS_REVOKED 1
+#define V_OCSP_CERTSTATUS_UNKNOWN 2
+typedef struct ocsp_cert_status_st
+ {
+ int type;
+ union {
+ ASN1_NULL *good;
+ OCSP_REVOKEDINFO *revoked;
+ ASN1_NULL *unknown;
+ } value;
+ } OCSP_CERTSTATUS;
+
+/* SingleResponse ::= SEQUENCE {
+ * certID CertID,
+ * certStatus CertStatus,
+ * thisUpdate GeneralizedTime,
+ * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
+ * singleExtensions [1] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_single_response_st
+ {
+ OCSP_CERTID *certId;
+ OCSP_CERTSTATUS *certStatus;
+ ASN1_GENERALIZEDTIME *thisUpdate;
+ ASN1_GENERALIZEDTIME *nextUpdate;
+ STACK_OF(X509_EXTENSION) *singleExtensions;
+ } OCSP_SINGLERESP;
+
+DECLARE_STACK_OF(OCSP_SINGLERESP)
+DECLARE_ASN1_SET_OF(OCSP_SINGLERESP)
+
+/* ResponseData ::= SEQUENCE {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * responderID ResponderID,
+ * producedAt GeneralizedTime,
+ * responses SEQUENCE OF SingleResponse,
+ * responseExtensions [1] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct ocsp_response_data_st
+ {
+ ASN1_INTEGER *version;
+ OCSP_RESPID *responderId;
+ ASN1_GENERALIZEDTIME *producedAt;
+ STACK_OF(OCSP_SINGLERESP) *responses;
+ STACK_OF(X509_EXTENSION) *responseExtensions;
+ } OCSP_RESPDATA;
+
+/* BasicOCSPResponse ::= SEQUENCE {
+ * tbsResponseData ResponseData,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING,
+ * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ */
+ /* Note 1:
+ The value for "signature" is specified in the OCSP rfc2560 as follows:
+ "The value for the signature SHALL be computed on the hash of the DER
+ encoding ResponseData." This means that you must hash the DER-encoded
+ tbsResponseData, and then run it through a crypto-signing function, which
+ will (at least w/RSA) do a hash-'n'-private-encrypt operation. This seems
+ a bit odd, but that's the spec. Also note that the data structures do not
+ leave anywhere to independently specify the algorithm used for the initial
+ hash. So, we look at the signature-specification algorithm, and try to do
+ something intelligent. -- Kathy Weinhold, CertCo */
+ /* Note 2:
+ It seems that the mentioned passage from RFC 2560 (section 4.2.1) is open
+ for interpretation. I've done tests against another responder, and found
+ that it doesn't do the double hashing that the RFC seems to say one
+ should. Therefore, all relevant functions take a flag saying which
+ variant should be used. -- Richard Levitte, OpenSSL team and CeloCom */
+typedef struct ocsp_basic_response_st
+ {
+ OCSP_RESPDATA *tbsResponseData;
+ X509_ALGOR *signatureAlgorithm;
+ ASN1_BIT_STRING *signature;
+ STACK_OF(X509) *certs;
+ } OCSP_BASICRESP;
+
+/*
+ * CRLReason ::= ENUMERATED {
+ * unspecified (0),
+ * keyCompromise (1),
+ * cACompromise (2),
+ * affiliationChanged (3),
+ * superseded (4),
+ * cessationOfOperation (5),
+ * certificateHold (6),
+ * removeFromCRL (8) }
+ */
+#define OCSP_REVOKED_STATUS_NOSTATUS -1
+#define OCSP_REVOKED_STATUS_UNSPECIFIED 0
+#define OCSP_REVOKED_STATUS_KEYCOMPROMISE 1
+#define OCSP_REVOKED_STATUS_CACOMPROMISE 2
+#define OCSP_REVOKED_STATUS_AFFILIATIONCHANGED 3
+#define OCSP_REVOKED_STATUS_SUPERSEDED 4
+#define OCSP_REVOKED_STATUS_CESSATIONOFOPERATION 5
+#define OCSP_REVOKED_STATUS_CERTIFICATEHOLD 6
+#define OCSP_REVOKED_STATUS_REMOVEFROMCRL 8
+
+/* CrlID ::= SEQUENCE {
+ * crlUrl [0] EXPLICIT IA5String OPTIONAL,
+ * crlNum [1] EXPLICIT INTEGER OPTIONAL,
+ * crlTime [2] EXPLICIT GeneralizedTime OPTIONAL }
+ */
+typedef struct ocsp_crl_id_st
+ {
+ ASN1_IA5STRING *crlUrl;
+ ASN1_INTEGER *crlNum;
+ ASN1_GENERALIZEDTIME *crlTime;
+ } OCSP_CRLID;
+
+/* ServiceLocator ::= SEQUENCE {
+ * issuer Name,
+ * locator AuthorityInfoAccessSyntax OPTIONAL }
+ */
+typedef struct ocsp_service_locator_st
+ {
+ X509_NAME* issuer;
+ STACK_OF(ACCESS_DESCRIPTION) *locator;
+ } OCSP_SERVICELOC;
+
+#define PEM_STRING_OCSP_REQUEST "OCSP REQUEST"
+#define PEM_STRING_OCSP_RESPONSE "OCSP RESPONSE"
+
+#define d2i_OCSP_REQUEST_bio(bp,p) ASN1_d2i_bio_of(OCSP_REQUEST,OCSP_REQUEST_new,d2i_OCSP_REQUEST,bp,p)
+
+#define d2i_OCSP_RESPONSE_bio(bp,p) ASN1_d2i_bio_of(OCSP_RESPONSE,OCSP_RESPONSE_new,d2i_OCSP_RESPONSE,bp,p)
+
+#define PEM_read_bio_OCSP_REQUEST(bp,x,cb) (OCSP_REQUEST *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,bp,(char **)x,cb,NULL)
+
+#define PEM_read_bio_OCSP_RESPONSE(bp,x,cb)(OCSP_RESPONSE *)PEM_ASN1_read_bio(\
+ (char *(*)())d2i_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,bp,(char **)x,cb,NULL)
+
+#define PEM_write_bio_OCSP_REQUEST(bp,o) \
+ PEM_ASN1_write_bio((int (*)())i2d_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,\
+ bp,(char *)o, NULL,NULL,0,NULL,NULL)
+
+#define PEM_write_bio_OCSP_RESPONSE(bp,o) \
+ PEM_ASN1_write_bio((int (*)())i2d_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,\
+ bp,(char *)o, NULL,NULL,0,NULL,NULL)
+
+#define i2d_OCSP_RESPONSE_bio(bp,o) ASN1_i2d_bio_of(OCSP_RESPONSE,i2d_OCSP_RESPONSE,bp,o)
+
+#define i2d_OCSP_REQUEST_bio(bp,o) ASN1_i2d_bio_of(OCSP_REQUEST,i2d_OCSP_REQUEST,bp,o)
+
+#define OCSP_REQUEST_sign(o,pkey,md) \
+ ASN1_item_sign(ASN1_ITEM_rptr(OCSP_REQINFO),\
+ o->optionalSignature->signatureAlgorithm,NULL,\
+ o->optionalSignature->signature,o->tbsRequest,pkey,md)
+
+#define OCSP_BASICRESP_sign(o,pkey,md,d) \
+ ASN1_item_sign(ASN1_ITEM_rptr(OCSP_RESPDATA),o->signatureAlgorithm,NULL,\
+ o->signature,o->tbsResponseData,pkey,md)
+
+#define OCSP_REQUEST_verify(a,r) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_REQINFO),\
+ a->optionalSignature->signatureAlgorithm,\
+ a->optionalSignature->signature,a->tbsRequest,r)
+
+#define OCSP_BASICRESP_verify(a,r,d) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_RESPDATA),\
+ a->signatureAlgorithm,a->signature,a->tbsResponseData,r)
+
+#define ASN1_BIT_STRING_digest(data,type,md,len) \
+ ASN1_item_digest(ASN1_ITEM_rptr(ASN1_BIT_STRING),type,data,md,len)
+
+#define OCSP_CERTID_dup(cid) ASN1_dup_of(OCSP_CERTID,i2d_OCSP_CERTID,d2i_OCSP_CERTID,cid)
+
+#define OCSP_CERTSTATUS_dup(cs)\
+ (OCSP_CERTSTATUS*)ASN1_dup((int(*)())i2d_OCSP_CERTSTATUS,\
+ (char *(*)())d2i_OCSP_CERTSTATUS,(char *)(cs))
+
+OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req);
+OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req,
+ int maxline);
+int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx);
+void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx);
+
+OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer);
+
+OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
+ X509_NAME *issuerName,
+ ASN1_BIT_STRING* issuerKey,
+ ASN1_INTEGER *serialNumber);
+
+OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid);
+
+int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len);
+int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len);
+int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs);
+int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req);
+
+int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm);
+int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert);
+
+int OCSP_request_sign(OCSP_REQUEST *req,
+ X509 *signer,
+ EVP_PKEY *key,
+ const EVP_MD *dgst,
+ STACK_OF(X509) *certs,
+ unsigned long flags);
+
+int OCSP_response_status(OCSP_RESPONSE *resp);
+OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp);
+
+int OCSP_resp_count(OCSP_BASICRESP *bs);
+OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx);
+int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last);
+int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason,
+ ASN1_GENERALIZEDTIME **revtime,
+ ASN1_GENERALIZEDTIME **thisupd,
+ ASN1_GENERALIZEDTIME **nextupd);
+int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
+ int *reason,
+ ASN1_GENERALIZEDTIME **revtime,
+ ASN1_GENERALIZEDTIME **thisupd,
+ ASN1_GENERALIZEDTIME **nextupd);
+int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd,
+ ASN1_GENERALIZEDTIME *nextupd,
+ long sec, long maxsec);
+
+int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, unsigned long flags);
+
+int OCSP_parse_url(char *url, char **phost, char **pport, char **ppath, int *pssl);
+
+int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
+int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
+
+int OCSP_request_onereq_count(OCSP_REQUEST *req);
+OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i);
+OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one);
+int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd,
+ ASN1_OCTET_STRING **pikeyHash,
+ ASN1_INTEGER **pserial, OCSP_CERTID *cid);
+int OCSP_request_is_signed(OCSP_REQUEST *req);
+OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs);
+OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp,
+ OCSP_CERTID *cid,
+ int status, int reason,
+ ASN1_TIME *revtime,
+ ASN1_TIME *thisupd, ASN1_TIME *nextupd);
+int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert);
+int OCSP_basic_sign(OCSP_BASICRESP *brsp,
+ X509 *signer, EVP_PKEY *key, const EVP_MD *dgst,
+ STACK_OF(X509) *certs, unsigned long flags);
+
+ASN1_STRING *ASN1_STRING_encode(ASN1_STRING *s, i2d_of_void *i2d,
+ void *data, STACK_OF(ASN1_OBJECT) *sk);
+#define ASN1_STRING_encode_of(type,s,i2d,data,sk) \
+ ASN1_STRING_encode(s, CHECKED_I2D_OF(type, i2d), data, sk)
+
+X509_EXTENSION *OCSP_crlID_new(char *url, long *n, char *tim);
+
+X509_EXTENSION *OCSP_accept_responses_new(char **oids);
+
+X509_EXTENSION *OCSP_archive_cutoff_new(char* tim);
+
+X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME* issuer, char **urls);
+
+int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x);
+int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos);
+int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, ASN1_OBJECT *obj, int lastpos);
+int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc);
+X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc);
+void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx);
+int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit,
+ unsigned long flags);
+int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc);
+
+int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x);
+int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos);
+int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, ASN1_OBJECT *obj, int lastpos);
+int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc);
+X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc);
+void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx);
+int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit,
+ unsigned long flags);
+int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc);
+
+int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x);
+int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos);
+int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, ASN1_OBJECT *obj, int lastpos);
+int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc);
+X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc);
+void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, int *idx);
+int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, int crit,
+ unsigned long flags);
+int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc);
+
+int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x);
+int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos);
+int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, ASN1_OBJECT *obj, int lastpos);
+int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, int lastpos);
+X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc);
+X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc);
+void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, int *idx);
+int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, int crit,
+ unsigned long flags);
+int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc);
+
+DECLARE_ASN1_FUNCTIONS(OCSP_SINGLERESP)
+DECLARE_ASN1_FUNCTIONS(OCSP_CERTSTATUS)
+DECLARE_ASN1_FUNCTIONS(OCSP_REVOKEDINFO)
+DECLARE_ASN1_FUNCTIONS(OCSP_BASICRESP)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPDATA)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPID)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPONSE)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPBYTES)
+DECLARE_ASN1_FUNCTIONS(OCSP_ONEREQ)
+DECLARE_ASN1_FUNCTIONS(OCSP_CERTID)
+DECLARE_ASN1_FUNCTIONS(OCSP_REQUEST)
+DECLARE_ASN1_FUNCTIONS(OCSP_SIGNATURE)
+DECLARE_ASN1_FUNCTIONS(OCSP_REQINFO)
+DECLARE_ASN1_FUNCTIONS(OCSP_CRLID)
+DECLARE_ASN1_FUNCTIONS(OCSP_SERVICELOC)
+
+char *OCSP_response_status_str(long s);
+char *OCSP_cert_status_str(long s);
+char *OCSP_crl_reason_str(long s);
+
+int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST* a, unsigned long flags);
+int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE* o, unsigned long flags);
+
+int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
+ X509_STORE *st, unsigned long flags);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_OCSP_strings(void);
+
+/* Error codes for the OCSP functions. */
+
+/* Function codes. */
+#define OCSP_F_ASN1_STRING_ENCODE 100
+#define OCSP_F_D2I_OCSP_NONCE 102
+#define OCSP_F_OCSP_BASIC_ADD1_STATUS 103
+#define OCSP_F_OCSP_BASIC_SIGN 104
+#define OCSP_F_OCSP_BASIC_VERIFY 105
+#define OCSP_F_OCSP_CERT_ID_NEW 101
+#define OCSP_F_OCSP_CHECK_DELEGATED 106
+#define OCSP_F_OCSP_CHECK_IDS 107
+#define OCSP_F_OCSP_CHECK_ISSUER 108
+#define OCSP_F_OCSP_CHECK_VALIDITY 115
+#define OCSP_F_OCSP_MATCH_ISSUERID 109
+#define OCSP_F_OCSP_PARSE_URL 114
+#define OCSP_F_OCSP_REQUEST_SIGN 110
+#define OCSP_F_OCSP_REQUEST_VERIFY 116
+#define OCSP_F_OCSP_RESPONSE_GET1_BASIC 111
+#define OCSP_F_OCSP_SENDREQ_BIO 112
+#define OCSP_F_PARSE_HTTP_LINE1 117
+#define OCSP_F_REQUEST_VERIFY 113
+
+/* Reason codes. */
+#define OCSP_R_BAD_DATA 100
+#define OCSP_R_CERTIFICATE_VERIFY_ERROR 101
+#define OCSP_R_DIGEST_ERR 102
+#define OCSP_R_ERROR_IN_NEXTUPDATE_FIELD 122
+#define OCSP_R_ERROR_IN_THISUPDATE_FIELD 123
+#define OCSP_R_ERROR_PARSING_URL 121
+#define OCSP_R_MISSING_OCSPSIGNING_USAGE 103
+#define OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE 124
+#define OCSP_R_NOT_BASIC_RESPONSE 104
+#define OCSP_R_NO_CERTIFICATES_IN_CHAIN 105
+#define OCSP_R_NO_CONTENT 106
+#define OCSP_R_NO_PUBLIC_KEY 107
+#define OCSP_R_NO_RESPONSE_DATA 108
+#define OCSP_R_NO_REVOKED_TIME 109
+#define OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 110
+#define OCSP_R_REQUEST_NOT_SIGNED 128
+#define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA 111
+#define OCSP_R_ROOT_CA_NOT_TRUSTED 112
+#define OCSP_R_SERVER_READ_ERROR 113
+#define OCSP_R_SERVER_RESPONSE_ERROR 114
+#define OCSP_R_SERVER_RESPONSE_PARSE_ERROR 115
+#define OCSP_R_SERVER_WRITE_ERROR 116
+#define OCSP_R_SIGNATURE_FAILURE 117
+#define OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND 118
+#define OCSP_R_STATUS_EXPIRED 125
+#define OCSP_R_STATUS_NOT_YET_VALID 126
+#define OCSP_R_STATUS_TOO_OLD 127
+#define OCSP_R_UNKNOWN_MESSAGE_DIGEST 119
+#define OCSP_R_UNKNOWN_NID 120
+#define OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE 129
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/opensslconf.h b/src/Mayaqua/win32_inc/openssl/opensslconf.h
new file mode 100644
index 00000000..48e4adf6
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/opensslconf.h
@@ -0,0 +1,259 @@
+/* opensslconf.h */
+/* WARNING: Generated automatically from opensslconf.h.in by Configure. */
+
+/* OpenSSL was configured with the following options: */
+/*#ifndef OPENSSL_SYSNAME_WIN32
+# define OPENSSL_SYSNAME_WIN32
+#endif*/
+#ifndef OPENSSL_DOING_MAKEDEPEND
+
+
+#ifndef OPENSSL_NO_CAMELLIA
+# define OPENSSL_NO_CAMELLIA
+#endif
+#ifndef OPENSSL_NO_CAPIENG
+# define OPENSSL_NO_CAPIENG
+#endif
+#ifndef OPENSSL_NO_CMS
+# define OPENSSL_NO_CMS
+#endif
+#ifndef OPENSSL_NO_GMP
+# define OPENSSL_NO_GMP
+#endif
+#ifndef OPENSSL_NO_JPAKE
+# define OPENSSL_NO_JPAKE
+#endif
+#ifndef OPENSSL_NO_KRB5
+# define OPENSSL_NO_KRB5
+#endif
+#ifndef OPENSSL_NO_MDC2
+# define OPENSSL_NO_MDC2
+#endif
+#ifndef OPENSSL_NO_RC5
+# define OPENSSL_NO_RC5
+#endif
+#ifndef OPENSSL_NO_RFC3779
+# define OPENSSL_NO_RFC3779
+#endif
+#ifndef OPENSSL_NO_SEED
+# define OPENSSL_NO_SEED
+#endif
+
+#endif /* OPENSSL_DOING_MAKEDEPEND */
+
+#ifndef OPENSSL_THREADS
+# define OPENSSL_THREADS
+#endif
+
+/* The OPENSSL_NO_* macros are also defined as NO_* if the application
+ asks for it. This is a transient feature that is provided for those
+ who haven't had the time to do the appropriate changes in their
+ applications. */
+#ifdef OPENSSL_ALGORITHM_DEFINES
+# if defined(OPENSSL_NO_CAMELLIA) && !defined(NO_CAMELLIA)
+# define NO_CAMELLIA
+# endif
+# if defined(OPENSSL_NO_CAPIENG) && !defined(NO_CAPIENG)
+# define NO_CAPIENG
+# endif
+# if defined(OPENSSL_NO_CMS) && !defined(NO_CMS)
+# define NO_CMS
+# endif
+# if defined(OPENSSL_NO_GMP) && !defined(NO_GMP)
+# define NO_GMP
+# endif
+# if defined(OPENSSL_NO_JPAKE) && !defined(NO_JPAKE)
+# define NO_JPAKE
+# endif
+# if defined(OPENSSL_NO_KRB5) && !defined(NO_KRB5)
+# define NO_KRB5
+# endif
+# if defined(OPENSSL_NO_MDC2) && !defined(NO_MDC2)
+# define NO_MDC2
+# endif
+# if defined(OPENSSL_NO_RC5) && !defined(NO_RC5)
+# define NO_RC5
+# endif
+# if defined(OPENSSL_NO_RFC3779) && !defined(NO_RFC3779)
+# define NO_RFC3779
+# endif
+# if defined(OPENSSL_NO_SEED) && !defined(NO_SEED)
+# define NO_SEED
+# endif
+#endif
+
+/* crypto/opensslconf.h.in */
+
+#ifdef OPENSSL_DOING_MAKEDEPEND
+
+/* Include any symbols here that have to be explicitly set to enable a feature
+ * that should be visible to makedepend.
+ *
+ * [Our "make depend" doesn't actually look at this, we use actual build settings
+ * instead; we want to make it easy to remove subdirectories with disabled algorithms.]
+ */
+
+#ifndef OPENSSL_FIPS
+#define OPENSSL_FIPS
+#endif
+
+#endif
+
+/* Generate 80386 code? */
+#undef I386_ONLY
+
+#if !(defined(VMS) || defined(__VMS)) /* VMS uses logical names instead */
+#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR)
+#define ENGINESDIR "/usr/local/ssl/lib/engines"
+#define OPENSSLDIR "/usr/local/ssl"
+#endif
+#endif
+
+#undef OPENSSL_UNISTD
+#define OPENSSL_UNISTD <unistd.h>
+
+#undef OPENSSL_EXPORT_VAR_AS_FUNCTION
+#define OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+#if defined(HEADER_IDEA_H) && !defined(IDEA_INT)
+#define IDEA_INT unsigned int
+#endif
+
+#if defined(HEADER_MD2_H) && !defined(MD2_INT)
+#define MD2_INT unsigned int
+#endif
+
+#if defined(HEADER_RC2_H) && !defined(RC2_INT)
+/* I need to put in a mod for the alpha - eay */
+#define RC2_INT unsigned int
+#endif
+
+#if defined(HEADER_RC4_H)
+#if !defined(RC4_INT)
+/* using int types make the structure larger but make the code faster
+ * on most boxes I have tested - up to %20 faster. */
+/*
+ * I don't know what does "most" mean, but declaring "int" is a must on:
+ * - Intel P6 because partial register stalls are very expensive;
+ * - elder Alpha because it lacks byte load/store instructions;
+ */
+#define RC4_INT unsigned int
+#endif
+#if !defined(RC4_CHUNK)
+/*
+ * This enables code handling data aligned at natural CPU word
+ * boundary. See crypto/rc4/rc4_enc.c for further details.
+ */
+#undef RC4_CHUNK
+#endif
+#endif
+
+#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG)
+/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a
+ * %20 speed up (longs are 8 bytes, int's are 4). */
+#ifndef DES_LONG
+#define DES_LONG unsigned long
+#endif
+#endif
+
+#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H)
+#define CONFIG_HEADER_BN_H
+#define BN_LLONG
+
+/* Should we define BN_DIV2W here? */
+
+/* Only one for the following should be defined */
+/* The prime number generation stuff may not work when
+ * EIGHT_BIT but I don't care since I've only used this mode
+ * for debuging the bignum libraries */
+#undef SIXTY_FOUR_BIT_LONG
+#undef SIXTY_FOUR_BIT
+#define THIRTY_TWO_BIT
+#undef SIXTEEN_BIT
+#undef EIGHT_BIT
+#endif
+
+#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H)
+#define CONFIG_HEADER_RC4_LOCL_H
+/* if this is defined data[i] is used instead of *data, this is a %20
+ * speedup on x86 */
+#define RC4_INDEX
+#endif
+
+#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H)
+#define CONFIG_HEADER_BF_LOCL_H
+#undef BF_PTR
+#endif /* HEADER_BF_LOCL_H */
+
+#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H)
+#define CONFIG_HEADER_DES_LOCL_H
+#ifndef DES_DEFAULT_OPTIONS
+/* the following is tweaked from a config script, that is why it is a
+ * protected undef/define */
+#ifndef DES_PTR
+#undef DES_PTR
+#endif
+
+/* This helps C compiler generate the correct code for multiple functional
+ * units. It reduces register dependancies at the expense of 2 more
+ * registers */
+#ifndef DES_RISC1
+#undef DES_RISC1
+#endif
+
+#ifndef DES_RISC2
+#undef DES_RISC2
+#endif
+
+#if defined(DES_RISC1) && defined(DES_RISC2)
+YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!!
+#endif
+
+/* Unroll the inner loop, this sometimes helps, sometimes hinders.
+ * Very mucy CPU dependant */
+#ifndef DES_UNROLL
+#undef DES_UNROLL
+#endif
+
+/* These default values were supplied by
+ * Peter Gutman <pgut001@cs.auckland.ac.nz>
+ * They are only used if nothing else has been defined */
+#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL)
+/* Special defines which change the way the code is built depending on the
+ CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find
+ even newer MIPS CPU's, but at the moment one size fits all for
+ optimization options. Older Sparc's work better with only UNROLL, but
+ there's no way to tell at compile time what it is you're running on */
+
+#if defined( sun ) /* Newer Sparc's */
+# define DES_PTR
+# define DES_RISC1
+# define DES_UNROLL
+#elif defined( __ultrix ) /* Older MIPS */
+# define DES_PTR
+# define DES_RISC2
+# define DES_UNROLL
+#elif defined( __osf1__ ) /* Alpha */
+# define DES_PTR
+# define DES_RISC2
+#elif defined ( _AIX ) /* RS6000 */
+ /* Unknown */
+#elif defined( __hpux ) /* HP-PA */
+ /* Unknown */
+#elif defined( __aux ) /* 68K */
+ /* Unknown */
+#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */
+# define DES_UNROLL
+#elif defined( __sgi ) /* Newer MIPS */
+# define DES_PTR
+# define DES_RISC2
+# define DES_UNROLL
+#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */
+# define DES_PTR
+# define DES_RISC1
+# define DES_UNROLL
+#endif /* Systems-specific speed defines */
+#endif
+
+#endif /* DES_DEFAULT_OPTIONS */
+#endif /* HEADER_DES_LOCL_H */
diff --git a/src/Mayaqua/win32_inc/openssl/opensslv.h b/src/Mayaqua/win32_inc/openssl/opensslv.h
new file mode 100644
index 00000000..39b504b0
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/opensslv.h
@@ -0,0 +1,89 @@
+#ifndef HEADER_OPENSSLV_H
+#define HEADER_OPENSSLV_H
+
+/* Numeric release version identifier:
+ * MNNFFPPS: major minor fix patch status
+ * The status nibble has one of the values 0 for development, 1 to e for betas
+ * 1 to 14, and f for release. The patch level is exactly that.
+ * For example:
+ * 0.9.3-dev 0x00903000
+ * 0.9.3-beta1 0x00903001
+ * 0.9.3-beta2-dev 0x00903002
+ * 0.9.3-beta2 0x00903002 (same as ...beta2-dev)
+ * 0.9.3 0x0090300f
+ * 0.9.3a 0x0090301f
+ * 0.9.4 0x0090400f
+ * 1.2.3z 0x102031af
+ *
+ * For continuity reasons (because 0.9.5 is already out, and is coded
+ * 0x00905100), between 0.9.5 and 0.9.6 the coding of the patch level
+ * part is slightly different, by setting the highest bit. This means
+ * that 0.9.5a looks like this: 0x0090581f. At 0.9.6, we can start
+ * with 0x0090600S...
+ *
+ * (Prior to 0.9.3-dev a different scheme was used: 0.9.2b is 0x0922.)
+ * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
+ * major minor fix final patch/beta)
+ */
+#define OPENSSL_VERSION_NUMBER 0x0090818fL
+#ifdef OPENSSL_FIPS
+#define OPENSSL_VERSION_TEXT "OpenSSL 0.9.8x-fips 10 May 2012"
+#else
+#define OPENSSL_VERSION_TEXT "OpenSSL 0.9.8x 10 May 2012"
+#endif
+#define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT
+
+
+/* The macros below are to be used for shared library (.so, .dll, ...)
+ * versioning. That kind of versioning works a bit differently between
+ * operating systems. The most usual scheme is to set a major and a minor
+ * number, and have the runtime loader check that the major number is equal
+ * to what it was at application link time, while the minor number has to
+ * be greater or equal to what it was at application link time. With this
+ * scheme, the version number is usually part of the file name, like this:
+ *
+ * libcrypto.so.0.9
+ *
+ * Some unixen also make a softlink with the major verson number only:
+ *
+ * libcrypto.so.0
+ *
+ * On Tru64 and IRIX 6.x it works a little bit differently. There, the
+ * shared library version is stored in the file, and is actually a series
+ * of versions, separated by colons. The rightmost version present in the
+ * library when linking an application is stored in the application to be
+ * matched at run time. When the application is run, a check is done to
+ * see if the library version stored in the application matches any of the
+ * versions in the version string of the library itself.
+ * This version string can be constructed in any way, depending on what
+ * kind of matching is desired. However, to implement the same scheme as
+ * the one used in the other unixen, all compatible versions, from lowest
+ * to highest, should be part of the string. Consecutive builds would
+ * give the following versions strings:
+ *
+ * 3.0
+ * 3.0:3.1
+ * 3.0:3.1:3.2
+ * 4.0
+ * 4.0:4.1
+ *
+ * Notice how version 4 is completely incompatible with version, and
+ * therefore give the breach you can see.
+ *
+ * There may be other schemes as well that I haven't yet discovered.
+ *
+ * So, here's the way it works here: first of all, the library version
+ * number doesn't need at all to match the overall OpenSSL version.
+ * However, it's nice and more understandable if it actually does.
+ * The current library version is stored in the macro SHLIB_VERSION_NUMBER,
+ * which is just a piece of text in the format "M.m.e" (Major, minor, edit).
+ * For the sake of Tru64, IRIX, and any other OS that behaves in similar ways,
+ * we need to keep a history of version numbers, which is done in the
+ * macro SHLIB_VERSION_HISTORY. The numbers are separated by colons and
+ * should only keep the versions that are binary compatible with the current.
+ */
+#define SHLIB_VERSION_HISTORY ""
+#define SHLIB_VERSION_NUMBER "0.9.8"
+
+
+#endif /* HEADER_OPENSSLV_H */
diff --git a/src/Mayaqua/win32_inc/openssl/ossl_typ.h b/src/Mayaqua/win32_inc/openssl/ossl_typ.h
new file mode 100644
index 00000000..f86374f7
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ossl_typ.h
@@ -0,0 +1,183 @@
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_OPENSSL_TYPES_H
+#define HEADER_OPENSSL_TYPES_H
+
+#include <openssl/e_os2.h>
+
+#ifdef NO_ASN1_TYPEDEFS
+#define ASN1_INTEGER ASN1_STRING
+#define ASN1_ENUMERATED ASN1_STRING
+#define ASN1_BIT_STRING ASN1_STRING
+#define ASN1_OCTET_STRING ASN1_STRING
+#define ASN1_PRINTABLESTRING ASN1_STRING
+#define ASN1_T61STRING ASN1_STRING
+#define ASN1_IA5STRING ASN1_STRING
+#define ASN1_UTCTIME ASN1_STRING
+#define ASN1_GENERALIZEDTIME ASN1_STRING
+#define ASN1_TIME ASN1_STRING
+#define ASN1_GENERALSTRING ASN1_STRING
+#define ASN1_UNIVERSALSTRING ASN1_STRING
+#define ASN1_BMPSTRING ASN1_STRING
+#define ASN1_VISIBLESTRING ASN1_STRING
+#define ASN1_UTF8STRING ASN1_STRING
+#define ASN1_BOOLEAN int
+#define ASN1_NULL int
+#else
+typedef struct asn1_string_st ASN1_INTEGER;
+typedef struct asn1_string_st ASN1_ENUMERATED;
+typedef struct asn1_string_st ASN1_BIT_STRING;
+typedef struct asn1_string_st ASN1_OCTET_STRING;
+typedef struct asn1_string_st ASN1_PRINTABLESTRING;
+typedef struct asn1_string_st ASN1_T61STRING;
+typedef struct asn1_string_st ASN1_IA5STRING;
+typedef struct asn1_string_st ASN1_GENERALSTRING;
+typedef struct asn1_string_st ASN1_UNIVERSALSTRING;
+typedef struct asn1_string_st ASN1_BMPSTRING;
+typedef struct asn1_string_st ASN1_UTCTIME;
+typedef struct asn1_string_st ASN1_TIME;
+typedef struct asn1_string_st ASN1_GENERALIZEDTIME;
+typedef struct asn1_string_st ASN1_VISIBLESTRING;
+typedef struct asn1_string_st ASN1_UTF8STRING;
+typedef int ASN1_BOOLEAN;
+typedef int ASN1_NULL;
+#endif
+
+#ifdef OPENSSL_SYS_WIN32
+#undef X509_NAME
+#undef X509_EXTENSIONS
+#undef X509_CERT_PAIR
+#undef PKCS7_ISSUER_AND_SERIAL
+#undef OCSP_REQUEST
+#undef OCSP_RESPONSE
+#endif
+
+#ifdef BIGNUM
+#undef BIGNUM
+#endif
+typedef struct bignum_st BIGNUM;
+typedef struct bignum_ctx BN_CTX;
+typedef struct bn_blinding_st BN_BLINDING;
+typedef struct bn_mont_ctx_st BN_MONT_CTX;
+typedef struct bn_recp_ctx_st BN_RECP_CTX;
+typedef struct bn_gencb_st BN_GENCB;
+
+typedef struct buf_mem_st BUF_MEM;
+
+typedef struct evp_cipher_st EVP_CIPHER;
+typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
+typedef struct env_md_st EVP_MD;
+typedef struct env_md_ctx_st EVP_MD_CTX;
+typedef struct evp_pkey_st EVP_PKEY;
+
+typedef struct dh_st DH;
+typedef struct dh_method DH_METHOD;
+
+typedef struct dsa_st DSA;
+typedef struct dsa_method DSA_METHOD;
+
+typedef struct rsa_st RSA;
+typedef struct rsa_meth_st RSA_METHOD;
+
+typedef struct rand_meth_st RAND_METHOD;
+
+typedef struct ecdh_method ECDH_METHOD;
+typedef struct ecdsa_method ECDSA_METHOD;
+
+typedef struct x509_st X509;
+typedef struct X509_algor_st X509_ALGOR;
+typedef struct X509_crl_st X509_CRL;
+typedef struct X509_name_st X509_NAME;
+typedef struct x509_store_st X509_STORE;
+typedef struct x509_store_ctx_st X509_STORE_CTX;
+typedef struct ssl_st SSL;
+typedef struct ssl_ctx_st SSL_CTX;
+
+typedef struct v3_ext_ctx X509V3_CTX;
+typedef struct conf_st CONF;
+
+typedef struct store_st STORE;
+typedef struct store_method_st STORE_METHOD;
+
+typedef struct ui_st UI;
+typedef struct ui_method_st UI_METHOD;
+
+typedef struct st_ERR_FNS ERR_FNS;
+
+typedef struct engine_st ENGINE;
+
+typedef struct X509_POLICY_NODE_st X509_POLICY_NODE;
+typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL;
+typedef struct X509_POLICY_TREE_st X509_POLICY_TREE;
+typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE;
+
+ /* If placed in pkcs12.h, we end up with a circular depency with pkcs7.h */
+#define DECLARE_PKCS12_STACK_OF(type) /* Nothing */
+#define IMPLEMENT_PKCS12_STACK_OF(type) /* Nothing */
+
+typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
+/* Callback types for crypto.h */
+typedef int CRYPTO_EX_new(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+ int idx, long argl, void *argp);
+typedef void CRYPTO_EX_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+ int idx, long argl, void *argp);
+typedef int CRYPTO_EX_dup(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, void *from_d,
+ int idx, long argl, void *argp);
+
+typedef struct ocsp_req_ctx_st OCSP_REQ_CTX;
+typedef struct ocsp_response_st OCSP_RESPONSE;
+typedef struct ocsp_responder_id_st OCSP_RESPID;
+
+#endif /* def HEADER_OPENSSL_TYPES_H */
diff --git a/src/Mayaqua/win32_inc/openssl/pem.h b/src/Mayaqua/win32_inc/openssl/pem.h
new file mode 100644
index 00000000..5881ac3e
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/pem.h
@@ -0,0 +1,782 @@
+/* crypto/pem/pem.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_PEM_H
+#define HEADER_PEM_H
+
+#include <openssl/e_os2.h>
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#ifndef OPENSSL_NO_STACK
+#include <openssl/stack.h>
+#endif
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/pem2.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PEM_BUFSIZE 1024
+
+#define PEM_OBJ_UNDEF 0
+#define PEM_OBJ_X509 1
+#define PEM_OBJ_X509_REQ 2
+#define PEM_OBJ_CRL 3
+#define PEM_OBJ_SSL_SESSION 4
+#define PEM_OBJ_PRIV_KEY 10
+#define PEM_OBJ_PRIV_RSA 11
+#define PEM_OBJ_PRIV_DSA 12
+#define PEM_OBJ_PRIV_DH 13
+#define PEM_OBJ_PUB_RSA 14
+#define PEM_OBJ_PUB_DSA 15
+#define PEM_OBJ_PUB_DH 16
+#define PEM_OBJ_DHPARAMS 17
+#define PEM_OBJ_DSAPARAMS 18
+#define PEM_OBJ_PRIV_RSA_PUBLIC 19
+#define PEM_OBJ_PRIV_ECDSA 20
+#define PEM_OBJ_PUB_ECDSA 21
+#define PEM_OBJ_ECPARAMETERS 22
+
+#define PEM_ERROR 30
+#define PEM_DEK_DES_CBC 40
+#define PEM_DEK_IDEA_CBC 45
+#define PEM_DEK_DES_EDE 50
+#define PEM_DEK_DES_ECB 60
+#define PEM_DEK_RSA 70
+#define PEM_DEK_RSA_MD2 80
+#define PEM_DEK_RSA_MD5 90
+
+#define PEM_MD_MD2 NID_md2
+#define PEM_MD_MD5 NID_md5
+#define PEM_MD_SHA NID_sha
+#define PEM_MD_MD2_RSA NID_md2WithRSAEncryption
+#define PEM_MD_MD5_RSA NID_md5WithRSAEncryption
+#define PEM_MD_SHA_RSA NID_sha1WithRSAEncryption
+
+#define PEM_STRING_X509_OLD "X509 CERTIFICATE"
+#define PEM_STRING_X509 "CERTIFICATE"
+#define PEM_STRING_X509_PAIR "CERTIFICATE PAIR"
+#define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE"
+#define PEM_STRING_X509_REQ_OLD "NEW CERTIFICATE REQUEST"
+#define PEM_STRING_X509_REQ "CERTIFICATE REQUEST"
+#define PEM_STRING_X509_CRL "X509 CRL"
+#define PEM_STRING_EVP_PKEY "ANY PRIVATE KEY"
+#define PEM_STRING_PUBLIC "PUBLIC KEY"
+#define PEM_STRING_RSA "RSA PRIVATE KEY"
+#define PEM_STRING_RSA_PUBLIC "RSA PUBLIC KEY"
+#define PEM_STRING_DSA "DSA PRIVATE KEY"
+#define PEM_STRING_DSA_PUBLIC "DSA PUBLIC KEY"
+#define PEM_STRING_PKCS7 "PKCS7"
+#define PEM_STRING_PKCS7_SIGNED "PKCS #7 SIGNED DATA"
+#define PEM_STRING_PKCS8 "ENCRYPTED PRIVATE KEY"
+#define PEM_STRING_PKCS8INF "PRIVATE KEY"
+#define PEM_STRING_DHPARAMS "DH PARAMETERS"
+#define PEM_STRING_SSL_SESSION "SSL SESSION PARAMETERS"
+#define PEM_STRING_DSAPARAMS "DSA PARAMETERS"
+#define PEM_STRING_ECDSA_PUBLIC "ECDSA PUBLIC KEY"
+#define PEM_STRING_ECPARAMETERS "EC PARAMETERS"
+#define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY"
+#define PEM_STRING_CMS "CMS"
+
+ /* Note that this structure is initialised by PEM_SealInit and cleaned up
+ by PEM_SealFinal (at least for now) */
+typedef struct PEM_Encode_Seal_st
+ {
+ EVP_ENCODE_CTX encode;
+ EVP_MD_CTX md;
+ EVP_CIPHER_CTX cipher;
+ } PEM_ENCODE_SEAL_CTX;
+
+/* enc_type is one off */
+#define PEM_TYPE_ENCRYPTED 10
+#define PEM_TYPE_MIC_ONLY 20
+#define PEM_TYPE_MIC_CLEAR 30
+#define PEM_TYPE_CLEAR 40
+
+typedef struct pem_recip_st
+ {
+ char *name;
+ X509_NAME *dn;
+
+ int cipher;
+ int key_enc;
+ /* char iv[8]; unused and wrong size */
+ } PEM_USER;
+
+typedef struct pem_ctx_st
+ {
+ int type; /* what type of object */
+
+ struct {
+ int version;
+ int mode;
+ } proc_type;
+
+ char *domain;
+
+ struct {
+ int cipher;
+ /* unused, and wrong size
+ unsigned char iv[8]; */
+ } DEK_info;
+
+ PEM_USER *originator;
+
+ int num_recipient;
+ PEM_USER **recipient;
+
+#ifndef OPENSSL_NO_STACK
+ STACK *x509_chain; /* certificate chain */
+#else
+ char *x509_chain; /* certificate chain */
+#endif
+ EVP_MD *md; /* signature type */
+
+ int md_enc; /* is the md encrypted or not? */
+ int md_len; /* length of md_data */
+ char *md_data; /* message digest, could be pkey encrypted */
+
+ EVP_CIPHER *dec; /* date encryption cipher */
+ int key_len; /* key length */
+ unsigned char *key; /* key */
+ /* unused, and wrong size
+ unsigned char iv[8]; */
+
+
+ int data_enc; /* is the data encrypted */
+ int data_len;
+ unsigned char *data;
+ } PEM_CTX;
+
+/* These macros make the PEM_read/PEM_write functions easier to maintain and
+ * write. Now they are all implemented with either:
+ * IMPLEMENT_PEM_rw(...) or IMPLEMENT_PEM_rw_cb(...)
+ */
+
+#ifdef OPENSSL_NO_FP_API
+
+#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) /**/
+#define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) /**/
+
+#else
+
+#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \
+type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u)\
+{ \
+ return (type*)PEM_ASN1_read(CHECKED_D2I_OF(type, d2i_##asn1), \
+ str, fp, \
+ CHECKED_PPTR_OF(type, x), \
+ cb, u); \
+}
+
+#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \
+int PEM_write_##name(FILE *fp, type *x) \
+{ \
+ return PEM_ASN1_write(CHECKED_I2D_OF(type, i2d_##asn1), \
+ str, fp, \
+ CHECKED_PTR_OF(type, x), \
+ NULL, NULL, 0, NULL, NULL); \
+}
+
+#define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) \
+int PEM_write_##name(FILE *fp, const type *x) \
+{ \
+ return PEM_ASN1_write(CHECKED_I2D_OF(const type, i2d_##asn1), \
+ str, fp, \
+ CHECKED_PTR_OF(const type, x), \
+ NULL, NULL, 0, NULL, NULL); \
+}
+
+#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \
+int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
+ unsigned char *kstr, int klen, pem_password_cb *cb, \
+ void *u) \
+ { \
+ return PEM_ASN1_write(CHECKED_I2D_OF(type, i2d_##asn1), \
+ str, fp, \
+ CHECKED_PTR_OF(type, x), \
+ enc, kstr, klen, cb, u); \
+ }
+
+#define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) \
+int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
+ unsigned char *kstr, int klen, pem_password_cb *cb, \
+ void *u) \
+ { \
+ return PEM_ASN1_write(CHECKED_I2D_OF(const type, i2d_##asn1), \
+ str, fp, \
+ CHECKED_PTR_OF(const type, x), \
+ enc, kstr, klen, cb, u); \
+ }
+
+#endif
+
+#define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
+type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u)\
+{ \
+ return (type*)PEM_ASN1_read_bio(CHECKED_D2I_OF(type, d2i_##asn1), \
+ str, bp, \
+ CHECKED_PPTR_OF(type, x), \
+ cb, u); \
+}
+
+#define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
+int PEM_write_bio_##name(BIO *bp, type *x) \
+{ \
+ return PEM_ASN1_write_bio(CHECKED_I2D_OF(type, i2d_##asn1), \
+ str, bp, \
+ CHECKED_PTR_OF(type, x), \
+ NULL, NULL, 0, NULL, NULL); \
+}
+
+#define IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \
+int PEM_write_bio_##name(BIO *bp, const type *x) \
+{ \
+ return PEM_ASN1_write_bio(CHECKED_I2D_OF(const type, i2d_##asn1), \
+ str, bp, \
+ CHECKED_PTR_OF(const type, x), \
+ NULL, NULL, 0, NULL, NULL); \
+}
+
+#define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \
+int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
+ unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
+ { \
+ return PEM_ASN1_write_bio(CHECKED_I2D_OF(type, i2d_##asn1), \
+ str, bp, \
+ CHECKED_PTR_OF(type, x), \
+ enc, kstr, klen, cb, u); \
+ }
+
+#define IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \
+int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
+ unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
+ { \
+ return PEM_ASN1_write_bio(CHECKED_I2D_OF(const type, i2d_##asn1), \
+ str, bp, \
+ CHECKED_PTR_OF(const type, x), \
+ enc, kstr, klen, cb, u); \
+ }
+
+#define IMPLEMENT_PEM_write(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_fp(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_write_const(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_fp_const(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_write_cb(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_write_cb_const(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_read(name, type, str, asn1) \
+ IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
+ IMPLEMENT_PEM_read_fp(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_rw(name, type, str, asn1) \
+ IMPLEMENT_PEM_read(name, type, str, asn1) \
+ IMPLEMENT_PEM_write(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_rw_const(name, type, str, asn1) \
+ IMPLEMENT_PEM_read(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_const(name, type, str, asn1)
+
+#define IMPLEMENT_PEM_rw_cb(name, type, str, asn1) \
+ IMPLEMENT_PEM_read(name, type, str, asn1) \
+ IMPLEMENT_PEM_write_cb(name, type, str, asn1)
+
+/* These are the same except they are for the declarations */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_NO_FP_API)
+
+#define DECLARE_PEM_read_fp(name, type) /**/
+#define DECLARE_PEM_write_fp(name, type) /**/
+#define DECLARE_PEM_write_fp_const(name, type) /**/
+#define DECLARE_PEM_write_cb_fp(name, type) /**/
+
+#else
+
+#define DECLARE_PEM_read_fp(name, type) \
+ type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u);
+
+#define DECLARE_PEM_write_fp(name, type) \
+ int PEM_write_##name(FILE *fp, type *x);
+
+#define DECLARE_PEM_write_fp_const(name, type) \
+ int PEM_write_##name(FILE *fp, const type *x);
+
+#define DECLARE_PEM_write_cb_fp(name, type) \
+ int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
+ unsigned char *kstr, int klen, pem_password_cb *cb, void *u);
+
+#endif
+
+#ifndef OPENSSL_NO_BIO
+#define DECLARE_PEM_read_bio(name, type) \
+ type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u);
+
+#define DECLARE_PEM_write_bio(name, type) \
+ int PEM_write_bio_##name(BIO *bp, type *x);
+
+#define DECLARE_PEM_write_bio_const(name, type) \
+ int PEM_write_bio_##name(BIO *bp, const type *x);
+
+#define DECLARE_PEM_write_cb_bio(name, type) \
+ int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
+ unsigned char *kstr, int klen, pem_password_cb *cb, void *u);
+
+#else
+
+#define DECLARE_PEM_read_bio(name, type) /**/
+#define DECLARE_PEM_write_bio(name, type) /**/
+#define DECLARE_PEM_write_bio_const(name, type) /**/
+#define DECLARE_PEM_write_cb_bio(name, type) /**/
+
+#endif
+
+#define DECLARE_PEM_write(name, type) \
+ DECLARE_PEM_write_bio(name, type) \
+ DECLARE_PEM_write_fp(name, type)
+
+#define DECLARE_PEM_write_const(name, type) \
+ DECLARE_PEM_write_bio_const(name, type) \
+ DECLARE_PEM_write_fp_const(name, type)
+
+#define DECLARE_PEM_write_cb(name, type) \
+ DECLARE_PEM_write_cb_bio(name, type) \
+ DECLARE_PEM_write_cb_fp(name, type)
+
+#define DECLARE_PEM_read(name, type) \
+ DECLARE_PEM_read_bio(name, type) \
+ DECLARE_PEM_read_fp(name, type)
+
+#define DECLARE_PEM_rw(name, type) \
+ DECLARE_PEM_read(name, type) \
+ DECLARE_PEM_write(name, type)
+
+#define DECLARE_PEM_rw_const(name, type) \
+ DECLARE_PEM_read(name, type) \
+ DECLARE_PEM_write_const(name, type)
+
+#define DECLARE_PEM_rw_cb(name, type) \
+ DECLARE_PEM_read(name, type) \
+ DECLARE_PEM_write_cb(name, type)
+
+#ifdef SSLEAY_MACROS
+
+#define PEM_write_SSL_SESSION(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_SSL_SESSION, \
+ PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_X509(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_X509,PEM_STRING_X509,fp, \
+ (char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_X509_REQ(fp,x) PEM_ASN1_write( \
+ (int (*)())i2d_X509_REQ,PEM_STRING_X509_REQ,fp,(char *)x, \
+ NULL,NULL,0,NULL,NULL)
+#define PEM_write_X509_CRL(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_X509_CRL,PEM_STRING_X509_CRL, \
+ fp,(char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_RSAPrivateKey(fp,x,enc,kstr,klen,cb,u) \
+ PEM_ASN1_write((int (*)())i2d_RSAPrivateKey,PEM_STRING_RSA,fp,\
+ (char *)x,enc,kstr,klen,cb,u)
+#define PEM_write_RSAPublicKey(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_RSAPublicKey,\
+ PEM_STRING_RSA_PUBLIC,fp,(char *)x,NULL,NULL,0,NULL,NULL)
+#define PEM_write_DSAPrivateKey(fp,x,enc,kstr,klen,cb,u) \
+ PEM_ASN1_write((int (*)())i2d_DSAPrivateKey,PEM_STRING_DSA,fp,\
+ (char *)x,enc,kstr,klen,cb,u)
+#define PEM_write_PrivateKey(bp,x,enc,kstr,klen,cb,u) \
+ PEM_ASN1_write((int (*)())i2d_PrivateKey,\
+ (((x)->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA),\
+ bp,(char *)x,enc,kstr,klen,cb,u)
+#define PEM_write_PKCS7(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_PKCS7,PEM_STRING_PKCS7,fp, \
+ (char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_DHparams(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_DHparams,PEM_STRING_DHPARAMS,fp,\
+ (char *)x,NULL,NULL,0,NULL,NULL)
+
+#define PEM_write_NETSCAPE_CERT_SEQUENCE(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_NETSCAPE_CERT_SEQUENCE, \
+ PEM_STRING_X509,fp, \
+ (char *)x, NULL,NULL,0,NULL,NULL)
+
+#define PEM_read_SSL_SESSION(fp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read( \
+ (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb,u)
+#define PEM_read_X509(fp,x,cb,u) (X509 *)PEM_ASN1_read( \
+ (char *(*)())d2i_X509,PEM_STRING_X509,fp,(char **)x,cb,u)
+#define PEM_read_X509_REQ(fp,x,cb,u) (X509_REQ *)PEM_ASN1_read( \
+ (char *(*)())d2i_X509_REQ,PEM_STRING_X509_REQ,fp,(char **)x,cb,u)
+#define PEM_read_X509_CRL(fp,x,cb,u) (X509_CRL *)PEM_ASN1_read( \
+ (char *(*)())d2i_X509_CRL,PEM_STRING_X509_CRL,fp,(char **)x,cb,u)
+#define PEM_read_RSAPrivateKey(fp,x,cb,u) (RSA *)PEM_ASN1_read( \
+ (char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,fp,(char **)x,cb,u)
+#define PEM_read_RSAPublicKey(fp,x,cb,u) (RSA *)PEM_ASN1_read( \
+ (char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,fp,(char **)x,cb,u)
+#define PEM_read_DSAPrivateKey(fp,x,cb,u) (DSA *)PEM_ASN1_read( \
+ (char *(*)())d2i_DSAPrivateKey,PEM_STRING_DSA,fp,(char **)x,cb,u)
+#define PEM_read_PrivateKey(fp,x,cb,u) (EVP_PKEY *)PEM_ASN1_read( \
+ (char *(*)())d2i_PrivateKey,PEM_STRING_EVP_PKEY,fp,(char **)x,cb,u)
+#define PEM_read_PKCS7(fp,x,cb,u) (PKCS7 *)PEM_ASN1_read( \
+ (char *(*)())d2i_PKCS7,PEM_STRING_PKCS7,fp,(char **)x,cb,u)
+#define PEM_read_DHparams(fp,x,cb,u) (DH *)PEM_ASN1_read( \
+ (char *(*)())d2i_DHparams,PEM_STRING_DHPARAMS,fp,(char **)x,cb,u)
+
+#define PEM_read_NETSCAPE_CERT_SEQUENCE(fp,x,cb,u) \
+ (NETSCAPE_CERT_SEQUENCE *)PEM_ASN1_read( \
+ (char *(*)())d2i_NETSCAPE_CERT_SEQUENCE,PEM_STRING_X509,fp,\
+ (char **)x,cb,u)
+
+#define PEM_write_bio_X509(bp,x) \
+ PEM_ASN1_write_bio((int (*)())i2d_X509,PEM_STRING_X509,bp, \
+ (char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_X509_REQ(bp,x) PEM_ASN1_write_bio( \
+ (int (*)())i2d_X509_REQ,PEM_STRING_X509_REQ,bp,(char *)x, \
+ NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_X509_CRL(bp,x) \
+ PEM_ASN1_write_bio((int (*)())i2d_X509_CRL,PEM_STRING_X509_CRL,\
+ bp,(char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_RSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
+ PEM_ASN1_write_bio((int (*)())i2d_RSAPrivateKey,PEM_STRING_RSA,\
+ bp,(char *)x,enc,kstr,klen,cb,u)
+#define PEM_write_bio_RSAPublicKey(bp,x) \
+ PEM_ASN1_write_bio((int (*)())i2d_RSAPublicKey, \
+ PEM_STRING_RSA_PUBLIC,\
+ bp,(char *)x,NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_DSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
+ PEM_ASN1_write_bio((int (*)())i2d_DSAPrivateKey,PEM_STRING_DSA,\
+ bp,(char *)x,enc,kstr,klen,cb,u)
+#define PEM_write_bio_PrivateKey(bp,x,enc,kstr,klen,cb,u) \
+ PEM_ASN1_write_bio((int (*)())i2d_PrivateKey,\
+ (((x)->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA),\
+ bp,(char *)x,enc,kstr,klen,cb,u)
+#define PEM_write_bio_PKCS7(bp,x) \
+ PEM_ASN1_write_bio((int (*)())i2d_PKCS7,PEM_STRING_PKCS7,bp, \
+ (char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_DHparams(bp,x) \
+ PEM_ASN1_write_bio((int (*)())i2d_DHparams,PEM_STRING_DHPARAMS,\
+ bp,(char *)x,NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_DSAparams(bp,x) \
+ PEM_ASN1_write_bio((int (*)())i2d_DSAparams, \
+ PEM_STRING_DSAPARAMS,bp,(char *)x,NULL,NULL,0,NULL,NULL)
+
+#define PEM_write_bio_NETSCAPE_CERT_SEQUENCE(bp,x) \
+ PEM_ASN1_write_bio((int (*)())i2d_NETSCAPE_CERT_SEQUENCE, \
+ PEM_STRING_X509,bp, \
+ (char *)x, NULL,NULL,0,NULL,NULL)
+
+#define PEM_read_bio_X509(bp,x,cb,u) (X509 *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_X509,PEM_STRING_X509,bp,(char **)x,cb,u)
+#define PEM_read_bio_X509_REQ(bp,x,cb,u) (X509_REQ *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_X509_REQ,PEM_STRING_X509_REQ,bp,(char **)x,cb,u)
+#define PEM_read_bio_X509_CRL(bp,x,cb,u) (X509_CRL *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_X509_CRL,PEM_STRING_X509_CRL,bp,(char **)x,cb,u)
+#define PEM_read_bio_RSAPrivateKey(bp,x,cb,u) (RSA *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,bp,(char **)x,cb,u)
+#define PEM_read_bio_RSAPublicKey(bp,x,cb,u) (RSA *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,bp,(char **)x,cb,u)
+#define PEM_read_bio_DSAPrivateKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_DSAPrivateKey,PEM_STRING_DSA,bp,(char **)x,cb,u)
+#define PEM_read_bio_PrivateKey(bp,x,cb,u) (EVP_PKEY *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_PrivateKey,PEM_STRING_EVP_PKEY,bp,(char **)x,cb,u)
+
+#define PEM_read_bio_PKCS7(bp,x,cb,u) (PKCS7 *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_PKCS7,PEM_STRING_PKCS7,bp,(char **)x,cb,u)
+#define PEM_read_bio_DHparams(bp,x,cb,u) (DH *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_DHparams,PEM_STRING_DHPARAMS,bp,(char **)x,cb,u)
+#define PEM_read_bio_DSAparams(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_DSAparams,PEM_STRING_DSAPARAMS,bp,(char **)x,cb,u)
+
+#define PEM_read_bio_NETSCAPE_CERT_SEQUENCE(bp,x,cb,u) \
+ (NETSCAPE_CERT_SEQUENCE *)PEM_ASN1_read_bio( \
+ (char *(*)())d2i_NETSCAPE_CERT_SEQUENCE,PEM_STRING_X509,bp,\
+ (char **)x,cb,u)
+
+#endif
+
+#if 1
+/* "userdata": new with OpenSSL 0.9.4 */
+typedef int pem_password_cb(char *buf, int size, int rwflag, void *userdata);
+#else
+/* OpenSSL 0.9.3, 0.9.3a */
+typedef int pem_password_cb(char *buf, int size, int rwflag);
+#endif
+
+int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher);
+int PEM_do_header (EVP_CIPHER_INFO *cipher, unsigned char *data,long *len,
+ pem_password_cb *callback,void *u);
+
+#ifndef OPENSSL_NO_BIO
+int PEM_read_bio(BIO *bp, char **name, char **header,
+ unsigned char **data,long *len);
+int PEM_write_bio(BIO *bp,const char *name,char *hdr,unsigned char *data,
+ long len);
+int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp,
+ pem_password_cb *cb, void *u);
+void * PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp,
+ void **x, pem_password_cb *cb, void *u);
+
+#define PEM_ASN1_read_bio_of(type,d2i,name,bp,x,cb,u) \
+ ((type*)PEM_ASN1_read_bio(CHECKED_D2I_OF(type, d2i), \
+ name, bp, \
+ CHECKED_PPTR_OF(type, x), \
+ cb, u))
+
+int PEM_ASN1_write_bio(i2d_of_void *i2d,const char *name,BIO *bp,char *x,
+ const EVP_CIPHER *enc,unsigned char *kstr,int klen,
+ pem_password_cb *cb, void *u);
+
+#define PEM_ASN1_write_bio_of(type,i2d,name,bp,x,enc,kstr,klen,cb,u) \
+ (PEM_ASN1_write_bio(CHECKED_I2D_OF(type, i2d), \
+ name, bp, \
+ CHECKED_PTR_OF(type, x), \
+ enc, kstr, klen, cb, u))
+
+STACK_OF(X509_INFO) * PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u);
+int PEM_X509_INFO_write_bio(BIO *bp,X509_INFO *xi, EVP_CIPHER *enc,
+ unsigned char *kstr, int klen, pem_password_cb *cd, void *u);
+#endif
+
+#ifndef OPENSSL_SYS_WIN16
+int PEM_read(FILE *fp, char **name, char **header,
+ unsigned char **data,long *len);
+int PEM_write(FILE *fp,char *name,char *hdr,unsigned char *data,long len);
+void * PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x,
+ pem_password_cb *cb, void *u);
+int PEM_ASN1_write(i2d_of_void *i2d,const char *name,FILE *fp,
+ char *x,const EVP_CIPHER *enc,unsigned char *kstr,
+ int klen,pem_password_cb *callback, void *u);
+STACK_OF(X509_INFO) * PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
+ pem_password_cb *cb, void *u);
+#endif
+
+int PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type,
+ EVP_MD *md_type, unsigned char **ek, int *ekl,
+ unsigned char *iv, EVP_PKEY **pubk, int npubk);
+void PEM_SealUpdate(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *out, int *outl,
+ unsigned char *in, int inl);
+int PEM_SealFinal(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *sig,int *sigl,
+ unsigned char *out, int *outl, EVP_PKEY *priv);
+
+void PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type);
+void PEM_SignUpdate(EVP_MD_CTX *ctx,unsigned char *d,unsigned int cnt);
+int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
+ unsigned int *siglen, EVP_PKEY *pkey);
+
+int PEM_def_callback(char *buf, int num, int w, void *key);
+void PEM_proc_type(char *buf, int type);
+void PEM_dek_info(char *buf, const char *type, int len, char *str);
+
+#ifndef SSLEAY_MACROS
+
+#include <openssl/symhacks.h>
+
+DECLARE_PEM_rw(X509, X509)
+
+DECLARE_PEM_rw(X509_AUX, X509)
+
+DECLARE_PEM_rw(X509_CERT_PAIR, X509_CERT_PAIR)
+
+DECLARE_PEM_rw(X509_REQ, X509_REQ)
+DECLARE_PEM_write(X509_REQ_NEW, X509_REQ)
+
+DECLARE_PEM_rw(X509_CRL, X509_CRL)
+
+DECLARE_PEM_rw(PKCS7, PKCS7)
+
+DECLARE_PEM_rw(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE)
+
+DECLARE_PEM_rw(PKCS8, X509_SIG)
+
+DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
+
+#ifndef OPENSSL_NO_RSA
+
+DECLARE_PEM_rw_cb(RSAPrivateKey, RSA)
+
+DECLARE_PEM_rw_const(RSAPublicKey, RSA)
+DECLARE_PEM_rw(RSA_PUBKEY, RSA)
+
+#endif
+
+#ifndef OPENSSL_NO_DSA
+
+DECLARE_PEM_rw_cb(DSAPrivateKey, DSA)
+
+DECLARE_PEM_rw(DSA_PUBKEY, DSA)
+
+DECLARE_PEM_rw_const(DSAparams, DSA)
+
+#endif
+
+#ifndef OPENSSL_NO_EC
+DECLARE_PEM_rw_const(ECPKParameters, EC_GROUP)
+DECLARE_PEM_rw_cb(ECPrivateKey, EC_KEY)
+DECLARE_PEM_rw(EC_PUBKEY, EC_KEY)
+#endif
+
+#ifndef OPENSSL_NO_DH
+
+DECLARE_PEM_rw_const(DHparams, DH)
+
+#endif
+
+DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY)
+
+DECLARE_PEM_rw(PUBKEY, EVP_PKEY)
+
+int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid,
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+int PEM_write_bio_PKCS8PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *,
+ char *, int, pem_password_cb *, void *);
+int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid,
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u);
+
+int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid,
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid,
+ char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+
+EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u);
+
+int PEM_write_PKCS8PrivateKey(FILE *fp,EVP_PKEY *x,const EVP_CIPHER *enc,
+ char *kstr,int klen, pem_password_cb *cd, void *u);
+
+#endif /* SSLEAY_MACROS */
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_PEM_strings(void);
+
+/* Error codes for the PEM functions. */
+
+/* Function codes. */
+#define PEM_F_D2I_PKCS8PRIVATEKEY_BIO 120
+#define PEM_F_D2I_PKCS8PRIVATEKEY_FP 121
+#define PEM_F_DO_PK8PKEY 126
+#define PEM_F_DO_PK8PKEY_FP 125
+#define PEM_F_LOAD_IV 101
+#define PEM_F_PEM_ASN1_READ 102
+#define PEM_F_PEM_ASN1_READ_BIO 103
+#define PEM_F_PEM_ASN1_WRITE 104
+#define PEM_F_PEM_ASN1_WRITE_BIO 105
+#define PEM_F_PEM_DEF_CALLBACK 100
+#define PEM_F_PEM_DO_HEADER 106
+#define PEM_F_PEM_F_PEM_WRITE_PKCS8PRIVATEKEY 118
+#define PEM_F_PEM_GET_EVP_CIPHER_INFO 107
+#define PEM_F_PEM_PK8PKEY 119
+#define PEM_F_PEM_READ 108
+#define PEM_F_PEM_READ_BIO 109
+#define PEM_F_PEM_READ_BIO_PRIVATEKEY 123
+#define PEM_F_PEM_READ_PRIVATEKEY 124
+#define PEM_F_PEM_SEALFINAL 110
+#define PEM_F_PEM_SEALINIT 111
+#define PEM_F_PEM_SIGNFINAL 112
+#define PEM_F_PEM_WRITE 113
+#define PEM_F_PEM_WRITE_BIO 114
+#define PEM_F_PEM_X509_INFO_READ 115
+#define PEM_F_PEM_X509_INFO_READ_BIO 116
+#define PEM_F_PEM_X509_INFO_WRITE_BIO 117
+
+/* Reason codes. */
+#define PEM_R_BAD_BASE64_DECODE 100
+#define PEM_R_BAD_DECRYPT 101
+#define PEM_R_BAD_END_LINE 102
+#define PEM_R_BAD_IV_CHARS 103
+#define PEM_R_BAD_PASSWORD_READ 104
+#define PEM_R_ERROR_CONVERTING_PRIVATE_KEY 115
+#define PEM_R_NOT_DEK_INFO 105
+#define PEM_R_NOT_ENCRYPTED 106
+#define PEM_R_NOT_PROC_TYPE 107
+#define PEM_R_NO_START_LINE 108
+#define PEM_R_PROBLEMS_GETTING_PASSWORD 109
+#define PEM_R_PUBLIC_KEY_NO_RSA 110
+#define PEM_R_READ_KEY 111
+#define PEM_R_SHORT_HEADER 112
+#define PEM_R_UNSUPPORTED_CIPHER 113
+#define PEM_R_UNSUPPORTED_ENCRYPTION 114
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/pem2.h b/src/Mayaqua/win32_inc/openssl/pem2.h
new file mode 100644
index 00000000..97ba68aa
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/pem2.h
@@ -0,0 +1,70 @@
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/*
+ * This header only exists to break a circular dependency between pem and err
+ * Ben 30 Jan 1999.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef HEADER_PEM_H
+void ERR_load_PEM_strings(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/pkcs12.h b/src/Mayaqua/win32_inc/openssl/pkcs12.h
new file mode 100644
index 00000000..3f45ee60
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/pkcs12.h
@@ -0,0 +1,338 @@
+/* pkcs12.h */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_PKCS12_H
+#define HEADER_PKCS12_H
+
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PKCS12_KEY_ID 1
+#define PKCS12_IV_ID 2
+#define PKCS12_MAC_ID 3
+
+/* Default iteration count */
+#ifndef PKCS12_DEFAULT_ITER
+#define PKCS12_DEFAULT_ITER PKCS5_DEFAULT_ITER
+#endif
+
+#define PKCS12_MAC_KEY_LENGTH 20
+
+#define PKCS12_SALT_LEN 8
+
+/* Uncomment out next line for unicode password and names, otherwise ASCII */
+
+/*#define PBE_UNICODE*/
+
+#ifdef PBE_UNICODE
+#define PKCS12_key_gen PKCS12_key_gen_uni
+#define PKCS12_add_friendlyname PKCS12_add_friendlyname_uni
+#else
+#define PKCS12_key_gen PKCS12_key_gen_asc
+#define PKCS12_add_friendlyname PKCS12_add_friendlyname_asc
+#endif
+
+/* MS key usage constants */
+
+#define KEY_EX 0x10
+#define KEY_SIG 0x80
+
+typedef struct {
+X509_SIG *dinfo;
+ASN1_OCTET_STRING *salt;
+ASN1_INTEGER *iter; /* defaults to 1 */
+} PKCS12_MAC_DATA;
+
+typedef struct {
+ASN1_INTEGER *version;
+PKCS12_MAC_DATA *mac;
+PKCS7 *authsafes;
+} PKCS12;
+
+PREDECLARE_STACK_OF(PKCS12_SAFEBAG)
+
+typedef struct {
+ASN1_OBJECT *type;
+union {
+ struct pkcs12_bag_st *bag; /* secret, crl and certbag */
+ struct pkcs8_priv_key_info_st *keybag; /* keybag */
+ X509_SIG *shkeybag; /* shrouded key bag */
+ STACK_OF(PKCS12_SAFEBAG) *safes;
+ ASN1_TYPE *other;
+}value;
+STACK_OF(X509_ATTRIBUTE) *attrib;
+} PKCS12_SAFEBAG;
+
+DECLARE_STACK_OF(PKCS12_SAFEBAG)
+DECLARE_ASN1_SET_OF(PKCS12_SAFEBAG)
+DECLARE_PKCS12_STACK_OF(PKCS12_SAFEBAG)
+
+typedef struct pkcs12_bag_st {
+ASN1_OBJECT *type;
+union {
+ ASN1_OCTET_STRING *x509cert;
+ ASN1_OCTET_STRING *x509crl;
+ ASN1_OCTET_STRING *octet;
+ ASN1_IA5STRING *sdsicert;
+ ASN1_TYPE *other; /* Secret or other bag */
+}value;
+} PKCS12_BAGS;
+
+#define PKCS12_ERROR 0
+#define PKCS12_OK 1
+
+/* Compatibility macros */
+
+#define M_PKCS12_x5092certbag PKCS12_x5092certbag
+#define M_PKCS12_x509crl2certbag PKCS12_x509crl2certbag
+
+#define M_PKCS12_certbag2x509 PKCS12_certbag2x509
+#define M_PKCS12_certbag2x509crl PKCS12_certbag2x509crl
+
+#define M_PKCS12_unpack_p7data PKCS12_unpack_p7data
+#define M_PKCS12_pack_authsafes PKCS12_pack_authsafes
+#define M_PKCS12_unpack_authsafes PKCS12_unpack_authsafes
+#define M_PKCS12_unpack_p7encdata PKCS12_unpack_p7encdata
+
+#define M_PKCS12_decrypt_skey PKCS12_decrypt_skey
+#define M_PKCS8_decrypt PKCS8_decrypt
+
+#define M_PKCS12_bag_type(bg) OBJ_obj2nid((bg)->type)
+#define M_PKCS12_cert_bag_type(bg) OBJ_obj2nid((bg)->value.bag->type)
+#define M_PKCS12_crl_bag_type M_PKCS12_cert_bag_type
+
+#define PKCS12_get_attr(bag, attr_nid) \
+ PKCS12_get_attr_gen(bag->attrib, attr_nid)
+
+#define PKCS8_get_attr(p8, attr_nid) \
+ PKCS12_get_attr_gen(p8->attributes, attr_nid)
+
+#define PKCS12_mac_present(p12) ((p12)->mac ? 1 : 0)
+
+
+PKCS12_SAFEBAG *PKCS12_x5092certbag(X509 *x509);
+PKCS12_SAFEBAG *PKCS12_x509crl2certbag(X509_CRL *crl);
+X509 *PKCS12_certbag2x509(PKCS12_SAFEBAG *bag);
+X509_CRL *PKCS12_certbag2x509crl(PKCS12_SAFEBAG *bag);
+
+PKCS12_SAFEBAG *PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it, int nid1,
+ int nid2);
+PKCS12_SAFEBAG *PKCS12_MAKE_KEYBAG(PKCS8_PRIV_KEY_INFO *p8);
+PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *p8, const char *pass, int passlen);
+PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(PKCS12_SAFEBAG *bag, const char *pass,
+ int passlen);
+X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
+ const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ PKCS8_PRIV_KEY_INFO *p8);
+PKCS12_SAFEBAG *PKCS12_MAKE_SHKEYBAG(int pbe_nid, const char *pass,
+ int passlen, unsigned char *salt,
+ int saltlen, int iter,
+ PKCS8_PRIV_KEY_INFO *p8);
+PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk);
+STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7);
+PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ STACK_OF(PKCS12_SAFEBAG) *bags);
+STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass, int passlen);
+
+int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes);
+STACK_OF(PKCS7) *PKCS12_unpack_authsafes(PKCS12 *p12);
+
+int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name, int namelen);
+int PKCS12_add_friendlyname_asc(PKCS12_SAFEBAG *bag, const char *name,
+ int namelen);
+int PKCS12_add_CSPName_asc(PKCS12_SAFEBAG *bag, const char *name,
+ int namelen);
+int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag, const unsigned char *name,
+ int namelen);
+int PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage);
+ASN1_TYPE *PKCS12_get_attr_gen(STACK_OF(X509_ATTRIBUTE) *attrs, int attr_nid);
+char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag);
+unsigned char *PKCS12_pbe_crypt(X509_ALGOR *algor, const char *pass,
+ int passlen, unsigned char *in, int inlen,
+ unsigned char **data, int *datalen, int en_de);
+void * PKCS12_item_decrypt_d2i(X509_ALGOR *algor, const ASN1_ITEM *it,
+ const char *pass, int passlen, ASN1_OCTET_STRING *oct, int zbuf);
+ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor, const ASN1_ITEM *it,
+ const char *pass, int passlen,
+ void *obj, int zbuf);
+PKCS12 *PKCS12_init(int mode);
+int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
+ int saltlen, int id, int iter, int n,
+ unsigned char *out, const EVP_MD *md_type);
+int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt, int saltlen, int id, int iter, int n, unsigned char *out, const EVP_MD *md_type);
+int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md_type,
+ int en_de);
+int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
+ unsigned char *mac, unsigned int *maclen);
+int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen);
+int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
+ unsigned char *salt, int saltlen, int iter,
+ const EVP_MD *md_type);
+int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt,
+ int saltlen, const EVP_MD *md_type);
+#if defined(NETWARE) || defined(OPENSSL_SYS_NETWARE)
+/* Rename these functions to avoid name clashes on NetWare OS */
+unsigned char *OPENSSL_asc2uni(const char *asc, int asclen, unsigned char **uni, int *unilen);
+char *OPENSSL_uni2asc(unsigned char *uni, int unilen);
+#else
+unsigned char *asc2uni(const char *asc, int asclen, unsigned char **uni, int *unilen);
+char *uni2asc(unsigned char *uni, int unilen);
+#endif
+DECLARE_ASN1_FUNCTIONS(PKCS12)
+DECLARE_ASN1_FUNCTIONS(PKCS12_MAC_DATA)
+DECLARE_ASN1_FUNCTIONS(PKCS12_SAFEBAG)
+DECLARE_ASN1_FUNCTIONS(PKCS12_BAGS)
+
+DECLARE_ASN1_ITEM(PKCS12_SAFEBAGS)
+DECLARE_ASN1_ITEM(PKCS12_AUTHSAFES)
+
+void PKCS12_PBE_add(void);
+int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
+ STACK_OF(X509) **ca);
+PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert,
+ STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter,
+ int mac_iter, int keytype);
+
+PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert);
+PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, EVP_PKEY *key,
+ int key_usage, int iter,
+ int key_nid, char *pass);
+int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+ int safe_nid, int iter, char *pass);
+PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int p7_nid);
+
+int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12);
+int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12);
+PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12);
+PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12);
+int PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_PKCS12_strings(void);
+
+/* Error codes for the PKCS12 functions. */
+
+/* Function codes. */
+#define PKCS12_F_PARSE_BAG 129
+#define PKCS12_F_PARSE_BAGS 103
+#define PKCS12_F_PKCS12_ADD_FRIENDLYNAME 100
+#define PKCS12_F_PKCS12_ADD_FRIENDLYNAME_ASC 127
+#define PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI 102
+#define PKCS12_F_PKCS12_ADD_LOCALKEYID 104
+#define PKCS12_F_PKCS12_CREATE 105
+#define PKCS12_F_PKCS12_GEN_MAC 107
+#define PKCS12_F_PKCS12_INIT 109
+#define PKCS12_F_PKCS12_ITEM_DECRYPT_D2I 106
+#define PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT 108
+#define PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG 117
+#define PKCS12_F_PKCS12_KEY_GEN_ASC 110
+#define PKCS12_F_PKCS12_KEY_GEN_UNI 111
+#define PKCS12_F_PKCS12_MAKE_KEYBAG 112
+#define PKCS12_F_PKCS12_MAKE_SHKEYBAG 113
+#define PKCS12_F_PKCS12_NEWPASS 128
+#define PKCS12_F_PKCS12_PACK_P7DATA 114
+#define PKCS12_F_PKCS12_PACK_P7ENCDATA 115
+#define PKCS12_F_PKCS12_PARSE 118
+#define PKCS12_F_PKCS12_PBE_CRYPT 119
+#define PKCS12_F_PKCS12_PBE_KEYIVGEN 120
+#define PKCS12_F_PKCS12_SETUP_MAC 122
+#define PKCS12_F_PKCS12_SET_MAC 123
+#define PKCS12_F_PKCS12_UNPACK_AUTHSAFES 130
+#define PKCS12_F_PKCS12_UNPACK_P7DATA 131
+#define PKCS12_F_PKCS12_VERIFY_MAC 126
+#define PKCS12_F_PKCS8_ADD_KEYUSAGE 124
+#define PKCS12_F_PKCS8_ENCRYPT 125
+
+/* Reason codes. */
+#define PKCS12_R_CANT_PACK_STRUCTURE 100
+#define PKCS12_R_CONTENT_TYPE_NOT_DATA 121
+#define PKCS12_R_DECODE_ERROR 101
+#define PKCS12_R_ENCODE_ERROR 102
+#define PKCS12_R_ENCRYPT_ERROR 103
+#define PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE 120
+#define PKCS12_R_INVALID_NULL_ARGUMENT 104
+#define PKCS12_R_INVALID_NULL_PKCS12_POINTER 105
+#define PKCS12_R_IV_GEN_ERROR 106
+#define PKCS12_R_KEY_GEN_ERROR 107
+#define PKCS12_R_MAC_ABSENT 108
+#define PKCS12_R_MAC_GENERATION_ERROR 109
+#define PKCS12_R_MAC_SETUP_ERROR 110
+#define PKCS12_R_MAC_STRING_SET_ERROR 111
+#define PKCS12_R_MAC_VERIFY_ERROR 112
+#define PKCS12_R_MAC_VERIFY_FAILURE 113
+#define PKCS12_R_PARSE_ERROR 114
+#define PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR 115
+#define PKCS12_R_PKCS12_CIPHERFINAL_ERROR 116
+#define PKCS12_R_PKCS12_PBE_CRYPT_ERROR 117
+#define PKCS12_R_UNKNOWN_DIGEST_ALGORITHM 118
+#define PKCS12_R_UNSUPPORTED_PKCS12_MODE 119
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/pkcs7.h b/src/Mayaqua/win32_inc/openssl/pkcs7.h
new file mode 100644
index 00000000..eeb05324
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/pkcs7.h
@@ -0,0 +1,464 @@
+/* crypto/pkcs7/pkcs7.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_PKCS7_H
+#define HEADER_PKCS7_H
+
+#include <openssl/asn1.h>
+#include <openssl/bio.h>
+#include <openssl/e_os2.h>
+
+#include <openssl/symhacks.h>
+#include <openssl/ossl_typ.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_SYS_WIN32
+/* Under Win32 thes are defined in wincrypt.h */
+#undef PKCS7_ISSUER_AND_SERIAL
+#undef PKCS7_SIGNER_INFO
+#endif
+
+/*
+Encryption_ID DES-CBC
+Digest_ID MD5
+Digest_Encryption_ID rsaEncryption
+Key_Encryption_ID rsaEncryption
+*/
+
+typedef struct pkcs7_issuer_and_serial_st
+ {
+ X509_NAME *issuer;
+ ASN1_INTEGER *serial;
+ } PKCS7_ISSUER_AND_SERIAL;
+
+typedef struct pkcs7_signer_info_st
+ {
+ ASN1_INTEGER *version; /* version 1 */
+ PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
+ X509_ALGOR *digest_alg;
+ STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
+ X509_ALGOR *digest_enc_alg;
+ ASN1_OCTET_STRING *enc_digest;
+ STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
+
+ /* The private key to sign with */
+ EVP_PKEY *pkey;
+ } PKCS7_SIGNER_INFO;
+
+DECLARE_STACK_OF(PKCS7_SIGNER_INFO)
+DECLARE_ASN1_SET_OF(PKCS7_SIGNER_INFO)
+
+typedef struct pkcs7_recip_info_st
+ {
+ ASN1_INTEGER *version; /* version 0 */
+ PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
+ X509_ALGOR *key_enc_algor;
+ ASN1_OCTET_STRING *enc_key;
+ X509 *cert; /* get the pub-key from this */
+ } PKCS7_RECIP_INFO;
+
+DECLARE_STACK_OF(PKCS7_RECIP_INFO)
+DECLARE_ASN1_SET_OF(PKCS7_RECIP_INFO)
+
+typedef struct pkcs7_signed_st
+ {
+ ASN1_INTEGER *version; /* version 1 */
+ STACK_OF(X509_ALGOR) *md_algs; /* md used */
+ STACK_OF(X509) *cert; /* [ 0 ] */
+ STACK_OF(X509_CRL) *crl; /* [ 1 ] */
+ STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
+
+ struct pkcs7_st *contents;
+ } PKCS7_SIGNED;
+/* The above structure is very very similar to PKCS7_SIGN_ENVELOPE.
+ * How about merging the two */
+
+typedef struct pkcs7_enc_content_st
+ {
+ ASN1_OBJECT *content_type;
+ X509_ALGOR *algorithm;
+ ASN1_OCTET_STRING *enc_data; /* [ 0 ] */
+ const EVP_CIPHER *cipher;
+ } PKCS7_ENC_CONTENT;
+
+typedef struct pkcs7_enveloped_st
+ {
+ ASN1_INTEGER *version; /* version 0 */
+ STACK_OF(PKCS7_RECIP_INFO) *recipientinfo;
+ PKCS7_ENC_CONTENT *enc_data;
+ } PKCS7_ENVELOPE;
+
+typedef struct pkcs7_signedandenveloped_st
+ {
+ ASN1_INTEGER *version; /* version 1 */
+ STACK_OF(X509_ALGOR) *md_algs; /* md used */
+ STACK_OF(X509) *cert; /* [ 0 ] */
+ STACK_OF(X509_CRL) *crl; /* [ 1 ] */
+ STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
+
+ PKCS7_ENC_CONTENT *enc_data;
+ STACK_OF(PKCS7_RECIP_INFO) *recipientinfo;
+ } PKCS7_SIGN_ENVELOPE;
+
+typedef struct pkcs7_digest_st
+ {
+ ASN1_INTEGER *version; /* version 0 */
+ X509_ALGOR *md; /* md used */
+ struct pkcs7_st *contents;
+ ASN1_OCTET_STRING *digest;
+ } PKCS7_DIGEST;
+
+typedef struct pkcs7_encrypted_st
+ {
+ ASN1_INTEGER *version; /* version 0 */
+ PKCS7_ENC_CONTENT *enc_data;
+ } PKCS7_ENCRYPT;
+
+typedef struct pkcs7_st
+ {
+ /* The following is non NULL if it contains ASN1 encoding of
+ * this structure */
+ unsigned char *asn1;
+ long length;
+
+#define PKCS7_S_HEADER 0
+#define PKCS7_S_BODY 1
+#define PKCS7_S_TAIL 2
+ int state; /* used during processing */
+
+ int detached;
+
+ ASN1_OBJECT *type;
+ /* content as defined by the type */
+ /* all encryption/message digests are applied to the 'contents',
+ * leaving out the 'type' field. */
+ union {
+ char *ptr;
+
+ /* NID_pkcs7_data */
+ ASN1_OCTET_STRING *data;
+
+ /* NID_pkcs7_signed */
+ PKCS7_SIGNED *sign;
+
+ /* NID_pkcs7_enveloped */
+ PKCS7_ENVELOPE *enveloped;
+
+ /* NID_pkcs7_signedAndEnveloped */
+ PKCS7_SIGN_ENVELOPE *signed_and_enveloped;
+
+ /* NID_pkcs7_digest */
+ PKCS7_DIGEST *digest;
+
+ /* NID_pkcs7_encrypted */
+ PKCS7_ENCRYPT *encrypted;
+
+ /* Anything else */
+ ASN1_TYPE *other;
+ } d;
+ } PKCS7;
+
+DECLARE_STACK_OF(PKCS7)
+DECLARE_ASN1_SET_OF(PKCS7)
+DECLARE_PKCS12_STACK_OF(PKCS7)
+
+#define PKCS7_OP_SET_DETACHED_SIGNATURE 1
+#define PKCS7_OP_GET_DETACHED_SIGNATURE 2
+
+#define PKCS7_get_signed_attributes(si) ((si)->auth_attr)
+#define PKCS7_get_attributes(si) ((si)->unauth_attr)
+
+#define PKCS7_type_is_signed(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_signed)
+#define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted)
+#define PKCS7_type_is_enveloped(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_enveloped)
+#define PKCS7_type_is_signedAndEnveloped(a) \
+ (OBJ_obj2nid((a)->type) == NID_pkcs7_signedAndEnveloped)
+#define PKCS7_type_is_data(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_data)
+
+#define PKCS7_type_is_digest(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_digest)
+
+#define PKCS7_set_detached(p,v) \
+ PKCS7_ctrl(p,PKCS7_OP_SET_DETACHED_SIGNATURE,v,NULL)
+#define PKCS7_get_detached(p) \
+ PKCS7_ctrl(p,PKCS7_OP_GET_DETACHED_SIGNATURE,0,NULL)
+
+#define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7))
+
+#ifdef SSLEAY_MACROS
+#ifndef PKCS7_ISSUER_AND_SERIAL_digest
+#define PKCS7_ISSUER_AND_SERIAL_digest(data,type,md,len) \
+ ASN1_digest((int (*)())i2d_PKCS7_ISSUER_AND_SERIAL,type,\
+ (char *)data,md,len)
+#endif
+#endif
+
+/* S/MIME related flags */
+
+#define PKCS7_TEXT 0x1
+#define PKCS7_NOCERTS 0x2
+#define PKCS7_NOSIGS 0x4
+#define PKCS7_NOCHAIN 0x8
+#define PKCS7_NOINTERN 0x10
+#define PKCS7_NOVERIFY 0x20
+#define PKCS7_DETACHED 0x40
+#define PKCS7_BINARY 0x80
+#define PKCS7_NOATTR 0x100
+#define PKCS7_NOSMIMECAP 0x200
+#define PKCS7_NOOLDMIMETYPE 0x400
+#define PKCS7_CRLFEOL 0x800
+#define PKCS7_STREAM 0x1000
+#define PKCS7_NOCRL 0x2000
+
+/* Flags: for compatibility with older code */
+
+#define SMIME_TEXT PKCS7_TEXT
+#define SMIME_NOCERTS PKCS7_NOCERTS
+#define SMIME_NOSIGS PKCS7_NOSIGS
+#define SMIME_NOCHAIN PKCS7_NOCHAIN
+#define SMIME_NOINTERN PKCS7_NOINTERN
+#define SMIME_NOVERIFY PKCS7_NOVERIFY
+#define SMIME_DETACHED PKCS7_DETACHED
+#define SMIME_BINARY PKCS7_BINARY
+#define SMIME_NOATTR PKCS7_NOATTR
+
+DECLARE_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL)
+
+#ifndef SSLEAY_MACROS
+int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data,const EVP_MD *type,
+ unsigned char *md,unsigned int *len);
+#ifndef OPENSSL_NO_FP_API
+PKCS7 *d2i_PKCS7_fp(FILE *fp,PKCS7 **p7);
+int i2d_PKCS7_fp(FILE *fp,PKCS7 *p7);
+#endif
+PKCS7 *PKCS7_dup(PKCS7 *p7);
+PKCS7 *d2i_PKCS7_bio(BIO *bp,PKCS7 **p7);
+int i2d_PKCS7_bio(BIO *bp,PKCS7 *p7);
+#endif
+
+DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNER_INFO)
+DECLARE_ASN1_FUNCTIONS(PKCS7_RECIP_INFO)
+DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNED)
+DECLARE_ASN1_FUNCTIONS(PKCS7_ENC_CONTENT)
+DECLARE_ASN1_FUNCTIONS(PKCS7_ENVELOPE)
+DECLARE_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE)
+DECLARE_ASN1_FUNCTIONS(PKCS7_DIGEST)
+DECLARE_ASN1_FUNCTIONS(PKCS7_ENCRYPT)
+DECLARE_ASN1_FUNCTIONS(PKCS7)
+
+DECLARE_ASN1_ITEM(PKCS7_ATTR_SIGN)
+DECLARE_ASN1_ITEM(PKCS7_ATTR_VERIFY)
+
+DECLARE_ASN1_NDEF_FUNCTION(PKCS7)
+
+long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg);
+
+int PKCS7_set_type(PKCS7 *p7, int type);
+int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other);
+int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data);
+int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
+ const EVP_MD *dgst);
+int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *p7i);
+int PKCS7_add_certificate(PKCS7 *p7, X509 *x509);
+int PKCS7_add_crl(PKCS7 *p7, X509_CRL *x509);
+int PKCS7_content_new(PKCS7 *p7, int nid);
+int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx,
+ BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si);
+int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
+ X509 *x509);
+
+BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio);
+int PKCS7_dataFinal(PKCS7 *p7, BIO *bio);
+BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert);
+
+
+PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509,
+ EVP_PKEY *pkey, const EVP_MD *dgst);
+X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si);
+int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md);
+STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7);
+
+PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509);
+int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri);
+int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509);
+int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher);
+
+PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx);
+ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk);
+int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si,int nid,int type,
+ void *data);
+int PKCS7_add_attribute (PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
+ void *value);
+ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid);
+ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid);
+int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
+ STACK_OF(X509_ATTRIBUTE) *sk);
+int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si,STACK_OF(X509_ATTRIBUTE) *sk);
+
+
+PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+ BIO *data, int flags);
+int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
+ BIO *indata, BIO *out, int flags);
+STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags);
+PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
+ int flags);
+int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags);
+
+int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si,
+ STACK_OF(X509_ALGOR) *cap);
+STACK_OF(X509_ALGOR) *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si);
+int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg);
+
+int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags);
+PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont);
+int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
+int SMIME_text(BIO *in, BIO *out);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_PKCS7_strings(void);
+
+/* Error codes for the PKCS7 functions. */
+
+/* Function codes. */
+#define PKCS7_F_B64_READ_PKCS7 120
+#define PKCS7_F_B64_WRITE_PKCS7 121
+#define PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP 118
+#define PKCS7_F_PKCS7_ADD_CERTIFICATE 100
+#define PKCS7_F_PKCS7_ADD_CRL 101
+#define PKCS7_F_PKCS7_ADD_RECIPIENT_INFO 102
+#define PKCS7_F_PKCS7_ADD_SIGNER 103
+#define PKCS7_F_PKCS7_BIO_ADD_DIGEST 125
+#define PKCS7_F_PKCS7_CTRL 104
+#define PKCS7_F_PKCS7_DATADECODE 112
+#define PKCS7_F_PKCS7_DATAFINAL 128
+#define PKCS7_F_PKCS7_DATAINIT 105
+#define PKCS7_F_PKCS7_DATASIGN 106
+#define PKCS7_F_PKCS7_DATAVERIFY 107
+#define PKCS7_F_PKCS7_DECRYPT 114
+#define PKCS7_F_PKCS7_ENCRYPT 115
+#define PKCS7_F_PKCS7_FIND_DIGEST 127
+#define PKCS7_F_PKCS7_GET0_SIGNERS 124
+#define PKCS7_F_PKCS7_SET_CIPHER 108
+#define PKCS7_F_PKCS7_SET_CONTENT 109
+#define PKCS7_F_PKCS7_SET_DIGEST 126
+#define PKCS7_F_PKCS7_SET_TYPE 110
+#define PKCS7_F_PKCS7_SIGN 116
+#define PKCS7_F_PKCS7_SIGNATUREVERIFY 113
+#define PKCS7_F_PKCS7_SIMPLE_SMIMECAP 119
+#define PKCS7_F_PKCS7_VERIFY 117
+#define PKCS7_F_SMIME_READ_PKCS7 122
+#define PKCS7_F_SMIME_TEXT 123
+
+/* Reason codes. */
+#define PKCS7_R_CERTIFICATE_VERIFY_ERROR 117
+#define PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 144
+#define PKCS7_R_CIPHER_NOT_INITIALIZED 116
+#define PKCS7_R_CONTENT_AND_DATA_PRESENT 118
+#define PKCS7_R_DECODE_ERROR 130
+#define PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH 100
+#define PKCS7_R_DECRYPT_ERROR 119
+#define PKCS7_R_DIGEST_FAILURE 101
+#define PKCS7_R_ERROR_ADDING_RECIPIENT 120
+#define PKCS7_R_ERROR_SETTING_CIPHER 121
+#define PKCS7_R_INVALID_MIME_TYPE 131
+#define PKCS7_R_INVALID_NULL_POINTER 143
+#define PKCS7_R_MIME_NO_CONTENT_TYPE 132
+#define PKCS7_R_MIME_PARSE_ERROR 133
+#define PKCS7_R_MIME_SIG_PARSE_ERROR 134
+#define PKCS7_R_MISSING_CERIPEND_INFO 103
+#define PKCS7_R_NO_CONTENT 122
+#define PKCS7_R_NO_CONTENT_TYPE 135
+#define PKCS7_R_NO_MULTIPART_BODY_FAILURE 136
+#define PKCS7_R_NO_MULTIPART_BOUNDARY 137
+#define PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE 115
+#define PKCS7_R_NO_RECIPIENT_MATCHES_KEY 146
+#define PKCS7_R_NO_SIGNATURES_ON_DATA 123
+#define PKCS7_R_NO_SIGNERS 142
+#define PKCS7_R_NO_SIG_CONTENT_TYPE 138
+#define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE 104
+#define PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR 124
+#define PKCS7_R_PKCS7_DATAFINAL 126
+#define PKCS7_R_PKCS7_DATAFINAL_ERROR 125
+#define PKCS7_R_PKCS7_DATASIGN 145
+#define PKCS7_R_PKCS7_PARSE_ERROR 139
+#define PKCS7_R_PKCS7_SIG_PARSE_ERROR 140
+#define PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 127
+#define PKCS7_R_SIGNATURE_FAILURE 105
+#define PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND 128
+#define PKCS7_R_SIG_INVALID_MIME_TYPE 141
+#define PKCS7_R_SMIME_TEXT_ERROR 129
+#define PKCS7_R_UNABLE_TO_FIND_CERTIFICATE 106
+#define PKCS7_R_UNABLE_TO_FIND_MEM_BIO 107
+#define PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST 108
+#define PKCS7_R_UNKNOWN_DIGEST_TYPE 109
+#define PKCS7_R_UNKNOWN_OPERATION 110
+#define PKCS7_R_UNSUPPORTED_CIPHER_TYPE 111
+#define PKCS7_R_UNSUPPORTED_CONTENT_TYPE 112
+#define PKCS7_R_WRONG_CONTENT_TYPE 113
+#define PKCS7_R_WRONG_PKCS7_TYPE 114
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/pq_compat.h b/src/Mayaqua/win32_inc/openssl/pq_compat.h
new file mode 100644
index 00000000..27a585fb
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/pq_compat.h
@@ -0,0 +1,152 @@
+/* crypto/pqueue/pqueue_compat.h */
+/*
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_PQ_COMPAT_H
+#define HEADER_PQ_COMPAT_H
+
+#include <openssl/opensslconf.h>
+#include <openssl/bn.h>
+
+/*
+ * The purpose of this header file is for supporting 64-bit integer
+ * manipulation on 32-bit (and lower) machines. Currently the only
+ * such environment is VMS, Utrix and those with smaller default integer
+ * sizes than 32 bits. For all such environment, we fall back to using
+ * BIGNUM. We may need to fine tune the conditions for systems that
+ * are incorrectly configured.
+ *
+ * The only clients of this code are (1) pqueue for priority, and
+ * (2) DTLS, for sequence number manipulation.
+ */
+
+#if (defined(THIRTY_TWO_BIT) && !defined(BN_LLONG)) || defined(SIXTEEN_BIT) || defined(EIGHT_BIT)
+
+#define PQ_64BIT_IS_INTEGER 0
+#define PQ_64BIT_IS_BIGNUM 1
+
+#define PQ_64BIT BIGNUM
+#define PQ_64BIT_CTX BN_CTX
+
+#define pq_64bit_init(x) BN_init(x)
+#define pq_64bit_free(x) BN_free(x)
+
+#define pq_64bit_ctx_new(ctx) BN_CTX_new()
+#define pq_64bit_ctx_free(x) BN_CTX_free(x)
+
+#define pq_64bit_assign(x, y) BN_copy(x, y)
+#define pq_64bit_assign_word(x, y) BN_set_word(x, y)
+#define pq_64bit_gt(x, y) BN_ucmp(x, y) >= 1 ? 1 : 0
+#define pq_64bit_eq(x, y) BN_ucmp(x, y) == 0 ? 1 : 0
+#define pq_64bit_add_word(x, w) BN_add_word(x, w)
+#define pq_64bit_sub(r, x, y) BN_sub(r, x, y)
+#define pq_64bit_sub_word(x, w) BN_sub_word(x, w)
+#define pq_64bit_mod(r, x, n, ctx) BN_mod(r, x, n, ctx)
+
+#define pq_64bit_bin2num(bn, bytes, len) BN_bin2bn(bytes, len, bn)
+#define pq_64bit_num2bin(bn, bytes) BN_bn2bin(bn, bytes)
+#define pq_64bit_get_word(x) BN_get_word(x)
+#define pq_64bit_is_bit_set(x, offset) BN_is_bit_set(x, offset)
+#define pq_64bit_lshift(r, x, shift) BN_lshift(r, x, shift)
+#define pq_64bit_set_bit(x, num) BN_set_bit(x, num)
+#define pq_64bit_get_length(x) BN_num_bits((x))
+
+#else
+
+#define PQ_64BIT_IS_INTEGER 1
+#define PQ_64BIT_IS_BIGNUM 0
+
+#if defined(SIXTY_FOUR_BIT)
+#define PQ_64BIT BN_ULONG
+#define PQ_64BIT_PRINT "%lld"
+#elif defined(SIXTY_FOUR_BIT_LONG)
+#define PQ_64BIT BN_ULONG
+#define PQ_64BIT_PRINT "%ld"
+#elif defined(THIRTY_TWO_BIT)
+#define PQ_64BIT BN_ULLONG
+#define PQ_64BIT_PRINT "%lld"
+#endif
+
+#define PQ_64BIT_CTX void
+
+#define pq_64bit_init(x)
+#define pq_64bit_free(x)
+#define pq_64bit_ctx_new(ctx) (ctx)
+#define pq_64bit_ctx_free(x)
+
+#define pq_64bit_assign(x, y) (*(x) = *(y))
+#define pq_64bit_assign_word(x, y) (*(x) = y)
+#define pq_64bit_gt(x, y) (*(x) > *(y))
+#define pq_64bit_eq(x, y) (*(x) == *(y))
+#define pq_64bit_add_word(x, w) (*(x) = (*(x) + (w)))
+#define pq_64bit_sub(r, x, y) (*(r) = (*(x) - *(y)))
+#define pq_64bit_sub_word(x, w) (*(x) = (*(x) - (w)))
+#define pq_64bit_mod(r, x, n, ctx)
+
+#define pq_64bit_bin2num(num, bytes, len) bytes_to_long_long(bytes, num)
+#define pq_64bit_num2bin(num, bytes) long_long_to_bytes(num, bytes)
+#define pq_64bit_get_word(x) *(x)
+#define pq_64bit_lshift(r, x, shift) (*(r) = (*(x) << (shift)))
+#define pq_64bit_set_bit(x, num) do { \
+ PQ_64BIT mask = 1; \
+ mask = mask << (num); \
+ *(x) |= mask; \
+ } while(0)
+#endif /* OPENSSL_SYS_VMS */
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/pqueue.h b/src/Mayaqua/win32_inc/openssl/pqueue.h
new file mode 100644
index 00000000..12b607dc
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/pqueue.h
@@ -0,0 +1,96 @@
+/* crypto/pqueue/pqueue.h */
+/*
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_PQUEUE_H
+#define HEADER_PQUEUE_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/pq_compat.h>
+
+typedef struct _pqueue *pqueue;
+
+typedef struct _pitem
+ {
+ PQ_64BIT priority;
+ void *data;
+ struct _pitem *next;
+ } pitem;
+
+typedef struct _pitem *piterator;
+
+pitem *pitem_new(PQ_64BIT priority, void *data);
+void pitem_free(pitem *item);
+
+pqueue pqueue_new(void);
+void pqueue_free(pqueue pq);
+
+pitem *pqueue_insert(pqueue pq, pitem *item);
+pitem *pqueue_peek(pqueue pq);
+pitem *pqueue_pop(pqueue pq);
+pitem *pqueue_find(pqueue pq, PQ_64BIT priority);
+pitem *pqueue_iterator(pqueue pq);
+pitem *pqueue_next(piterator *iter);
+
+void pqueue_print(pqueue pq);
+int pqueue_size(pqueue pq);
+
+#endif /* ! HEADER_PQUEUE_H */
diff --git a/src/Mayaqua/win32_inc/openssl/rand.h b/src/Mayaqua/win32_inc/openssl/rand.h
new file mode 100644
index 00000000..07aabc07
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/rand.h
@@ -0,0 +1,167 @@
+/* crypto/rand/rand.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RAND_H
+#define HEADER_RAND_H
+
+#include <stdlib.h>
+#include <openssl/ossl_typ.h>
+#include <openssl/e_os2.h>
+
+#if defined(OPENSSL_SYS_WINDOWS)
+#include <windows.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(OPENSSL_FIPS)
+#define FIPS_RAND_SIZE_T int
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct rand_meth_st RAND_METHOD; */
+
+struct rand_meth_st
+ {
+ void (*seed)(const void *buf, int num);
+ int (*bytes)(unsigned char *buf, int num);
+ void (*cleanup)(void);
+ void (*add)(const void *buf, int num, double entropy);
+ int (*pseudorand)(unsigned char *buf, int num);
+ int (*status)(void);
+ };
+
+#ifdef BN_DEBUG
+extern int rand_predictable;
+#endif
+
+int RAND_set_rand_method(const RAND_METHOD *meth);
+const RAND_METHOD *RAND_get_rand_method(void);
+#ifndef OPENSSL_NO_ENGINE
+int RAND_set_rand_engine(ENGINE *engine);
+#endif
+RAND_METHOD *RAND_SSLeay(void);
+void RAND_cleanup(void );
+int RAND_bytes(unsigned char *buf,int num);
+int RAND_pseudo_bytes(unsigned char *buf,int num);
+void RAND_seed(const void *buf,int num);
+void RAND_add(const void *buf,int num,double entropy);
+int RAND_load_file(const char *file,long max_bytes);
+int RAND_write_file(const char *file);
+const char *RAND_file_name(char *file,size_t num);
+int RAND_status(void);
+int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes);
+int RAND_egd(const char *path);
+int RAND_egd_bytes(const char *path,int bytes);
+int RAND_poll(void);
+#ifndef OPENSSL_NO_ENGINE
+#ifdef OPENSSL_FIPS
+void int_RAND_init_engine_callbacks(void);
+void int_RAND_set_callbacks(
+ int (*set_rand_func)(const RAND_METHOD *meth,
+ const RAND_METHOD **pmeth),
+ const RAND_METHOD *(*get_rand_func)(const RAND_METHOD **pmeth));
+#endif
+#endif
+
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
+
+void RAND_screen(void);
+int RAND_event(UINT, WPARAM, LPARAM);
+
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_RAND_strings(void);
+
+/* Error codes for the RAND functions. */
+
+/* Function codes. */
+#define RAND_F_ENG_RAND_GET_RAND_METHOD 108
+#define RAND_F_FIPS_RAND 103
+#define RAND_F_FIPS_RAND_BYTES 102
+#define RAND_F_FIPS_RAND_GET_RAND_METHOD 109
+#define RAND_F_FIPS_RAND_SET_DT 106
+#define RAND_F_FIPS_SET_DT 104
+#define RAND_F_FIPS_SET_PRNG_SEED 107
+#define RAND_F_FIPS_SET_TEST_MODE 105
+#define RAND_F_RAND_GET_RAND_METHOD 101
+#define RAND_F_SSLEAY_RAND_BYTES 100
+
+/* Reason codes. */
+#define RAND_R_NON_FIPS_METHOD 105
+#define RAND_R_NOT_IN_TEST_MODE 106
+#define RAND_R_NO_KEY_SET 107
+#define RAND_R_PRNG_ASKING_FOR_TOO_MUCH 101
+#define RAND_R_PRNG_ERROR 108
+#define RAND_R_PRNG_KEYED 109
+#define RAND_R_PRNG_NOT_REKEYED 102
+#define RAND_R_PRNG_NOT_RESEEDED 103
+#define RAND_R_PRNG_NOT_SEEDED 100
+#define RAND_R_PRNG_SEED_MUST_NOT_MATCH_KEY 110
+#define RAND_R_PRNG_STUCK 104
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/rc2.h b/src/Mayaqua/win32_inc/openssl/rc2.h
new file mode 100644
index 00000000..cf0876e3
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/rc2.h
@@ -0,0 +1,103 @@
+/* crypto/rc2/rc2.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RC2_H
+#define HEADER_RC2_H
+
+#include <openssl/opensslconf.h> /* OPENSSL_NO_RC2, RC2_INT */
+#ifdef OPENSSL_NO_RC2
+#error RC2 is disabled.
+#endif
+
+#define RC2_ENCRYPT 1
+#define RC2_DECRYPT 0
+
+#define RC2_BLOCK 8
+#define RC2_KEY_LENGTH 16
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct rc2_key_st
+ {
+ RC2_INT data[64];
+ } RC2_KEY;
+
+#ifdef OPENSSL_FIPS
+void private_RC2_set_key(RC2_KEY *key, int len, const unsigned char *data,int bits);
+#endif
+void RC2_set_key(RC2_KEY *key, int len, const unsigned char *data,int bits);
+void RC2_ecb_encrypt(const unsigned char *in,unsigned char *out,RC2_KEY *key,
+ int enc);
+void RC2_encrypt(unsigned long *data,RC2_KEY *key);
+void RC2_decrypt(unsigned long *data,RC2_KEY *key);
+void RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+ RC2_KEY *ks, unsigned char *iv, int enc);
+void RC2_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, RC2_KEY *schedule, unsigned char *ivec,
+ int *num, int enc);
+void RC2_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, RC2_KEY *schedule, unsigned char *ivec,
+ int *num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/rc4.h b/src/Mayaqua/win32_inc/openssl/rc4.h
new file mode 100644
index 00000000..f598804b
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/rc4.h
@@ -0,0 +1,90 @@
+/* crypto/rc4/rc4.h */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RC4_H
+#define HEADER_RC4_H
+
+#include <openssl/opensslconf.h> /* OPENSSL_NO_RC4, RC4_INT */
+#ifdef OPENSSL_NO_RC4
+#error RC4 is disabled.
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct rc4_key_st
+ {
+ RC4_INT x,y;
+ RC4_INT data[256];
+ } RC4_KEY;
+
+
+const char *RC4_options(void);
+#ifdef OPENSSL_FIPS
+void private_RC4_set_key(RC4_KEY *key, int len, const unsigned char *data);
+#endif
+void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data);
+void RC4(RC4_KEY *key, unsigned long len, const unsigned char *indata,
+ unsigned char *outdata);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/rc5.h b/src/Mayaqua/win32_inc/openssl/rc5.h
new file mode 100644
index 00000000..ea227272
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/rc5.h
@@ -0,0 +1,120 @@
+/* crypto/rc5/rc5.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RC5_H
+#define HEADER_RC5_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_RC5
+#error RC5 is disabled.
+#endif
+
+#define RC5_ENCRYPT 1
+#define RC5_DECRYPT 0
+
+/* 32 bit. For Alpha, things may get weird */
+#define RC5_32_INT unsigned long
+
+#define RC5_32_BLOCK 8
+#define RC5_32_KEY_LENGTH 16 /* This is a default, max is 255 */
+
+/* This are the only values supported. Tweak the code if you want more
+ * The most supported modes will be
+ * RC5-32/12/16
+ * RC5-32/16/8
+ */
+#define RC5_8_ROUNDS 8
+#define RC5_12_ROUNDS 12
+#define RC5_16_ROUNDS 16
+
+typedef struct rc5_key_st
+ {
+ /* Number of rounds */
+ int rounds;
+ RC5_32_INT data[2*(RC5_16_ROUNDS+1)];
+ } RC5_32_KEY;
+
+#ifdef OPENSSL_FIPS
+void private_RC5_32_set_key(RC5_32_KEY *key, int len, const unsigned char *data,
+ int rounds);
+#endif
+void RC5_32_set_key(RC5_32_KEY *key, int len, const unsigned char *data,
+ int rounds);
+void RC5_32_ecb_encrypt(const unsigned char *in,unsigned char *out,RC5_32_KEY *key,
+ int enc);
+void RC5_32_encrypt(unsigned long *data,RC5_32_KEY *key);
+void RC5_32_decrypt(unsigned long *data,RC5_32_KEY *key);
+void RC5_32_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ long length, RC5_32_KEY *ks, unsigned char *iv,
+ int enc);
+void RC5_32_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, RC5_32_KEY *schedule,
+ unsigned char *ivec, int *num, int enc);
+void RC5_32_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+ long length, RC5_32_KEY *schedule,
+ unsigned char *ivec, int *num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/ripemd.h b/src/Mayaqua/win32_inc/openssl/ripemd.h
new file mode 100644
index 00000000..af7eca59
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ripemd.h
@@ -0,0 +1,106 @@
+/* crypto/ripemd/ripemd.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RIPEMD_H
+#define HEADER_RIPEMD_H
+
+#include <openssl/e_os2.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_NO_RIPEMD
+#error RIPEMD is disabled.
+#endif
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define RIPEMD160_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define RIPEMD160_LONG unsigned long
+#define RIPEMD160_LONG_LOG2 3
+#else
+#define RIPEMD160_LONG unsigned int
+#endif
+
+#define RIPEMD160_CBLOCK 64
+#define RIPEMD160_LBLOCK (RIPEMD160_CBLOCK/4)
+#define RIPEMD160_DIGEST_LENGTH 20
+
+typedef struct RIPEMD160state_st
+ {
+ RIPEMD160_LONG A,B,C,D,E;
+ RIPEMD160_LONG Nl,Nh;
+ RIPEMD160_LONG data[RIPEMD160_LBLOCK];
+ unsigned int num;
+ } RIPEMD160_CTX;
+#ifdef OPENSSL_FIPS
+int private_RIPEMD160_Init(RIPEMD160_CTX *c);
+#endif
+int RIPEMD160_Init(RIPEMD160_CTX *c);
+int RIPEMD160_Update(RIPEMD160_CTX *c, const void *data, size_t len);
+int RIPEMD160_Final(unsigned char *md, RIPEMD160_CTX *c);
+unsigned char *RIPEMD160(const unsigned char *d, size_t n,
+ unsigned char *md);
+void RIPEMD160_Transform(RIPEMD160_CTX *c, const unsigned char *b);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/rsa.h b/src/Mayaqua/win32_inc/openssl/rsa.h
new file mode 100644
index 00000000..8e5e1b8d
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/rsa.h
@@ -0,0 +1,496 @@
+/* crypto/rsa/rsa.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_RSA_H
+#define HEADER_RSA_H
+
+#include <openssl/asn1.h>
+
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#include <openssl/crypto.h>
+#include <openssl/ossl_typ.h>
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#endif
+
+#ifdef OPENSSL_NO_RSA
+#error RSA is disabled.
+#endif
+
+/* If this flag is set the RSA method is FIPS compliant and can be used
+ * in FIPS mode. This is set in the validated module method. If an
+ * application sets this flag in its own methods it is its reposibility
+ * to ensure the result is compliant.
+ */
+
+#define RSA_FLAG_FIPS_METHOD 0x0400
+
+/* If this flag is set the operations normally disabled in FIPS mode are
+ * permitted it is then the applications responsibility to ensure that the
+ * usage is compliant.
+ */
+
+#define RSA_FLAG_NON_FIPS_ALLOW 0x0400
+
+#ifdef OPENSSL_FIPS
+#define FIPS_RSA_SIZE_T int
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Declared already in ossl_typ.h */
+/* typedef struct rsa_st RSA; */
+/* typedef struct rsa_meth_st RSA_METHOD; */
+
+struct rsa_meth_st
+ {
+ const char *name;
+ int (*rsa_pub_enc)(int flen,const unsigned char *from,
+ unsigned char *to,
+ RSA *rsa,int padding);
+ int (*rsa_pub_dec)(int flen,const unsigned char *from,
+ unsigned char *to,
+ RSA *rsa,int padding);
+ int (*rsa_priv_enc)(int flen,const unsigned char *from,
+ unsigned char *to,
+ RSA *rsa,int padding);
+ int (*rsa_priv_dec)(int flen,const unsigned char *from,
+ unsigned char *to,
+ RSA *rsa,int padding);
+ int (*rsa_mod_exp)(BIGNUM *r0,const BIGNUM *I,RSA *rsa,BN_CTX *ctx); /* Can be null */
+ int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx); /* Can be null */
+ int (*init)(RSA *rsa); /* called at new */
+ int (*finish)(RSA *rsa); /* called at free */
+ int flags; /* RSA_METHOD_FLAG_* things */
+ char *app_data; /* may be needed! */
+/* New sign and verify functions: some libraries don't allow arbitrary data
+ * to be signed/verified: this allows them to be used. Note: for this to work
+ * the RSA_public_decrypt() and RSA_private_encrypt() should *NOT* be used
+ * RSA_sign(), RSA_verify() should be used instead. Note: for backwards
+ * compatibility this functionality is only enabled if the RSA_FLAG_SIGN_VER
+ * option is set in 'flags'.
+ */
+ int (*rsa_sign)(int type,
+ const unsigned char *m, unsigned int m_length,
+ unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
+ int (*rsa_verify)(int dtype,
+ const unsigned char *m, unsigned int m_length,
+ unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);
+/* If this callback is NULL, the builtin software RSA key-gen will be used. This
+ * is for behavioural compatibility whilst the code gets rewired, but one day
+ * it would be nice to assume there are no such things as "builtin software"
+ * implementations. */
+ int (*rsa_keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
+ };
+
+struct rsa_st
+ {
+ /* The first parameter is used to pickup errors where
+ * this is passed instead of aEVP_PKEY, it is set to 0 */
+ int pad;
+ long version;
+ const RSA_METHOD *meth;
+ /* functional reference if 'meth' is ENGINE-provided */
+ ENGINE *engine;
+ BIGNUM *n;
+ BIGNUM *e;
+ BIGNUM *d;
+ BIGNUM *p;
+ BIGNUM *q;
+ BIGNUM *dmp1;
+ BIGNUM *dmq1;
+ BIGNUM *iqmp;
+ /* be careful using this if the RSA structure is shared */
+ CRYPTO_EX_DATA ex_data;
+ int references;
+ int flags;
+
+ /* Used to cache montgomery values */
+ BN_MONT_CTX *_method_mod_n;
+ BN_MONT_CTX *_method_mod_p;
+ BN_MONT_CTX *_method_mod_q;
+
+ /* all BIGNUM values are actually in the following data, if it is not
+ * NULL */
+ char *bignum_data;
+ BN_BLINDING *blinding;
+ BN_BLINDING *mt_blinding;
+ };
+
+#ifndef OPENSSL_RSA_MAX_MODULUS_BITS
+# define OPENSSL_RSA_MAX_MODULUS_BITS 16384
+#endif
+
+#define OPENSSL_RSA_FIPS_MIN_MODULUS_BITS 1024
+
+#ifndef OPENSSL_RSA_SMALL_MODULUS_BITS
+# define OPENSSL_RSA_SMALL_MODULUS_BITS 3072
+#endif
+#ifndef OPENSSL_RSA_MAX_PUBEXP_BITS
+# define OPENSSL_RSA_MAX_PUBEXP_BITS 64 /* exponent limit enforced for "large" modulus only */
+#endif
+
+#define RSA_3 0x3L
+#define RSA_F4 0x10001L
+
+#define RSA_METHOD_FLAG_NO_CHECK 0x0001 /* don't check pub/private match */
+
+#define RSA_FLAG_CACHE_PUBLIC 0x0002
+#define RSA_FLAG_CACHE_PRIVATE 0x0004
+#define RSA_FLAG_BLINDING 0x0008
+#define RSA_FLAG_THREAD_SAFE 0x0010
+/* This flag means the private key operations will be handled by rsa_mod_exp
+ * and that they do not depend on the private key components being present:
+ * for example a key stored in external hardware. Without this flag bn_mod_exp
+ * gets called when private key components are absent.
+ */
+#define RSA_FLAG_EXT_PKEY 0x0020
+
+/* This flag in the RSA_METHOD enables the new rsa_sign, rsa_verify functions.
+ */
+#define RSA_FLAG_SIGN_VER 0x0040
+
+#define RSA_FLAG_NO_BLINDING 0x0080 /* new with 0.9.6j and 0.9.7b; the built-in
+ * RSA implementation now uses blinding by
+ * default (ignoring RSA_FLAG_BLINDING),
+ * but other engines might not need it
+ */
+#define RSA_FLAG_NO_CONSTTIME 0x0100 /* new with 0.9.8f; the built-in RSA
+ * implementation now uses constant time
+ * operations by default in private key operations,
+ * e.g., constant time modular exponentiation,
+ * modular inverse without leaking branches,
+ * division without leaking branches. This
+ * flag disables these constant time
+ * operations and results in faster RSA
+ * private key operations.
+ */
+#ifndef OPENSSL_NO_DEPRECATED
+#define RSA_FLAG_NO_EXP_CONSTTIME RSA_FLAG_NO_CONSTTIME /* deprecated name for the flag*/
+ /* new with 0.9.7h; the built-in RSA
+ * implementation now uses constant time
+ * modular exponentiation for secret exponents
+ * by default. This flag causes the
+ * faster variable sliding window method to
+ * be used for all exponents.
+ */
+#endif
+
+
+#define RSA_PKCS1_PADDING 1
+#define RSA_SSLV23_PADDING 2
+#define RSA_NO_PADDING 3
+#define RSA_PKCS1_OAEP_PADDING 4
+#define RSA_X931_PADDING 5
+
+#define RSA_PKCS1_PADDING_SIZE 11
+
+#define RSA_set_app_data(s,arg) RSA_set_ex_data(s,0,arg)
+#define RSA_get_app_data(s) RSA_get_ex_data(s,0)
+
+RSA * RSA_new(void);
+RSA * RSA_new_method(ENGINE *engine);
+int RSA_size(const RSA *);
+
+/* Deprecated version */
+#ifndef OPENSSL_NO_DEPRECATED
+RSA * RSA_generate_key(int bits, unsigned long e,void
+ (*callback)(int,int,void *),void *cb_arg);
+#endif /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* New version */
+int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
+int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1, BIGNUM *q2,
+ const BIGNUM *Xp1, const BIGNUM *Xp2, const BIGNUM *Xp,
+ const BIGNUM *Xq1, const BIGNUM *Xq2, const BIGNUM *Xq,
+ const BIGNUM *e, BN_GENCB *cb);
+int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e, BN_GENCB *cb);
+
+int RSA_check_key(const RSA *);
+ /* next 4 return -1 on error */
+int RSA_public_encrypt(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa,int padding);
+int RSA_private_encrypt(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa,int padding);
+int RSA_public_decrypt(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa,int padding);
+int RSA_private_decrypt(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa,int padding);
+void RSA_free (RSA *r);
+/* "up" the RSA object's reference count */
+int RSA_up_ref(RSA *r);
+
+int RSA_flags(const RSA *r);
+
+#ifdef OPENSSL_FIPS
+RSA *FIPS_rsa_new(void);
+void FIPS_rsa_free(RSA *r);
+#endif
+
+void RSA_set_default_method(const RSA_METHOD *meth);
+const RSA_METHOD *RSA_get_default_method(void);
+const RSA_METHOD *RSA_get_method(const RSA *rsa);
+int RSA_set_method(RSA *rsa, const RSA_METHOD *meth);
+
+/* This function needs the memory locking malloc callbacks to be installed */
+int RSA_memory_lock(RSA *r);
+
+/* these are the actual SSLeay RSA functions */
+const RSA_METHOD *RSA_PKCS1_SSLeay(void);
+
+const RSA_METHOD *RSA_null_method(void);
+
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPublicKey)
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPrivateKey)
+
+#ifndef OPENSSL_NO_FP_API
+int RSA_print_fp(FILE *fp, const RSA *r,int offset);
+#endif
+
+#ifndef OPENSSL_NO_BIO
+int RSA_print(BIO *bp, const RSA *r,int offset);
+#endif
+
+#ifndef OPENSSL_NO_RC4
+int i2d_RSA_NET(const RSA *a, unsigned char **pp,
+ int (*cb)(char *buf, int len, const char *prompt, int verify),
+ int sgckey);
+RSA *d2i_RSA_NET(RSA **a, const unsigned char **pp, long length,
+ int (*cb)(char *buf, int len, const char *prompt, int verify),
+ int sgckey);
+
+int i2d_Netscape_RSA(const RSA *a, unsigned char **pp,
+ int (*cb)(char *buf, int len, const char *prompt,
+ int verify));
+RSA *d2i_Netscape_RSA(RSA **a, const unsigned char **pp, long length,
+ int (*cb)(char *buf, int len, const char *prompt,
+ int verify));
+#endif
+
+/* The following 2 functions sign and verify a X509_SIG ASN1 object
+ * inside PKCS#1 padded RSA encryption */
+int RSA_sign(int type, const unsigned char *m, unsigned int m_length,
+ unsigned char *sigret, unsigned int *siglen, RSA *rsa);
+int RSA_verify(int type, const unsigned char *m, unsigned int m_length,
+ unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
+
+/* The following 2 function sign and verify a ASN1_OCTET_STRING
+ * object inside PKCS#1 padded RSA encryption */
+int RSA_sign_ASN1_OCTET_STRING(int type,
+ const unsigned char *m, unsigned int m_length,
+ unsigned char *sigret, unsigned int *siglen, RSA *rsa);
+int RSA_verify_ASN1_OCTET_STRING(int type,
+ const unsigned char *m, unsigned int m_length,
+ unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
+
+int RSA_blinding_on(RSA *rsa, BN_CTX *ctx);
+void RSA_blinding_off(RSA *rsa);
+BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *ctx);
+
+int RSA_padding_add_PKCS1_type_1(unsigned char *to,int tlen,
+ const unsigned char *f,int fl);
+int RSA_padding_check_PKCS1_type_1(unsigned char *to,int tlen,
+ const unsigned char *f,int fl,int rsa_len);
+int RSA_padding_add_PKCS1_type_2(unsigned char *to,int tlen,
+ const unsigned char *f,int fl);
+int RSA_padding_check_PKCS1_type_2(unsigned char *to,int tlen,
+ const unsigned char *f,int fl,int rsa_len);
+int PKCS1_MGF1(unsigned char *mask, long len,
+ const unsigned char *seed, long seedlen, const EVP_MD *dgst);
+int RSA_padding_add_PKCS1_OAEP(unsigned char *to,int tlen,
+ const unsigned char *f,int fl,
+ const unsigned char *p,int pl);
+int RSA_padding_check_PKCS1_OAEP(unsigned char *to,int tlen,
+ const unsigned char *f,int fl,int rsa_len,
+ const unsigned char *p,int pl);
+int RSA_padding_add_SSLv23(unsigned char *to,int tlen,
+ const unsigned char *f,int fl);
+int RSA_padding_check_SSLv23(unsigned char *to,int tlen,
+ const unsigned char *f,int fl,int rsa_len);
+int RSA_padding_add_none(unsigned char *to,int tlen,
+ const unsigned char *f,int fl);
+int RSA_padding_check_none(unsigned char *to,int tlen,
+ const unsigned char *f,int fl,int rsa_len);
+int RSA_padding_add_X931(unsigned char *to,int tlen,
+ const unsigned char *f,int fl);
+int RSA_padding_check_X931(unsigned char *to,int tlen,
+ const unsigned char *f,int fl,int rsa_len);
+int RSA_X931_hash_id(int nid);
+
+int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
+ const EVP_MD *Hash, const unsigned char *EM, int sLen);
+int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
+ const unsigned char *mHash,
+ const EVP_MD *Hash, int sLen);
+
+int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int RSA_set_ex_data(RSA *r,int idx,void *arg);
+void *RSA_get_ex_data(const RSA *r, int idx);
+
+RSA *RSAPublicKey_dup(RSA *rsa);
+RSA *RSAPrivateKey_dup(RSA *rsa);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_RSA_strings(void);
+
+/* Error codes for the RSA functions. */
+
+/* Function codes. */
+#define RSA_F_FIPS_RSA_SIGN 140
+#define RSA_F_FIPS_RSA_VERIFY 141
+#define RSA_F_MEMORY_LOCK 100
+#define RSA_F_RSA_BUILTIN_KEYGEN 129
+#define RSA_F_RSA_CHECK_KEY 123
+#define RSA_F_RSA_EAY_PRIVATE_DECRYPT 101
+#define RSA_F_RSA_EAY_PRIVATE_ENCRYPT 102
+#define RSA_F_RSA_EAY_PUBLIC_DECRYPT 103
+#define RSA_F_RSA_EAY_PUBLIC_ENCRYPT 104
+#define RSA_F_RSA_GENERATE_KEY 105
+#define RSA_F_RSA_MEMORY_LOCK 130
+#define RSA_F_RSA_NEW_METHOD 106
+#define RSA_F_RSA_NULL 124
+#define RSA_F_RSA_NULL_MOD_EXP 131
+#define RSA_F_RSA_NULL_PRIVATE_DECRYPT 132
+#define RSA_F_RSA_NULL_PRIVATE_ENCRYPT 133
+#define RSA_F_RSA_NULL_PUBLIC_DECRYPT 134
+#define RSA_F_RSA_NULL_PUBLIC_ENCRYPT 135
+#define RSA_F_RSA_PADDING_ADD_NONE 107
+#define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP 121
+#define RSA_F_RSA_PADDING_ADD_PKCS1_PSS 125
+#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1 108
+#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2 109
+#define RSA_F_RSA_PADDING_ADD_SSLV23 110
+#define RSA_F_RSA_PADDING_ADD_X931 127
+#define RSA_F_RSA_PADDING_CHECK_NONE 111
+#define RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP 122
+#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1 112
+#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2 113
+#define RSA_F_RSA_PADDING_CHECK_SSLV23 114
+#define RSA_F_RSA_PADDING_CHECK_X931 128
+#define RSA_F_RSA_PRINT 115
+#define RSA_F_RSA_PRINT_FP 116
+#define RSA_F_RSA_PRIVATE_ENCRYPT 137
+#define RSA_F_RSA_PUBLIC_DECRYPT 138
+#define RSA_F_RSA_SETUP_BLINDING 136
+#define RSA_F_RSA_SET_DEFAULT_METHOD 139
+#define RSA_F_RSA_SET_METHOD 142
+#define RSA_F_RSA_SIGN 117
+#define RSA_F_RSA_SIGN_ASN1_OCTET_STRING 118
+#define RSA_F_RSA_VERIFY 119
+#define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING 120
+#define RSA_F_RSA_VERIFY_PKCS1_PSS 126
+
+/* Reason codes. */
+#define RSA_R_ALGORITHM_MISMATCH 100
+#define RSA_R_BAD_E_VALUE 101
+#define RSA_R_BAD_FIXED_HEADER_DECRYPT 102
+#define RSA_R_BAD_PAD_BYTE_COUNT 103
+#define RSA_R_BAD_SIGNATURE 104
+#define RSA_R_BLOCK_TYPE_IS_NOT_01 106
+#define RSA_R_BLOCK_TYPE_IS_NOT_02 107
+#define RSA_R_DATA_GREATER_THAN_MOD_LEN 108
+#define RSA_R_DATA_TOO_LARGE 109
+#define RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 110
+#define RSA_R_DATA_TOO_LARGE_FOR_MODULUS 132
+#define RSA_R_DATA_TOO_SMALL 111
+#define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE 122
+#define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY 112
+#define RSA_R_DMP1_NOT_CONGRUENT_TO_D 124
+#define RSA_R_DMQ1_NOT_CONGRUENT_TO_D 125
+#define RSA_R_D_E_NOT_CONGRUENT_TO_1 123
+#define RSA_R_FIRST_OCTET_INVALID 133
+#define RSA_R_INVALID_HEADER 137
+#define RSA_R_INVALID_MESSAGE_LENGTH 131
+#define RSA_R_INVALID_PADDING 138
+#define RSA_R_INVALID_TRAILER 139
+#define RSA_R_IQMP_NOT_INVERSE_OF_Q 126
+#define RSA_R_KEY_SIZE_TOO_SMALL 120
+#define RSA_R_LAST_OCTET_INVALID 134
+#define RSA_R_MODULUS_TOO_LARGE 105
+#define RSA_R_NON_FIPS_METHOD 141
+#define RSA_R_NO_PUBLIC_EXPONENT 140
+#define RSA_R_NULL_BEFORE_BLOCK_MISSING 113
+#define RSA_R_N_DOES_NOT_EQUAL_P_Q 127
+#define RSA_R_OAEP_DECODING_ERROR 121
+#define RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE 142
+#define RSA_R_PADDING_CHECK_FAILED 114
+#define RSA_R_P_NOT_PRIME 128
+#define RSA_R_Q_NOT_PRIME 129
+#define RSA_R_RSA_OPERATIONS_NOT_SUPPORTED 130
+#define RSA_R_SLEN_CHECK_FAILED 136
+#define RSA_R_SLEN_RECOVERY_FAILED 135
+#define RSA_R_SSLV3_ROLLBACK_ATTACK 115
+#define RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 116
+#define RSA_R_UNKNOWN_ALGORITHM_TYPE 117
+#define RSA_R_UNKNOWN_PADDING_TYPE 118
+#define RSA_R_WRONG_SIGNATURE_LENGTH 119
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/safestack.h b/src/Mayaqua/win32_inc/openssl/safestack.h
new file mode 100644
index 00000000..54c82031
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/safestack.h
@@ -0,0 +1,1986 @@
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_SAFESTACK_H
+#define HEADER_SAFESTACK_H
+
+#include <openssl/stack.h>
+
+#ifdef DEBUG_SAFESTACK
+
+#ifndef CHECKED_PTR_OF
+#define CHECKED_PTR_OF(type, p) \
+ ((void*) (1 ? p : (type*)0))
+#endif
+
+#define CHECKED_SK_FREE_FUNC(type, p) \
+ ((void (*)(void *)) ((1 ? p : (void (*)(type *))0)))
+
+#define CHECKED_SK_CMP_FUNC(type, p) \
+ ((int (*)(const char * const *, const char * const *)) \
+ ((1 ? p : (int (*)(const type * const *, const type * const *))0)))
+
+#define STACK_OF(type) struct stack_st_##type
+#define PREDECLARE_STACK_OF(type) STACK_OF(type);
+
+#define DECLARE_STACK_OF(type) \
+STACK_OF(type) \
+ { \
+ STACK stack; \
+ };
+
+#define IMPLEMENT_STACK_OF(type) /* nada (obsolete in new safestack approach)*/
+
+/* SKM_sk_... stack macros are internal to safestack.h:
+ * never use them directly, use sk_<type>_... instead */
+#define SKM_sk_new(type, cmp) \
+ ((STACK_OF(type) *)sk_new(CHECKED_SK_CMP_FUNC(type, cmp)))
+#define SKM_sk_new_null(type) \
+ ((STACK_OF(type) *)sk_new_null())
+#define SKM_sk_free(type, st) \
+ sk_free(CHECKED_PTR_OF(STACK_OF(type), st))
+#define SKM_sk_num(type, st) \
+ sk_num(CHECKED_PTR_OF(STACK_OF(type), st))
+#define SKM_sk_value(type, st,i) \
+ ((type *)sk_value(CHECKED_PTR_OF(STACK_OF(type), st), i))
+#define SKM_sk_set(type, st,i,val) \
+ sk_set(CHECKED_PTR_OF(STACK_OF(type), st), i, CHECKED_PTR_OF(type, val))
+#define SKM_sk_zero(type, st) \
+ sk_zero(CHECKED_PTR_OF(STACK_OF(type), st))
+#define SKM_sk_push(type, st,val) \
+ sk_push(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_PTR_OF(type, val))
+#define SKM_sk_unshift(type, st,val) \
+ sk_unshift(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_PTR_OF(type, val))
+#define SKM_sk_find(type, st,val) \
+ sk_find(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_PTR_OF(type, val))
+#define SKM_sk_delete(type, st,i) \
+ (type *)sk_delete(CHECKED_PTR_OF(STACK_OF(type), st), i)
+#define SKM_sk_delete_ptr(type, st,ptr) \
+ (type *)sk_delete_ptr(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_PTR_OF(type, ptr))
+#define SKM_sk_insert(type, st,val,i) \
+ sk_insert(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_PTR_OF(type, val), i)
+#define SKM_sk_set_cmp_func(type, st,cmp) \
+ ((int (*)(const type * const *,const type * const *)) \
+ sk_set_cmp_func(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_SK_CMP_FUNC(type, cmp)))
+#define SKM_sk_dup(type, st) \
+ (STACK_OF(type) *)sk_dup(CHECKED_PTR_OF(STACK_OF(type), st))
+#define SKM_sk_pop_free(type, st,free_func) \
+ sk_pop_free(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_SK_FREE_FUNC(type, free_func))
+#define SKM_sk_shift(type, st) \
+ (type *)sk_shift(CHECKED_PTR_OF(STACK_OF(type), st))
+#define SKM_sk_pop(type, st) \
+ (type *)sk_pop(CHECKED_PTR_OF(STACK_OF(type), st))
+#define SKM_sk_sort(type, st) \
+ sk_sort(CHECKED_PTR_OF(STACK_OF(type), st))
+#define SKM_sk_is_sorted(type, st) \
+ sk_is_sorted(CHECKED_PTR_OF(STACK_OF(type), st))
+
+#define SKM_ASN1_SET_OF_d2i(type, st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ (STACK_OF(type) *)d2i_ASN1_SET(CHECKED_PTR_OF(STACK_OF(type)*, st), \
+ pp, length, \
+ CHECKED_D2I_OF(type, d2i_func), \
+ CHECKED_SK_FREE_FUNC(type, free_func), \
+ ex_tag, ex_class)
+
+#define SKM_ASN1_SET_OF_i2d(type, st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ i2d_ASN1_SET(CHECKED_PTR_OF(STACK_OF(type), st), pp, \
+ CHECKED_I2D_OF(type, i2d_func), \
+ ex_tag, ex_class, is_set)
+
+#define SKM_ASN1_seq_pack(type, st, i2d_func, buf, len) \
+ ASN1_seq_pack(CHECKED_PTR_OF(STACK_OF(type), st), \
+ CHECKED_I2D_OF(type, i2d_func), buf, len)
+
+#define SKM_ASN1_seq_unpack(type, buf, len, d2i_func, free_func) \
+ (STACK_OF(type) *)ASN1_seq_unpack(buf, len, CHECKED_D2I_OF(type, d2i_func), CHECKED_SK_FREE_FUNC(type, free_func))
+
+#define SKM_PKCS12_decrypt_d2i(type, algor, d2i_func, free_func, pass, passlen, oct, seq) \
+ (STACK_OF(type) *)PKCS12_decrypt_d2i(algor, \
+ CHECKED_D2I_OF(type, d2i_func), \
+ CHECKED_SK_FREE_FUNC(type, free_func), \
+ pass, passlen, oct, seq)
+
+#else
+
+#define STACK_OF(type) STACK
+#define PREDECLARE_STACK_OF(type) /* nada */
+#define DECLARE_STACK_OF(type) /* nada */
+#define IMPLEMENT_STACK_OF(type) /* nada */
+
+#define SKM_sk_new(type, cmp) \
+ sk_new((int (*)(const char * const *, const char * const *))(cmp))
+#define SKM_sk_new_null(type) \
+ sk_new_null()
+#define SKM_sk_free(type, st) \
+ sk_free(st)
+#define SKM_sk_num(type, st) \
+ sk_num(st)
+#define SKM_sk_value(type, st,i) \
+ ((type *)sk_value(st, i))
+#define SKM_sk_set(type, st,i,val) \
+ ((type *)sk_set(st, i,(char *)val))
+#define SKM_sk_zero(type, st) \
+ sk_zero(st)
+#define SKM_sk_push(type, st,val) \
+ sk_push(st, (char *)val)
+#define SKM_sk_unshift(type, st,val) \
+ sk_unshift(st, (char *)val)
+#define SKM_sk_find(type, st,val) \
+ sk_find(st, (char *)val)
+#define SKM_sk_delete(type, st,i) \
+ ((type *)sk_delete(st, i))
+#define SKM_sk_delete_ptr(type, st,ptr) \
+ ((type *)sk_delete_ptr(st,(char *)ptr))
+#define SKM_sk_insert(type, st,val,i) \
+ sk_insert(st, (char *)val, i)
+#define SKM_sk_set_cmp_func(type, st,cmp) \
+ ((int (*)(const type * const *,const type * const *)) \
+ sk_set_cmp_func(st, (int (*)(const char * const *, const char * const *))(cmp)))
+#define SKM_sk_dup(type, st) \
+ sk_dup(st)
+#define SKM_sk_pop_free(type, st,free_func) \
+ sk_pop_free(st, (void (*)(void *))free_func)
+#define SKM_sk_shift(type, st) \
+ ((type *)sk_shift(st))
+#define SKM_sk_pop(type, st) \
+ ((type *)sk_pop(st))
+#define SKM_sk_sort(type, st) \
+ sk_sort(st)
+#define SKM_sk_is_sorted(type, st) \
+ sk_is_sorted(st)
+
+#define SKM_ASN1_SET_OF_d2i(type, st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ d2i_ASN1_SET(st,pp,length, (void *(*)(void ** ,const unsigned char ** ,long))d2i_func, (void (*)(void *))free_func, ex_tag,ex_class)
+#define SKM_ASN1_SET_OF_i2d(type, st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ i2d_ASN1_SET(st,pp,(int (*)(void *, unsigned char **))i2d_func,ex_tag,ex_class,is_set)
+
+#define SKM_ASN1_seq_pack(type, st, i2d_func, buf, len) \
+ ASN1_seq_pack(st, (int (*)(void *, unsigned char **))i2d_func, buf, len)
+#define SKM_ASN1_seq_unpack(type, buf, len, d2i_func, free_func) \
+ ASN1_seq_unpack(buf,len,(void *(*)(void **,const unsigned char **,long))d2i_func, (void(*)(void *))free_func)
+
+#define SKM_PKCS12_decrypt_d2i(type, algor, d2i_func, free_func, pass, passlen, oct, seq) \
+ ((STACK *)PKCS12_decrypt_d2i(algor,(char *(*)())d2i_func, (void(*)(void *))free_func,pass,passlen,oct,seq))
+
+#endif
+
+/* This block of defines is updated by util/mkstack.pl, please do not touch! */
+#define sk_ACCESS_DESCRIPTION_new(st) SKM_sk_new(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_new_null() SKM_sk_new_null(ACCESS_DESCRIPTION)
+#define sk_ACCESS_DESCRIPTION_free(st) SKM_sk_free(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_num(st) SKM_sk_num(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_value(st, i) SKM_sk_value(ACCESS_DESCRIPTION, (st), (i))
+#define sk_ACCESS_DESCRIPTION_set(st, i, val) SKM_sk_set(ACCESS_DESCRIPTION, (st), (i), (val))
+#define sk_ACCESS_DESCRIPTION_zero(st) SKM_sk_zero(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_push(st, val) SKM_sk_push(ACCESS_DESCRIPTION, (st), (val))
+#define sk_ACCESS_DESCRIPTION_unshift(st, val) SKM_sk_unshift(ACCESS_DESCRIPTION, (st), (val))
+#define sk_ACCESS_DESCRIPTION_find(st, val) SKM_sk_find(ACCESS_DESCRIPTION, (st), (val))
+#define sk_ACCESS_DESCRIPTION_find_ex(st, val) SKM_sk_find_ex(ACCESS_DESCRIPTION, (st), (val))
+#define sk_ACCESS_DESCRIPTION_delete(st, i) SKM_sk_delete(ACCESS_DESCRIPTION, (st), (i))
+#define sk_ACCESS_DESCRIPTION_delete_ptr(st, ptr) SKM_sk_delete_ptr(ACCESS_DESCRIPTION, (st), (ptr))
+#define sk_ACCESS_DESCRIPTION_insert(st, val, i) SKM_sk_insert(ACCESS_DESCRIPTION, (st), (val), (i))
+#define sk_ACCESS_DESCRIPTION_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ACCESS_DESCRIPTION, (st), (cmp))
+#define sk_ACCESS_DESCRIPTION_dup(st) SKM_sk_dup(ACCESS_DESCRIPTION, st)
+#define sk_ACCESS_DESCRIPTION_pop_free(st, free_func) SKM_sk_pop_free(ACCESS_DESCRIPTION, (st), (free_func))
+#define sk_ACCESS_DESCRIPTION_shift(st) SKM_sk_shift(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_pop(st) SKM_sk_pop(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_sort(st) SKM_sk_sort(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_is_sorted(st) SKM_sk_is_sorted(ACCESS_DESCRIPTION, (st))
+
+#define sk_ASIdOrRange_new(st) SKM_sk_new(ASIdOrRange, (st))
+#define sk_ASIdOrRange_new_null() SKM_sk_new_null(ASIdOrRange)
+#define sk_ASIdOrRange_free(st) SKM_sk_free(ASIdOrRange, (st))
+#define sk_ASIdOrRange_num(st) SKM_sk_num(ASIdOrRange, (st))
+#define sk_ASIdOrRange_value(st, i) SKM_sk_value(ASIdOrRange, (st), (i))
+#define sk_ASIdOrRange_set(st, i, val) SKM_sk_set(ASIdOrRange, (st), (i), (val))
+#define sk_ASIdOrRange_zero(st) SKM_sk_zero(ASIdOrRange, (st))
+#define sk_ASIdOrRange_push(st, val) SKM_sk_push(ASIdOrRange, (st), (val))
+#define sk_ASIdOrRange_unshift(st, val) SKM_sk_unshift(ASIdOrRange, (st), (val))
+#define sk_ASIdOrRange_find(st, val) SKM_sk_find(ASIdOrRange, (st), (val))
+#define sk_ASIdOrRange_find_ex(st, val) SKM_sk_find_ex(ASIdOrRange, (st), (val))
+#define sk_ASIdOrRange_delete(st, i) SKM_sk_delete(ASIdOrRange, (st), (i))
+#define sk_ASIdOrRange_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASIdOrRange, (st), (ptr))
+#define sk_ASIdOrRange_insert(st, val, i) SKM_sk_insert(ASIdOrRange, (st), (val), (i))
+#define sk_ASIdOrRange_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASIdOrRange, (st), (cmp))
+#define sk_ASIdOrRange_dup(st) SKM_sk_dup(ASIdOrRange, st)
+#define sk_ASIdOrRange_pop_free(st, free_func) SKM_sk_pop_free(ASIdOrRange, (st), (free_func))
+#define sk_ASIdOrRange_shift(st) SKM_sk_shift(ASIdOrRange, (st))
+#define sk_ASIdOrRange_pop(st) SKM_sk_pop(ASIdOrRange, (st))
+#define sk_ASIdOrRange_sort(st) SKM_sk_sort(ASIdOrRange, (st))
+#define sk_ASIdOrRange_is_sorted(st) SKM_sk_is_sorted(ASIdOrRange, (st))
+
+#define sk_ASN1_GENERALSTRING_new(st) SKM_sk_new(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_new_null() SKM_sk_new_null(ASN1_GENERALSTRING)
+#define sk_ASN1_GENERALSTRING_free(st) SKM_sk_free(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_num(st) SKM_sk_num(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_value(st, i) SKM_sk_value(ASN1_GENERALSTRING, (st), (i))
+#define sk_ASN1_GENERALSTRING_set(st, i, val) SKM_sk_set(ASN1_GENERALSTRING, (st), (i), (val))
+#define sk_ASN1_GENERALSTRING_zero(st) SKM_sk_zero(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_push(st, val) SKM_sk_push(ASN1_GENERALSTRING, (st), (val))
+#define sk_ASN1_GENERALSTRING_unshift(st, val) SKM_sk_unshift(ASN1_GENERALSTRING, (st), (val))
+#define sk_ASN1_GENERALSTRING_find(st, val) SKM_sk_find(ASN1_GENERALSTRING, (st), (val))
+#define sk_ASN1_GENERALSTRING_find_ex(st, val) SKM_sk_find_ex(ASN1_GENERALSTRING, (st), (val))
+#define sk_ASN1_GENERALSTRING_delete(st, i) SKM_sk_delete(ASN1_GENERALSTRING, (st), (i))
+#define sk_ASN1_GENERALSTRING_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_GENERALSTRING, (st), (ptr))
+#define sk_ASN1_GENERALSTRING_insert(st, val, i) SKM_sk_insert(ASN1_GENERALSTRING, (st), (val), (i))
+#define sk_ASN1_GENERALSTRING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_GENERALSTRING, (st), (cmp))
+#define sk_ASN1_GENERALSTRING_dup(st) SKM_sk_dup(ASN1_GENERALSTRING, st)
+#define sk_ASN1_GENERALSTRING_pop_free(st, free_func) SKM_sk_pop_free(ASN1_GENERALSTRING, (st), (free_func))
+#define sk_ASN1_GENERALSTRING_shift(st) SKM_sk_shift(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_pop(st) SKM_sk_pop(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_sort(st) SKM_sk_sort(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_is_sorted(st) SKM_sk_is_sorted(ASN1_GENERALSTRING, (st))
+
+#define sk_ASN1_INTEGER_new(st) SKM_sk_new(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_new_null() SKM_sk_new_null(ASN1_INTEGER)
+#define sk_ASN1_INTEGER_free(st) SKM_sk_free(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_num(st) SKM_sk_num(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_value(st, i) SKM_sk_value(ASN1_INTEGER, (st), (i))
+#define sk_ASN1_INTEGER_set(st, i, val) SKM_sk_set(ASN1_INTEGER, (st), (i), (val))
+#define sk_ASN1_INTEGER_zero(st) SKM_sk_zero(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_push(st, val) SKM_sk_push(ASN1_INTEGER, (st), (val))
+#define sk_ASN1_INTEGER_unshift(st, val) SKM_sk_unshift(ASN1_INTEGER, (st), (val))
+#define sk_ASN1_INTEGER_find(st, val) SKM_sk_find(ASN1_INTEGER, (st), (val))
+#define sk_ASN1_INTEGER_find_ex(st, val) SKM_sk_find_ex(ASN1_INTEGER, (st), (val))
+#define sk_ASN1_INTEGER_delete(st, i) SKM_sk_delete(ASN1_INTEGER, (st), (i))
+#define sk_ASN1_INTEGER_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_INTEGER, (st), (ptr))
+#define sk_ASN1_INTEGER_insert(st, val, i) SKM_sk_insert(ASN1_INTEGER, (st), (val), (i))
+#define sk_ASN1_INTEGER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_INTEGER, (st), (cmp))
+#define sk_ASN1_INTEGER_dup(st) SKM_sk_dup(ASN1_INTEGER, st)
+#define sk_ASN1_INTEGER_pop_free(st, free_func) SKM_sk_pop_free(ASN1_INTEGER, (st), (free_func))
+#define sk_ASN1_INTEGER_shift(st) SKM_sk_shift(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_pop(st) SKM_sk_pop(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_sort(st) SKM_sk_sort(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_is_sorted(st) SKM_sk_is_sorted(ASN1_INTEGER, (st))
+
+#define sk_ASN1_OBJECT_new(st) SKM_sk_new(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_new_null() SKM_sk_new_null(ASN1_OBJECT)
+#define sk_ASN1_OBJECT_free(st) SKM_sk_free(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_num(st) SKM_sk_num(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_value(st, i) SKM_sk_value(ASN1_OBJECT, (st), (i))
+#define sk_ASN1_OBJECT_set(st, i, val) SKM_sk_set(ASN1_OBJECT, (st), (i), (val))
+#define sk_ASN1_OBJECT_zero(st) SKM_sk_zero(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_push(st, val) SKM_sk_push(ASN1_OBJECT, (st), (val))
+#define sk_ASN1_OBJECT_unshift(st, val) SKM_sk_unshift(ASN1_OBJECT, (st), (val))
+#define sk_ASN1_OBJECT_find(st, val) SKM_sk_find(ASN1_OBJECT, (st), (val))
+#define sk_ASN1_OBJECT_find_ex(st, val) SKM_sk_find_ex(ASN1_OBJECT, (st), (val))
+#define sk_ASN1_OBJECT_delete(st, i) SKM_sk_delete(ASN1_OBJECT, (st), (i))
+#define sk_ASN1_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_OBJECT, (st), (ptr))
+#define sk_ASN1_OBJECT_insert(st, val, i) SKM_sk_insert(ASN1_OBJECT, (st), (val), (i))
+#define sk_ASN1_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_OBJECT, (st), (cmp))
+#define sk_ASN1_OBJECT_dup(st) SKM_sk_dup(ASN1_OBJECT, st)
+#define sk_ASN1_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(ASN1_OBJECT, (st), (free_func))
+#define sk_ASN1_OBJECT_shift(st) SKM_sk_shift(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_pop(st) SKM_sk_pop(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_sort(st) SKM_sk_sort(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_is_sorted(st) SKM_sk_is_sorted(ASN1_OBJECT, (st))
+
+#define sk_ASN1_STRING_TABLE_new(st) SKM_sk_new(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_new_null() SKM_sk_new_null(ASN1_STRING_TABLE)
+#define sk_ASN1_STRING_TABLE_free(st) SKM_sk_free(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_num(st) SKM_sk_num(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_value(st, i) SKM_sk_value(ASN1_STRING_TABLE, (st), (i))
+#define sk_ASN1_STRING_TABLE_set(st, i, val) SKM_sk_set(ASN1_STRING_TABLE, (st), (i), (val))
+#define sk_ASN1_STRING_TABLE_zero(st) SKM_sk_zero(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_push(st, val) SKM_sk_push(ASN1_STRING_TABLE, (st), (val))
+#define sk_ASN1_STRING_TABLE_unshift(st, val) SKM_sk_unshift(ASN1_STRING_TABLE, (st), (val))
+#define sk_ASN1_STRING_TABLE_find(st, val) SKM_sk_find(ASN1_STRING_TABLE, (st), (val))
+#define sk_ASN1_STRING_TABLE_find_ex(st, val) SKM_sk_find_ex(ASN1_STRING_TABLE, (st), (val))
+#define sk_ASN1_STRING_TABLE_delete(st, i) SKM_sk_delete(ASN1_STRING_TABLE, (st), (i))
+#define sk_ASN1_STRING_TABLE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_STRING_TABLE, (st), (ptr))
+#define sk_ASN1_STRING_TABLE_insert(st, val, i) SKM_sk_insert(ASN1_STRING_TABLE, (st), (val), (i))
+#define sk_ASN1_STRING_TABLE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_STRING_TABLE, (st), (cmp))
+#define sk_ASN1_STRING_TABLE_dup(st) SKM_sk_dup(ASN1_STRING_TABLE, st)
+#define sk_ASN1_STRING_TABLE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_STRING_TABLE, (st), (free_func))
+#define sk_ASN1_STRING_TABLE_shift(st) SKM_sk_shift(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_pop(st) SKM_sk_pop(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_sort(st) SKM_sk_sort(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_is_sorted(st) SKM_sk_is_sorted(ASN1_STRING_TABLE, (st))
+
+#define sk_ASN1_TYPE_new(st) SKM_sk_new(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_new_null() SKM_sk_new_null(ASN1_TYPE)
+#define sk_ASN1_TYPE_free(st) SKM_sk_free(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_num(st) SKM_sk_num(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_value(st, i) SKM_sk_value(ASN1_TYPE, (st), (i))
+#define sk_ASN1_TYPE_set(st, i, val) SKM_sk_set(ASN1_TYPE, (st), (i), (val))
+#define sk_ASN1_TYPE_zero(st) SKM_sk_zero(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_push(st, val) SKM_sk_push(ASN1_TYPE, (st), (val))
+#define sk_ASN1_TYPE_unshift(st, val) SKM_sk_unshift(ASN1_TYPE, (st), (val))
+#define sk_ASN1_TYPE_find(st, val) SKM_sk_find(ASN1_TYPE, (st), (val))
+#define sk_ASN1_TYPE_find_ex(st, val) SKM_sk_find_ex(ASN1_TYPE, (st), (val))
+#define sk_ASN1_TYPE_delete(st, i) SKM_sk_delete(ASN1_TYPE, (st), (i))
+#define sk_ASN1_TYPE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_TYPE, (st), (ptr))
+#define sk_ASN1_TYPE_insert(st, val, i) SKM_sk_insert(ASN1_TYPE, (st), (val), (i))
+#define sk_ASN1_TYPE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_TYPE, (st), (cmp))
+#define sk_ASN1_TYPE_dup(st) SKM_sk_dup(ASN1_TYPE, st)
+#define sk_ASN1_TYPE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_TYPE, (st), (free_func))
+#define sk_ASN1_TYPE_shift(st) SKM_sk_shift(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_pop(st) SKM_sk_pop(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_sort(st) SKM_sk_sort(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_is_sorted(st) SKM_sk_is_sorted(ASN1_TYPE, (st))
+
+#define sk_ASN1_VALUE_new(st) SKM_sk_new(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_new_null() SKM_sk_new_null(ASN1_VALUE)
+#define sk_ASN1_VALUE_free(st) SKM_sk_free(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_num(st) SKM_sk_num(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_value(st, i) SKM_sk_value(ASN1_VALUE, (st), (i))
+#define sk_ASN1_VALUE_set(st, i, val) SKM_sk_set(ASN1_VALUE, (st), (i), (val))
+#define sk_ASN1_VALUE_zero(st) SKM_sk_zero(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_push(st, val) SKM_sk_push(ASN1_VALUE, (st), (val))
+#define sk_ASN1_VALUE_unshift(st, val) SKM_sk_unshift(ASN1_VALUE, (st), (val))
+#define sk_ASN1_VALUE_find(st, val) SKM_sk_find(ASN1_VALUE, (st), (val))
+#define sk_ASN1_VALUE_find_ex(st, val) SKM_sk_find_ex(ASN1_VALUE, (st), (val))
+#define sk_ASN1_VALUE_delete(st, i) SKM_sk_delete(ASN1_VALUE, (st), (i))
+#define sk_ASN1_VALUE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_VALUE, (st), (ptr))
+#define sk_ASN1_VALUE_insert(st, val, i) SKM_sk_insert(ASN1_VALUE, (st), (val), (i))
+#define sk_ASN1_VALUE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_VALUE, (st), (cmp))
+#define sk_ASN1_VALUE_dup(st) SKM_sk_dup(ASN1_VALUE, st)
+#define sk_ASN1_VALUE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_VALUE, (st), (free_func))
+#define sk_ASN1_VALUE_shift(st) SKM_sk_shift(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_pop(st) SKM_sk_pop(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_sort(st) SKM_sk_sort(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_is_sorted(st) SKM_sk_is_sorted(ASN1_VALUE, (st))
+
+#define sk_BIO_new(st) SKM_sk_new(BIO, (st))
+#define sk_BIO_new_null() SKM_sk_new_null(BIO)
+#define sk_BIO_free(st) SKM_sk_free(BIO, (st))
+#define sk_BIO_num(st) SKM_sk_num(BIO, (st))
+#define sk_BIO_value(st, i) SKM_sk_value(BIO, (st), (i))
+#define sk_BIO_set(st, i, val) SKM_sk_set(BIO, (st), (i), (val))
+#define sk_BIO_zero(st) SKM_sk_zero(BIO, (st))
+#define sk_BIO_push(st, val) SKM_sk_push(BIO, (st), (val))
+#define sk_BIO_unshift(st, val) SKM_sk_unshift(BIO, (st), (val))
+#define sk_BIO_find(st, val) SKM_sk_find(BIO, (st), (val))
+#define sk_BIO_find_ex(st, val) SKM_sk_find_ex(BIO, (st), (val))
+#define sk_BIO_delete(st, i) SKM_sk_delete(BIO, (st), (i))
+#define sk_BIO_delete_ptr(st, ptr) SKM_sk_delete_ptr(BIO, (st), (ptr))
+#define sk_BIO_insert(st, val, i) SKM_sk_insert(BIO, (st), (val), (i))
+#define sk_BIO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(BIO, (st), (cmp))
+#define sk_BIO_dup(st) SKM_sk_dup(BIO, st)
+#define sk_BIO_pop_free(st, free_func) SKM_sk_pop_free(BIO, (st), (free_func))
+#define sk_BIO_shift(st) SKM_sk_shift(BIO, (st))
+#define sk_BIO_pop(st) SKM_sk_pop(BIO, (st))
+#define sk_BIO_sort(st) SKM_sk_sort(BIO, (st))
+#define sk_BIO_is_sorted(st) SKM_sk_is_sorted(BIO, (st))
+
+#define sk_CMS_CertificateChoices_new(st) SKM_sk_new(CMS_CertificateChoices, (st))
+#define sk_CMS_CertificateChoices_new_null() SKM_sk_new_null(CMS_CertificateChoices)
+#define sk_CMS_CertificateChoices_free(st) SKM_sk_free(CMS_CertificateChoices, (st))
+#define sk_CMS_CertificateChoices_num(st) SKM_sk_num(CMS_CertificateChoices, (st))
+#define sk_CMS_CertificateChoices_value(st, i) SKM_sk_value(CMS_CertificateChoices, (st), (i))
+#define sk_CMS_CertificateChoices_set(st, i, val) SKM_sk_set(CMS_CertificateChoices, (st), (i), (val))
+#define sk_CMS_CertificateChoices_zero(st) SKM_sk_zero(CMS_CertificateChoices, (st))
+#define sk_CMS_CertificateChoices_push(st, val) SKM_sk_push(CMS_CertificateChoices, (st), (val))
+#define sk_CMS_CertificateChoices_unshift(st, val) SKM_sk_unshift(CMS_CertificateChoices, (st), (val))
+#define sk_CMS_CertificateChoices_find(st, val) SKM_sk_find(CMS_CertificateChoices, (st), (val))
+#define sk_CMS_CertificateChoices_find_ex(st, val) SKM_sk_find_ex(CMS_CertificateChoices, (st), (val))
+#define sk_CMS_CertificateChoices_delete(st, i) SKM_sk_delete(CMS_CertificateChoices, (st), (i))
+#define sk_CMS_CertificateChoices_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_CertificateChoices, (st), (ptr))
+#define sk_CMS_CertificateChoices_insert(st, val, i) SKM_sk_insert(CMS_CertificateChoices, (st), (val), (i))
+#define sk_CMS_CertificateChoices_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_CertificateChoices, (st), (cmp))
+#define sk_CMS_CertificateChoices_dup(st) SKM_sk_dup(CMS_CertificateChoices, st)
+#define sk_CMS_CertificateChoices_pop_free(st, free_func) SKM_sk_pop_free(CMS_CertificateChoices, (st), (free_func))
+#define sk_CMS_CertificateChoices_shift(st) SKM_sk_shift(CMS_CertificateChoices, (st))
+#define sk_CMS_CertificateChoices_pop(st) SKM_sk_pop(CMS_CertificateChoices, (st))
+#define sk_CMS_CertificateChoices_sort(st) SKM_sk_sort(CMS_CertificateChoices, (st))
+#define sk_CMS_CertificateChoices_is_sorted(st) SKM_sk_is_sorted(CMS_CertificateChoices, (st))
+
+#define sk_CMS_RecipientInfo_new(st) SKM_sk_new(CMS_RecipientInfo, (st))
+#define sk_CMS_RecipientInfo_new_null() SKM_sk_new_null(CMS_RecipientInfo)
+#define sk_CMS_RecipientInfo_free(st) SKM_sk_free(CMS_RecipientInfo, (st))
+#define sk_CMS_RecipientInfo_num(st) SKM_sk_num(CMS_RecipientInfo, (st))
+#define sk_CMS_RecipientInfo_value(st, i) SKM_sk_value(CMS_RecipientInfo, (st), (i))
+#define sk_CMS_RecipientInfo_set(st, i, val) SKM_sk_set(CMS_RecipientInfo, (st), (i), (val))
+#define sk_CMS_RecipientInfo_zero(st) SKM_sk_zero(CMS_RecipientInfo, (st))
+#define sk_CMS_RecipientInfo_push(st, val) SKM_sk_push(CMS_RecipientInfo, (st), (val))
+#define sk_CMS_RecipientInfo_unshift(st, val) SKM_sk_unshift(CMS_RecipientInfo, (st), (val))
+#define sk_CMS_RecipientInfo_find(st, val) SKM_sk_find(CMS_RecipientInfo, (st), (val))
+#define sk_CMS_RecipientInfo_find_ex(st, val) SKM_sk_find_ex(CMS_RecipientInfo, (st), (val))
+#define sk_CMS_RecipientInfo_delete(st, i) SKM_sk_delete(CMS_RecipientInfo, (st), (i))
+#define sk_CMS_RecipientInfo_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_RecipientInfo, (st), (ptr))
+#define sk_CMS_RecipientInfo_insert(st, val, i) SKM_sk_insert(CMS_RecipientInfo, (st), (val), (i))
+#define sk_CMS_RecipientInfo_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_RecipientInfo, (st), (cmp))
+#define sk_CMS_RecipientInfo_dup(st) SKM_sk_dup(CMS_RecipientInfo, st)
+#define sk_CMS_RecipientInfo_pop_free(st, free_func) SKM_sk_pop_free(CMS_RecipientInfo, (st), (free_func))
+#define sk_CMS_RecipientInfo_shift(st) SKM_sk_shift(CMS_RecipientInfo, (st))
+#define sk_CMS_RecipientInfo_pop(st) SKM_sk_pop(CMS_RecipientInfo, (st))
+#define sk_CMS_RecipientInfo_sort(st) SKM_sk_sort(CMS_RecipientInfo, (st))
+#define sk_CMS_RecipientInfo_is_sorted(st) SKM_sk_is_sorted(CMS_RecipientInfo, (st))
+
+#define sk_CMS_RevocationInfoChoice_new(st) SKM_sk_new(CMS_RevocationInfoChoice, (st))
+#define sk_CMS_RevocationInfoChoice_new_null() SKM_sk_new_null(CMS_RevocationInfoChoice)
+#define sk_CMS_RevocationInfoChoice_free(st) SKM_sk_free(CMS_RevocationInfoChoice, (st))
+#define sk_CMS_RevocationInfoChoice_num(st) SKM_sk_num(CMS_RevocationInfoChoice, (st))
+#define sk_CMS_RevocationInfoChoice_value(st, i) SKM_sk_value(CMS_RevocationInfoChoice, (st), (i))
+#define sk_CMS_RevocationInfoChoice_set(st, i, val) SKM_sk_set(CMS_RevocationInfoChoice, (st), (i), (val))
+#define sk_CMS_RevocationInfoChoice_zero(st) SKM_sk_zero(CMS_RevocationInfoChoice, (st))
+#define sk_CMS_RevocationInfoChoice_push(st, val) SKM_sk_push(CMS_RevocationInfoChoice, (st), (val))
+#define sk_CMS_RevocationInfoChoice_unshift(st, val) SKM_sk_unshift(CMS_RevocationInfoChoice, (st), (val))
+#define sk_CMS_RevocationInfoChoice_find(st, val) SKM_sk_find(CMS_RevocationInfoChoice, (st), (val))
+#define sk_CMS_RevocationInfoChoice_find_ex(st, val) SKM_sk_find_ex(CMS_RevocationInfoChoice, (st), (val))
+#define sk_CMS_RevocationInfoChoice_delete(st, i) SKM_sk_delete(CMS_RevocationInfoChoice, (st), (i))
+#define sk_CMS_RevocationInfoChoice_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_RevocationInfoChoice, (st), (ptr))
+#define sk_CMS_RevocationInfoChoice_insert(st, val, i) SKM_sk_insert(CMS_RevocationInfoChoice, (st), (val), (i))
+#define sk_CMS_RevocationInfoChoice_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_RevocationInfoChoice, (st), (cmp))
+#define sk_CMS_RevocationInfoChoice_dup(st) SKM_sk_dup(CMS_RevocationInfoChoice, st)
+#define sk_CMS_RevocationInfoChoice_pop_free(st, free_func) SKM_sk_pop_free(CMS_RevocationInfoChoice, (st), (free_func))
+#define sk_CMS_RevocationInfoChoice_shift(st) SKM_sk_shift(CMS_RevocationInfoChoice, (st))
+#define sk_CMS_RevocationInfoChoice_pop(st) SKM_sk_pop(CMS_RevocationInfoChoice, (st))
+#define sk_CMS_RevocationInfoChoice_sort(st) SKM_sk_sort(CMS_RevocationInfoChoice, (st))
+#define sk_CMS_RevocationInfoChoice_is_sorted(st) SKM_sk_is_sorted(CMS_RevocationInfoChoice, (st))
+
+#define sk_CMS_SignerInfo_new(st) SKM_sk_new(CMS_SignerInfo, (st))
+#define sk_CMS_SignerInfo_new_null() SKM_sk_new_null(CMS_SignerInfo)
+#define sk_CMS_SignerInfo_free(st) SKM_sk_free(CMS_SignerInfo, (st))
+#define sk_CMS_SignerInfo_num(st) SKM_sk_num(CMS_SignerInfo, (st))
+#define sk_CMS_SignerInfo_value(st, i) SKM_sk_value(CMS_SignerInfo, (st), (i))
+#define sk_CMS_SignerInfo_set(st, i, val) SKM_sk_set(CMS_SignerInfo, (st), (i), (val))
+#define sk_CMS_SignerInfo_zero(st) SKM_sk_zero(CMS_SignerInfo, (st))
+#define sk_CMS_SignerInfo_push(st, val) SKM_sk_push(CMS_SignerInfo, (st), (val))
+#define sk_CMS_SignerInfo_unshift(st, val) SKM_sk_unshift(CMS_SignerInfo, (st), (val))
+#define sk_CMS_SignerInfo_find(st, val) SKM_sk_find(CMS_SignerInfo, (st), (val))
+#define sk_CMS_SignerInfo_find_ex(st, val) SKM_sk_find_ex(CMS_SignerInfo, (st), (val))
+#define sk_CMS_SignerInfo_delete(st, i) SKM_sk_delete(CMS_SignerInfo, (st), (i))
+#define sk_CMS_SignerInfo_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_SignerInfo, (st), (ptr))
+#define sk_CMS_SignerInfo_insert(st, val, i) SKM_sk_insert(CMS_SignerInfo, (st), (val), (i))
+#define sk_CMS_SignerInfo_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_SignerInfo, (st), (cmp))
+#define sk_CMS_SignerInfo_dup(st) SKM_sk_dup(CMS_SignerInfo, st)
+#define sk_CMS_SignerInfo_pop_free(st, free_func) SKM_sk_pop_free(CMS_SignerInfo, (st), (free_func))
+#define sk_CMS_SignerInfo_shift(st) SKM_sk_shift(CMS_SignerInfo, (st))
+#define sk_CMS_SignerInfo_pop(st) SKM_sk_pop(CMS_SignerInfo, (st))
+#define sk_CMS_SignerInfo_sort(st) SKM_sk_sort(CMS_SignerInfo, (st))
+#define sk_CMS_SignerInfo_is_sorted(st) SKM_sk_is_sorted(CMS_SignerInfo, (st))
+
+#define sk_CONF_IMODULE_new(st) SKM_sk_new(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_new_null() SKM_sk_new_null(CONF_IMODULE)
+#define sk_CONF_IMODULE_free(st) SKM_sk_free(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_num(st) SKM_sk_num(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_value(st, i) SKM_sk_value(CONF_IMODULE, (st), (i))
+#define sk_CONF_IMODULE_set(st, i, val) SKM_sk_set(CONF_IMODULE, (st), (i), (val))
+#define sk_CONF_IMODULE_zero(st) SKM_sk_zero(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_push(st, val) SKM_sk_push(CONF_IMODULE, (st), (val))
+#define sk_CONF_IMODULE_unshift(st, val) SKM_sk_unshift(CONF_IMODULE, (st), (val))
+#define sk_CONF_IMODULE_find(st, val) SKM_sk_find(CONF_IMODULE, (st), (val))
+#define sk_CONF_IMODULE_find_ex(st, val) SKM_sk_find_ex(CONF_IMODULE, (st), (val))
+#define sk_CONF_IMODULE_delete(st, i) SKM_sk_delete(CONF_IMODULE, (st), (i))
+#define sk_CONF_IMODULE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_IMODULE, (st), (ptr))
+#define sk_CONF_IMODULE_insert(st, val, i) SKM_sk_insert(CONF_IMODULE, (st), (val), (i))
+#define sk_CONF_IMODULE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_IMODULE, (st), (cmp))
+#define sk_CONF_IMODULE_dup(st) SKM_sk_dup(CONF_IMODULE, st)
+#define sk_CONF_IMODULE_pop_free(st, free_func) SKM_sk_pop_free(CONF_IMODULE, (st), (free_func))
+#define sk_CONF_IMODULE_shift(st) SKM_sk_shift(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_pop(st) SKM_sk_pop(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_sort(st) SKM_sk_sort(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_is_sorted(st) SKM_sk_is_sorted(CONF_IMODULE, (st))
+
+#define sk_CONF_MODULE_new(st) SKM_sk_new(CONF_MODULE, (st))
+#define sk_CONF_MODULE_new_null() SKM_sk_new_null(CONF_MODULE)
+#define sk_CONF_MODULE_free(st) SKM_sk_free(CONF_MODULE, (st))
+#define sk_CONF_MODULE_num(st) SKM_sk_num(CONF_MODULE, (st))
+#define sk_CONF_MODULE_value(st, i) SKM_sk_value(CONF_MODULE, (st), (i))
+#define sk_CONF_MODULE_set(st, i, val) SKM_sk_set(CONF_MODULE, (st), (i), (val))
+#define sk_CONF_MODULE_zero(st) SKM_sk_zero(CONF_MODULE, (st))
+#define sk_CONF_MODULE_push(st, val) SKM_sk_push(CONF_MODULE, (st), (val))
+#define sk_CONF_MODULE_unshift(st, val) SKM_sk_unshift(CONF_MODULE, (st), (val))
+#define sk_CONF_MODULE_find(st, val) SKM_sk_find(CONF_MODULE, (st), (val))
+#define sk_CONF_MODULE_find_ex(st, val) SKM_sk_find_ex(CONF_MODULE, (st), (val))
+#define sk_CONF_MODULE_delete(st, i) SKM_sk_delete(CONF_MODULE, (st), (i))
+#define sk_CONF_MODULE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_MODULE, (st), (ptr))
+#define sk_CONF_MODULE_insert(st, val, i) SKM_sk_insert(CONF_MODULE, (st), (val), (i))
+#define sk_CONF_MODULE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_MODULE, (st), (cmp))
+#define sk_CONF_MODULE_dup(st) SKM_sk_dup(CONF_MODULE, st)
+#define sk_CONF_MODULE_pop_free(st, free_func) SKM_sk_pop_free(CONF_MODULE, (st), (free_func))
+#define sk_CONF_MODULE_shift(st) SKM_sk_shift(CONF_MODULE, (st))
+#define sk_CONF_MODULE_pop(st) SKM_sk_pop(CONF_MODULE, (st))
+#define sk_CONF_MODULE_sort(st) SKM_sk_sort(CONF_MODULE, (st))
+#define sk_CONF_MODULE_is_sorted(st) SKM_sk_is_sorted(CONF_MODULE, (st))
+
+#define sk_CONF_VALUE_new(st) SKM_sk_new(CONF_VALUE, (st))
+#define sk_CONF_VALUE_new_null() SKM_sk_new_null(CONF_VALUE)
+#define sk_CONF_VALUE_free(st) SKM_sk_free(CONF_VALUE, (st))
+#define sk_CONF_VALUE_num(st) SKM_sk_num(CONF_VALUE, (st))
+#define sk_CONF_VALUE_value(st, i) SKM_sk_value(CONF_VALUE, (st), (i))
+#define sk_CONF_VALUE_set(st, i, val) SKM_sk_set(CONF_VALUE, (st), (i), (val))
+#define sk_CONF_VALUE_zero(st) SKM_sk_zero(CONF_VALUE, (st))
+#define sk_CONF_VALUE_push(st, val) SKM_sk_push(CONF_VALUE, (st), (val))
+#define sk_CONF_VALUE_unshift(st, val) SKM_sk_unshift(CONF_VALUE, (st), (val))
+#define sk_CONF_VALUE_find(st, val) SKM_sk_find(CONF_VALUE, (st), (val))
+#define sk_CONF_VALUE_find_ex(st, val) SKM_sk_find_ex(CONF_VALUE, (st), (val))
+#define sk_CONF_VALUE_delete(st, i) SKM_sk_delete(CONF_VALUE, (st), (i))
+#define sk_CONF_VALUE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_VALUE, (st), (ptr))
+#define sk_CONF_VALUE_insert(st, val, i) SKM_sk_insert(CONF_VALUE, (st), (val), (i))
+#define sk_CONF_VALUE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_VALUE, (st), (cmp))
+#define sk_CONF_VALUE_dup(st) SKM_sk_dup(CONF_VALUE, st)
+#define sk_CONF_VALUE_pop_free(st, free_func) SKM_sk_pop_free(CONF_VALUE, (st), (free_func))
+#define sk_CONF_VALUE_shift(st) SKM_sk_shift(CONF_VALUE, (st))
+#define sk_CONF_VALUE_pop(st) SKM_sk_pop(CONF_VALUE, (st))
+#define sk_CONF_VALUE_sort(st) SKM_sk_sort(CONF_VALUE, (st))
+#define sk_CONF_VALUE_is_sorted(st) SKM_sk_is_sorted(CONF_VALUE, (st))
+
+#define sk_CRYPTO_EX_DATA_FUNCS_new(st) SKM_sk_new(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_new_null() SKM_sk_new_null(CRYPTO_EX_DATA_FUNCS)
+#define sk_CRYPTO_EX_DATA_FUNCS_free(st) SKM_sk_free(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_num(st) SKM_sk_num(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_value(st, i) SKM_sk_value(CRYPTO_EX_DATA_FUNCS, (st), (i))
+#define sk_CRYPTO_EX_DATA_FUNCS_set(st, i, val) SKM_sk_set(CRYPTO_EX_DATA_FUNCS, (st), (i), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_zero(st) SKM_sk_zero(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_push(st, val) SKM_sk_push(CRYPTO_EX_DATA_FUNCS, (st), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_unshift(st, val) SKM_sk_unshift(CRYPTO_EX_DATA_FUNCS, (st), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_find(st, val) SKM_sk_find(CRYPTO_EX_DATA_FUNCS, (st), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_find_ex(st, val) SKM_sk_find_ex(CRYPTO_EX_DATA_FUNCS, (st), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_delete(st, i) SKM_sk_delete(CRYPTO_EX_DATA_FUNCS, (st), (i))
+#define sk_CRYPTO_EX_DATA_FUNCS_delete_ptr(st, ptr) SKM_sk_delete_ptr(CRYPTO_EX_DATA_FUNCS, (st), (ptr))
+#define sk_CRYPTO_EX_DATA_FUNCS_insert(st, val, i) SKM_sk_insert(CRYPTO_EX_DATA_FUNCS, (st), (val), (i))
+#define sk_CRYPTO_EX_DATA_FUNCS_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CRYPTO_EX_DATA_FUNCS, (st), (cmp))
+#define sk_CRYPTO_EX_DATA_FUNCS_dup(st) SKM_sk_dup(CRYPTO_EX_DATA_FUNCS, st)
+#define sk_CRYPTO_EX_DATA_FUNCS_pop_free(st, free_func) SKM_sk_pop_free(CRYPTO_EX_DATA_FUNCS, (st), (free_func))
+#define sk_CRYPTO_EX_DATA_FUNCS_shift(st) SKM_sk_shift(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_pop(st) SKM_sk_pop(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_sort(st) SKM_sk_sort(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_is_sorted(st) SKM_sk_is_sorted(CRYPTO_EX_DATA_FUNCS, (st))
+
+#define sk_CRYPTO_dynlock_new(st) SKM_sk_new(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_new_null() SKM_sk_new_null(CRYPTO_dynlock)
+#define sk_CRYPTO_dynlock_free(st) SKM_sk_free(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_num(st) SKM_sk_num(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_value(st, i) SKM_sk_value(CRYPTO_dynlock, (st), (i))
+#define sk_CRYPTO_dynlock_set(st, i, val) SKM_sk_set(CRYPTO_dynlock, (st), (i), (val))
+#define sk_CRYPTO_dynlock_zero(st) SKM_sk_zero(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_push(st, val) SKM_sk_push(CRYPTO_dynlock, (st), (val))
+#define sk_CRYPTO_dynlock_unshift(st, val) SKM_sk_unshift(CRYPTO_dynlock, (st), (val))
+#define sk_CRYPTO_dynlock_find(st, val) SKM_sk_find(CRYPTO_dynlock, (st), (val))
+#define sk_CRYPTO_dynlock_find_ex(st, val) SKM_sk_find_ex(CRYPTO_dynlock, (st), (val))
+#define sk_CRYPTO_dynlock_delete(st, i) SKM_sk_delete(CRYPTO_dynlock, (st), (i))
+#define sk_CRYPTO_dynlock_delete_ptr(st, ptr) SKM_sk_delete_ptr(CRYPTO_dynlock, (st), (ptr))
+#define sk_CRYPTO_dynlock_insert(st, val, i) SKM_sk_insert(CRYPTO_dynlock, (st), (val), (i))
+#define sk_CRYPTO_dynlock_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CRYPTO_dynlock, (st), (cmp))
+#define sk_CRYPTO_dynlock_dup(st) SKM_sk_dup(CRYPTO_dynlock, st)
+#define sk_CRYPTO_dynlock_pop_free(st, free_func) SKM_sk_pop_free(CRYPTO_dynlock, (st), (free_func))
+#define sk_CRYPTO_dynlock_shift(st) SKM_sk_shift(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_pop(st) SKM_sk_pop(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_sort(st) SKM_sk_sort(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_is_sorted(st) SKM_sk_is_sorted(CRYPTO_dynlock, (st))
+
+#define sk_DIST_POINT_new(st) SKM_sk_new(DIST_POINT, (st))
+#define sk_DIST_POINT_new_null() SKM_sk_new_null(DIST_POINT)
+#define sk_DIST_POINT_free(st) SKM_sk_free(DIST_POINT, (st))
+#define sk_DIST_POINT_num(st) SKM_sk_num(DIST_POINT, (st))
+#define sk_DIST_POINT_value(st, i) SKM_sk_value(DIST_POINT, (st), (i))
+#define sk_DIST_POINT_set(st, i, val) SKM_sk_set(DIST_POINT, (st), (i), (val))
+#define sk_DIST_POINT_zero(st) SKM_sk_zero(DIST_POINT, (st))
+#define sk_DIST_POINT_push(st, val) SKM_sk_push(DIST_POINT, (st), (val))
+#define sk_DIST_POINT_unshift(st, val) SKM_sk_unshift(DIST_POINT, (st), (val))
+#define sk_DIST_POINT_find(st, val) SKM_sk_find(DIST_POINT, (st), (val))
+#define sk_DIST_POINT_find_ex(st, val) SKM_sk_find_ex(DIST_POINT, (st), (val))
+#define sk_DIST_POINT_delete(st, i) SKM_sk_delete(DIST_POINT, (st), (i))
+#define sk_DIST_POINT_delete_ptr(st, ptr) SKM_sk_delete_ptr(DIST_POINT, (st), (ptr))
+#define sk_DIST_POINT_insert(st, val, i) SKM_sk_insert(DIST_POINT, (st), (val), (i))
+#define sk_DIST_POINT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(DIST_POINT, (st), (cmp))
+#define sk_DIST_POINT_dup(st) SKM_sk_dup(DIST_POINT, st)
+#define sk_DIST_POINT_pop_free(st, free_func) SKM_sk_pop_free(DIST_POINT, (st), (free_func))
+#define sk_DIST_POINT_shift(st) SKM_sk_shift(DIST_POINT, (st))
+#define sk_DIST_POINT_pop(st) SKM_sk_pop(DIST_POINT, (st))
+#define sk_DIST_POINT_sort(st) SKM_sk_sort(DIST_POINT, (st))
+#define sk_DIST_POINT_is_sorted(st) SKM_sk_is_sorted(DIST_POINT, (st))
+
+#define sk_ENGINE_new(st) SKM_sk_new(ENGINE, (st))
+#define sk_ENGINE_new_null() SKM_sk_new_null(ENGINE)
+#define sk_ENGINE_free(st) SKM_sk_free(ENGINE, (st))
+#define sk_ENGINE_num(st) SKM_sk_num(ENGINE, (st))
+#define sk_ENGINE_value(st, i) SKM_sk_value(ENGINE, (st), (i))
+#define sk_ENGINE_set(st, i, val) SKM_sk_set(ENGINE, (st), (i), (val))
+#define sk_ENGINE_zero(st) SKM_sk_zero(ENGINE, (st))
+#define sk_ENGINE_push(st, val) SKM_sk_push(ENGINE, (st), (val))
+#define sk_ENGINE_unshift(st, val) SKM_sk_unshift(ENGINE, (st), (val))
+#define sk_ENGINE_find(st, val) SKM_sk_find(ENGINE, (st), (val))
+#define sk_ENGINE_find_ex(st, val) SKM_sk_find_ex(ENGINE, (st), (val))
+#define sk_ENGINE_delete(st, i) SKM_sk_delete(ENGINE, (st), (i))
+#define sk_ENGINE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ENGINE, (st), (ptr))
+#define sk_ENGINE_insert(st, val, i) SKM_sk_insert(ENGINE, (st), (val), (i))
+#define sk_ENGINE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ENGINE, (st), (cmp))
+#define sk_ENGINE_dup(st) SKM_sk_dup(ENGINE, st)
+#define sk_ENGINE_pop_free(st, free_func) SKM_sk_pop_free(ENGINE, (st), (free_func))
+#define sk_ENGINE_shift(st) SKM_sk_shift(ENGINE, (st))
+#define sk_ENGINE_pop(st) SKM_sk_pop(ENGINE, (st))
+#define sk_ENGINE_sort(st) SKM_sk_sort(ENGINE, (st))
+#define sk_ENGINE_is_sorted(st) SKM_sk_is_sorted(ENGINE, (st))
+
+#define sk_ENGINE_CLEANUP_ITEM_new(st) SKM_sk_new(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_new_null() SKM_sk_new_null(ENGINE_CLEANUP_ITEM)
+#define sk_ENGINE_CLEANUP_ITEM_free(st) SKM_sk_free(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_num(st) SKM_sk_num(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_value(st, i) SKM_sk_value(ENGINE_CLEANUP_ITEM, (st), (i))
+#define sk_ENGINE_CLEANUP_ITEM_set(st, i, val) SKM_sk_set(ENGINE_CLEANUP_ITEM, (st), (i), (val))
+#define sk_ENGINE_CLEANUP_ITEM_zero(st) SKM_sk_zero(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_push(st, val) SKM_sk_push(ENGINE_CLEANUP_ITEM, (st), (val))
+#define sk_ENGINE_CLEANUP_ITEM_unshift(st, val) SKM_sk_unshift(ENGINE_CLEANUP_ITEM, (st), (val))
+#define sk_ENGINE_CLEANUP_ITEM_find(st, val) SKM_sk_find(ENGINE_CLEANUP_ITEM, (st), (val))
+#define sk_ENGINE_CLEANUP_ITEM_find_ex(st, val) SKM_sk_find_ex(ENGINE_CLEANUP_ITEM, (st), (val))
+#define sk_ENGINE_CLEANUP_ITEM_delete(st, i) SKM_sk_delete(ENGINE_CLEANUP_ITEM, (st), (i))
+#define sk_ENGINE_CLEANUP_ITEM_delete_ptr(st, ptr) SKM_sk_delete_ptr(ENGINE_CLEANUP_ITEM, (st), (ptr))
+#define sk_ENGINE_CLEANUP_ITEM_insert(st, val, i) SKM_sk_insert(ENGINE_CLEANUP_ITEM, (st), (val), (i))
+#define sk_ENGINE_CLEANUP_ITEM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ENGINE_CLEANUP_ITEM, (st), (cmp))
+#define sk_ENGINE_CLEANUP_ITEM_dup(st) SKM_sk_dup(ENGINE_CLEANUP_ITEM, st)
+#define sk_ENGINE_CLEANUP_ITEM_pop_free(st, free_func) SKM_sk_pop_free(ENGINE_CLEANUP_ITEM, (st), (free_func))
+#define sk_ENGINE_CLEANUP_ITEM_shift(st) SKM_sk_shift(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_pop(st) SKM_sk_pop(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_sort(st) SKM_sk_sort(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_is_sorted(st) SKM_sk_is_sorted(ENGINE_CLEANUP_ITEM, (st))
+
+#define sk_GENERAL_NAME_new(st) SKM_sk_new(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_new_null() SKM_sk_new_null(GENERAL_NAME)
+#define sk_GENERAL_NAME_free(st) SKM_sk_free(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_num(st) SKM_sk_num(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_value(st, i) SKM_sk_value(GENERAL_NAME, (st), (i))
+#define sk_GENERAL_NAME_set(st, i, val) SKM_sk_set(GENERAL_NAME, (st), (i), (val))
+#define sk_GENERAL_NAME_zero(st) SKM_sk_zero(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_push(st, val) SKM_sk_push(GENERAL_NAME, (st), (val))
+#define sk_GENERAL_NAME_unshift(st, val) SKM_sk_unshift(GENERAL_NAME, (st), (val))
+#define sk_GENERAL_NAME_find(st, val) SKM_sk_find(GENERAL_NAME, (st), (val))
+#define sk_GENERAL_NAME_find_ex(st, val) SKM_sk_find_ex(GENERAL_NAME, (st), (val))
+#define sk_GENERAL_NAME_delete(st, i) SKM_sk_delete(GENERAL_NAME, (st), (i))
+#define sk_GENERAL_NAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_NAME, (st), (ptr))
+#define sk_GENERAL_NAME_insert(st, val, i) SKM_sk_insert(GENERAL_NAME, (st), (val), (i))
+#define sk_GENERAL_NAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_NAME, (st), (cmp))
+#define sk_GENERAL_NAME_dup(st) SKM_sk_dup(GENERAL_NAME, st)
+#define sk_GENERAL_NAME_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_NAME, (st), (free_func))
+#define sk_GENERAL_NAME_shift(st) SKM_sk_shift(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_pop(st) SKM_sk_pop(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_sort(st) SKM_sk_sort(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_is_sorted(st) SKM_sk_is_sorted(GENERAL_NAME, (st))
+
+#define sk_GENERAL_NAMES_new(st) SKM_sk_new(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_new_null() SKM_sk_new_null(GENERAL_NAMES)
+#define sk_GENERAL_NAMES_free(st) SKM_sk_free(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_num(st) SKM_sk_num(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_value(st, i) SKM_sk_value(GENERAL_NAMES, (st), (i))
+#define sk_GENERAL_NAMES_set(st, i, val) SKM_sk_set(GENERAL_NAMES, (st), (i), (val))
+#define sk_GENERAL_NAMES_zero(st) SKM_sk_zero(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_push(st, val) SKM_sk_push(GENERAL_NAMES, (st), (val))
+#define sk_GENERAL_NAMES_unshift(st, val) SKM_sk_unshift(GENERAL_NAMES, (st), (val))
+#define sk_GENERAL_NAMES_find(st, val) SKM_sk_find(GENERAL_NAMES, (st), (val))
+#define sk_GENERAL_NAMES_find_ex(st, val) SKM_sk_find_ex(GENERAL_NAMES, (st), (val))
+#define sk_GENERAL_NAMES_delete(st, i) SKM_sk_delete(GENERAL_NAMES, (st), (i))
+#define sk_GENERAL_NAMES_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_NAMES, (st), (ptr))
+#define sk_GENERAL_NAMES_insert(st, val, i) SKM_sk_insert(GENERAL_NAMES, (st), (val), (i))
+#define sk_GENERAL_NAMES_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_NAMES, (st), (cmp))
+#define sk_GENERAL_NAMES_dup(st) SKM_sk_dup(GENERAL_NAMES, st)
+#define sk_GENERAL_NAMES_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_NAMES, (st), (free_func))
+#define sk_GENERAL_NAMES_shift(st) SKM_sk_shift(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_pop(st) SKM_sk_pop(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_sort(st) SKM_sk_sort(GENERAL_NAMES, (st))
+#define sk_GENERAL_NAMES_is_sorted(st) SKM_sk_is_sorted(GENERAL_NAMES, (st))
+
+#define sk_GENERAL_SUBTREE_new(st) SKM_sk_new(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_new_null() SKM_sk_new_null(GENERAL_SUBTREE)
+#define sk_GENERAL_SUBTREE_free(st) SKM_sk_free(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_num(st) SKM_sk_num(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_value(st, i) SKM_sk_value(GENERAL_SUBTREE, (st), (i))
+#define sk_GENERAL_SUBTREE_set(st, i, val) SKM_sk_set(GENERAL_SUBTREE, (st), (i), (val))
+#define sk_GENERAL_SUBTREE_zero(st) SKM_sk_zero(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_push(st, val) SKM_sk_push(GENERAL_SUBTREE, (st), (val))
+#define sk_GENERAL_SUBTREE_unshift(st, val) SKM_sk_unshift(GENERAL_SUBTREE, (st), (val))
+#define sk_GENERAL_SUBTREE_find(st, val) SKM_sk_find(GENERAL_SUBTREE, (st), (val))
+#define sk_GENERAL_SUBTREE_find_ex(st, val) SKM_sk_find_ex(GENERAL_SUBTREE, (st), (val))
+#define sk_GENERAL_SUBTREE_delete(st, i) SKM_sk_delete(GENERAL_SUBTREE, (st), (i))
+#define sk_GENERAL_SUBTREE_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_SUBTREE, (st), (ptr))
+#define sk_GENERAL_SUBTREE_insert(st, val, i) SKM_sk_insert(GENERAL_SUBTREE, (st), (val), (i))
+#define sk_GENERAL_SUBTREE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_SUBTREE, (st), (cmp))
+#define sk_GENERAL_SUBTREE_dup(st) SKM_sk_dup(GENERAL_SUBTREE, st)
+#define sk_GENERAL_SUBTREE_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_SUBTREE, (st), (free_func))
+#define sk_GENERAL_SUBTREE_shift(st) SKM_sk_shift(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_pop(st) SKM_sk_pop(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_sort(st) SKM_sk_sort(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_is_sorted(st) SKM_sk_is_sorted(GENERAL_SUBTREE, (st))
+
+#define sk_IPAddressFamily_new(st) SKM_sk_new(IPAddressFamily, (st))
+#define sk_IPAddressFamily_new_null() SKM_sk_new_null(IPAddressFamily)
+#define sk_IPAddressFamily_free(st) SKM_sk_free(IPAddressFamily, (st))
+#define sk_IPAddressFamily_num(st) SKM_sk_num(IPAddressFamily, (st))
+#define sk_IPAddressFamily_value(st, i) SKM_sk_value(IPAddressFamily, (st), (i))
+#define sk_IPAddressFamily_set(st, i, val) SKM_sk_set(IPAddressFamily, (st), (i), (val))
+#define sk_IPAddressFamily_zero(st) SKM_sk_zero(IPAddressFamily, (st))
+#define sk_IPAddressFamily_push(st, val) SKM_sk_push(IPAddressFamily, (st), (val))
+#define sk_IPAddressFamily_unshift(st, val) SKM_sk_unshift(IPAddressFamily, (st), (val))
+#define sk_IPAddressFamily_find(st, val) SKM_sk_find(IPAddressFamily, (st), (val))
+#define sk_IPAddressFamily_find_ex(st, val) SKM_sk_find_ex(IPAddressFamily, (st), (val))
+#define sk_IPAddressFamily_delete(st, i) SKM_sk_delete(IPAddressFamily, (st), (i))
+#define sk_IPAddressFamily_delete_ptr(st, ptr) SKM_sk_delete_ptr(IPAddressFamily, (st), (ptr))
+#define sk_IPAddressFamily_insert(st, val, i) SKM_sk_insert(IPAddressFamily, (st), (val), (i))
+#define sk_IPAddressFamily_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(IPAddressFamily, (st), (cmp))
+#define sk_IPAddressFamily_dup(st) SKM_sk_dup(IPAddressFamily, st)
+#define sk_IPAddressFamily_pop_free(st, free_func) SKM_sk_pop_free(IPAddressFamily, (st), (free_func))
+#define sk_IPAddressFamily_shift(st) SKM_sk_shift(IPAddressFamily, (st))
+#define sk_IPAddressFamily_pop(st) SKM_sk_pop(IPAddressFamily, (st))
+#define sk_IPAddressFamily_sort(st) SKM_sk_sort(IPAddressFamily, (st))
+#define sk_IPAddressFamily_is_sorted(st) SKM_sk_is_sorted(IPAddressFamily, (st))
+
+#define sk_IPAddressOrRange_new(st) SKM_sk_new(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_new_null() SKM_sk_new_null(IPAddressOrRange)
+#define sk_IPAddressOrRange_free(st) SKM_sk_free(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_num(st) SKM_sk_num(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_value(st, i) SKM_sk_value(IPAddressOrRange, (st), (i))
+#define sk_IPAddressOrRange_set(st, i, val) SKM_sk_set(IPAddressOrRange, (st), (i), (val))
+#define sk_IPAddressOrRange_zero(st) SKM_sk_zero(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_push(st, val) SKM_sk_push(IPAddressOrRange, (st), (val))
+#define sk_IPAddressOrRange_unshift(st, val) SKM_sk_unshift(IPAddressOrRange, (st), (val))
+#define sk_IPAddressOrRange_find(st, val) SKM_sk_find(IPAddressOrRange, (st), (val))
+#define sk_IPAddressOrRange_find_ex(st, val) SKM_sk_find_ex(IPAddressOrRange, (st), (val))
+#define sk_IPAddressOrRange_delete(st, i) SKM_sk_delete(IPAddressOrRange, (st), (i))
+#define sk_IPAddressOrRange_delete_ptr(st, ptr) SKM_sk_delete_ptr(IPAddressOrRange, (st), (ptr))
+#define sk_IPAddressOrRange_insert(st, val, i) SKM_sk_insert(IPAddressOrRange, (st), (val), (i))
+#define sk_IPAddressOrRange_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(IPAddressOrRange, (st), (cmp))
+#define sk_IPAddressOrRange_dup(st) SKM_sk_dup(IPAddressOrRange, st)
+#define sk_IPAddressOrRange_pop_free(st, free_func) SKM_sk_pop_free(IPAddressOrRange, (st), (free_func))
+#define sk_IPAddressOrRange_shift(st) SKM_sk_shift(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_pop(st) SKM_sk_pop(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_sort(st) SKM_sk_sort(IPAddressOrRange, (st))
+#define sk_IPAddressOrRange_is_sorted(st) SKM_sk_is_sorted(IPAddressOrRange, (st))
+
+#define sk_KRB5_APREQBODY_new(st) SKM_sk_new(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_new_null() SKM_sk_new_null(KRB5_APREQBODY)
+#define sk_KRB5_APREQBODY_free(st) SKM_sk_free(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_num(st) SKM_sk_num(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_value(st, i) SKM_sk_value(KRB5_APREQBODY, (st), (i))
+#define sk_KRB5_APREQBODY_set(st, i, val) SKM_sk_set(KRB5_APREQBODY, (st), (i), (val))
+#define sk_KRB5_APREQBODY_zero(st) SKM_sk_zero(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_push(st, val) SKM_sk_push(KRB5_APREQBODY, (st), (val))
+#define sk_KRB5_APREQBODY_unshift(st, val) SKM_sk_unshift(KRB5_APREQBODY, (st), (val))
+#define sk_KRB5_APREQBODY_find(st, val) SKM_sk_find(KRB5_APREQBODY, (st), (val))
+#define sk_KRB5_APREQBODY_find_ex(st, val) SKM_sk_find_ex(KRB5_APREQBODY, (st), (val))
+#define sk_KRB5_APREQBODY_delete(st, i) SKM_sk_delete(KRB5_APREQBODY, (st), (i))
+#define sk_KRB5_APREQBODY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_APREQBODY, (st), (ptr))
+#define sk_KRB5_APREQBODY_insert(st, val, i) SKM_sk_insert(KRB5_APREQBODY, (st), (val), (i))
+#define sk_KRB5_APREQBODY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_APREQBODY, (st), (cmp))
+#define sk_KRB5_APREQBODY_dup(st) SKM_sk_dup(KRB5_APREQBODY, st)
+#define sk_KRB5_APREQBODY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_APREQBODY, (st), (free_func))
+#define sk_KRB5_APREQBODY_shift(st) SKM_sk_shift(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_pop(st) SKM_sk_pop(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_sort(st) SKM_sk_sort(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_is_sorted(st) SKM_sk_is_sorted(KRB5_APREQBODY, (st))
+
+#define sk_KRB5_AUTHDATA_new(st) SKM_sk_new(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_new_null() SKM_sk_new_null(KRB5_AUTHDATA)
+#define sk_KRB5_AUTHDATA_free(st) SKM_sk_free(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_num(st) SKM_sk_num(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_value(st, i) SKM_sk_value(KRB5_AUTHDATA, (st), (i))
+#define sk_KRB5_AUTHDATA_set(st, i, val) SKM_sk_set(KRB5_AUTHDATA, (st), (i), (val))
+#define sk_KRB5_AUTHDATA_zero(st) SKM_sk_zero(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_push(st, val) SKM_sk_push(KRB5_AUTHDATA, (st), (val))
+#define sk_KRB5_AUTHDATA_unshift(st, val) SKM_sk_unshift(KRB5_AUTHDATA, (st), (val))
+#define sk_KRB5_AUTHDATA_find(st, val) SKM_sk_find(KRB5_AUTHDATA, (st), (val))
+#define sk_KRB5_AUTHDATA_find_ex(st, val) SKM_sk_find_ex(KRB5_AUTHDATA, (st), (val))
+#define sk_KRB5_AUTHDATA_delete(st, i) SKM_sk_delete(KRB5_AUTHDATA, (st), (i))
+#define sk_KRB5_AUTHDATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_AUTHDATA, (st), (ptr))
+#define sk_KRB5_AUTHDATA_insert(st, val, i) SKM_sk_insert(KRB5_AUTHDATA, (st), (val), (i))
+#define sk_KRB5_AUTHDATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_AUTHDATA, (st), (cmp))
+#define sk_KRB5_AUTHDATA_dup(st) SKM_sk_dup(KRB5_AUTHDATA, st)
+#define sk_KRB5_AUTHDATA_pop_free(st, free_func) SKM_sk_pop_free(KRB5_AUTHDATA, (st), (free_func))
+#define sk_KRB5_AUTHDATA_shift(st) SKM_sk_shift(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_pop(st) SKM_sk_pop(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_sort(st) SKM_sk_sort(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_is_sorted(st) SKM_sk_is_sorted(KRB5_AUTHDATA, (st))
+
+#define sk_KRB5_AUTHENTBODY_new(st) SKM_sk_new(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_new_null() SKM_sk_new_null(KRB5_AUTHENTBODY)
+#define sk_KRB5_AUTHENTBODY_free(st) SKM_sk_free(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_num(st) SKM_sk_num(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_value(st, i) SKM_sk_value(KRB5_AUTHENTBODY, (st), (i))
+#define sk_KRB5_AUTHENTBODY_set(st, i, val) SKM_sk_set(KRB5_AUTHENTBODY, (st), (i), (val))
+#define sk_KRB5_AUTHENTBODY_zero(st) SKM_sk_zero(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_push(st, val) SKM_sk_push(KRB5_AUTHENTBODY, (st), (val))
+#define sk_KRB5_AUTHENTBODY_unshift(st, val) SKM_sk_unshift(KRB5_AUTHENTBODY, (st), (val))
+#define sk_KRB5_AUTHENTBODY_find(st, val) SKM_sk_find(KRB5_AUTHENTBODY, (st), (val))
+#define sk_KRB5_AUTHENTBODY_find_ex(st, val) SKM_sk_find_ex(KRB5_AUTHENTBODY, (st), (val))
+#define sk_KRB5_AUTHENTBODY_delete(st, i) SKM_sk_delete(KRB5_AUTHENTBODY, (st), (i))
+#define sk_KRB5_AUTHENTBODY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_AUTHENTBODY, (st), (ptr))
+#define sk_KRB5_AUTHENTBODY_insert(st, val, i) SKM_sk_insert(KRB5_AUTHENTBODY, (st), (val), (i))
+#define sk_KRB5_AUTHENTBODY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_AUTHENTBODY, (st), (cmp))
+#define sk_KRB5_AUTHENTBODY_dup(st) SKM_sk_dup(KRB5_AUTHENTBODY, st)
+#define sk_KRB5_AUTHENTBODY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_AUTHENTBODY, (st), (free_func))
+#define sk_KRB5_AUTHENTBODY_shift(st) SKM_sk_shift(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_pop(st) SKM_sk_pop(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_sort(st) SKM_sk_sort(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_is_sorted(st) SKM_sk_is_sorted(KRB5_AUTHENTBODY, (st))
+
+#define sk_KRB5_CHECKSUM_new(st) SKM_sk_new(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_new_null() SKM_sk_new_null(KRB5_CHECKSUM)
+#define sk_KRB5_CHECKSUM_free(st) SKM_sk_free(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_num(st) SKM_sk_num(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_value(st, i) SKM_sk_value(KRB5_CHECKSUM, (st), (i))
+#define sk_KRB5_CHECKSUM_set(st, i, val) SKM_sk_set(KRB5_CHECKSUM, (st), (i), (val))
+#define sk_KRB5_CHECKSUM_zero(st) SKM_sk_zero(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_push(st, val) SKM_sk_push(KRB5_CHECKSUM, (st), (val))
+#define sk_KRB5_CHECKSUM_unshift(st, val) SKM_sk_unshift(KRB5_CHECKSUM, (st), (val))
+#define sk_KRB5_CHECKSUM_find(st, val) SKM_sk_find(KRB5_CHECKSUM, (st), (val))
+#define sk_KRB5_CHECKSUM_find_ex(st, val) SKM_sk_find_ex(KRB5_CHECKSUM, (st), (val))
+#define sk_KRB5_CHECKSUM_delete(st, i) SKM_sk_delete(KRB5_CHECKSUM, (st), (i))
+#define sk_KRB5_CHECKSUM_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_CHECKSUM, (st), (ptr))
+#define sk_KRB5_CHECKSUM_insert(st, val, i) SKM_sk_insert(KRB5_CHECKSUM, (st), (val), (i))
+#define sk_KRB5_CHECKSUM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_CHECKSUM, (st), (cmp))
+#define sk_KRB5_CHECKSUM_dup(st) SKM_sk_dup(KRB5_CHECKSUM, st)
+#define sk_KRB5_CHECKSUM_pop_free(st, free_func) SKM_sk_pop_free(KRB5_CHECKSUM, (st), (free_func))
+#define sk_KRB5_CHECKSUM_shift(st) SKM_sk_shift(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_pop(st) SKM_sk_pop(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_sort(st) SKM_sk_sort(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_is_sorted(st) SKM_sk_is_sorted(KRB5_CHECKSUM, (st))
+
+#define sk_KRB5_ENCDATA_new(st) SKM_sk_new(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_new_null() SKM_sk_new_null(KRB5_ENCDATA)
+#define sk_KRB5_ENCDATA_free(st) SKM_sk_free(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_num(st) SKM_sk_num(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_value(st, i) SKM_sk_value(KRB5_ENCDATA, (st), (i))
+#define sk_KRB5_ENCDATA_set(st, i, val) SKM_sk_set(KRB5_ENCDATA, (st), (i), (val))
+#define sk_KRB5_ENCDATA_zero(st) SKM_sk_zero(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_push(st, val) SKM_sk_push(KRB5_ENCDATA, (st), (val))
+#define sk_KRB5_ENCDATA_unshift(st, val) SKM_sk_unshift(KRB5_ENCDATA, (st), (val))
+#define sk_KRB5_ENCDATA_find(st, val) SKM_sk_find(KRB5_ENCDATA, (st), (val))
+#define sk_KRB5_ENCDATA_find_ex(st, val) SKM_sk_find_ex(KRB5_ENCDATA, (st), (val))
+#define sk_KRB5_ENCDATA_delete(st, i) SKM_sk_delete(KRB5_ENCDATA, (st), (i))
+#define sk_KRB5_ENCDATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_ENCDATA, (st), (ptr))
+#define sk_KRB5_ENCDATA_insert(st, val, i) SKM_sk_insert(KRB5_ENCDATA, (st), (val), (i))
+#define sk_KRB5_ENCDATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_ENCDATA, (st), (cmp))
+#define sk_KRB5_ENCDATA_dup(st) SKM_sk_dup(KRB5_ENCDATA, st)
+#define sk_KRB5_ENCDATA_pop_free(st, free_func) SKM_sk_pop_free(KRB5_ENCDATA, (st), (free_func))
+#define sk_KRB5_ENCDATA_shift(st) SKM_sk_shift(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_pop(st) SKM_sk_pop(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_sort(st) SKM_sk_sort(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_is_sorted(st) SKM_sk_is_sorted(KRB5_ENCDATA, (st))
+
+#define sk_KRB5_ENCKEY_new(st) SKM_sk_new(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_new_null() SKM_sk_new_null(KRB5_ENCKEY)
+#define sk_KRB5_ENCKEY_free(st) SKM_sk_free(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_num(st) SKM_sk_num(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_value(st, i) SKM_sk_value(KRB5_ENCKEY, (st), (i))
+#define sk_KRB5_ENCKEY_set(st, i, val) SKM_sk_set(KRB5_ENCKEY, (st), (i), (val))
+#define sk_KRB5_ENCKEY_zero(st) SKM_sk_zero(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_push(st, val) SKM_sk_push(KRB5_ENCKEY, (st), (val))
+#define sk_KRB5_ENCKEY_unshift(st, val) SKM_sk_unshift(KRB5_ENCKEY, (st), (val))
+#define sk_KRB5_ENCKEY_find(st, val) SKM_sk_find(KRB5_ENCKEY, (st), (val))
+#define sk_KRB5_ENCKEY_find_ex(st, val) SKM_sk_find_ex(KRB5_ENCKEY, (st), (val))
+#define sk_KRB5_ENCKEY_delete(st, i) SKM_sk_delete(KRB5_ENCKEY, (st), (i))
+#define sk_KRB5_ENCKEY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_ENCKEY, (st), (ptr))
+#define sk_KRB5_ENCKEY_insert(st, val, i) SKM_sk_insert(KRB5_ENCKEY, (st), (val), (i))
+#define sk_KRB5_ENCKEY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_ENCKEY, (st), (cmp))
+#define sk_KRB5_ENCKEY_dup(st) SKM_sk_dup(KRB5_ENCKEY, st)
+#define sk_KRB5_ENCKEY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_ENCKEY, (st), (free_func))
+#define sk_KRB5_ENCKEY_shift(st) SKM_sk_shift(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_pop(st) SKM_sk_pop(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_sort(st) SKM_sk_sort(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_is_sorted(st) SKM_sk_is_sorted(KRB5_ENCKEY, (st))
+
+#define sk_KRB5_PRINCNAME_new(st) SKM_sk_new(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_new_null() SKM_sk_new_null(KRB5_PRINCNAME)
+#define sk_KRB5_PRINCNAME_free(st) SKM_sk_free(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_num(st) SKM_sk_num(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_value(st, i) SKM_sk_value(KRB5_PRINCNAME, (st), (i))
+#define sk_KRB5_PRINCNAME_set(st, i, val) SKM_sk_set(KRB5_PRINCNAME, (st), (i), (val))
+#define sk_KRB5_PRINCNAME_zero(st) SKM_sk_zero(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_push(st, val) SKM_sk_push(KRB5_PRINCNAME, (st), (val))
+#define sk_KRB5_PRINCNAME_unshift(st, val) SKM_sk_unshift(KRB5_PRINCNAME, (st), (val))
+#define sk_KRB5_PRINCNAME_find(st, val) SKM_sk_find(KRB5_PRINCNAME, (st), (val))
+#define sk_KRB5_PRINCNAME_find_ex(st, val) SKM_sk_find_ex(KRB5_PRINCNAME, (st), (val))
+#define sk_KRB5_PRINCNAME_delete(st, i) SKM_sk_delete(KRB5_PRINCNAME, (st), (i))
+#define sk_KRB5_PRINCNAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_PRINCNAME, (st), (ptr))
+#define sk_KRB5_PRINCNAME_insert(st, val, i) SKM_sk_insert(KRB5_PRINCNAME, (st), (val), (i))
+#define sk_KRB5_PRINCNAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_PRINCNAME, (st), (cmp))
+#define sk_KRB5_PRINCNAME_dup(st) SKM_sk_dup(KRB5_PRINCNAME, st)
+#define sk_KRB5_PRINCNAME_pop_free(st, free_func) SKM_sk_pop_free(KRB5_PRINCNAME, (st), (free_func))
+#define sk_KRB5_PRINCNAME_shift(st) SKM_sk_shift(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_pop(st) SKM_sk_pop(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_sort(st) SKM_sk_sort(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_is_sorted(st) SKM_sk_is_sorted(KRB5_PRINCNAME, (st))
+
+#define sk_KRB5_TKTBODY_new(st) SKM_sk_new(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_new_null() SKM_sk_new_null(KRB5_TKTBODY)
+#define sk_KRB5_TKTBODY_free(st) SKM_sk_free(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_num(st) SKM_sk_num(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_value(st, i) SKM_sk_value(KRB5_TKTBODY, (st), (i))
+#define sk_KRB5_TKTBODY_set(st, i, val) SKM_sk_set(KRB5_TKTBODY, (st), (i), (val))
+#define sk_KRB5_TKTBODY_zero(st) SKM_sk_zero(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_push(st, val) SKM_sk_push(KRB5_TKTBODY, (st), (val))
+#define sk_KRB5_TKTBODY_unshift(st, val) SKM_sk_unshift(KRB5_TKTBODY, (st), (val))
+#define sk_KRB5_TKTBODY_find(st, val) SKM_sk_find(KRB5_TKTBODY, (st), (val))
+#define sk_KRB5_TKTBODY_find_ex(st, val) SKM_sk_find_ex(KRB5_TKTBODY, (st), (val))
+#define sk_KRB5_TKTBODY_delete(st, i) SKM_sk_delete(KRB5_TKTBODY, (st), (i))
+#define sk_KRB5_TKTBODY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_TKTBODY, (st), (ptr))
+#define sk_KRB5_TKTBODY_insert(st, val, i) SKM_sk_insert(KRB5_TKTBODY, (st), (val), (i))
+#define sk_KRB5_TKTBODY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_TKTBODY, (st), (cmp))
+#define sk_KRB5_TKTBODY_dup(st) SKM_sk_dup(KRB5_TKTBODY, st)
+#define sk_KRB5_TKTBODY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_TKTBODY, (st), (free_func))
+#define sk_KRB5_TKTBODY_shift(st) SKM_sk_shift(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_pop(st) SKM_sk_pop(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_sort(st) SKM_sk_sort(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_is_sorted(st) SKM_sk_is_sorted(KRB5_TKTBODY, (st))
+
+#define sk_MIME_HEADER_new(st) SKM_sk_new(MIME_HEADER, (st))
+#define sk_MIME_HEADER_new_null() SKM_sk_new_null(MIME_HEADER)
+#define sk_MIME_HEADER_free(st) SKM_sk_free(MIME_HEADER, (st))
+#define sk_MIME_HEADER_num(st) SKM_sk_num(MIME_HEADER, (st))
+#define sk_MIME_HEADER_value(st, i) SKM_sk_value(MIME_HEADER, (st), (i))
+#define sk_MIME_HEADER_set(st, i, val) SKM_sk_set(MIME_HEADER, (st), (i), (val))
+#define sk_MIME_HEADER_zero(st) SKM_sk_zero(MIME_HEADER, (st))
+#define sk_MIME_HEADER_push(st, val) SKM_sk_push(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_unshift(st, val) SKM_sk_unshift(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_find(st, val) SKM_sk_find(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_find_ex(st, val) SKM_sk_find_ex(MIME_HEADER, (st), (val))
+#define sk_MIME_HEADER_delete(st, i) SKM_sk_delete(MIME_HEADER, (st), (i))
+#define sk_MIME_HEADER_delete_ptr(st, ptr) SKM_sk_delete_ptr(MIME_HEADER, (st), (ptr))
+#define sk_MIME_HEADER_insert(st, val, i) SKM_sk_insert(MIME_HEADER, (st), (val), (i))
+#define sk_MIME_HEADER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MIME_HEADER, (st), (cmp))
+#define sk_MIME_HEADER_dup(st) SKM_sk_dup(MIME_HEADER, st)
+#define sk_MIME_HEADER_pop_free(st, free_func) SKM_sk_pop_free(MIME_HEADER, (st), (free_func))
+#define sk_MIME_HEADER_shift(st) SKM_sk_shift(MIME_HEADER, (st))
+#define sk_MIME_HEADER_pop(st) SKM_sk_pop(MIME_HEADER, (st))
+#define sk_MIME_HEADER_sort(st) SKM_sk_sort(MIME_HEADER, (st))
+#define sk_MIME_HEADER_is_sorted(st) SKM_sk_is_sorted(MIME_HEADER, (st))
+
+#define sk_MIME_PARAM_new(st) SKM_sk_new(MIME_PARAM, (st))
+#define sk_MIME_PARAM_new_null() SKM_sk_new_null(MIME_PARAM)
+#define sk_MIME_PARAM_free(st) SKM_sk_free(MIME_PARAM, (st))
+#define sk_MIME_PARAM_num(st) SKM_sk_num(MIME_PARAM, (st))
+#define sk_MIME_PARAM_value(st, i) SKM_sk_value(MIME_PARAM, (st), (i))
+#define sk_MIME_PARAM_set(st, i, val) SKM_sk_set(MIME_PARAM, (st), (i), (val))
+#define sk_MIME_PARAM_zero(st) SKM_sk_zero(MIME_PARAM, (st))
+#define sk_MIME_PARAM_push(st, val) SKM_sk_push(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_unshift(st, val) SKM_sk_unshift(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_find(st, val) SKM_sk_find(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_find_ex(st, val) SKM_sk_find_ex(MIME_PARAM, (st), (val))
+#define sk_MIME_PARAM_delete(st, i) SKM_sk_delete(MIME_PARAM, (st), (i))
+#define sk_MIME_PARAM_delete_ptr(st, ptr) SKM_sk_delete_ptr(MIME_PARAM, (st), (ptr))
+#define sk_MIME_PARAM_insert(st, val, i) SKM_sk_insert(MIME_PARAM, (st), (val), (i))
+#define sk_MIME_PARAM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MIME_PARAM, (st), (cmp))
+#define sk_MIME_PARAM_dup(st) SKM_sk_dup(MIME_PARAM, st)
+#define sk_MIME_PARAM_pop_free(st, free_func) SKM_sk_pop_free(MIME_PARAM, (st), (free_func))
+#define sk_MIME_PARAM_shift(st) SKM_sk_shift(MIME_PARAM, (st))
+#define sk_MIME_PARAM_pop(st) SKM_sk_pop(MIME_PARAM, (st))
+#define sk_MIME_PARAM_sort(st) SKM_sk_sort(MIME_PARAM, (st))
+#define sk_MIME_PARAM_is_sorted(st) SKM_sk_is_sorted(MIME_PARAM, (st))
+
+#define sk_NAME_FUNCS_new(st) SKM_sk_new(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_new_null() SKM_sk_new_null(NAME_FUNCS)
+#define sk_NAME_FUNCS_free(st) SKM_sk_free(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_num(st) SKM_sk_num(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_value(st, i) SKM_sk_value(NAME_FUNCS, (st), (i))
+#define sk_NAME_FUNCS_set(st, i, val) SKM_sk_set(NAME_FUNCS, (st), (i), (val))
+#define sk_NAME_FUNCS_zero(st) SKM_sk_zero(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_push(st, val) SKM_sk_push(NAME_FUNCS, (st), (val))
+#define sk_NAME_FUNCS_unshift(st, val) SKM_sk_unshift(NAME_FUNCS, (st), (val))
+#define sk_NAME_FUNCS_find(st, val) SKM_sk_find(NAME_FUNCS, (st), (val))
+#define sk_NAME_FUNCS_find_ex(st, val) SKM_sk_find_ex(NAME_FUNCS, (st), (val))
+#define sk_NAME_FUNCS_delete(st, i) SKM_sk_delete(NAME_FUNCS, (st), (i))
+#define sk_NAME_FUNCS_delete_ptr(st, ptr) SKM_sk_delete_ptr(NAME_FUNCS, (st), (ptr))
+#define sk_NAME_FUNCS_insert(st, val, i) SKM_sk_insert(NAME_FUNCS, (st), (val), (i))
+#define sk_NAME_FUNCS_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(NAME_FUNCS, (st), (cmp))
+#define sk_NAME_FUNCS_dup(st) SKM_sk_dup(NAME_FUNCS, st)
+#define sk_NAME_FUNCS_pop_free(st, free_func) SKM_sk_pop_free(NAME_FUNCS, (st), (free_func))
+#define sk_NAME_FUNCS_shift(st) SKM_sk_shift(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_pop(st) SKM_sk_pop(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_sort(st) SKM_sk_sort(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_is_sorted(st) SKM_sk_is_sorted(NAME_FUNCS, (st))
+
+#define sk_OCSP_CERTID_new(st) SKM_sk_new(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_new_null() SKM_sk_new_null(OCSP_CERTID)
+#define sk_OCSP_CERTID_free(st) SKM_sk_free(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_num(st) SKM_sk_num(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_value(st, i) SKM_sk_value(OCSP_CERTID, (st), (i))
+#define sk_OCSP_CERTID_set(st, i, val) SKM_sk_set(OCSP_CERTID, (st), (i), (val))
+#define sk_OCSP_CERTID_zero(st) SKM_sk_zero(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_push(st, val) SKM_sk_push(OCSP_CERTID, (st), (val))
+#define sk_OCSP_CERTID_unshift(st, val) SKM_sk_unshift(OCSP_CERTID, (st), (val))
+#define sk_OCSP_CERTID_find(st, val) SKM_sk_find(OCSP_CERTID, (st), (val))
+#define sk_OCSP_CERTID_find_ex(st, val) SKM_sk_find_ex(OCSP_CERTID, (st), (val))
+#define sk_OCSP_CERTID_delete(st, i) SKM_sk_delete(OCSP_CERTID, (st), (i))
+#define sk_OCSP_CERTID_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_CERTID, (st), (ptr))
+#define sk_OCSP_CERTID_insert(st, val, i) SKM_sk_insert(OCSP_CERTID, (st), (val), (i))
+#define sk_OCSP_CERTID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_CERTID, (st), (cmp))
+#define sk_OCSP_CERTID_dup(st) SKM_sk_dup(OCSP_CERTID, st)
+#define sk_OCSP_CERTID_pop_free(st, free_func) SKM_sk_pop_free(OCSP_CERTID, (st), (free_func))
+#define sk_OCSP_CERTID_shift(st) SKM_sk_shift(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_pop(st) SKM_sk_pop(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_sort(st) SKM_sk_sort(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_is_sorted(st) SKM_sk_is_sorted(OCSP_CERTID, (st))
+
+#define sk_OCSP_ONEREQ_new(st) SKM_sk_new(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_new_null() SKM_sk_new_null(OCSP_ONEREQ)
+#define sk_OCSP_ONEREQ_free(st) SKM_sk_free(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_num(st) SKM_sk_num(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_value(st, i) SKM_sk_value(OCSP_ONEREQ, (st), (i))
+#define sk_OCSP_ONEREQ_set(st, i, val) SKM_sk_set(OCSP_ONEREQ, (st), (i), (val))
+#define sk_OCSP_ONEREQ_zero(st) SKM_sk_zero(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_push(st, val) SKM_sk_push(OCSP_ONEREQ, (st), (val))
+#define sk_OCSP_ONEREQ_unshift(st, val) SKM_sk_unshift(OCSP_ONEREQ, (st), (val))
+#define sk_OCSP_ONEREQ_find(st, val) SKM_sk_find(OCSP_ONEREQ, (st), (val))
+#define sk_OCSP_ONEREQ_find_ex(st, val) SKM_sk_find_ex(OCSP_ONEREQ, (st), (val))
+#define sk_OCSP_ONEREQ_delete(st, i) SKM_sk_delete(OCSP_ONEREQ, (st), (i))
+#define sk_OCSP_ONEREQ_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_ONEREQ, (st), (ptr))
+#define sk_OCSP_ONEREQ_insert(st, val, i) SKM_sk_insert(OCSP_ONEREQ, (st), (val), (i))
+#define sk_OCSP_ONEREQ_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_ONEREQ, (st), (cmp))
+#define sk_OCSP_ONEREQ_dup(st) SKM_sk_dup(OCSP_ONEREQ, st)
+#define sk_OCSP_ONEREQ_pop_free(st, free_func) SKM_sk_pop_free(OCSP_ONEREQ, (st), (free_func))
+#define sk_OCSP_ONEREQ_shift(st) SKM_sk_shift(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_pop(st) SKM_sk_pop(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_sort(st) SKM_sk_sort(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_is_sorted(st) SKM_sk_is_sorted(OCSP_ONEREQ, (st))
+
+#define sk_OCSP_RESPID_new(st) SKM_sk_new(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_new_null() SKM_sk_new_null(OCSP_RESPID)
+#define sk_OCSP_RESPID_free(st) SKM_sk_free(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_num(st) SKM_sk_num(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_value(st, i) SKM_sk_value(OCSP_RESPID, (st), (i))
+#define sk_OCSP_RESPID_set(st, i, val) SKM_sk_set(OCSP_RESPID, (st), (i), (val))
+#define sk_OCSP_RESPID_zero(st) SKM_sk_zero(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_push(st, val) SKM_sk_push(OCSP_RESPID, (st), (val))
+#define sk_OCSP_RESPID_unshift(st, val) SKM_sk_unshift(OCSP_RESPID, (st), (val))
+#define sk_OCSP_RESPID_find(st, val) SKM_sk_find(OCSP_RESPID, (st), (val))
+#define sk_OCSP_RESPID_find_ex(st, val) SKM_sk_find_ex(OCSP_RESPID, (st), (val))
+#define sk_OCSP_RESPID_delete(st, i) SKM_sk_delete(OCSP_RESPID, (st), (i))
+#define sk_OCSP_RESPID_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_RESPID, (st), (ptr))
+#define sk_OCSP_RESPID_insert(st, val, i) SKM_sk_insert(OCSP_RESPID, (st), (val), (i))
+#define sk_OCSP_RESPID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_RESPID, (st), (cmp))
+#define sk_OCSP_RESPID_dup(st) SKM_sk_dup(OCSP_RESPID, st)
+#define sk_OCSP_RESPID_pop_free(st, free_func) SKM_sk_pop_free(OCSP_RESPID, (st), (free_func))
+#define sk_OCSP_RESPID_shift(st) SKM_sk_shift(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_pop(st) SKM_sk_pop(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_sort(st) SKM_sk_sort(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_is_sorted(st) SKM_sk_is_sorted(OCSP_RESPID, (st))
+
+#define sk_OCSP_SINGLERESP_new(st) SKM_sk_new(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_new_null() SKM_sk_new_null(OCSP_SINGLERESP)
+#define sk_OCSP_SINGLERESP_free(st) SKM_sk_free(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_num(st) SKM_sk_num(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_value(st, i) SKM_sk_value(OCSP_SINGLERESP, (st), (i))
+#define sk_OCSP_SINGLERESP_set(st, i, val) SKM_sk_set(OCSP_SINGLERESP, (st), (i), (val))
+#define sk_OCSP_SINGLERESP_zero(st) SKM_sk_zero(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_push(st, val) SKM_sk_push(OCSP_SINGLERESP, (st), (val))
+#define sk_OCSP_SINGLERESP_unshift(st, val) SKM_sk_unshift(OCSP_SINGLERESP, (st), (val))
+#define sk_OCSP_SINGLERESP_find(st, val) SKM_sk_find(OCSP_SINGLERESP, (st), (val))
+#define sk_OCSP_SINGLERESP_find_ex(st, val) SKM_sk_find_ex(OCSP_SINGLERESP, (st), (val))
+#define sk_OCSP_SINGLERESP_delete(st, i) SKM_sk_delete(OCSP_SINGLERESP, (st), (i))
+#define sk_OCSP_SINGLERESP_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_SINGLERESP, (st), (ptr))
+#define sk_OCSP_SINGLERESP_insert(st, val, i) SKM_sk_insert(OCSP_SINGLERESP, (st), (val), (i))
+#define sk_OCSP_SINGLERESP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_SINGLERESP, (st), (cmp))
+#define sk_OCSP_SINGLERESP_dup(st) SKM_sk_dup(OCSP_SINGLERESP, st)
+#define sk_OCSP_SINGLERESP_pop_free(st, free_func) SKM_sk_pop_free(OCSP_SINGLERESP, (st), (free_func))
+#define sk_OCSP_SINGLERESP_shift(st) SKM_sk_shift(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_pop(st) SKM_sk_pop(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_sort(st) SKM_sk_sort(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_is_sorted(st) SKM_sk_is_sorted(OCSP_SINGLERESP, (st))
+
+#define sk_PKCS12_SAFEBAG_new(st) SKM_sk_new(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_new_null() SKM_sk_new_null(PKCS12_SAFEBAG)
+#define sk_PKCS12_SAFEBAG_free(st) SKM_sk_free(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_num(st) SKM_sk_num(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_value(st, i) SKM_sk_value(PKCS12_SAFEBAG, (st), (i))
+#define sk_PKCS12_SAFEBAG_set(st, i, val) SKM_sk_set(PKCS12_SAFEBAG, (st), (i), (val))
+#define sk_PKCS12_SAFEBAG_zero(st) SKM_sk_zero(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_push(st, val) SKM_sk_push(PKCS12_SAFEBAG, (st), (val))
+#define sk_PKCS12_SAFEBAG_unshift(st, val) SKM_sk_unshift(PKCS12_SAFEBAG, (st), (val))
+#define sk_PKCS12_SAFEBAG_find(st, val) SKM_sk_find(PKCS12_SAFEBAG, (st), (val))
+#define sk_PKCS12_SAFEBAG_find_ex(st, val) SKM_sk_find_ex(PKCS12_SAFEBAG, (st), (val))
+#define sk_PKCS12_SAFEBAG_delete(st, i) SKM_sk_delete(PKCS12_SAFEBAG, (st), (i))
+#define sk_PKCS12_SAFEBAG_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS12_SAFEBAG, (st), (ptr))
+#define sk_PKCS12_SAFEBAG_insert(st, val, i) SKM_sk_insert(PKCS12_SAFEBAG, (st), (val), (i))
+#define sk_PKCS12_SAFEBAG_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS12_SAFEBAG, (st), (cmp))
+#define sk_PKCS12_SAFEBAG_dup(st) SKM_sk_dup(PKCS12_SAFEBAG, st)
+#define sk_PKCS12_SAFEBAG_pop_free(st, free_func) SKM_sk_pop_free(PKCS12_SAFEBAG, (st), (free_func))
+#define sk_PKCS12_SAFEBAG_shift(st) SKM_sk_shift(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_pop(st) SKM_sk_pop(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_sort(st) SKM_sk_sort(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_is_sorted(st) SKM_sk_is_sorted(PKCS12_SAFEBAG, (st))
+
+#define sk_PKCS7_new(st) SKM_sk_new(PKCS7, (st))
+#define sk_PKCS7_new_null() SKM_sk_new_null(PKCS7)
+#define sk_PKCS7_free(st) SKM_sk_free(PKCS7, (st))
+#define sk_PKCS7_num(st) SKM_sk_num(PKCS7, (st))
+#define sk_PKCS7_value(st, i) SKM_sk_value(PKCS7, (st), (i))
+#define sk_PKCS7_set(st, i, val) SKM_sk_set(PKCS7, (st), (i), (val))
+#define sk_PKCS7_zero(st) SKM_sk_zero(PKCS7, (st))
+#define sk_PKCS7_push(st, val) SKM_sk_push(PKCS7, (st), (val))
+#define sk_PKCS7_unshift(st, val) SKM_sk_unshift(PKCS7, (st), (val))
+#define sk_PKCS7_find(st, val) SKM_sk_find(PKCS7, (st), (val))
+#define sk_PKCS7_find_ex(st, val) SKM_sk_find_ex(PKCS7, (st), (val))
+#define sk_PKCS7_delete(st, i) SKM_sk_delete(PKCS7, (st), (i))
+#define sk_PKCS7_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7, (st), (ptr))
+#define sk_PKCS7_insert(st, val, i) SKM_sk_insert(PKCS7, (st), (val), (i))
+#define sk_PKCS7_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7, (st), (cmp))
+#define sk_PKCS7_dup(st) SKM_sk_dup(PKCS7, st)
+#define sk_PKCS7_pop_free(st, free_func) SKM_sk_pop_free(PKCS7, (st), (free_func))
+#define sk_PKCS7_shift(st) SKM_sk_shift(PKCS7, (st))
+#define sk_PKCS7_pop(st) SKM_sk_pop(PKCS7, (st))
+#define sk_PKCS7_sort(st) SKM_sk_sort(PKCS7, (st))
+#define sk_PKCS7_is_sorted(st) SKM_sk_is_sorted(PKCS7, (st))
+
+#define sk_PKCS7_RECIP_INFO_new(st) SKM_sk_new(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_new_null() SKM_sk_new_null(PKCS7_RECIP_INFO)
+#define sk_PKCS7_RECIP_INFO_free(st) SKM_sk_free(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_num(st) SKM_sk_num(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_value(st, i) SKM_sk_value(PKCS7_RECIP_INFO, (st), (i))
+#define sk_PKCS7_RECIP_INFO_set(st, i, val) SKM_sk_set(PKCS7_RECIP_INFO, (st), (i), (val))
+#define sk_PKCS7_RECIP_INFO_zero(st) SKM_sk_zero(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_push(st, val) SKM_sk_push(PKCS7_RECIP_INFO, (st), (val))
+#define sk_PKCS7_RECIP_INFO_unshift(st, val) SKM_sk_unshift(PKCS7_RECIP_INFO, (st), (val))
+#define sk_PKCS7_RECIP_INFO_find(st, val) SKM_sk_find(PKCS7_RECIP_INFO, (st), (val))
+#define sk_PKCS7_RECIP_INFO_find_ex(st, val) SKM_sk_find_ex(PKCS7_RECIP_INFO, (st), (val))
+#define sk_PKCS7_RECIP_INFO_delete(st, i) SKM_sk_delete(PKCS7_RECIP_INFO, (st), (i))
+#define sk_PKCS7_RECIP_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7_RECIP_INFO, (st), (ptr))
+#define sk_PKCS7_RECIP_INFO_insert(st, val, i) SKM_sk_insert(PKCS7_RECIP_INFO, (st), (val), (i))
+#define sk_PKCS7_RECIP_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7_RECIP_INFO, (st), (cmp))
+#define sk_PKCS7_RECIP_INFO_dup(st) SKM_sk_dup(PKCS7_RECIP_INFO, st)
+#define sk_PKCS7_RECIP_INFO_pop_free(st, free_func) SKM_sk_pop_free(PKCS7_RECIP_INFO, (st), (free_func))
+#define sk_PKCS7_RECIP_INFO_shift(st) SKM_sk_shift(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_pop(st) SKM_sk_pop(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_sort(st) SKM_sk_sort(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_is_sorted(st) SKM_sk_is_sorted(PKCS7_RECIP_INFO, (st))
+
+#define sk_PKCS7_SIGNER_INFO_new(st) SKM_sk_new(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_new_null() SKM_sk_new_null(PKCS7_SIGNER_INFO)
+#define sk_PKCS7_SIGNER_INFO_free(st) SKM_sk_free(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_num(st) SKM_sk_num(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_value(st, i) SKM_sk_value(PKCS7_SIGNER_INFO, (st), (i))
+#define sk_PKCS7_SIGNER_INFO_set(st, i, val) SKM_sk_set(PKCS7_SIGNER_INFO, (st), (i), (val))
+#define sk_PKCS7_SIGNER_INFO_zero(st) SKM_sk_zero(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_push(st, val) SKM_sk_push(PKCS7_SIGNER_INFO, (st), (val))
+#define sk_PKCS7_SIGNER_INFO_unshift(st, val) SKM_sk_unshift(PKCS7_SIGNER_INFO, (st), (val))
+#define sk_PKCS7_SIGNER_INFO_find(st, val) SKM_sk_find(PKCS7_SIGNER_INFO, (st), (val))
+#define sk_PKCS7_SIGNER_INFO_find_ex(st, val) SKM_sk_find_ex(PKCS7_SIGNER_INFO, (st), (val))
+#define sk_PKCS7_SIGNER_INFO_delete(st, i) SKM_sk_delete(PKCS7_SIGNER_INFO, (st), (i))
+#define sk_PKCS7_SIGNER_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7_SIGNER_INFO, (st), (ptr))
+#define sk_PKCS7_SIGNER_INFO_insert(st, val, i) SKM_sk_insert(PKCS7_SIGNER_INFO, (st), (val), (i))
+#define sk_PKCS7_SIGNER_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7_SIGNER_INFO, (st), (cmp))
+#define sk_PKCS7_SIGNER_INFO_dup(st) SKM_sk_dup(PKCS7_SIGNER_INFO, st)
+#define sk_PKCS7_SIGNER_INFO_pop_free(st, free_func) SKM_sk_pop_free(PKCS7_SIGNER_INFO, (st), (free_func))
+#define sk_PKCS7_SIGNER_INFO_shift(st) SKM_sk_shift(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_pop(st) SKM_sk_pop(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_sort(st) SKM_sk_sort(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_is_sorted(st) SKM_sk_is_sorted(PKCS7_SIGNER_INFO, (st))
+
+#define sk_POLICYINFO_new(st) SKM_sk_new(POLICYINFO, (st))
+#define sk_POLICYINFO_new_null() SKM_sk_new_null(POLICYINFO)
+#define sk_POLICYINFO_free(st) SKM_sk_free(POLICYINFO, (st))
+#define sk_POLICYINFO_num(st) SKM_sk_num(POLICYINFO, (st))
+#define sk_POLICYINFO_value(st, i) SKM_sk_value(POLICYINFO, (st), (i))
+#define sk_POLICYINFO_set(st, i, val) SKM_sk_set(POLICYINFO, (st), (i), (val))
+#define sk_POLICYINFO_zero(st) SKM_sk_zero(POLICYINFO, (st))
+#define sk_POLICYINFO_push(st, val) SKM_sk_push(POLICYINFO, (st), (val))
+#define sk_POLICYINFO_unshift(st, val) SKM_sk_unshift(POLICYINFO, (st), (val))
+#define sk_POLICYINFO_find(st, val) SKM_sk_find(POLICYINFO, (st), (val))
+#define sk_POLICYINFO_find_ex(st, val) SKM_sk_find_ex(POLICYINFO, (st), (val))
+#define sk_POLICYINFO_delete(st, i) SKM_sk_delete(POLICYINFO, (st), (i))
+#define sk_POLICYINFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICYINFO, (st), (ptr))
+#define sk_POLICYINFO_insert(st, val, i) SKM_sk_insert(POLICYINFO, (st), (val), (i))
+#define sk_POLICYINFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICYINFO, (st), (cmp))
+#define sk_POLICYINFO_dup(st) SKM_sk_dup(POLICYINFO, st)
+#define sk_POLICYINFO_pop_free(st, free_func) SKM_sk_pop_free(POLICYINFO, (st), (free_func))
+#define sk_POLICYINFO_shift(st) SKM_sk_shift(POLICYINFO, (st))
+#define sk_POLICYINFO_pop(st) SKM_sk_pop(POLICYINFO, (st))
+#define sk_POLICYINFO_sort(st) SKM_sk_sort(POLICYINFO, (st))
+#define sk_POLICYINFO_is_sorted(st) SKM_sk_is_sorted(POLICYINFO, (st))
+
+#define sk_POLICYQUALINFO_new(st) SKM_sk_new(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_new_null() SKM_sk_new_null(POLICYQUALINFO)
+#define sk_POLICYQUALINFO_free(st) SKM_sk_free(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_num(st) SKM_sk_num(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_value(st, i) SKM_sk_value(POLICYQUALINFO, (st), (i))
+#define sk_POLICYQUALINFO_set(st, i, val) SKM_sk_set(POLICYQUALINFO, (st), (i), (val))
+#define sk_POLICYQUALINFO_zero(st) SKM_sk_zero(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_push(st, val) SKM_sk_push(POLICYQUALINFO, (st), (val))
+#define sk_POLICYQUALINFO_unshift(st, val) SKM_sk_unshift(POLICYQUALINFO, (st), (val))
+#define sk_POLICYQUALINFO_find(st, val) SKM_sk_find(POLICYQUALINFO, (st), (val))
+#define sk_POLICYQUALINFO_find_ex(st, val) SKM_sk_find_ex(POLICYQUALINFO, (st), (val))
+#define sk_POLICYQUALINFO_delete(st, i) SKM_sk_delete(POLICYQUALINFO, (st), (i))
+#define sk_POLICYQUALINFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICYQUALINFO, (st), (ptr))
+#define sk_POLICYQUALINFO_insert(st, val, i) SKM_sk_insert(POLICYQUALINFO, (st), (val), (i))
+#define sk_POLICYQUALINFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICYQUALINFO, (st), (cmp))
+#define sk_POLICYQUALINFO_dup(st) SKM_sk_dup(POLICYQUALINFO, st)
+#define sk_POLICYQUALINFO_pop_free(st, free_func) SKM_sk_pop_free(POLICYQUALINFO, (st), (free_func))
+#define sk_POLICYQUALINFO_shift(st) SKM_sk_shift(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_pop(st) SKM_sk_pop(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_sort(st) SKM_sk_sort(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_is_sorted(st) SKM_sk_is_sorted(POLICYQUALINFO, (st))
+
+#define sk_POLICY_MAPPING_new(st) SKM_sk_new(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_new_null() SKM_sk_new_null(POLICY_MAPPING)
+#define sk_POLICY_MAPPING_free(st) SKM_sk_free(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_num(st) SKM_sk_num(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_value(st, i) SKM_sk_value(POLICY_MAPPING, (st), (i))
+#define sk_POLICY_MAPPING_set(st, i, val) SKM_sk_set(POLICY_MAPPING, (st), (i), (val))
+#define sk_POLICY_MAPPING_zero(st) SKM_sk_zero(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_push(st, val) SKM_sk_push(POLICY_MAPPING, (st), (val))
+#define sk_POLICY_MAPPING_unshift(st, val) SKM_sk_unshift(POLICY_MAPPING, (st), (val))
+#define sk_POLICY_MAPPING_find(st, val) SKM_sk_find(POLICY_MAPPING, (st), (val))
+#define sk_POLICY_MAPPING_find_ex(st, val) SKM_sk_find_ex(POLICY_MAPPING, (st), (val))
+#define sk_POLICY_MAPPING_delete(st, i) SKM_sk_delete(POLICY_MAPPING, (st), (i))
+#define sk_POLICY_MAPPING_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICY_MAPPING, (st), (ptr))
+#define sk_POLICY_MAPPING_insert(st, val, i) SKM_sk_insert(POLICY_MAPPING, (st), (val), (i))
+#define sk_POLICY_MAPPING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICY_MAPPING, (st), (cmp))
+#define sk_POLICY_MAPPING_dup(st) SKM_sk_dup(POLICY_MAPPING, st)
+#define sk_POLICY_MAPPING_pop_free(st, free_func) SKM_sk_pop_free(POLICY_MAPPING, (st), (free_func))
+#define sk_POLICY_MAPPING_shift(st) SKM_sk_shift(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_pop(st) SKM_sk_pop(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_sort(st) SKM_sk_sort(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_is_sorted(st) SKM_sk_is_sorted(POLICY_MAPPING, (st))
+
+#define sk_SSL_CIPHER_new(st) SKM_sk_new(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_new_null() SKM_sk_new_null(SSL_CIPHER)
+#define sk_SSL_CIPHER_free(st) SKM_sk_free(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_num(st) SKM_sk_num(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_value(st, i) SKM_sk_value(SSL_CIPHER, (st), (i))
+#define sk_SSL_CIPHER_set(st, i, val) SKM_sk_set(SSL_CIPHER, (st), (i), (val))
+#define sk_SSL_CIPHER_zero(st) SKM_sk_zero(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_push(st, val) SKM_sk_push(SSL_CIPHER, (st), (val))
+#define sk_SSL_CIPHER_unshift(st, val) SKM_sk_unshift(SSL_CIPHER, (st), (val))
+#define sk_SSL_CIPHER_find(st, val) SKM_sk_find(SSL_CIPHER, (st), (val))
+#define sk_SSL_CIPHER_find_ex(st, val) SKM_sk_find_ex(SSL_CIPHER, (st), (val))
+#define sk_SSL_CIPHER_delete(st, i) SKM_sk_delete(SSL_CIPHER, (st), (i))
+#define sk_SSL_CIPHER_delete_ptr(st, ptr) SKM_sk_delete_ptr(SSL_CIPHER, (st), (ptr))
+#define sk_SSL_CIPHER_insert(st, val, i) SKM_sk_insert(SSL_CIPHER, (st), (val), (i))
+#define sk_SSL_CIPHER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SSL_CIPHER, (st), (cmp))
+#define sk_SSL_CIPHER_dup(st) SKM_sk_dup(SSL_CIPHER, st)
+#define sk_SSL_CIPHER_pop_free(st, free_func) SKM_sk_pop_free(SSL_CIPHER, (st), (free_func))
+#define sk_SSL_CIPHER_shift(st) SKM_sk_shift(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_pop(st) SKM_sk_pop(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_sort(st) SKM_sk_sort(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_is_sorted(st) SKM_sk_is_sorted(SSL_CIPHER, (st))
+
+#define sk_SSL_COMP_new(st) SKM_sk_new(SSL_COMP, (st))
+#define sk_SSL_COMP_new_null() SKM_sk_new_null(SSL_COMP)
+#define sk_SSL_COMP_free(st) SKM_sk_free(SSL_COMP, (st))
+#define sk_SSL_COMP_num(st) SKM_sk_num(SSL_COMP, (st))
+#define sk_SSL_COMP_value(st, i) SKM_sk_value(SSL_COMP, (st), (i))
+#define sk_SSL_COMP_set(st, i, val) SKM_sk_set(SSL_COMP, (st), (i), (val))
+#define sk_SSL_COMP_zero(st) SKM_sk_zero(SSL_COMP, (st))
+#define sk_SSL_COMP_push(st, val) SKM_sk_push(SSL_COMP, (st), (val))
+#define sk_SSL_COMP_unshift(st, val) SKM_sk_unshift(SSL_COMP, (st), (val))
+#define sk_SSL_COMP_find(st, val) SKM_sk_find(SSL_COMP, (st), (val))
+#define sk_SSL_COMP_find_ex(st, val) SKM_sk_find_ex(SSL_COMP, (st), (val))
+#define sk_SSL_COMP_delete(st, i) SKM_sk_delete(SSL_COMP, (st), (i))
+#define sk_SSL_COMP_delete_ptr(st, ptr) SKM_sk_delete_ptr(SSL_COMP, (st), (ptr))
+#define sk_SSL_COMP_insert(st, val, i) SKM_sk_insert(SSL_COMP, (st), (val), (i))
+#define sk_SSL_COMP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SSL_COMP, (st), (cmp))
+#define sk_SSL_COMP_dup(st) SKM_sk_dup(SSL_COMP, st)
+#define sk_SSL_COMP_pop_free(st, free_func) SKM_sk_pop_free(SSL_COMP, (st), (free_func))
+#define sk_SSL_COMP_shift(st) SKM_sk_shift(SSL_COMP, (st))
+#define sk_SSL_COMP_pop(st) SKM_sk_pop(SSL_COMP, (st))
+#define sk_SSL_COMP_sort(st) SKM_sk_sort(SSL_COMP, (st))
+#define sk_SSL_COMP_is_sorted(st) SKM_sk_is_sorted(SSL_COMP, (st))
+
+#define sk_STORE_OBJECT_new(st) SKM_sk_new(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_new_null() SKM_sk_new_null(STORE_OBJECT)
+#define sk_STORE_OBJECT_free(st) SKM_sk_free(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_num(st) SKM_sk_num(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_value(st, i) SKM_sk_value(STORE_OBJECT, (st), (i))
+#define sk_STORE_OBJECT_set(st, i, val) SKM_sk_set(STORE_OBJECT, (st), (i), (val))
+#define sk_STORE_OBJECT_zero(st) SKM_sk_zero(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_push(st, val) SKM_sk_push(STORE_OBJECT, (st), (val))
+#define sk_STORE_OBJECT_unshift(st, val) SKM_sk_unshift(STORE_OBJECT, (st), (val))
+#define sk_STORE_OBJECT_find(st, val) SKM_sk_find(STORE_OBJECT, (st), (val))
+#define sk_STORE_OBJECT_find_ex(st, val) SKM_sk_find_ex(STORE_OBJECT, (st), (val))
+#define sk_STORE_OBJECT_delete(st, i) SKM_sk_delete(STORE_OBJECT, (st), (i))
+#define sk_STORE_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(STORE_OBJECT, (st), (ptr))
+#define sk_STORE_OBJECT_insert(st, val, i) SKM_sk_insert(STORE_OBJECT, (st), (val), (i))
+#define sk_STORE_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(STORE_OBJECT, (st), (cmp))
+#define sk_STORE_OBJECT_dup(st) SKM_sk_dup(STORE_OBJECT, st)
+#define sk_STORE_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(STORE_OBJECT, (st), (free_func))
+#define sk_STORE_OBJECT_shift(st) SKM_sk_shift(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_pop(st) SKM_sk_pop(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_sort(st) SKM_sk_sort(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_is_sorted(st) SKM_sk_is_sorted(STORE_OBJECT, (st))
+
+#define sk_SXNETID_new(st) SKM_sk_new(SXNETID, (st))
+#define sk_SXNETID_new_null() SKM_sk_new_null(SXNETID)
+#define sk_SXNETID_free(st) SKM_sk_free(SXNETID, (st))
+#define sk_SXNETID_num(st) SKM_sk_num(SXNETID, (st))
+#define sk_SXNETID_value(st, i) SKM_sk_value(SXNETID, (st), (i))
+#define sk_SXNETID_set(st, i, val) SKM_sk_set(SXNETID, (st), (i), (val))
+#define sk_SXNETID_zero(st) SKM_sk_zero(SXNETID, (st))
+#define sk_SXNETID_push(st, val) SKM_sk_push(SXNETID, (st), (val))
+#define sk_SXNETID_unshift(st, val) SKM_sk_unshift(SXNETID, (st), (val))
+#define sk_SXNETID_find(st, val) SKM_sk_find(SXNETID, (st), (val))
+#define sk_SXNETID_find_ex(st, val) SKM_sk_find_ex(SXNETID, (st), (val))
+#define sk_SXNETID_delete(st, i) SKM_sk_delete(SXNETID, (st), (i))
+#define sk_SXNETID_delete_ptr(st, ptr) SKM_sk_delete_ptr(SXNETID, (st), (ptr))
+#define sk_SXNETID_insert(st, val, i) SKM_sk_insert(SXNETID, (st), (val), (i))
+#define sk_SXNETID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SXNETID, (st), (cmp))
+#define sk_SXNETID_dup(st) SKM_sk_dup(SXNETID, st)
+#define sk_SXNETID_pop_free(st, free_func) SKM_sk_pop_free(SXNETID, (st), (free_func))
+#define sk_SXNETID_shift(st) SKM_sk_shift(SXNETID, (st))
+#define sk_SXNETID_pop(st) SKM_sk_pop(SXNETID, (st))
+#define sk_SXNETID_sort(st) SKM_sk_sort(SXNETID, (st))
+#define sk_SXNETID_is_sorted(st) SKM_sk_is_sorted(SXNETID, (st))
+
+#define sk_UI_STRING_new(st) SKM_sk_new(UI_STRING, (st))
+#define sk_UI_STRING_new_null() SKM_sk_new_null(UI_STRING)
+#define sk_UI_STRING_free(st) SKM_sk_free(UI_STRING, (st))
+#define sk_UI_STRING_num(st) SKM_sk_num(UI_STRING, (st))
+#define sk_UI_STRING_value(st, i) SKM_sk_value(UI_STRING, (st), (i))
+#define sk_UI_STRING_set(st, i, val) SKM_sk_set(UI_STRING, (st), (i), (val))
+#define sk_UI_STRING_zero(st) SKM_sk_zero(UI_STRING, (st))
+#define sk_UI_STRING_push(st, val) SKM_sk_push(UI_STRING, (st), (val))
+#define sk_UI_STRING_unshift(st, val) SKM_sk_unshift(UI_STRING, (st), (val))
+#define sk_UI_STRING_find(st, val) SKM_sk_find(UI_STRING, (st), (val))
+#define sk_UI_STRING_find_ex(st, val) SKM_sk_find_ex(UI_STRING, (st), (val))
+#define sk_UI_STRING_delete(st, i) SKM_sk_delete(UI_STRING, (st), (i))
+#define sk_UI_STRING_delete_ptr(st, ptr) SKM_sk_delete_ptr(UI_STRING, (st), (ptr))
+#define sk_UI_STRING_insert(st, val, i) SKM_sk_insert(UI_STRING, (st), (val), (i))
+#define sk_UI_STRING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(UI_STRING, (st), (cmp))
+#define sk_UI_STRING_dup(st) SKM_sk_dup(UI_STRING, st)
+#define sk_UI_STRING_pop_free(st, free_func) SKM_sk_pop_free(UI_STRING, (st), (free_func))
+#define sk_UI_STRING_shift(st) SKM_sk_shift(UI_STRING, (st))
+#define sk_UI_STRING_pop(st) SKM_sk_pop(UI_STRING, (st))
+#define sk_UI_STRING_sort(st) SKM_sk_sort(UI_STRING, (st))
+#define sk_UI_STRING_is_sorted(st) SKM_sk_is_sorted(UI_STRING, (st))
+
+#define sk_X509_new(st) SKM_sk_new(X509, (st))
+#define sk_X509_new_null() SKM_sk_new_null(X509)
+#define sk_X509_free(st) SKM_sk_free(X509, (st))
+#define sk_X509_num(st) SKM_sk_num(X509, (st))
+#define sk_X509_value(st, i) SKM_sk_value(X509, (st), (i))
+#define sk_X509_set(st, i, val) SKM_sk_set(X509, (st), (i), (val))
+#define sk_X509_zero(st) SKM_sk_zero(X509, (st))
+#define sk_X509_push(st, val) SKM_sk_push(X509, (st), (val))
+#define sk_X509_unshift(st, val) SKM_sk_unshift(X509, (st), (val))
+#define sk_X509_find(st, val) SKM_sk_find(X509, (st), (val))
+#define sk_X509_find_ex(st, val) SKM_sk_find_ex(X509, (st), (val))
+#define sk_X509_delete(st, i) SKM_sk_delete(X509, (st), (i))
+#define sk_X509_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509, (st), (ptr))
+#define sk_X509_insert(st, val, i) SKM_sk_insert(X509, (st), (val), (i))
+#define sk_X509_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509, (st), (cmp))
+#define sk_X509_dup(st) SKM_sk_dup(X509, st)
+#define sk_X509_pop_free(st, free_func) SKM_sk_pop_free(X509, (st), (free_func))
+#define sk_X509_shift(st) SKM_sk_shift(X509, (st))
+#define sk_X509_pop(st) SKM_sk_pop(X509, (st))
+#define sk_X509_sort(st) SKM_sk_sort(X509, (st))
+#define sk_X509_is_sorted(st) SKM_sk_is_sorted(X509, (st))
+
+#define sk_X509V3_EXT_METHOD_new(st) SKM_sk_new(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_new_null() SKM_sk_new_null(X509V3_EXT_METHOD)
+#define sk_X509V3_EXT_METHOD_free(st) SKM_sk_free(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_num(st) SKM_sk_num(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_value(st, i) SKM_sk_value(X509V3_EXT_METHOD, (st), (i))
+#define sk_X509V3_EXT_METHOD_set(st, i, val) SKM_sk_set(X509V3_EXT_METHOD, (st), (i), (val))
+#define sk_X509V3_EXT_METHOD_zero(st) SKM_sk_zero(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_push(st, val) SKM_sk_push(X509V3_EXT_METHOD, (st), (val))
+#define sk_X509V3_EXT_METHOD_unshift(st, val) SKM_sk_unshift(X509V3_EXT_METHOD, (st), (val))
+#define sk_X509V3_EXT_METHOD_find(st, val) SKM_sk_find(X509V3_EXT_METHOD, (st), (val))
+#define sk_X509V3_EXT_METHOD_find_ex(st, val) SKM_sk_find_ex(X509V3_EXT_METHOD, (st), (val))
+#define sk_X509V3_EXT_METHOD_delete(st, i) SKM_sk_delete(X509V3_EXT_METHOD, (st), (i))
+#define sk_X509V3_EXT_METHOD_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509V3_EXT_METHOD, (st), (ptr))
+#define sk_X509V3_EXT_METHOD_insert(st, val, i) SKM_sk_insert(X509V3_EXT_METHOD, (st), (val), (i))
+#define sk_X509V3_EXT_METHOD_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509V3_EXT_METHOD, (st), (cmp))
+#define sk_X509V3_EXT_METHOD_dup(st) SKM_sk_dup(X509V3_EXT_METHOD, st)
+#define sk_X509V3_EXT_METHOD_pop_free(st, free_func) SKM_sk_pop_free(X509V3_EXT_METHOD, (st), (free_func))
+#define sk_X509V3_EXT_METHOD_shift(st) SKM_sk_shift(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_pop(st) SKM_sk_pop(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_sort(st) SKM_sk_sort(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_is_sorted(st) SKM_sk_is_sorted(X509V3_EXT_METHOD, (st))
+
+#define sk_X509_ALGOR_new(st) SKM_sk_new(X509_ALGOR, (st))
+#define sk_X509_ALGOR_new_null() SKM_sk_new_null(X509_ALGOR)
+#define sk_X509_ALGOR_free(st) SKM_sk_free(X509_ALGOR, (st))
+#define sk_X509_ALGOR_num(st) SKM_sk_num(X509_ALGOR, (st))
+#define sk_X509_ALGOR_value(st, i) SKM_sk_value(X509_ALGOR, (st), (i))
+#define sk_X509_ALGOR_set(st, i, val) SKM_sk_set(X509_ALGOR, (st), (i), (val))
+#define sk_X509_ALGOR_zero(st) SKM_sk_zero(X509_ALGOR, (st))
+#define sk_X509_ALGOR_push(st, val) SKM_sk_push(X509_ALGOR, (st), (val))
+#define sk_X509_ALGOR_unshift(st, val) SKM_sk_unshift(X509_ALGOR, (st), (val))
+#define sk_X509_ALGOR_find(st, val) SKM_sk_find(X509_ALGOR, (st), (val))
+#define sk_X509_ALGOR_find_ex(st, val) SKM_sk_find_ex(X509_ALGOR, (st), (val))
+#define sk_X509_ALGOR_delete(st, i) SKM_sk_delete(X509_ALGOR, (st), (i))
+#define sk_X509_ALGOR_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_ALGOR, (st), (ptr))
+#define sk_X509_ALGOR_insert(st, val, i) SKM_sk_insert(X509_ALGOR, (st), (val), (i))
+#define sk_X509_ALGOR_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_ALGOR, (st), (cmp))
+#define sk_X509_ALGOR_dup(st) SKM_sk_dup(X509_ALGOR, st)
+#define sk_X509_ALGOR_pop_free(st, free_func) SKM_sk_pop_free(X509_ALGOR, (st), (free_func))
+#define sk_X509_ALGOR_shift(st) SKM_sk_shift(X509_ALGOR, (st))
+#define sk_X509_ALGOR_pop(st) SKM_sk_pop(X509_ALGOR, (st))
+#define sk_X509_ALGOR_sort(st) SKM_sk_sort(X509_ALGOR, (st))
+#define sk_X509_ALGOR_is_sorted(st) SKM_sk_is_sorted(X509_ALGOR, (st))
+
+#define sk_X509_ATTRIBUTE_new(st) SKM_sk_new(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_new_null() SKM_sk_new_null(X509_ATTRIBUTE)
+#define sk_X509_ATTRIBUTE_free(st) SKM_sk_free(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_num(st) SKM_sk_num(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_value(st, i) SKM_sk_value(X509_ATTRIBUTE, (st), (i))
+#define sk_X509_ATTRIBUTE_set(st, i, val) SKM_sk_set(X509_ATTRIBUTE, (st), (i), (val))
+#define sk_X509_ATTRIBUTE_zero(st) SKM_sk_zero(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_push(st, val) SKM_sk_push(X509_ATTRIBUTE, (st), (val))
+#define sk_X509_ATTRIBUTE_unshift(st, val) SKM_sk_unshift(X509_ATTRIBUTE, (st), (val))
+#define sk_X509_ATTRIBUTE_find(st, val) SKM_sk_find(X509_ATTRIBUTE, (st), (val))
+#define sk_X509_ATTRIBUTE_find_ex(st, val) SKM_sk_find_ex(X509_ATTRIBUTE, (st), (val))
+#define sk_X509_ATTRIBUTE_delete(st, i) SKM_sk_delete(X509_ATTRIBUTE, (st), (i))
+#define sk_X509_ATTRIBUTE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_ATTRIBUTE, (st), (ptr))
+#define sk_X509_ATTRIBUTE_insert(st, val, i) SKM_sk_insert(X509_ATTRIBUTE, (st), (val), (i))
+#define sk_X509_ATTRIBUTE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_ATTRIBUTE, (st), (cmp))
+#define sk_X509_ATTRIBUTE_dup(st) SKM_sk_dup(X509_ATTRIBUTE, st)
+#define sk_X509_ATTRIBUTE_pop_free(st, free_func) SKM_sk_pop_free(X509_ATTRIBUTE, (st), (free_func))
+#define sk_X509_ATTRIBUTE_shift(st) SKM_sk_shift(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_pop(st) SKM_sk_pop(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_sort(st) SKM_sk_sort(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_is_sorted(st) SKM_sk_is_sorted(X509_ATTRIBUTE, (st))
+
+#define sk_X509_CRL_new(st) SKM_sk_new(X509_CRL, (st))
+#define sk_X509_CRL_new_null() SKM_sk_new_null(X509_CRL)
+#define sk_X509_CRL_free(st) SKM_sk_free(X509_CRL, (st))
+#define sk_X509_CRL_num(st) SKM_sk_num(X509_CRL, (st))
+#define sk_X509_CRL_value(st, i) SKM_sk_value(X509_CRL, (st), (i))
+#define sk_X509_CRL_set(st, i, val) SKM_sk_set(X509_CRL, (st), (i), (val))
+#define sk_X509_CRL_zero(st) SKM_sk_zero(X509_CRL, (st))
+#define sk_X509_CRL_push(st, val) SKM_sk_push(X509_CRL, (st), (val))
+#define sk_X509_CRL_unshift(st, val) SKM_sk_unshift(X509_CRL, (st), (val))
+#define sk_X509_CRL_find(st, val) SKM_sk_find(X509_CRL, (st), (val))
+#define sk_X509_CRL_find_ex(st, val) SKM_sk_find_ex(X509_CRL, (st), (val))
+#define sk_X509_CRL_delete(st, i) SKM_sk_delete(X509_CRL, (st), (i))
+#define sk_X509_CRL_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_CRL, (st), (ptr))
+#define sk_X509_CRL_insert(st, val, i) SKM_sk_insert(X509_CRL, (st), (val), (i))
+#define sk_X509_CRL_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_CRL, (st), (cmp))
+#define sk_X509_CRL_dup(st) SKM_sk_dup(X509_CRL, st)
+#define sk_X509_CRL_pop_free(st, free_func) SKM_sk_pop_free(X509_CRL, (st), (free_func))
+#define sk_X509_CRL_shift(st) SKM_sk_shift(X509_CRL, (st))
+#define sk_X509_CRL_pop(st) SKM_sk_pop(X509_CRL, (st))
+#define sk_X509_CRL_sort(st) SKM_sk_sort(X509_CRL, (st))
+#define sk_X509_CRL_is_sorted(st) SKM_sk_is_sorted(X509_CRL, (st))
+
+#define sk_X509_EXTENSION_new(st) SKM_sk_new(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_new_null() SKM_sk_new_null(X509_EXTENSION)
+#define sk_X509_EXTENSION_free(st) SKM_sk_free(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_num(st) SKM_sk_num(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_value(st, i) SKM_sk_value(X509_EXTENSION, (st), (i))
+#define sk_X509_EXTENSION_set(st, i, val) SKM_sk_set(X509_EXTENSION, (st), (i), (val))
+#define sk_X509_EXTENSION_zero(st) SKM_sk_zero(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_push(st, val) SKM_sk_push(X509_EXTENSION, (st), (val))
+#define sk_X509_EXTENSION_unshift(st, val) SKM_sk_unshift(X509_EXTENSION, (st), (val))
+#define sk_X509_EXTENSION_find(st, val) SKM_sk_find(X509_EXTENSION, (st), (val))
+#define sk_X509_EXTENSION_find_ex(st, val) SKM_sk_find_ex(X509_EXTENSION, (st), (val))
+#define sk_X509_EXTENSION_delete(st, i) SKM_sk_delete(X509_EXTENSION, (st), (i))
+#define sk_X509_EXTENSION_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_EXTENSION, (st), (ptr))
+#define sk_X509_EXTENSION_insert(st, val, i) SKM_sk_insert(X509_EXTENSION, (st), (val), (i))
+#define sk_X509_EXTENSION_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_EXTENSION, (st), (cmp))
+#define sk_X509_EXTENSION_dup(st) SKM_sk_dup(X509_EXTENSION, st)
+#define sk_X509_EXTENSION_pop_free(st, free_func) SKM_sk_pop_free(X509_EXTENSION, (st), (free_func))
+#define sk_X509_EXTENSION_shift(st) SKM_sk_shift(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_pop(st) SKM_sk_pop(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_sort(st) SKM_sk_sort(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_is_sorted(st) SKM_sk_is_sorted(X509_EXTENSION, (st))
+
+#define sk_X509_INFO_new(st) SKM_sk_new(X509_INFO, (st))
+#define sk_X509_INFO_new_null() SKM_sk_new_null(X509_INFO)
+#define sk_X509_INFO_free(st) SKM_sk_free(X509_INFO, (st))
+#define sk_X509_INFO_num(st) SKM_sk_num(X509_INFO, (st))
+#define sk_X509_INFO_value(st, i) SKM_sk_value(X509_INFO, (st), (i))
+#define sk_X509_INFO_set(st, i, val) SKM_sk_set(X509_INFO, (st), (i), (val))
+#define sk_X509_INFO_zero(st) SKM_sk_zero(X509_INFO, (st))
+#define sk_X509_INFO_push(st, val) SKM_sk_push(X509_INFO, (st), (val))
+#define sk_X509_INFO_unshift(st, val) SKM_sk_unshift(X509_INFO, (st), (val))
+#define sk_X509_INFO_find(st, val) SKM_sk_find(X509_INFO, (st), (val))
+#define sk_X509_INFO_find_ex(st, val) SKM_sk_find_ex(X509_INFO, (st), (val))
+#define sk_X509_INFO_delete(st, i) SKM_sk_delete(X509_INFO, (st), (i))
+#define sk_X509_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_INFO, (st), (ptr))
+#define sk_X509_INFO_insert(st, val, i) SKM_sk_insert(X509_INFO, (st), (val), (i))
+#define sk_X509_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_INFO, (st), (cmp))
+#define sk_X509_INFO_dup(st) SKM_sk_dup(X509_INFO, st)
+#define sk_X509_INFO_pop_free(st, free_func) SKM_sk_pop_free(X509_INFO, (st), (free_func))
+#define sk_X509_INFO_shift(st) SKM_sk_shift(X509_INFO, (st))
+#define sk_X509_INFO_pop(st) SKM_sk_pop(X509_INFO, (st))
+#define sk_X509_INFO_sort(st) SKM_sk_sort(X509_INFO, (st))
+#define sk_X509_INFO_is_sorted(st) SKM_sk_is_sorted(X509_INFO, (st))
+
+#define sk_X509_LOOKUP_new(st) SKM_sk_new(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_new_null() SKM_sk_new_null(X509_LOOKUP)
+#define sk_X509_LOOKUP_free(st) SKM_sk_free(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_num(st) SKM_sk_num(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_value(st, i) SKM_sk_value(X509_LOOKUP, (st), (i))
+#define sk_X509_LOOKUP_set(st, i, val) SKM_sk_set(X509_LOOKUP, (st), (i), (val))
+#define sk_X509_LOOKUP_zero(st) SKM_sk_zero(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_push(st, val) SKM_sk_push(X509_LOOKUP, (st), (val))
+#define sk_X509_LOOKUP_unshift(st, val) SKM_sk_unshift(X509_LOOKUP, (st), (val))
+#define sk_X509_LOOKUP_find(st, val) SKM_sk_find(X509_LOOKUP, (st), (val))
+#define sk_X509_LOOKUP_find_ex(st, val) SKM_sk_find_ex(X509_LOOKUP, (st), (val))
+#define sk_X509_LOOKUP_delete(st, i) SKM_sk_delete(X509_LOOKUP, (st), (i))
+#define sk_X509_LOOKUP_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_LOOKUP, (st), (ptr))
+#define sk_X509_LOOKUP_insert(st, val, i) SKM_sk_insert(X509_LOOKUP, (st), (val), (i))
+#define sk_X509_LOOKUP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_LOOKUP, (st), (cmp))
+#define sk_X509_LOOKUP_dup(st) SKM_sk_dup(X509_LOOKUP, st)
+#define sk_X509_LOOKUP_pop_free(st, free_func) SKM_sk_pop_free(X509_LOOKUP, (st), (free_func))
+#define sk_X509_LOOKUP_shift(st) SKM_sk_shift(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_pop(st) SKM_sk_pop(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_sort(st) SKM_sk_sort(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_is_sorted(st) SKM_sk_is_sorted(X509_LOOKUP, (st))
+
+#define sk_X509_NAME_new(st) SKM_sk_new(X509_NAME, (st))
+#define sk_X509_NAME_new_null() SKM_sk_new_null(X509_NAME)
+#define sk_X509_NAME_free(st) SKM_sk_free(X509_NAME, (st))
+#define sk_X509_NAME_num(st) SKM_sk_num(X509_NAME, (st))
+#define sk_X509_NAME_value(st, i) SKM_sk_value(X509_NAME, (st), (i))
+#define sk_X509_NAME_set(st, i, val) SKM_sk_set(X509_NAME, (st), (i), (val))
+#define sk_X509_NAME_zero(st) SKM_sk_zero(X509_NAME, (st))
+#define sk_X509_NAME_push(st, val) SKM_sk_push(X509_NAME, (st), (val))
+#define sk_X509_NAME_unshift(st, val) SKM_sk_unshift(X509_NAME, (st), (val))
+#define sk_X509_NAME_find(st, val) SKM_sk_find(X509_NAME, (st), (val))
+#define sk_X509_NAME_find_ex(st, val) SKM_sk_find_ex(X509_NAME, (st), (val))
+#define sk_X509_NAME_delete(st, i) SKM_sk_delete(X509_NAME, (st), (i))
+#define sk_X509_NAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_NAME, (st), (ptr))
+#define sk_X509_NAME_insert(st, val, i) SKM_sk_insert(X509_NAME, (st), (val), (i))
+#define sk_X509_NAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_NAME, (st), (cmp))
+#define sk_X509_NAME_dup(st) SKM_sk_dup(X509_NAME, st)
+#define sk_X509_NAME_pop_free(st, free_func) SKM_sk_pop_free(X509_NAME, (st), (free_func))
+#define sk_X509_NAME_shift(st) SKM_sk_shift(X509_NAME, (st))
+#define sk_X509_NAME_pop(st) SKM_sk_pop(X509_NAME, (st))
+#define sk_X509_NAME_sort(st) SKM_sk_sort(X509_NAME, (st))
+#define sk_X509_NAME_is_sorted(st) SKM_sk_is_sorted(X509_NAME, (st))
+
+#define sk_X509_NAME_ENTRY_new(st) SKM_sk_new(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_new_null() SKM_sk_new_null(X509_NAME_ENTRY)
+#define sk_X509_NAME_ENTRY_free(st) SKM_sk_free(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_num(st) SKM_sk_num(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_value(st, i) SKM_sk_value(X509_NAME_ENTRY, (st), (i))
+#define sk_X509_NAME_ENTRY_set(st, i, val) SKM_sk_set(X509_NAME_ENTRY, (st), (i), (val))
+#define sk_X509_NAME_ENTRY_zero(st) SKM_sk_zero(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_push(st, val) SKM_sk_push(X509_NAME_ENTRY, (st), (val))
+#define sk_X509_NAME_ENTRY_unshift(st, val) SKM_sk_unshift(X509_NAME_ENTRY, (st), (val))
+#define sk_X509_NAME_ENTRY_find(st, val) SKM_sk_find(X509_NAME_ENTRY, (st), (val))
+#define sk_X509_NAME_ENTRY_find_ex(st, val) SKM_sk_find_ex(X509_NAME_ENTRY, (st), (val))
+#define sk_X509_NAME_ENTRY_delete(st, i) SKM_sk_delete(X509_NAME_ENTRY, (st), (i))
+#define sk_X509_NAME_ENTRY_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_NAME_ENTRY, (st), (ptr))
+#define sk_X509_NAME_ENTRY_insert(st, val, i) SKM_sk_insert(X509_NAME_ENTRY, (st), (val), (i))
+#define sk_X509_NAME_ENTRY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_NAME_ENTRY, (st), (cmp))
+#define sk_X509_NAME_ENTRY_dup(st) SKM_sk_dup(X509_NAME_ENTRY, st)
+#define sk_X509_NAME_ENTRY_pop_free(st, free_func) SKM_sk_pop_free(X509_NAME_ENTRY, (st), (free_func))
+#define sk_X509_NAME_ENTRY_shift(st) SKM_sk_shift(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_pop(st) SKM_sk_pop(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_sort(st) SKM_sk_sort(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_is_sorted(st) SKM_sk_is_sorted(X509_NAME_ENTRY, (st))
+
+#define sk_X509_OBJECT_new(st) SKM_sk_new(X509_OBJECT, (st))
+#define sk_X509_OBJECT_new_null() SKM_sk_new_null(X509_OBJECT)
+#define sk_X509_OBJECT_free(st) SKM_sk_free(X509_OBJECT, (st))
+#define sk_X509_OBJECT_num(st) SKM_sk_num(X509_OBJECT, (st))
+#define sk_X509_OBJECT_value(st, i) SKM_sk_value(X509_OBJECT, (st), (i))
+#define sk_X509_OBJECT_set(st, i, val) SKM_sk_set(X509_OBJECT, (st), (i), (val))
+#define sk_X509_OBJECT_zero(st) SKM_sk_zero(X509_OBJECT, (st))
+#define sk_X509_OBJECT_push(st, val) SKM_sk_push(X509_OBJECT, (st), (val))
+#define sk_X509_OBJECT_unshift(st, val) SKM_sk_unshift(X509_OBJECT, (st), (val))
+#define sk_X509_OBJECT_find(st, val) SKM_sk_find(X509_OBJECT, (st), (val))
+#define sk_X509_OBJECT_find_ex(st, val) SKM_sk_find_ex(X509_OBJECT, (st), (val))
+#define sk_X509_OBJECT_delete(st, i) SKM_sk_delete(X509_OBJECT, (st), (i))
+#define sk_X509_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_OBJECT, (st), (ptr))
+#define sk_X509_OBJECT_insert(st, val, i) SKM_sk_insert(X509_OBJECT, (st), (val), (i))
+#define sk_X509_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_OBJECT, (st), (cmp))
+#define sk_X509_OBJECT_dup(st) SKM_sk_dup(X509_OBJECT, st)
+#define sk_X509_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(X509_OBJECT, (st), (free_func))
+#define sk_X509_OBJECT_shift(st) SKM_sk_shift(X509_OBJECT, (st))
+#define sk_X509_OBJECT_pop(st) SKM_sk_pop(X509_OBJECT, (st))
+#define sk_X509_OBJECT_sort(st) SKM_sk_sort(X509_OBJECT, (st))
+#define sk_X509_OBJECT_is_sorted(st) SKM_sk_is_sorted(X509_OBJECT, (st))
+
+#define sk_X509_POLICY_DATA_new(st) SKM_sk_new(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_new_null() SKM_sk_new_null(X509_POLICY_DATA)
+#define sk_X509_POLICY_DATA_free(st) SKM_sk_free(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_num(st) SKM_sk_num(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_value(st, i) SKM_sk_value(X509_POLICY_DATA, (st), (i))
+#define sk_X509_POLICY_DATA_set(st, i, val) SKM_sk_set(X509_POLICY_DATA, (st), (i), (val))
+#define sk_X509_POLICY_DATA_zero(st) SKM_sk_zero(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_push(st, val) SKM_sk_push(X509_POLICY_DATA, (st), (val))
+#define sk_X509_POLICY_DATA_unshift(st, val) SKM_sk_unshift(X509_POLICY_DATA, (st), (val))
+#define sk_X509_POLICY_DATA_find(st, val) SKM_sk_find(X509_POLICY_DATA, (st), (val))
+#define sk_X509_POLICY_DATA_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_DATA, (st), (val))
+#define sk_X509_POLICY_DATA_delete(st, i) SKM_sk_delete(X509_POLICY_DATA, (st), (i))
+#define sk_X509_POLICY_DATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_DATA, (st), (ptr))
+#define sk_X509_POLICY_DATA_insert(st, val, i) SKM_sk_insert(X509_POLICY_DATA, (st), (val), (i))
+#define sk_X509_POLICY_DATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_DATA, (st), (cmp))
+#define sk_X509_POLICY_DATA_dup(st) SKM_sk_dup(X509_POLICY_DATA, st)
+#define sk_X509_POLICY_DATA_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_DATA, (st), (free_func))
+#define sk_X509_POLICY_DATA_shift(st) SKM_sk_shift(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_pop(st) SKM_sk_pop(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_sort(st) SKM_sk_sort(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_DATA, (st))
+
+#define sk_X509_POLICY_NODE_new(st) SKM_sk_new(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_new_null() SKM_sk_new_null(X509_POLICY_NODE)
+#define sk_X509_POLICY_NODE_free(st) SKM_sk_free(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_num(st) SKM_sk_num(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_value(st, i) SKM_sk_value(X509_POLICY_NODE, (st), (i))
+#define sk_X509_POLICY_NODE_set(st, i, val) SKM_sk_set(X509_POLICY_NODE, (st), (i), (val))
+#define sk_X509_POLICY_NODE_zero(st) SKM_sk_zero(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_push(st, val) SKM_sk_push(X509_POLICY_NODE, (st), (val))
+#define sk_X509_POLICY_NODE_unshift(st, val) SKM_sk_unshift(X509_POLICY_NODE, (st), (val))
+#define sk_X509_POLICY_NODE_find(st, val) SKM_sk_find(X509_POLICY_NODE, (st), (val))
+#define sk_X509_POLICY_NODE_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_NODE, (st), (val))
+#define sk_X509_POLICY_NODE_delete(st, i) SKM_sk_delete(X509_POLICY_NODE, (st), (i))
+#define sk_X509_POLICY_NODE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_NODE, (st), (ptr))
+#define sk_X509_POLICY_NODE_insert(st, val, i) SKM_sk_insert(X509_POLICY_NODE, (st), (val), (i))
+#define sk_X509_POLICY_NODE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_NODE, (st), (cmp))
+#define sk_X509_POLICY_NODE_dup(st) SKM_sk_dup(X509_POLICY_NODE, st)
+#define sk_X509_POLICY_NODE_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_NODE, (st), (free_func))
+#define sk_X509_POLICY_NODE_shift(st) SKM_sk_shift(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_pop(st) SKM_sk_pop(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_sort(st) SKM_sk_sort(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_NODE, (st))
+
+#define sk_X509_POLICY_REF_new(st) SKM_sk_new(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_new_null() SKM_sk_new_null(X509_POLICY_REF)
+#define sk_X509_POLICY_REF_free(st) SKM_sk_free(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_num(st) SKM_sk_num(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_value(st, i) SKM_sk_value(X509_POLICY_REF, (st), (i))
+#define sk_X509_POLICY_REF_set(st, i, val) SKM_sk_set(X509_POLICY_REF, (st), (i), (val))
+#define sk_X509_POLICY_REF_zero(st) SKM_sk_zero(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_push(st, val) SKM_sk_push(X509_POLICY_REF, (st), (val))
+#define sk_X509_POLICY_REF_unshift(st, val) SKM_sk_unshift(X509_POLICY_REF, (st), (val))
+#define sk_X509_POLICY_REF_find(st, val) SKM_sk_find(X509_POLICY_REF, (st), (val))
+#define sk_X509_POLICY_REF_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_REF, (st), (val))
+#define sk_X509_POLICY_REF_delete(st, i) SKM_sk_delete(X509_POLICY_REF, (st), (i))
+#define sk_X509_POLICY_REF_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_REF, (st), (ptr))
+#define sk_X509_POLICY_REF_insert(st, val, i) SKM_sk_insert(X509_POLICY_REF, (st), (val), (i))
+#define sk_X509_POLICY_REF_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_REF, (st), (cmp))
+#define sk_X509_POLICY_REF_dup(st) SKM_sk_dup(X509_POLICY_REF, st)
+#define sk_X509_POLICY_REF_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_REF, (st), (free_func))
+#define sk_X509_POLICY_REF_shift(st) SKM_sk_shift(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_pop(st) SKM_sk_pop(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_sort(st) SKM_sk_sort(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_REF, (st))
+
+#define sk_X509_PURPOSE_new(st) SKM_sk_new(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_new_null() SKM_sk_new_null(X509_PURPOSE)
+#define sk_X509_PURPOSE_free(st) SKM_sk_free(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_num(st) SKM_sk_num(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_value(st, i) SKM_sk_value(X509_PURPOSE, (st), (i))
+#define sk_X509_PURPOSE_set(st, i, val) SKM_sk_set(X509_PURPOSE, (st), (i), (val))
+#define sk_X509_PURPOSE_zero(st) SKM_sk_zero(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_push(st, val) SKM_sk_push(X509_PURPOSE, (st), (val))
+#define sk_X509_PURPOSE_unshift(st, val) SKM_sk_unshift(X509_PURPOSE, (st), (val))
+#define sk_X509_PURPOSE_find(st, val) SKM_sk_find(X509_PURPOSE, (st), (val))
+#define sk_X509_PURPOSE_find_ex(st, val) SKM_sk_find_ex(X509_PURPOSE, (st), (val))
+#define sk_X509_PURPOSE_delete(st, i) SKM_sk_delete(X509_PURPOSE, (st), (i))
+#define sk_X509_PURPOSE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_PURPOSE, (st), (ptr))
+#define sk_X509_PURPOSE_insert(st, val, i) SKM_sk_insert(X509_PURPOSE, (st), (val), (i))
+#define sk_X509_PURPOSE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_PURPOSE, (st), (cmp))
+#define sk_X509_PURPOSE_dup(st) SKM_sk_dup(X509_PURPOSE, st)
+#define sk_X509_PURPOSE_pop_free(st, free_func) SKM_sk_pop_free(X509_PURPOSE, (st), (free_func))
+#define sk_X509_PURPOSE_shift(st) SKM_sk_shift(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_pop(st) SKM_sk_pop(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_sort(st) SKM_sk_sort(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_is_sorted(st) SKM_sk_is_sorted(X509_PURPOSE, (st))
+
+#define sk_X509_REVOKED_new(st) SKM_sk_new(X509_REVOKED, (st))
+#define sk_X509_REVOKED_new_null() SKM_sk_new_null(X509_REVOKED)
+#define sk_X509_REVOKED_free(st) SKM_sk_free(X509_REVOKED, (st))
+#define sk_X509_REVOKED_num(st) SKM_sk_num(X509_REVOKED, (st))
+#define sk_X509_REVOKED_value(st, i) SKM_sk_value(X509_REVOKED, (st), (i))
+#define sk_X509_REVOKED_set(st, i, val) SKM_sk_set(X509_REVOKED, (st), (i), (val))
+#define sk_X509_REVOKED_zero(st) SKM_sk_zero(X509_REVOKED, (st))
+#define sk_X509_REVOKED_push(st, val) SKM_sk_push(X509_REVOKED, (st), (val))
+#define sk_X509_REVOKED_unshift(st, val) SKM_sk_unshift(X509_REVOKED, (st), (val))
+#define sk_X509_REVOKED_find(st, val) SKM_sk_find(X509_REVOKED, (st), (val))
+#define sk_X509_REVOKED_find_ex(st, val) SKM_sk_find_ex(X509_REVOKED, (st), (val))
+#define sk_X509_REVOKED_delete(st, i) SKM_sk_delete(X509_REVOKED, (st), (i))
+#define sk_X509_REVOKED_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_REVOKED, (st), (ptr))
+#define sk_X509_REVOKED_insert(st, val, i) SKM_sk_insert(X509_REVOKED, (st), (val), (i))
+#define sk_X509_REVOKED_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_REVOKED, (st), (cmp))
+#define sk_X509_REVOKED_dup(st) SKM_sk_dup(X509_REVOKED, st)
+#define sk_X509_REVOKED_pop_free(st, free_func) SKM_sk_pop_free(X509_REVOKED, (st), (free_func))
+#define sk_X509_REVOKED_shift(st) SKM_sk_shift(X509_REVOKED, (st))
+#define sk_X509_REVOKED_pop(st) SKM_sk_pop(X509_REVOKED, (st))
+#define sk_X509_REVOKED_sort(st) SKM_sk_sort(X509_REVOKED, (st))
+#define sk_X509_REVOKED_is_sorted(st) SKM_sk_is_sorted(X509_REVOKED, (st))
+
+#define sk_X509_TRUST_new(st) SKM_sk_new(X509_TRUST, (st))
+#define sk_X509_TRUST_new_null() SKM_sk_new_null(X509_TRUST)
+#define sk_X509_TRUST_free(st) SKM_sk_free(X509_TRUST, (st))
+#define sk_X509_TRUST_num(st) SKM_sk_num(X509_TRUST, (st))
+#define sk_X509_TRUST_value(st, i) SKM_sk_value(X509_TRUST, (st), (i))
+#define sk_X509_TRUST_set(st, i, val) SKM_sk_set(X509_TRUST, (st), (i), (val))
+#define sk_X509_TRUST_zero(st) SKM_sk_zero(X509_TRUST, (st))
+#define sk_X509_TRUST_push(st, val) SKM_sk_push(X509_TRUST, (st), (val))
+#define sk_X509_TRUST_unshift(st, val) SKM_sk_unshift(X509_TRUST, (st), (val))
+#define sk_X509_TRUST_find(st, val) SKM_sk_find(X509_TRUST, (st), (val))
+#define sk_X509_TRUST_find_ex(st, val) SKM_sk_find_ex(X509_TRUST, (st), (val))
+#define sk_X509_TRUST_delete(st, i) SKM_sk_delete(X509_TRUST, (st), (i))
+#define sk_X509_TRUST_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_TRUST, (st), (ptr))
+#define sk_X509_TRUST_insert(st, val, i) SKM_sk_insert(X509_TRUST, (st), (val), (i))
+#define sk_X509_TRUST_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_TRUST, (st), (cmp))
+#define sk_X509_TRUST_dup(st) SKM_sk_dup(X509_TRUST, st)
+#define sk_X509_TRUST_pop_free(st, free_func) SKM_sk_pop_free(X509_TRUST, (st), (free_func))
+#define sk_X509_TRUST_shift(st) SKM_sk_shift(X509_TRUST, (st))
+#define sk_X509_TRUST_pop(st) SKM_sk_pop(X509_TRUST, (st))
+#define sk_X509_TRUST_sort(st) SKM_sk_sort(X509_TRUST, (st))
+#define sk_X509_TRUST_is_sorted(st) SKM_sk_is_sorted(X509_TRUST, (st))
+
+#define sk_X509_VERIFY_PARAM_new(st) SKM_sk_new(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_new_null() SKM_sk_new_null(X509_VERIFY_PARAM)
+#define sk_X509_VERIFY_PARAM_free(st) SKM_sk_free(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_num(st) SKM_sk_num(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_value(st, i) SKM_sk_value(X509_VERIFY_PARAM, (st), (i))
+#define sk_X509_VERIFY_PARAM_set(st, i, val) SKM_sk_set(X509_VERIFY_PARAM, (st), (i), (val))
+#define sk_X509_VERIFY_PARAM_zero(st) SKM_sk_zero(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_push(st, val) SKM_sk_push(X509_VERIFY_PARAM, (st), (val))
+#define sk_X509_VERIFY_PARAM_unshift(st, val) SKM_sk_unshift(X509_VERIFY_PARAM, (st), (val))
+#define sk_X509_VERIFY_PARAM_find(st, val) SKM_sk_find(X509_VERIFY_PARAM, (st), (val))
+#define sk_X509_VERIFY_PARAM_find_ex(st, val) SKM_sk_find_ex(X509_VERIFY_PARAM, (st), (val))
+#define sk_X509_VERIFY_PARAM_delete(st, i) SKM_sk_delete(X509_VERIFY_PARAM, (st), (i))
+#define sk_X509_VERIFY_PARAM_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_VERIFY_PARAM, (st), (ptr))
+#define sk_X509_VERIFY_PARAM_insert(st, val, i) SKM_sk_insert(X509_VERIFY_PARAM, (st), (val), (i))
+#define sk_X509_VERIFY_PARAM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_VERIFY_PARAM, (st), (cmp))
+#define sk_X509_VERIFY_PARAM_dup(st) SKM_sk_dup(X509_VERIFY_PARAM, st)
+#define sk_X509_VERIFY_PARAM_pop_free(st, free_func) SKM_sk_pop_free(X509_VERIFY_PARAM, (st), (free_func))
+#define sk_X509_VERIFY_PARAM_shift(st) SKM_sk_shift(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_pop(st) SKM_sk_pop(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_sort(st) SKM_sk_sort(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_is_sorted(st) SKM_sk_is_sorted(X509_VERIFY_PARAM, (st))
+
+#define d2i_ASN1_SET_OF_ACCESS_DESCRIPTION(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(ACCESS_DESCRIPTION, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_ACCESS_DESCRIPTION(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(ACCESS_DESCRIPTION, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_ACCESS_DESCRIPTION(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(ACCESS_DESCRIPTION, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_ACCESS_DESCRIPTION(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(ACCESS_DESCRIPTION, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_ASN1_INTEGER(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(ASN1_INTEGER, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_ASN1_INTEGER(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(ASN1_INTEGER, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_ASN1_INTEGER(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(ASN1_INTEGER, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_ASN1_INTEGER(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(ASN1_INTEGER, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_ASN1_OBJECT(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(ASN1_OBJECT, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_ASN1_OBJECT(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(ASN1_OBJECT, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_ASN1_OBJECT(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(ASN1_OBJECT, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_ASN1_OBJECT(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(ASN1_OBJECT, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_ASN1_TYPE(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(ASN1_TYPE, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_ASN1_TYPE(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(ASN1_TYPE, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_ASN1_TYPE(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(ASN1_TYPE, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_ASN1_TYPE(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(ASN1_TYPE, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_DIST_POINT(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(DIST_POINT, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_DIST_POINT(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(DIST_POINT, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_DIST_POINT(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(DIST_POINT, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_DIST_POINT(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(DIST_POINT, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_GENERAL_NAME(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(GENERAL_NAME, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_GENERAL_NAME(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(GENERAL_NAME, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_GENERAL_NAME(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(GENERAL_NAME, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_GENERAL_NAME(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(GENERAL_NAME, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_OCSP_ONEREQ(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(OCSP_ONEREQ, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_OCSP_ONEREQ(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(OCSP_ONEREQ, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_OCSP_ONEREQ(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(OCSP_ONEREQ, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_OCSP_ONEREQ(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(OCSP_ONEREQ, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_OCSP_SINGLERESP(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(OCSP_SINGLERESP, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_OCSP_SINGLERESP(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(OCSP_SINGLERESP, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_OCSP_SINGLERESP(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(OCSP_SINGLERESP, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_OCSP_SINGLERESP(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(OCSP_SINGLERESP, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_PKCS12_SAFEBAG(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(PKCS12_SAFEBAG, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_PKCS12_SAFEBAG(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(PKCS12_SAFEBAG, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_PKCS12_SAFEBAG(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(PKCS12_SAFEBAG, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_PKCS12_SAFEBAG(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(PKCS12_SAFEBAG, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_PKCS7(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(PKCS7, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_PKCS7(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(PKCS7, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_PKCS7(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(PKCS7, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_PKCS7(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(PKCS7, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_PKCS7_RECIP_INFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(PKCS7_RECIP_INFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_PKCS7_RECIP_INFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(PKCS7_RECIP_INFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_PKCS7_RECIP_INFO(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(PKCS7_RECIP_INFO, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_PKCS7_RECIP_INFO(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(PKCS7_RECIP_INFO, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_PKCS7_SIGNER_INFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(PKCS7_SIGNER_INFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_PKCS7_SIGNER_INFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(PKCS7_SIGNER_INFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_PKCS7_SIGNER_INFO(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(PKCS7_SIGNER_INFO, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_PKCS7_SIGNER_INFO(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(PKCS7_SIGNER_INFO, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_POLICYINFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(POLICYINFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_POLICYINFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(POLICYINFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_POLICYINFO(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(POLICYINFO, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_POLICYINFO(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(POLICYINFO, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_POLICYQUALINFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(POLICYQUALINFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_POLICYQUALINFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(POLICYQUALINFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_POLICYQUALINFO(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(POLICYQUALINFO, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_POLICYQUALINFO(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(POLICYQUALINFO, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_SXNETID(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(SXNETID, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_SXNETID(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(SXNETID, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_SXNETID(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(SXNETID, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_SXNETID(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(SXNETID, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(X509, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_X509(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(X509, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(X509, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(X509, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_ALGOR(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(X509_ALGOR, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_X509_ALGOR(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(X509_ALGOR, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_ALGOR(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(X509_ALGOR, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_ALGOR(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(X509_ALGOR, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_ATTRIBUTE(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(X509_ATTRIBUTE, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_X509_ATTRIBUTE(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(X509_ATTRIBUTE, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_ATTRIBUTE(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(X509_ATTRIBUTE, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_ATTRIBUTE(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(X509_ATTRIBUTE, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_CRL(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(X509_CRL, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_X509_CRL(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(X509_CRL, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_CRL(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(X509_CRL, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_CRL(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(X509_CRL, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_EXTENSION(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(X509_EXTENSION, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_X509_EXTENSION(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(X509_EXTENSION, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_EXTENSION(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(X509_EXTENSION, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_EXTENSION(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(X509_EXTENSION, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_NAME_ENTRY(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(X509_NAME_ENTRY, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_X509_NAME_ENTRY(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(X509_NAME_ENTRY, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_NAME_ENTRY(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(X509_NAME_ENTRY, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_NAME_ENTRY(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(X509_NAME_ENTRY, (buf), (len), (d2i_func), (free_func))
+
+#define d2i_ASN1_SET_OF_X509_REVOKED(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
+ SKM_ASN1_SET_OF_d2i(X509_REVOKED, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class))
+#define i2d_ASN1_SET_OF_X509_REVOKED(st, pp, i2d_func, ex_tag, ex_class, is_set) \
+ SKM_ASN1_SET_OF_i2d(X509_REVOKED, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set))
+#define ASN1_seq_pack_X509_REVOKED(st, i2d_func, buf, len) \
+ SKM_ASN1_seq_pack(X509_REVOKED, (st), (i2d_func), (buf), (len))
+#define ASN1_seq_unpack_X509_REVOKED(buf, len, d2i_func, free_func) \
+ SKM_ASN1_seq_unpack(X509_REVOKED, (buf), (len), (d2i_func), (free_func))
+
+#define PKCS12_decrypt_d2i_PKCS12_SAFEBAG(algor, d2i_func, free_func, pass, passlen, oct, seq) \
+ SKM_PKCS12_decrypt_d2i(PKCS12_SAFEBAG, (algor), (d2i_func), (free_func), (pass), (passlen), (oct), (seq))
+
+#define PKCS12_decrypt_d2i_PKCS7(algor, d2i_func, free_func, pass, passlen, oct, seq) \
+ SKM_PKCS12_decrypt_d2i(PKCS7, (algor), (d2i_func), (free_func), (pass), (passlen), (oct), (seq))
+/* End of util/mkstack.pl block, you may now edit :-) */
+
+#endif /* !defined HEADER_SAFESTACK_H */
diff --git a/src/Mayaqua/win32_inc/openssl/sha.h b/src/Mayaqua/win32_inc/openssl/sha.h
new file mode 100644
index 00000000..3e9bde9a
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/sha.h
@@ -0,0 +1,203 @@
+/* crypto/sha/sha.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_SHA_H
+#define HEADER_SHA_H
+
+#include <openssl/e_os2.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(OPENSSL_NO_SHA) || (defined(OPENSSL_NO_SHA0) && defined(OPENSSL_NO_SHA1))
+#error SHA is disabled.
+#endif
+
+#if defined(OPENSSL_FIPS)
+#define FIPS_SHA_SIZE_T size_t
+#endif
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! SHA_LONG_LOG2 has to be defined along. !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define SHA_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define SHA_LONG unsigned long
+#define SHA_LONG_LOG2 3
+#else
+#define SHA_LONG unsigned int
+#endif
+
+#define SHA_LBLOCK 16
+#define SHA_CBLOCK (SHA_LBLOCK*4) /* SHA treats input data as a
+ * contiguous array of 32 bit
+ * wide big-endian values. */
+#define SHA_LAST_BLOCK (SHA_CBLOCK-8)
+#define SHA_DIGEST_LENGTH 20
+
+typedef struct SHAstate_st
+ {
+ SHA_LONG h0,h1,h2,h3,h4;
+ SHA_LONG Nl,Nh;
+ SHA_LONG data[SHA_LBLOCK];
+ unsigned int num;
+ } SHA_CTX;
+
+#ifndef OPENSSL_NO_SHA0
+#ifdef OPENSSL_FIPS
+int private_SHA_Init(SHA_CTX *c);
+#endif
+int SHA_Init(SHA_CTX *c);
+int SHA_Update(SHA_CTX *c, const void *data, size_t len);
+int SHA_Final(unsigned char *md, SHA_CTX *c);
+unsigned char *SHA(const unsigned char *d, size_t n, unsigned char *md);
+void SHA_Transform(SHA_CTX *c, const unsigned char *data);
+#endif
+#ifndef OPENSSL_NO_SHA1
+int SHA1_Init(SHA_CTX *c);
+int SHA1_Update(SHA_CTX *c, const void *data, size_t len);
+int SHA1_Final(unsigned char *md, SHA_CTX *c);
+unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md);
+void SHA1_Transform(SHA_CTX *c, const unsigned char *data);
+#endif
+
+#define SHA256_CBLOCK (SHA_LBLOCK*4) /* SHA-256 treats input data as a
+ * contiguous array of 32 bit
+ * wide big-endian values. */
+#define SHA224_DIGEST_LENGTH 28
+#define SHA256_DIGEST_LENGTH 32
+
+typedef struct SHA256state_st
+ {
+ SHA_LONG h[8];
+ SHA_LONG Nl,Nh;
+ SHA_LONG data[SHA_LBLOCK];
+ unsigned int num,md_len;
+ } SHA256_CTX;
+
+#ifndef OPENSSL_NO_SHA256
+int SHA224_Init(SHA256_CTX *c);
+int SHA224_Update(SHA256_CTX *c, const void *data, size_t len);
+int SHA224_Final(unsigned char *md, SHA256_CTX *c);
+unsigned char *SHA224(const unsigned char *d, size_t n,unsigned char *md);
+int SHA256_Init(SHA256_CTX *c);
+int SHA256_Update(SHA256_CTX *c, const void *data, size_t len);
+int SHA256_Final(unsigned char *md, SHA256_CTX *c);
+unsigned char *SHA256(const unsigned char *d, size_t n,unsigned char *md);
+void SHA256_Transform(SHA256_CTX *c, const unsigned char *data);
+#endif
+
+#define SHA384_DIGEST_LENGTH 48
+#define SHA512_DIGEST_LENGTH 64
+
+#ifndef OPENSSL_NO_SHA512
+/*
+ * Unlike 32-bit digest algorithms, SHA-512 *relies* on SHA_LONG64
+ * being exactly 64-bit wide. See Implementation Notes in sha512.c
+ * for further details.
+ */
+#define SHA512_CBLOCK (SHA_LBLOCK*8) /* SHA-512 treats input data as a
+ * contiguous array of 64 bit
+ * wide big-endian values. */
+#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
+#define SHA_LONG64 unsigned __int64
+#define U64(C) C##UI64
+#elif defined(__arch64__)
+#define SHA_LONG64 unsigned long
+#define U64(C) C##UL
+#else
+#define SHA_LONG64 unsigned long long
+#define U64(C) C##ULL
+#endif
+
+typedef struct SHA512state_st
+ {
+ SHA_LONG64 h[8];
+ SHA_LONG64 Nl,Nh;
+ union {
+ SHA_LONG64 d[SHA_LBLOCK];
+ unsigned char p[SHA512_CBLOCK];
+ } u;
+ unsigned int num,md_len;
+ } SHA512_CTX;
+#endif
+
+#ifndef OPENSSL_NO_SHA512
+int SHA384_Init(SHA512_CTX *c);
+int SHA384_Update(SHA512_CTX *c, const void *data, size_t len);
+int SHA384_Final(unsigned char *md, SHA512_CTX *c);
+unsigned char *SHA384(const unsigned char *d, size_t n,unsigned char *md);
+int SHA512_Init(SHA512_CTX *c);
+int SHA512_Update(SHA512_CTX *c, const void *data, size_t len);
+int SHA512_Final(unsigned char *md, SHA512_CTX *c);
+unsigned char *SHA512(const unsigned char *d, size_t n,unsigned char *md);
+void SHA512_Transform(SHA512_CTX *c, const unsigned char *data);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ssl.h b/src/Mayaqua/win32_inc/openssl/ssl.h
new file mode 100644
index 00000000..5071fdd8
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ssl.h
@@ -0,0 +1,2125 @@
+/* ssl/ssl.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_SSL_H
+#define HEADER_SSL_H
+
+#include <openssl/e_os2.h>
+
+#ifndef OPENSSL_NO_COMP
+#include <openssl/comp.h>
+#endif
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#ifndef OPENSSL_NO_DEPRECATED
+#ifndef OPENSSL_NO_X509
+#include <openssl/x509.h>
+#endif
+#include <openssl/crypto.h>
+#include <openssl/lhash.h>
+#include <openssl/buffer.h>
+#endif
+#include <openssl/pem.h>
+#include <openssl/hmac.h>
+
+#include <openssl/kssl.h>
+#include <openssl/safestack.h>
+#include <openssl/symhacks.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* SSLeay version number for ASN.1 encoding of the session information */
+/* Version 0 - initial version
+ * Version 1 - added the optional peer certificate
+ */
+#define SSL_SESSION_ASN1_VERSION 0x0001
+
+/* text strings for the ciphers */
+#define SSL_TXT_NULL_WITH_MD5 SSL2_TXT_NULL_WITH_MD5
+#define SSL_TXT_RC4_128_WITH_MD5 SSL2_TXT_RC4_128_WITH_MD5
+#define SSL_TXT_RC4_128_EXPORT40_WITH_MD5 SSL2_TXT_RC4_128_EXPORT40_WITH_MD5
+#define SSL_TXT_RC2_128_CBC_WITH_MD5 SSL2_TXT_RC2_128_CBC_WITH_MD5
+#define SSL_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5
+#define SSL_TXT_IDEA_128_CBC_WITH_MD5 SSL2_TXT_IDEA_128_CBC_WITH_MD5
+#define SSL_TXT_DES_64_CBC_WITH_MD5 SSL2_TXT_DES_64_CBC_WITH_MD5
+#define SSL_TXT_DES_64_CBC_WITH_SHA SSL2_TXT_DES_64_CBC_WITH_SHA
+#define SSL_TXT_DES_192_EDE3_CBC_WITH_MD5 SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5
+#define SSL_TXT_DES_192_EDE3_CBC_WITH_SHA SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA
+
+/* VRS Additional Kerberos5 entries
+ */
+#define SSL_TXT_KRB5_DES_64_CBC_SHA SSL3_TXT_KRB5_DES_64_CBC_SHA
+#define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA
+#define SSL_TXT_KRB5_RC4_128_SHA SSL3_TXT_KRB5_RC4_128_SHA
+#define SSL_TXT_KRB5_IDEA_128_CBC_SHA SSL3_TXT_KRB5_IDEA_128_CBC_SHA
+#define SSL_TXT_KRB5_DES_64_CBC_MD5 SSL3_TXT_KRB5_DES_64_CBC_MD5
+#define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5
+#define SSL_TXT_KRB5_RC4_128_MD5 SSL3_TXT_KRB5_RC4_128_MD5
+#define SSL_TXT_KRB5_IDEA_128_CBC_MD5 SSL3_TXT_KRB5_IDEA_128_CBC_MD5
+
+#define SSL_TXT_KRB5_DES_40_CBC_SHA SSL3_TXT_KRB5_DES_40_CBC_SHA
+#define SSL_TXT_KRB5_RC2_40_CBC_SHA SSL3_TXT_KRB5_RC2_40_CBC_SHA
+#define SSL_TXT_KRB5_RC4_40_SHA SSL3_TXT_KRB5_RC4_40_SHA
+#define SSL_TXT_KRB5_DES_40_CBC_MD5 SSL3_TXT_KRB5_DES_40_CBC_MD5
+#define SSL_TXT_KRB5_RC2_40_CBC_MD5 SSL3_TXT_KRB5_RC2_40_CBC_MD5
+#define SSL_TXT_KRB5_RC4_40_MD5 SSL3_TXT_KRB5_RC4_40_MD5
+
+#define SSL_TXT_KRB5_DES_40_CBC_SHA SSL3_TXT_KRB5_DES_40_CBC_SHA
+#define SSL_TXT_KRB5_DES_40_CBC_MD5 SSL3_TXT_KRB5_DES_40_CBC_MD5
+#define SSL_TXT_KRB5_DES_64_CBC_SHA SSL3_TXT_KRB5_DES_64_CBC_SHA
+#define SSL_TXT_KRB5_DES_64_CBC_MD5 SSL3_TXT_KRB5_DES_64_CBC_MD5
+#define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA
+#define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5
+#define SSL_MAX_KRB5_PRINCIPAL_LENGTH 256
+
+#define SSL_MAX_SSL_SESSION_ID_LENGTH 32
+#define SSL_MAX_SID_CTX_LENGTH 32
+
+#define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES (512/8)
+#define SSL_MAX_KEY_ARG_LENGTH 8
+#define SSL_MAX_MASTER_KEY_LENGTH 48
+
+/* These are used to specify which ciphers to use and not to use */
+#define SSL_TXT_LOW "LOW"
+#define SSL_TXT_MEDIUM "MEDIUM"
+#define SSL_TXT_HIGH "HIGH"
+#define SSL_TXT_FIPS "FIPS"
+#define SSL_TXT_kFZA "kFZA"
+#define SSL_TXT_aFZA "aFZA"
+#define SSL_TXT_eFZA "eFZA"
+#define SSL_TXT_FZA "FZA"
+
+#define SSL_TXT_aNULL "aNULL"
+#define SSL_TXT_eNULL "eNULL"
+#define SSL_TXT_NULL "NULL"
+
+#define SSL_TXT_kKRB5 "kKRB5"
+#define SSL_TXT_aKRB5 "aKRB5"
+#define SSL_TXT_KRB5 "KRB5"
+
+#define SSL_TXT_kRSA "kRSA"
+#define SSL_TXT_kDHr "kDHr"
+#define SSL_TXT_kDHd "kDHd"
+#define SSL_TXT_kEDH "kEDH"
+#define SSL_TXT_aRSA "aRSA"
+#define SSL_TXT_aDSS "aDSS"
+#define SSL_TXT_aDH "aDH"
+#define SSL_TXT_DSS "DSS"
+#define SSL_TXT_DH "DH"
+#define SSL_TXT_EDH "EDH"
+#define SSL_TXT_ADH "ADH"
+#define SSL_TXT_RSA "RSA"
+#define SSL_TXT_DES "DES"
+#define SSL_TXT_3DES "3DES"
+#define SSL_TXT_RC4 "RC4"
+#define SSL_TXT_RC2 "RC2"
+#define SSL_TXT_IDEA "IDEA"
+#define SSL_TXT_SEED "SEED"
+#define SSL_TXT_AES "AES"
+#define SSL_TXT_CAMELLIA "CAMELLIA"
+#define SSL_TXT_MD5 "MD5"
+#define SSL_TXT_SHA1 "SHA1"
+#define SSL_TXT_SHA "SHA"
+#define SSL_TXT_EXP "EXP"
+#define SSL_TXT_EXPORT "EXPORT"
+#define SSL_TXT_EXP40 "EXPORT40"
+#define SSL_TXT_EXP56 "EXPORT56"
+#define SSL_TXT_SSLV2 "SSLv2"
+#define SSL_TXT_SSLV3 "SSLv3"
+#define SSL_TXT_TLSV1 "TLSv1"
+#define SSL_TXT_ALL "ALL"
+#define SSL_TXT_ECC "ECCdraft" /* ECC ciphersuites are not yet official */
+
+/*
+ * COMPLEMENTOF* definitions. These identifiers are used to (de-select)
+ * ciphers normally not being used.
+ * Example: "RC4" will activate all ciphers using RC4 including ciphers
+ * without authentication, which would normally disabled by DEFAULT (due
+ * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT"
+ * will make sure that it is also disabled in the specific selection.
+ * COMPLEMENTOF* identifiers are portable between version, as adjustments
+ * to the default cipher setup will also be included here.
+ *
+ * COMPLEMENTOFDEFAULT does not experience the same special treatment that
+ * DEFAULT gets, as only selection is being done and no sorting as needed
+ * for DEFAULT.
+ */
+#define SSL_TXT_CMPALL "COMPLEMENTOFALL"
+#define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT"
+
+/* The following cipher list is used by default.
+ * It also is substituted when an application-defined cipher list string
+ * starts with 'DEFAULT'. */
+#define SSL_DEFAULT_CIPHER_LIST "AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH" /* low priority for RC4 */
+
+/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
+#define SSL_SENT_SHUTDOWN 1
+#define SSL_RECEIVED_SHUTDOWN 2
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (defined(OPENSSL_NO_RSA) || defined(OPENSSL_NO_MD5)) && !defined(OPENSSL_NO_SSL2)
+#define OPENSSL_NO_SSL2
+#endif
+
+#define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1
+#define SSL_FILETYPE_PEM X509_FILETYPE_PEM
+
+/* This is needed to stop compilers complaining about the
+ * 'struct ssl_st *' function parameters used to prototype callbacks
+ * in SSL_CTX. */
+typedef struct ssl_st *ssl_crock_st;
+
+/* used to hold info on the particular ciphers used */
+typedef struct ssl_cipher_st
+ {
+ int valid;
+ const char *name; /* text name */
+ unsigned long id; /* id, 4 bytes, first is version */
+ unsigned long algorithms; /* what ciphers are used */
+ unsigned long algo_strength; /* strength and export flags */
+ unsigned long algorithm2; /* Extra flags */
+ int strength_bits; /* Number of bits really used */
+ int alg_bits; /* Number of bits for algorithm */
+ unsigned long mask; /* used for matching */
+ unsigned long mask_strength; /* also used for matching */
+ } SSL_CIPHER;
+
+DECLARE_STACK_OF(SSL_CIPHER)
+
+/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
+typedef struct ssl_method_st
+ {
+ int version;
+ int (*ssl_new)(SSL *s);
+ void (*ssl_clear)(SSL *s);
+ void (*ssl_free)(SSL *s);
+ int (*ssl_accept)(SSL *s);
+ int (*ssl_connect)(SSL *s);
+ int (*ssl_read)(SSL *s,void *buf,int len);
+ int (*ssl_peek)(SSL *s,void *buf,int len);
+ int (*ssl_write)(SSL *s,const void *buf,int len);
+ int (*ssl_shutdown)(SSL *s);
+ int (*ssl_renegotiate)(SSL *s);
+ int (*ssl_renegotiate_check)(SSL *s);
+ long (*ssl_get_message)(SSL *s, int st1, int stn, int mt, long
+ max, int *ok);
+ int (*ssl_read_bytes)(SSL *s, int type, unsigned char *buf, int len,
+ int peek);
+ int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len);
+ int (*ssl_dispatch_alert)(SSL *s);
+ long (*ssl_ctrl)(SSL *s,int cmd,long larg,void *parg);
+ long (*ssl_ctx_ctrl)(SSL_CTX *ctx,int cmd,long larg,void *parg);
+ SSL_CIPHER *(*get_cipher_by_char)(const unsigned char *ptr);
+ int (*put_cipher_by_char)(const SSL_CIPHER *cipher,unsigned char *ptr);
+ int (*ssl_pending)(const SSL *s);
+ int (*num_ciphers)(void);
+ SSL_CIPHER *(*get_cipher)(unsigned ncipher);
+ struct ssl_method_st *(*get_ssl_method)(int version);
+ long (*get_timeout)(void);
+ struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */
+ int (*ssl_version)(void);
+ long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void));
+ long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void));
+ } SSL_METHOD;
+
+/* Lets make this into an ASN.1 type structure as follows
+ * SSL_SESSION_ID ::= SEQUENCE {
+ * version INTEGER, -- structure version number
+ * SSLversion INTEGER, -- SSL version number
+ * Cipher OCTET_STRING, -- the 3 byte cipher ID
+ * Session_ID OCTET_STRING, -- the Session ID
+ * Master_key OCTET_STRING, -- the master key
+ * KRB5_principal OCTET_STRING -- optional Kerberos principal
+ * Key_Arg [ 0 ] IMPLICIT OCTET_STRING, -- the optional Key argument
+ * Time [ 1 ] EXPLICIT INTEGER, -- optional Start Time
+ * Timeout [ 2 ] EXPLICIT INTEGER, -- optional Timeout ins seconds
+ * Peer [ 3 ] EXPLICIT X509, -- optional Peer Certificate
+ * Session_ID_context [ 4 ] EXPLICIT OCTET_STRING, -- the Session ID context
+ * Verify_result [ 5 ] EXPLICIT INTEGER -- X509_V_... code for `Peer'
+ * Compression [6] IMPLICIT ASN1_OBJECT -- compression OID XXXXX
+ * }
+ * Look in ssl/ssl_asn1.c for more details
+ * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-).
+ */
+typedef struct ssl_session_st
+ {
+ int ssl_version; /* what ssl version session info is
+ * being kept in here? */
+
+ /* only really used in SSLv2 */
+ unsigned int key_arg_length;
+ unsigned char key_arg[SSL_MAX_KEY_ARG_LENGTH];
+ int master_key_length;
+ unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
+ /* session_id - valid? */
+ unsigned int session_id_length;
+ unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
+ /* this is used to determine whether the session is being reused in
+ * the appropriate context. It is up to the application to set this,
+ * via SSL_new */
+ unsigned int sid_ctx_length;
+ unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+
+#ifndef OPENSSL_NO_KRB5
+ unsigned int krb5_client_princ_len;
+ unsigned char krb5_client_princ[SSL_MAX_KRB5_PRINCIPAL_LENGTH];
+#endif /* OPENSSL_NO_KRB5 */
+
+ int not_resumable;
+
+ /* The cert is the certificate used to establish this connection */
+ struct sess_cert_st /* SESS_CERT */ *sess_cert;
+
+ /* This is the cert for the other end.
+ * On clients, it will be the same as sess_cert->peer_key->x509
+ * (the latter is not enough as sess_cert is not retained
+ * in the external representation of sessions, see ssl_asn1.c). */
+ X509 *peer;
+ /* when app_verify_callback accepts a session where the peer's certificate
+ * is not ok, we must remember the error for session reuse: */
+ long verify_result; /* only for servers */
+
+ int references;
+ long timeout;
+ long time;
+
+ int compress_meth; /* Need to lookup the method */
+
+ SSL_CIPHER *cipher;
+ unsigned long cipher_id; /* when ASN.1 loaded, this
+ * needs to be used to load
+ * the 'cipher' structure */
+
+ STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */
+
+ CRYPTO_EX_DATA ex_data; /* application specific data */
+
+ /* These are used to make removal of session-ids more
+ * efficient and to implement a maximum cache size. */
+ struct ssl_session_st *prev,*next;
+#ifndef OPENSSL_NO_TLSEXT
+ char *tlsext_hostname;
+ /* RFC4507 info */
+ unsigned char *tlsext_tick; /* Session ticket */
+ size_t tlsext_ticklen; /* Session ticket length */
+ long tlsext_tick_lifetime_hint; /* Session lifetime hint in seconds */
+#endif
+ } SSL_SESSION;
+
+
+#define SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001L
+#define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002L
+/* Allow initial connection to servers that don't support RI */
+#define SSL_OP_LEGACY_SERVER_CONNECT 0x00000004L
+#define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008L
+#define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x00000010L
+#define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L
+#define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x00000040L /* no effect since 0.9.7h and 0.9.8b */
+#define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x00000080L
+#define SSL_OP_TLS_D5_BUG 0x00000100L
+#define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L
+
+/* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added
+ * in OpenSSL 0.9.6d. Usually (depending on the application protocol)
+ * the workaround is not needed. Unfortunately some broken SSL/TLS
+ * implementations cannot handle it at all, which is why we include
+ * it in SSL_OP_ALL. */
+#define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800L /* added in 0.9.6e */
+
+/* SSL_OP_ALL: various bug workarounds that should be rather harmless.
+ * This used to be 0x000FFFFFL before 0.9.7. */
+#define SSL_OP_ALL 0x00000FFFL
+
+/* DTLS options */
+#define SSL_OP_NO_QUERY_MTU 0x00001000L
+/* Turn on Cookie Exchange (on relevant for servers) */
+#define SSL_OP_COOKIE_EXCHANGE 0x00002000L
+/* Don't use RFC4507 ticket extension */
+#define SSL_OP_NO_TICKET 0x00004000L
+/* Use Cisco's "speshul" version of DTLS_BAD_VER (as client) */
+#define SSL_OP_CISCO_ANYCONNECT 0x00008000L
+
+/* As server, disallow session resumption on renegotiation */
+#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L
+/* Permit unsafe legacy renegotiation */
+#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000L
+/* If set, always create a new key when using tmp_ecdh parameters */
+#define SSL_OP_SINGLE_ECDH_USE 0x00080000L
+/* If set, always create a new key when using tmp_dh parameters */
+#define SSL_OP_SINGLE_DH_USE 0x00100000L
+/* Set to always use the tmp_rsa key when doing RSA operations,
+ * even when this violates protocol specs */
+#define SSL_OP_EPHEMERAL_RSA 0x00200000L
+/* Set on servers to choose the cipher according to the server's
+ * preferences */
+#define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L
+/* If set, a server will allow a client to issue a SSLv3.0 version number
+ * as latest version supported in the premaster secret, even when TLSv1.0
+ * (version 3.1) was announced in the client hello. Normally this is
+ * forbidden to prevent version rollback attacks. */
+#define SSL_OP_TLS_ROLLBACK_BUG 0x00800000L
+
+#define SSL_OP_NO_SSLv2 0x01000000L
+#define SSL_OP_NO_SSLv3 0x02000000L
+#define SSL_OP_NO_TLSv1 0x04000000L
+
+/* The next flag deliberately changes the ciphertest, this is a check
+ * for the PKCS#1 attack */
+#define SSL_OP_PKCS1_CHECK_1 0x08000000L
+#define SSL_OP_PKCS1_CHECK_2 0x10000000L
+#define SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000L
+#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000L
+
+
+/* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
+ * when just a single record has been written): */
+#define SSL_MODE_ENABLE_PARTIAL_WRITE 0x00000001L
+/* Make it possible to retry SSL_write() with changed buffer location
+ * (buffer contents must stay the same!); this is not the default to avoid
+ * the misconception that non-blocking SSL_write() behaves like
+ * non-blocking write(): */
+#define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L
+/* Never bother the application with retries if the transport
+ * is blocking: */
+#define SSL_MODE_AUTO_RETRY 0x00000004L
+/* Don't attempt to automatically build certificate chain */
+#define SSL_MODE_NO_AUTO_CHAIN 0x00000008L
+
+
+/* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,
+ * they cannot be used to clear bits. */
+
+#define SSL_CTX_set_options(ctx,op) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
+#define SSL_CTX_clear_options(ctx,op) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_OPTIONS,(op),NULL)
+#define SSL_CTX_get_options(ctx) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,0,NULL)
+#define SSL_set_options(ssl,op) \
+ SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL)
+#define SSL_clear_options(ssl,op) \
+ SSL_ctrl((ssl),SSL_CTRL_CLEAR_OPTIONS,(op),NULL)
+#define SSL_get_options(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_OPTIONS,0,NULL)
+
+#define SSL_CTX_set_mode(ctx,op) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
+#define SSL_CTX_clear_mode(ctx,op) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL)
+#define SSL_CTX_get_mode(ctx) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL)
+#define SSL_clear_mode(ssl,op) \
+ SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL)
+#define SSL_set_mode(ssl,op) \
+ SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
+#define SSL_get_mode(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
+#define SSL_set_mtu(ssl, mtu) \
+ SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL)
+
+#define SSL_get_secure_renegotiation_support(ssl) \
+ SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL)
+
+void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
+void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
+#define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
+#define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
+
+
+
+#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32)
+#define SSL_MAX_CERT_LIST_DEFAULT 1024*30 /* 30k max cert list :-) */
+#else
+#define SSL_MAX_CERT_LIST_DEFAULT 1024*100 /* 100k max cert list :-) */
+#endif
+
+#define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (1024*20)
+
+/* This callback type is used inside SSL_CTX, SSL, and in the functions that set
+ * them. It is used to override the generation of SSL/TLS session IDs in a
+ * server. Return value should be zero on an error, non-zero to proceed. Also,
+ * callbacks should themselves check if the id they generate is unique otherwise
+ * the SSL handshake will fail with an error - callbacks can do this using the
+ * 'ssl' value they're passed by;
+ * SSL_has_matching_session_id(ssl, id, *id_len)
+ * The length value passed in is set at the maximum size the session ID can be.
+ * In SSLv2 this is 16 bytes, whereas SSLv3/TLSv1 it is 32 bytes. The callback
+ * can alter this length to be less if desired, but under SSLv2 session IDs are
+ * supposed to be fixed at 16 bytes so the id will be padded after the callback
+ * returns in this case. It is also an error for the callback to set the size to
+ * zero. */
+typedef int (*GEN_SESSION_CB)(const SSL *ssl, unsigned char *id,
+ unsigned int *id_len);
+
+typedef struct ssl_comp_st
+ {
+ int id;
+ const char *name;
+#ifndef OPENSSL_NO_COMP
+ COMP_METHOD *method;
+#else
+ char *method;
+#endif
+ } SSL_COMP;
+
+DECLARE_STACK_OF(SSL_COMP)
+
+struct ssl_ctx_st
+ {
+ SSL_METHOD *method;
+
+ STACK_OF(SSL_CIPHER) *cipher_list;
+ /* same as above but sorted for lookup */
+ STACK_OF(SSL_CIPHER) *cipher_list_by_id;
+
+ struct x509_store_st /* X509_STORE */ *cert_store;
+ struct lhash_st /* LHASH */ *sessions; /* a set of SSL_SESSIONs */
+ /* Most session-ids that will be cached, default is
+ * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited. */
+ unsigned long session_cache_size;
+ struct ssl_session_st *session_cache_head;
+ struct ssl_session_st *session_cache_tail;
+
+ /* This can have one of 2 values, ored together,
+ * SSL_SESS_CACHE_CLIENT,
+ * SSL_SESS_CACHE_SERVER,
+ * Default is SSL_SESSION_CACHE_SERVER, which means only
+ * SSL_accept which cache SSL_SESSIONS. */
+ int session_cache_mode;
+
+ /* If timeout is not 0, it is the default timeout value set
+ * when SSL_new() is called. This has been put in to make
+ * life easier to set things up */
+ long session_timeout;
+
+ /* If this callback is not null, it will be called each
+ * time a session id is added to the cache. If this function
+ * returns 1, it means that the callback will do a
+ * SSL_SESSION_free() when it has finished using it. Otherwise,
+ * on 0, it means the callback has finished with it.
+ * If remove_session_cb is not null, it will be called when
+ * a session-id is removed from the cache. After the call,
+ * OpenSSL will SSL_SESSION_free() it. */
+ int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess);
+ void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess);
+ SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl,
+ unsigned char *data,int len,int *copy);
+
+ struct
+ {
+ int sess_connect; /* SSL new conn - started */
+ int sess_connect_renegotiate;/* SSL reneg - requested */
+ int sess_connect_good; /* SSL new conne/reneg - finished */
+ int sess_accept; /* SSL new accept - started */
+ int sess_accept_renegotiate;/* SSL reneg - requested */
+ int sess_accept_good; /* SSL accept/reneg - finished */
+ int sess_miss; /* session lookup misses */
+ int sess_timeout; /* reuse attempt on timeouted session */
+ int sess_cache_full; /* session removed due to full cache */
+ int sess_hit; /* session reuse actually done */
+ int sess_cb_hit; /* session-id that was not
+ * in the cache was
+ * passed back via the callback. This
+ * indicates that the application is
+ * supplying session-id's from other
+ * processes - spooky :-) */
+ } stats;
+
+ int references;
+
+ /* if defined, these override the X509_verify_cert() calls */
+ int (*app_verify_callback)(X509_STORE_CTX *, void *);
+ void *app_verify_arg;
+ /* before OpenSSL 0.9.7, 'app_verify_arg' was ignored
+ * ('app_verify_callback' was called with just one argument) */
+
+ /* Default password callback. */
+ pem_password_cb *default_passwd_callback;
+
+ /* Default password callback user data. */
+ void *default_passwd_callback_userdata;
+
+ /* get client cert callback */
+ int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
+
+ /* cookie generate callback */
+ int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie,
+ unsigned int *cookie_len);
+
+ /* verify cookie callback */
+ int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie,
+ unsigned int cookie_len);
+
+ CRYPTO_EX_DATA ex_data;
+
+ const EVP_MD *rsa_md5;/* For SSLv2 - name is 'ssl2-md5' */
+ const EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */
+ const EVP_MD *sha1; /* For SSLv3/TLSv1 'ssl3->sha1' */
+
+ STACK_OF(X509) *extra_certs;
+ STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */
+
+
+ /* Default values used when no per-SSL value is defined follow */
+
+ void (*info_callback)(const SSL *ssl,int type,int val); /* used if SSL's info_callback is NULL */
+
+ /* what we put in client cert requests */
+ STACK_OF(X509_NAME) *client_CA;
+
+
+ /* Default values to use in SSL structures follow (these are copied by SSL_new) */
+
+ unsigned long options;
+ unsigned long mode;
+ long max_cert_list;
+
+ struct cert_st /* CERT */ *cert;
+ int read_ahead;
+
+ /* callback that allows applications to peek at protocol messages */
+ void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
+ void *msg_callback_arg;
+
+ int verify_mode;
+ unsigned int sid_ctx_length;
+ unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+ int (*default_verify_callback)(int ok,X509_STORE_CTX *ctx); /* called 'verify_callback' in the SSL */
+
+ /* Default generate session ID callback. */
+ GEN_SESSION_CB generate_session_id;
+
+ X509_VERIFY_PARAM *param;
+
+#if 0
+ int purpose; /* Purpose setting */
+ int trust; /* Trust setting */
+#endif
+
+ int quiet_shutdown;
+
+#ifndef OPENSSL_ENGINE
+ /* Engine to pass requests for client certs to
+ */
+ ENGINE *client_cert_engine;
+#endif
+
+#ifndef OPENSSL_NO_TLSEXT
+ /* TLS extensions servername callback */
+ int (*tlsext_servername_callback)(SSL*, int *, void *);
+ void *tlsext_servername_arg;
+ /* RFC 4507 session ticket keys */
+ unsigned char tlsext_tick_key_name[16];
+ unsigned char tlsext_tick_hmac_key[16];
+ unsigned char tlsext_tick_aes_key[16];
+ /* Callback to support customisation of ticket key setting */
+ int (*tlsext_ticket_key_cb)(SSL *ssl,
+ unsigned char *name, unsigned char *iv,
+ EVP_CIPHER_CTX *ectx,
+ HMAC_CTX *hctx, int enc);
+
+ /* certificate status request info */
+ /* Callback for status request */
+ int (*tlsext_status_cb)(SSL *ssl, void *arg);
+ void *tlsext_status_arg;
+#endif
+
+ };
+
+#define SSL_SESS_CACHE_OFF 0x0000
+#define SSL_SESS_CACHE_CLIENT 0x0001
+#define SSL_SESS_CACHE_SERVER 0x0002
+#define SSL_SESS_CACHE_BOTH (SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER)
+#define SSL_SESS_CACHE_NO_AUTO_CLEAR 0x0080
+/* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */
+#define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0100
+#define SSL_SESS_CACHE_NO_INTERNAL_STORE 0x0200
+#define SSL_SESS_CACHE_NO_INTERNAL \
+ (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE)
+
+ struct lhash_st *SSL_CTX_sessions(SSL_CTX *ctx);
+#define SSL_CTX_sess_number(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL)
+#define SSL_CTX_sess_connect(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL)
+#define SSL_CTX_sess_connect_good(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL)
+#define SSL_CTX_sess_connect_renegotiate(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL)
+#define SSL_CTX_sess_accept(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL)
+#define SSL_CTX_sess_accept_renegotiate(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL)
+#define SSL_CTX_sess_accept_good(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL)
+#define SSL_CTX_sess_hits(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL)
+#define SSL_CTX_sess_cb_hits(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL)
+#define SSL_CTX_sess_misses(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL)
+#define SSL_CTX_sess_timeouts(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL)
+#define SSL_CTX_sess_cache_full(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL)
+
+void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, int (*new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess));
+int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(struct ssl_st *ssl, SSL_SESSION *sess);
+void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, void (*remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess));
+void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(struct ssl_ctx_st *ctx, SSL_SESSION *sess);
+void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, unsigned char *data,int len,int *copy));
+SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(struct ssl_st *ssl, unsigned char *Data, int len, int *copy);
+void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*cb)(const SSL *ssl,int type,int val));
+void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val);
+void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey));
+int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
+#ifndef OPENSSL_NO_ENGINE
+int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e);
+#endif
+void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len));
+void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, int (*app_verify_cookie_cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len));
+
+#define SSL_NOTHING 1
+#define SSL_WRITING 2
+#define SSL_READING 3
+#define SSL_X509_LOOKUP 4
+
+/* These will only be used when doing non-blocking IO */
+#define SSL_want_nothing(s) (SSL_want(s) == SSL_NOTHING)
+#define SSL_want_read(s) (SSL_want(s) == SSL_READING)
+#define SSL_want_write(s) (SSL_want(s) == SSL_WRITING)
+#define SSL_want_x509_lookup(s) (SSL_want(s) == SSL_X509_LOOKUP)
+
+struct ssl_st
+ {
+ /* protocol version
+ * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION)
+ */
+ int version;
+ int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */
+
+ SSL_METHOD *method; /* SSLv3 */
+
+ /* There are 2 BIO's even though they are normally both the
+ * same. This is so data can be read and written to different
+ * handlers */
+
+#ifndef OPENSSL_NO_BIO
+ BIO *rbio; /* used by SSL_read */
+ BIO *wbio; /* used by SSL_write */
+ BIO *bbio; /* used during session-id reuse to concatenate
+ * messages */
+#else
+ char *rbio; /* used by SSL_read */
+ char *wbio; /* used by SSL_write */
+ char *bbio;
+#endif
+ /* This holds a variable that indicates what we were doing
+ * when a 0 or -1 is returned. This is needed for
+ * non-blocking IO so we know what request needs re-doing when
+ * in SSL_accept or SSL_connect */
+ int rwstate;
+
+ /* true when we are actually in SSL_accept() or SSL_connect() */
+ int in_handshake;
+ int (*handshake_func)(SSL *);
+
+ /* Imagine that here's a boolean member "init" that is
+ * switched as soon as SSL_set_{accept/connect}_state
+ * is called for the first time, so that "state" and
+ * "handshake_func" are properly initialized. But as
+ * handshake_func is == 0 until then, we use this
+ * test instead of an "init" member.
+ */
+
+ int server; /* are we the server side? - mostly used by SSL_clear*/
+
+ int new_session;/* 1 if we are to use a new session.
+ * 2 if we are a server and are inside a handshake
+ * (i.e. not just sending a HelloRequest)
+ * NB: For servers, the 'new' session may actually be a previously
+ * cached session or even the previous session unless
+ * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
+ int quiet_shutdown;/* don't send shutdown packets */
+ int shutdown; /* we have shut things down, 0x01 sent, 0x02
+ * for received */
+ int state; /* where we are */
+ int rstate; /* where we are when reading */
+
+ BUF_MEM *init_buf; /* buffer used during init */
+ void *init_msg; /* pointer to handshake message body, set by ssl3_get_message() */
+ int init_num; /* amount read/written */
+ int init_off; /* amount read/written */
+
+ /* used internally to point at a raw packet */
+ unsigned char *packet;
+ unsigned int packet_length;
+
+ struct ssl2_state_st *s2; /* SSLv2 variables */
+ struct ssl3_state_st *s3; /* SSLv3 variables */
+ struct dtls1_state_st *d1; /* DTLSv1 variables */
+
+ int read_ahead; /* Read as many input bytes as possible
+ * (for non-blocking reads) */
+
+ /* callback that allows applications to peek at protocol messages */
+ void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
+ void *msg_callback_arg;
+
+ int hit; /* reusing a previous session */
+
+ X509_VERIFY_PARAM *param;
+
+#if 0
+ int purpose; /* Purpose setting */
+ int trust; /* Trust setting */
+#endif
+
+ /* crypto */
+ STACK_OF(SSL_CIPHER) *cipher_list;
+ STACK_OF(SSL_CIPHER) *cipher_list_by_id;
+
+ /* These are the ones being used, the ones in SSL_SESSION are
+ * the ones to be 'copied' into these ones */
+
+ EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */
+ const EVP_MD *read_hash; /* used for mac generation */
+#ifndef OPENSSL_NO_COMP
+ COMP_CTX *expand; /* uncompress */
+#else
+ char *expand;
+#endif
+
+ EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */
+ const EVP_MD *write_hash; /* used for mac generation */
+#ifndef OPENSSL_NO_COMP
+ COMP_CTX *compress; /* compression */
+#else
+ char *compress;
+#endif
+
+ /* session info */
+
+ /* client cert? */
+ /* This is used to hold the server certificate used */
+ struct cert_st /* CERT */ *cert;
+
+ /* the session_id_context is used to ensure sessions are only reused
+ * in the appropriate context */
+ unsigned int sid_ctx_length;
+ unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
+
+ /* This can also be in the session once a session is established */
+ SSL_SESSION *session;
+
+ /* Default generate session ID callback. */
+ GEN_SESSION_CB generate_session_id;
+
+ /* Used in SSL2 and SSL3 */
+ int verify_mode; /* 0 don't care about verify failure.
+ * 1 fail if verify fails */
+ int (*verify_callback)(int ok,X509_STORE_CTX *ctx); /* fail if callback returns 0 */
+
+ void (*info_callback)(const SSL *ssl,int type,int val); /* optional informational callback */
+
+ int error; /* error bytes to be written */
+ int error_code; /* actual code */
+
+#ifndef OPENSSL_NO_KRB5
+ KSSL_CTX *kssl_ctx; /* Kerberos 5 context */
+#endif /* OPENSSL_NO_KRB5 */
+
+ SSL_CTX *ctx;
+ /* set this flag to 1 and a sleep(1) is put into all SSL_read()
+ * and SSL_write() calls, good for nbio debuging :-) */
+ int debug;
+
+ /* extra application data */
+ long verify_result;
+ CRYPTO_EX_DATA ex_data;
+
+ /* for server side, keep the list of CA_dn we can use */
+ STACK_OF(X509_NAME) *client_CA;
+
+ int references;
+ unsigned long options; /* protocol behaviour */
+ unsigned long mode; /* API behaviour */
+ long max_cert_list;
+ int first_packet;
+ int client_version; /* what was passed, used for
+ * SSLv3/TLS rollback check */
+#ifndef OPENSSL_NO_TLSEXT
+ /* TLS extension debug callback */
+ void (*tlsext_debug_cb)(SSL *s, int client_server, int type,
+ unsigned char *data, int len,
+ void *arg);
+ void *tlsext_debug_arg;
+ char *tlsext_hostname;
+ int servername_done; /* no further mod of servername
+ 0 : call the servername extension callback.
+ 1 : prepare 2, allow last ack just after in server callback.
+ 2 : don't call servername callback, no ack in server hello
+ */
+ /* certificate status request info */
+ /* Status type or -1 if no status type */
+ int tlsext_status_type;
+ /* Expect OCSP CertificateStatus message */
+ int tlsext_status_expected;
+ /* OCSP status request only */
+ STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids;
+ X509_EXTENSIONS *tlsext_ocsp_exts;
+ /* OCSP response received or to be sent */
+ unsigned char *tlsext_ocsp_resp;
+ int tlsext_ocsp_resplen;
+
+ /* RFC4507 session ticket expected to be received or sent */
+ int tlsext_ticket_expected;
+ SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
+#define session_ctx initial_ctx
+#else
+#define session_ctx ctx
+#endif
+ };
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <openssl/ssl2.h>
+#include <openssl/ssl3.h>
+#include <openssl/tls1.h> /* This is mostly sslv3 with a few tweaks */
+#include <openssl/dtls1.h> /* Datagram TLS */
+#include <openssl/ssl23.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* compatibility */
+#define SSL_set_app_data(s,arg) (SSL_set_ex_data(s,0,(char *)arg))
+#define SSL_get_app_data(s) (SSL_get_ex_data(s,0))
+#define SSL_SESSION_set_app_data(s,a) (SSL_SESSION_set_ex_data(s,0,(char *)a))
+#define SSL_SESSION_get_app_data(s) (SSL_SESSION_get_ex_data(s,0))
+#define SSL_CTX_get_app_data(ctx) (SSL_CTX_get_ex_data(ctx,0))
+#define SSL_CTX_set_app_data(ctx,arg) (SSL_CTX_set_ex_data(ctx,0,(char *)arg))
+
+/* The following are the possible values for ssl->state are are
+ * used to indicate where we are up to in the SSL connection establishment.
+ * The macros that follow are about the only things you should need to use
+ * and even then, only when using non-blocking IO.
+ * It can also be useful to work out where you were when the connection
+ * failed */
+
+#define SSL_ST_CONNECT 0x1000
+#define SSL_ST_ACCEPT 0x2000
+#define SSL_ST_MASK 0x0FFF
+#define SSL_ST_INIT (SSL_ST_CONNECT|SSL_ST_ACCEPT)
+#define SSL_ST_BEFORE 0x4000
+#define SSL_ST_OK 0x03
+#define SSL_ST_RENEGOTIATE (0x04|SSL_ST_INIT)
+
+#define SSL_CB_LOOP 0x01
+#define SSL_CB_EXIT 0x02
+#define SSL_CB_READ 0x04
+#define SSL_CB_WRITE 0x08
+#define SSL_CB_ALERT 0x4000 /* used in callback */
+#define SSL_CB_READ_ALERT (SSL_CB_ALERT|SSL_CB_READ)
+#define SSL_CB_WRITE_ALERT (SSL_CB_ALERT|SSL_CB_WRITE)
+#define SSL_CB_ACCEPT_LOOP (SSL_ST_ACCEPT|SSL_CB_LOOP)
+#define SSL_CB_ACCEPT_EXIT (SSL_ST_ACCEPT|SSL_CB_EXIT)
+#define SSL_CB_CONNECT_LOOP (SSL_ST_CONNECT|SSL_CB_LOOP)
+#define SSL_CB_CONNECT_EXIT (SSL_ST_CONNECT|SSL_CB_EXIT)
+#define SSL_CB_HANDSHAKE_START 0x10
+#define SSL_CB_HANDSHAKE_DONE 0x20
+
+/* Is the SSL_connection established? */
+#define SSL_get_state(a) SSL_state(a)
+#define SSL_is_init_finished(a) (SSL_state(a) == SSL_ST_OK)
+#define SSL_in_init(a) (SSL_state(a)&SSL_ST_INIT)
+#define SSL_in_before(a) (SSL_state(a)&SSL_ST_BEFORE)
+#define SSL_in_connect_init(a) (SSL_state(a)&SSL_ST_CONNECT)
+#define SSL_in_accept_init(a) (SSL_state(a)&SSL_ST_ACCEPT)
+
+/* The following 2 states are kept in ssl->rstate when reads fail,
+ * you should not need these */
+#define SSL_ST_READ_HEADER 0xF0
+#define SSL_ST_READ_BODY 0xF1
+#define SSL_ST_READ_DONE 0xF2
+
+/* Obtain latest Finished message
+ * -- that we sent (SSL_get_finished)
+ * -- that we expected from peer (SSL_get_peer_finished).
+ * Returns length (0 == no Finished so far), copies up to 'count' bytes. */
+size_t SSL_get_finished(const SSL *s, void *buf, size_t count);
+size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
+
+/* use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options
+ * are 'ored' with SSL_VERIFY_PEER if they are desired */
+#define SSL_VERIFY_NONE 0x00
+#define SSL_VERIFY_PEER 0x01
+#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
+#define SSL_VERIFY_CLIENT_ONCE 0x04
+
+#define OpenSSL_add_ssl_algorithms() SSL_library_init()
+#define SSLeay_add_ssl_algorithms() SSL_library_init()
+
+/* this is for backward compatibility */
+#if 0 /* NEW_SSLEAY */
+#define SSL_CTX_set_default_verify(a,b,c) SSL_CTX_set_verify(a,b,c)
+#define SSL_set_pref_cipher(c,n) SSL_set_cipher_list(c,n)
+#define SSL_add_session(a,b) SSL_CTX_add_session((a),(b))
+#define SSL_remove_session(a,b) SSL_CTX_remove_session((a),(b))
+#define SSL_flush_sessions(a,b) SSL_CTX_flush_sessions((a),(b))
+#endif
+/* More backward compatibility */
+#define SSL_get_cipher(s) \
+ SSL_CIPHER_get_name(SSL_get_current_cipher(s))
+#define SSL_get_cipher_bits(s,np) \
+ SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np)
+#define SSL_get_cipher_version(s) \
+ SSL_CIPHER_get_version(SSL_get_current_cipher(s))
+#define SSL_get_cipher_name(s) \
+ SSL_CIPHER_get_name(SSL_get_current_cipher(s))
+#define SSL_get_time(a) SSL_SESSION_get_time(a)
+#define SSL_set_time(a,b) SSL_SESSION_set_time((a),(b))
+#define SSL_get_timeout(a) SSL_SESSION_get_timeout(a)
+#define SSL_set_timeout(a,b) SSL_SESSION_set_timeout((a),(b))
+
+#if 1 /*SSLEAY_MACROS*/
+#define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id)
+#define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id)
+#define PEM_read_SSL_SESSION(fp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read( \
+ (char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb,u)
+#define PEM_read_bio_SSL_SESSION(bp,x,cb,u) PEM_ASN1_read_bio_of(SSL_SESSION,d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,x,cb,u)
+#define PEM_write_SSL_SESSION(fp,x) \
+ PEM_ASN1_write((int (*)())i2d_SSL_SESSION, \
+ PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL,NULL)
+#define PEM_write_bio_SSL_SESSION(bp,x) \
+ PEM_ASN1_write_bio_of(SSL_SESSION,i2d_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,x,NULL,NULL,0,NULL,NULL)
+#endif
+
+#define SSL_AD_REASON_OFFSET 1000
+/* These alert types are for SSLv3 and TLSv1 */
+#define SSL_AD_CLOSE_NOTIFY SSL3_AD_CLOSE_NOTIFY
+#define SSL_AD_UNEXPECTED_MESSAGE SSL3_AD_UNEXPECTED_MESSAGE /* fatal */
+#define SSL_AD_BAD_RECORD_MAC SSL3_AD_BAD_RECORD_MAC /* fatal */
+#define SSL_AD_DECRYPTION_FAILED TLS1_AD_DECRYPTION_FAILED
+#define SSL_AD_RECORD_OVERFLOW TLS1_AD_RECORD_OVERFLOW
+#define SSL_AD_DECOMPRESSION_FAILURE SSL3_AD_DECOMPRESSION_FAILURE/* fatal */
+#define SSL_AD_HANDSHAKE_FAILURE SSL3_AD_HANDSHAKE_FAILURE/* fatal */
+#define SSL_AD_NO_CERTIFICATE SSL3_AD_NO_CERTIFICATE /* Not for TLS */
+#define SSL_AD_BAD_CERTIFICATE SSL3_AD_BAD_CERTIFICATE
+#define SSL_AD_UNSUPPORTED_CERTIFICATE SSL3_AD_UNSUPPORTED_CERTIFICATE
+#define SSL_AD_CERTIFICATE_REVOKED SSL3_AD_CERTIFICATE_REVOKED
+#define SSL_AD_CERTIFICATE_EXPIRED SSL3_AD_CERTIFICATE_EXPIRED
+#define SSL_AD_CERTIFICATE_UNKNOWN SSL3_AD_CERTIFICATE_UNKNOWN
+#define SSL_AD_ILLEGAL_PARAMETER SSL3_AD_ILLEGAL_PARAMETER /* fatal */
+#define SSL_AD_UNKNOWN_CA TLS1_AD_UNKNOWN_CA /* fatal */
+#define SSL_AD_ACCESS_DENIED TLS1_AD_ACCESS_DENIED /* fatal */
+#define SSL_AD_DECODE_ERROR TLS1_AD_DECODE_ERROR /* fatal */
+#define SSL_AD_DECRYPT_ERROR TLS1_AD_DECRYPT_ERROR
+#define SSL_AD_EXPORT_RESTRICTION TLS1_AD_EXPORT_RESTRICTION/* fatal */
+#define SSL_AD_PROTOCOL_VERSION TLS1_AD_PROTOCOL_VERSION /* fatal */
+#define SSL_AD_INSUFFICIENT_SECURITY TLS1_AD_INSUFFICIENT_SECURITY/* fatal */
+#define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR /* fatal */
+#define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED
+#define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION
+#define SSL_AD_UNSUPPORTED_EXTENSION TLS1_AD_UNSUPPORTED_EXTENSION
+#define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
+#define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME
+#define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
+
+#define SSL_ERROR_NONE 0
+#define SSL_ERROR_SSL 1
+#define SSL_ERROR_WANT_READ 2
+#define SSL_ERROR_WANT_WRITE 3
+#define SSL_ERROR_WANT_X509_LOOKUP 4
+#define SSL_ERROR_SYSCALL 5 /* look at error stack/return value/errno */
+#define SSL_ERROR_ZERO_RETURN 6
+#define SSL_ERROR_WANT_CONNECT 7
+#define SSL_ERROR_WANT_ACCEPT 8
+
+#define SSL_CTRL_NEED_TMP_RSA 1
+#define SSL_CTRL_SET_TMP_RSA 2
+#define SSL_CTRL_SET_TMP_DH 3
+#define SSL_CTRL_SET_TMP_ECDH 4
+#define SSL_CTRL_SET_TMP_RSA_CB 5
+#define SSL_CTRL_SET_TMP_DH_CB 6
+#define SSL_CTRL_SET_TMP_ECDH_CB 7
+
+#define SSL_CTRL_GET_SESSION_REUSED 8
+#define SSL_CTRL_GET_CLIENT_CERT_REQUEST 9
+#define SSL_CTRL_GET_NUM_RENEGOTIATIONS 10
+#define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS 11
+#define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 12
+#define SSL_CTRL_GET_FLAGS 13
+#define SSL_CTRL_EXTRA_CHAIN_CERT 14
+
+#define SSL_CTRL_SET_MSG_CALLBACK 15
+#define SSL_CTRL_SET_MSG_CALLBACK_ARG 16
+
+/* only applies to datagram connections */
+#define SSL_CTRL_SET_MTU 17
+/* Stats */
+#define SSL_CTRL_SESS_NUMBER 20
+#define SSL_CTRL_SESS_CONNECT 21
+#define SSL_CTRL_SESS_CONNECT_GOOD 22
+#define SSL_CTRL_SESS_CONNECT_RENEGOTIATE 23
+#define SSL_CTRL_SESS_ACCEPT 24
+#define SSL_CTRL_SESS_ACCEPT_GOOD 25
+#define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE 26
+#define SSL_CTRL_SESS_HIT 27
+#define SSL_CTRL_SESS_CB_HIT 28
+#define SSL_CTRL_SESS_MISSES 29
+#define SSL_CTRL_SESS_TIMEOUTS 30
+#define SSL_CTRL_SESS_CACHE_FULL 31
+#define SSL_CTRL_OPTIONS 32
+#define SSL_CTRL_MODE 33
+
+#define SSL_CTRL_GET_READ_AHEAD 40
+#define SSL_CTRL_SET_READ_AHEAD 41
+#define SSL_CTRL_SET_SESS_CACHE_SIZE 42
+#define SSL_CTRL_GET_SESS_CACHE_SIZE 43
+#define SSL_CTRL_SET_SESS_CACHE_MODE 44
+#define SSL_CTRL_GET_SESS_CACHE_MODE 45
+
+#define SSL_CTRL_GET_MAX_CERT_LIST 50
+#define SSL_CTRL_SET_MAX_CERT_LIST 51
+
+/* see tls1.h for macros based on these */
+#ifndef OPENSSL_NO_TLSEXT
+#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53
+#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54
+#define SSL_CTRL_SET_TLSEXT_HOSTNAME 55
+#define SSL_CTRL_SET_TLSEXT_DEBUG_CB 56
+#define SSL_CTRL_SET_TLSEXT_DEBUG_ARG 57
+#define SSL_CTRL_GET_TLSEXT_TICKET_KEYS 58
+#define SSL_CTRL_SET_TLSEXT_TICKET_KEYS 59
+
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 63
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 67
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 68
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71
+
+#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72
+#endif
+
+#define DTLS_CTRL_GET_TIMEOUT 73
+#define DTLS_CTRL_HANDLE_TIMEOUT 74
+#define DTLS_CTRL_LISTEN 75
+
+#define SSL_CTRL_GET_RI_SUPPORT 76
+#define SSL_CTRL_CLEAR_OPTIONS 77
+#define SSL_CTRL_CLEAR_MODE 78
+
+#define DTLSv1_get_timeout(ssl, arg) \
+ SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
+#define DTLSv1_handle_timeout(ssl) \
+ SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL)
+#define DTLSv1_listen(ssl, peer) \
+ SSL_ctrl(ssl,DTLS_CTRL_LISTEN,0, (void *)peer)
+
+#define SSL_session_reused(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL)
+#define SSL_num_renegotiations(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL)
+#define SSL_clear_num_renegotiations(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL)
+#define SSL_total_renegotiations(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL)
+
+#define SSL_CTX_need_tmp_RSA(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_NEED_TMP_RSA,0,NULL)
+#define SSL_CTX_set_tmp_rsa(ctx,rsa) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
+#define SSL_CTX_set_tmp_dh(ctx,dh) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
+#define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
+
+#define SSL_need_tmp_RSA(ssl) \
+ SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL)
+#define SSL_set_tmp_rsa(ssl,rsa) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
+#define SSL_set_tmp_dh(ssl,dh) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
+#define SSL_set_tmp_ecdh(ssl,ecdh) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
+
+#define SSL_CTX_add_extra_chain_cert(ctx,x509) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509)
+
+#ifndef OPENSSL_NO_BIO
+BIO_METHOD *BIO_f_ssl(void);
+BIO *BIO_new_ssl(SSL_CTX *ctx,int client);
+BIO *BIO_new_ssl_connect(SSL_CTX *ctx);
+BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx);
+int BIO_ssl_copy_session_id(BIO *to,BIO *from);
+void BIO_ssl_shutdown(BIO *ssl_bio);
+
+#endif
+
+int SSL_CTX_set_cipher_list(SSL_CTX *,const char *str);
+SSL_CTX *SSL_CTX_new(SSL_METHOD *meth);
+void SSL_CTX_free(SSL_CTX *);
+long SSL_CTX_set_timeout(SSL_CTX *ctx,long t);
+long SSL_CTX_get_timeout(const SSL_CTX *ctx);
+X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
+void SSL_CTX_set_cert_store(SSL_CTX *,X509_STORE *);
+int SSL_want(const SSL *s);
+int SSL_clear(SSL *s);
+
+void SSL_CTX_flush_sessions(SSL_CTX *ctx,long tm);
+
+SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
+int SSL_CIPHER_get_bits(const SSL_CIPHER *c,int *alg_bits);
+char * SSL_CIPHER_get_version(const SSL_CIPHER *c);
+const char * SSL_CIPHER_get_name(const SSL_CIPHER *c);
+
+int SSL_get_fd(const SSL *s);
+int SSL_get_rfd(const SSL *s);
+int SSL_get_wfd(const SSL *s);
+const char * SSL_get_cipher_list(const SSL *s,int n);
+char * SSL_get_shared_ciphers(const SSL *s, char *buf, int len);
+int SSL_get_read_ahead(const SSL * s);
+int SSL_pending(const SSL *s);
+#ifndef OPENSSL_NO_SOCK
+int SSL_set_fd(SSL *s, int fd);
+int SSL_set_rfd(SSL *s, int fd);
+int SSL_set_wfd(SSL *s, int fd);
+#endif
+#ifndef OPENSSL_NO_BIO
+void SSL_set_bio(SSL *s, BIO *rbio,BIO *wbio);
+BIO * SSL_get_rbio(const SSL *s);
+BIO * SSL_get_wbio(const SSL *s);
+#endif
+int SSL_set_cipher_list(SSL *s, const char *str);
+void SSL_set_read_ahead(SSL *s, int yes);
+int SSL_get_verify_mode(const SSL *s);
+int SSL_get_verify_depth(const SSL *s);
+int (*SSL_get_verify_callback(const SSL *s))(int,X509_STORE_CTX *);
+void SSL_set_verify(SSL *s, int mode,
+ int (*callback)(int ok,X509_STORE_CTX *ctx));
+void SSL_set_verify_depth(SSL *s, int depth);
+#ifndef OPENSSL_NO_RSA
+int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
+#endif
+int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len);
+int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
+int SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, const unsigned char *d, long len);
+int SSL_use_certificate(SSL *ssl, X509 *x);
+int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
+
+#ifndef OPENSSL_NO_STDIO
+int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
+int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
+int SSL_use_certificate_file(SSL *ssl, const char *file, int type);
+int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type);
+int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);
+int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type);
+int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); /* PEM type */
+STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
+int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
+ const char *file);
+#ifndef OPENSSL_SYS_VMS
+#ifndef OPENSSL_SYS_MACINTOSH_CLASSIC /* XXXXX: Better scheme needed! [was: #ifndef MAC_OS_pre_X] */
+int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
+ const char *dir);
+#endif
+#endif
+
+#endif
+
+void SSL_load_error_strings(void );
+const char *SSL_state_string(const SSL *s);
+const char *SSL_rstate_string(const SSL *s);
+const char *SSL_state_string_long(const SSL *s);
+const char *SSL_rstate_string_long(const SSL *s);
+long SSL_SESSION_get_time(const SSL_SESSION *s);
+long SSL_SESSION_set_time(SSL_SESSION *s, long t);
+long SSL_SESSION_get_timeout(const SSL_SESSION *s);
+long SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
+void SSL_copy_session_id(SSL *to,const SSL *from);
+
+SSL_SESSION *SSL_SESSION_new(void);
+unsigned long SSL_SESSION_hash(const SSL_SESSION *a);
+int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b);
+const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len);
+#ifndef OPENSSL_NO_FP_API
+int SSL_SESSION_print_fp(FILE *fp,const SSL_SESSION *ses);
+#endif
+#ifndef OPENSSL_NO_BIO
+int SSL_SESSION_print(BIO *fp,const SSL_SESSION *ses);
+#endif
+void SSL_SESSION_free(SSL_SESSION *ses);
+int i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp);
+int SSL_set_session(SSL *to, SSL_SESSION *session);
+int SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c);
+int SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c);
+int SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB);
+int SSL_set_generate_session_id(SSL *, GEN_SESSION_CB);
+int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id,
+ unsigned int id_len);
+SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a,const unsigned char **pp,
+ long length);
+
+#ifdef HEADER_X509_H
+X509 * SSL_get_peer_certificate(const SSL *s);
+#endif
+
+STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s);
+
+int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
+int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
+int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int,X509_STORE_CTX *);
+void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,
+ int (*callback)(int, X509_STORE_CTX *));
+void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth);
+void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg);
+#ifndef OPENSSL_NO_RSA
+int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
+#endif
+int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len);
+int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
+int SSL_CTX_use_PrivateKey_ASN1(int pk,SSL_CTX *ctx,
+ const unsigned char *d, long len);
+int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
+int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d);
+
+void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
+void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
+
+int SSL_CTX_check_private_key(const SSL_CTX *ctx);
+int SSL_check_private_key(const SSL *ctx);
+
+int SSL_CTX_set_session_id_context(SSL_CTX *ctx,const unsigned char *sid_ctx,
+ unsigned int sid_ctx_len);
+
+SSL * SSL_new(SSL_CTX *ctx);
+int SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx,
+ unsigned int sid_ctx_len);
+
+int SSL_CTX_set_purpose(SSL_CTX *s, int purpose);
+int SSL_set_purpose(SSL *s, int purpose);
+int SSL_CTX_set_trust(SSL_CTX *s, int trust);
+int SSL_set_trust(SSL *s, int trust);
+
+void SSL_free(SSL *ssl);
+int SSL_accept(SSL *ssl);
+int SSL_connect(SSL *ssl);
+int SSL_read(SSL *ssl,void *buf,int num);
+int SSL_peek(SSL *ssl,void *buf,int num);
+int SSL_write(SSL *ssl,const void *buf,int num);
+long SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg);
+long SSL_callback_ctrl(SSL *, int, void (*)(void));
+long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd, long larg, void *parg);
+long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));
+
+int SSL_get_error(const SSL *s,int ret_code);
+const char *SSL_get_version(const SSL *s);
+
+/* This sets the 'default' SSL version that SSL_new() will create */
+int SSL_CTX_set_ssl_version(SSL_CTX *ctx,SSL_METHOD *meth);
+
+SSL_METHOD *SSLv2_method(void); /* SSLv2 */
+SSL_METHOD *SSLv2_server_method(void); /* SSLv2 */
+SSL_METHOD *SSLv2_client_method(void); /* SSLv2 */
+
+SSL_METHOD *SSLv3_method(void); /* SSLv3 */
+SSL_METHOD *SSLv3_server_method(void); /* SSLv3 */
+SSL_METHOD *SSLv3_client_method(void); /* SSLv3 */
+
+SSL_METHOD *SSLv23_method(void); /* SSLv3 but can rollback to v2 */
+SSL_METHOD *SSLv23_server_method(void); /* SSLv3 but can rollback to v2 */
+SSL_METHOD *SSLv23_client_method(void); /* SSLv3 but can rollback to v2 */
+
+SSL_METHOD *TLSv1_method(void); /* TLSv1.0 */
+SSL_METHOD *TLSv1_server_method(void); /* TLSv1.0 */
+SSL_METHOD *TLSv1_client_method(void); /* TLSv1.0 */
+
+SSL_METHOD *DTLSv1_method(void); /* DTLSv1.0 */
+SSL_METHOD *DTLSv1_server_method(void); /* DTLSv1.0 */
+SSL_METHOD *DTLSv1_client_method(void); /* DTLSv1.0 */
+
+STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
+
+int SSL_do_handshake(SSL *s);
+int SSL_renegotiate(SSL *s);
+int SSL_renegotiate_pending(SSL *s);
+int SSL_shutdown(SSL *s);
+
+SSL_METHOD *SSL_get_ssl_method(SSL *s);
+int SSL_set_ssl_method(SSL *s,SSL_METHOD *method);
+const char *SSL_alert_type_string_long(int value);
+const char *SSL_alert_type_string(int value);
+const char *SSL_alert_desc_string_long(int value);
+const char *SSL_alert_desc_string(int value);
+
+void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
+void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
+STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
+STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s);
+int SSL_add_client_CA(SSL *ssl,X509 *x);
+int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x);
+
+void SSL_set_connect_state(SSL *s);
+void SSL_set_accept_state(SSL *s);
+
+long SSL_get_default_timeout(const SSL *s);
+
+int SSL_library_init(void );
+
+char *SSL_CIPHER_description(const SSL_CIPHER *,char *buf,int size);
+STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk);
+
+SSL *SSL_dup(SSL *ssl);
+
+X509 *SSL_get_certificate(const SSL *ssl);
+/* EVP_PKEY */ struct evp_pkey_st *SSL_get_privatekey(SSL *ssl);
+
+void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx,int mode);
+int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
+void SSL_set_quiet_shutdown(SSL *ssl,int mode);
+int SSL_get_quiet_shutdown(const SSL *ssl);
+void SSL_set_shutdown(SSL *ssl,int mode);
+int SSL_get_shutdown(const SSL *ssl);
+int SSL_version(const SSL *ssl);
+int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
+int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
+ const char *CApath);
+#define SSL_get0_session SSL_get_session /* just peek at pointer */
+SSL_SESSION *SSL_get_session(const SSL *ssl);
+SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */
+SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
+SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx);
+void SSL_set_info_callback(SSL *ssl,
+ void (*cb)(const SSL *ssl,int type,int val));
+void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl,int type,int val);
+int SSL_state(const SSL *ssl);
+
+void SSL_set_verify_result(SSL *ssl,long v);
+long SSL_get_verify_result(const SSL *ssl);
+
+int SSL_set_ex_data(SSL *ssl,int idx,void *data);
+void *SSL_get_ex_data(const SSL *ssl,int idx);
+int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+
+int SSL_SESSION_set_ex_data(SSL_SESSION *ss,int idx,void *data);
+void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss,int idx);
+int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+
+int SSL_CTX_set_ex_data(SSL_CTX *ssl,int idx,void *data);
+void *SSL_CTX_get_ex_data(const SSL_CTX *ssl,int idx);
+int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+
+int SSL_get_ex_data_X509_STORE_CTX_idx(void );
+
+#define SSL_CTX_sess_set_cache_size(ctx,t) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL)
+#define SSL_CTX_sess_get_cache_size(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL)
+#define SSL_CTX_set_session_cache_mode(ctx,m) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL)
+#define SSL_CTX_get_session_cache_mode(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL)
+
+#define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx)
+#define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m)
+#define SSL_CTX_get_read_ahead(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL)
+#define SSL_CTX_set_read_ahead(ctx,m) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL)
+#define SSL_CTX_get_max_cert_list(ctx) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
+#define SSL_CTX_set_max_cert_list(ctx,m) \
+ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
+#define SSL_get_max_cert_list(ssl) \
+ SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
+#define SSL_set_max_cert_list(ssl,m) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
+
+ /* NB: the keylength is only applicable when is_export is true */
+#ifndef OPENSSL_NO_RSA
+void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,
+ RSA *(*cb)(SSL *ssl,int is_export,
+ int keylength));
+
+void SSL_set_tmp_rsa_callback(SSL *ssl,
+ RSA *(*cb)(SSL *ssl,int is_export,
+ int keylength));
+#endif
+#ifndef OPENSSL_NO_DH
+void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
+ DH *(*dh)(SSL *ssl,int is_export,
+ int keylength));
+void SSL_set_tmp_dh_callback(SSL *ssl,
+ DH *(*dh)(SSL *ssl,int is_export,
+ int keylength));
+#endif
+#ifndef OPENSSL_NO_ECDH
+void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,
+ EC_KEY *(*ecdh)(SSL *ssl,int is_export,
+ int keylength));
+void SSL_set_tmp_ecdh_callback(SSL *ssl,
+ EC_KEY *(*ecdh)(SSL *ssl,int is_export,
+ int keylength));
+#endif
+
+#ifndef OPENSSL_NO_COMP
+const COMP_METHOD *SSL_get_current_compression(SSL *s);
+const COMP_METHOD *SSL_get_current_expansion(SSL *s);
+const char *SSL_COMP_get_name(const COMP_METHOD *comp);
+STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
+int SSL_COMP_add_compression_method(int id,COMP_METHOD *cm);
+#else
+const void *SSL_get_current_compression(SSL *s);
+const void *SSL_get_current_expansion(SSL *s);
+const char *SSL_COMP_get_name(const void *comp);
+void *SSL_COMP_get_compression_methods(void);
+int SSL_COMP_add_compression_method(int id,void *cm);
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_SSL_strings(void);
+
+/* Error codes for the SSL functions. */
+
+/* Function codes. */
+#define SSL_F_CLIENT_CERTIFICATE 100
+#define SSL_F_CLIENT_FINISHED 167
+#define SSL_F_CLIENT_HELLO 101
+#define SSL_F_CLIENT_MASTER_KEY 102
+#define SSL_F_D2I_SSL_SESSION 103
+#define SSL_F_DO_DTLS1_WRITE 245
+#define SSL_F_DO_SSL3_WRITE 104
+#define SSL_F_DTLS1_ACCEPT 246
+#define SSL_F_DTLS1_ADD_CERT_TO_BUF 280
+#define SSL_F_DTLS1_BUFFER_RECORD 247
+#define SSL_F_DTLS1_CHECK_TIMEOUT_NUM 293
+#define SSL_F_DTLS1_CLIENT_HELLO 248
+#define SSL_F_DTLS1_CONNECT 249
+#define SSL_F_DTLS1_ENC 250
+#define SSL_F_DTLS1_GET_HELLO_VERIFY 251
+#define SSL_F_DTLS1_GET_MESSAGE 252
+#define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT 253
+#define SSL_F_DTLS1_GET_RECORD 254
+#define SSL_F_DTLS1_HANDLE_TIMEOUT 282
+#define SSL_F_DTLS1_OUTPUT_CERT_CHAIN 255
+#define SSL_F_DTLS1_PREPROCESS_FRAGMENT 277
+#define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE 256
+#define SSL_F_DTLS1_PROCESS_RECORD 257
+#define SSL_F_DTLS1_READ_BYTES 258
+#define SSL_F_DTLS1_READ_FAILED 259
+#define SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST 260
+#define SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE 261
+#define SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE 262
+#define SSL_F_DTLS1_SEND_CLIENT_VERIFY 263
+#define SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST 264
+#define SSL_F_DTLS1_SEND_SERVER_CERTIFICATE 265
+#define SSL_F_DTLS1_SEND_SERVER_HELLO 266
+#define SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE 267
+#define SSL_F_DTLS1_WRITE_APP_DATA_BYTES 268
+#define SSL_F_GET_CLIENT_FINISHED 105
+#define SSL_F_GET_CLIENT_HELLO 106
+#define SSL_F_GET_CLIENT_MASTER_KEY 107
+#define SSL_F_GET_SERVER_FINISHED 108
+#define SSL_F_GET_SERVER_HELLO 109
+#define SSL_F_GET_SERVER_VERIFY 110
+#define SSL_F_I2D_SSL_SESSION 111
+#define SSL_F_READ_N 112
+#define SSL_F_REQUEST_CERTIFICATE 113
+#define SSL_F_SERVER_FINISH 239
+#define SSL_F_SERVER_HELLO 114
+#define SSL_F_SERVER_VERIFY 240
+#define SSL_F_SSL23_ACCEPT 115
+#define SSL_F_SSL23_CLIENT_HELLO 116
+#define SSL_F_SSL23_CONNECT 117
+#define SSL_F_SSL23_GET_CLIENT_HELLO 118
+#define SSL_F_SSL23_GET_SERVER_HELLO 119
+#define SSL_F_SSL23_PEEK 237
+#define SSL_F_SSL23_READ 120
+#define SSL_F_SSL23_WRITE 121
+#define SSL_F_SSL2_ACCEPT 122
+#define SSL_F_SSL2_CONNECT 123
+#define SSL_F_SSL2_ENC_INIT 124
+#define SSL_F_SSL2_GENERATE_KEY_MATERIAL 241
+#define SSL_F_SSL2_PEEK 234
+#define SSL_F_SSL2_READ 125
+#define SSL_F_SSL2_READ_INTERNAL 236
+#define SSL_F_SSL2_SET_CERTIFICATE 126
+#define SSL_F_SSL2_WRITE 127
+#define SSL_F_SSL3_ACCEPT 128
+#define SSL_F_SSL3_ADD_CERT_TO_BUF 281
+#define SSL_F_SSL3_CALLBACK_CTRL 233
+#define SSL_F_SSL3_CHANGE_CIPHER_STATE 129
+#define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130
+#define SSL_F_SSL3_CHECK_CLIENT_HELLO 292
+#define SSL_F_SSL3_CLIENT_HELLO 131
+#define SSL_F_SSL3_CONNECT 132
+#define SSL_F_SSL3_CTRL 213
+#define SSL_F_SSL3_CTX_CTRL 133
+#define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC 279
+#define SSL_F_SSL3_ENC 134
+#define SSL_F_SSL3_GENERATE_KEY_BLOCK 238
+#define SSL_F_SSL3_GET_CERTIFICATE_REQUEST 135
+#define SSL_F_SSL3_GET_CERT_STATUS 288
+#define SSL_F_SSL3_GET_CERT_VERIFY 136
+#define SSL_F_SSL3_GET_CLIENT_CERTIFICATE 137
+#define SSL_F_SSL3_GET_CLIENT_HELLO 138
+#define SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE 139
+#define SSL_F_SSL3_GET_FINISHED 140
+#define SSL_F_SSL3_GET_KEY_EXCHANGE 141
+#define SSL_F_SSL3_GET_MESSAGE 142
+#define SSL_F_SSL3_GET_NEW_SESSION_TICKET 283
+#define SSL_F_SSL3_GET_RECORD 143
+#define SSL_F_SSL3_GET_SERVER_CERTIFICATE 144
+#define SSL_F_SSL3_GET_SERVER_DONE 145
+#define SSL_F_SSL3_GET_SERVER_HELLO 146
+#define SSL_F_SSL3_NEW_SESSION_TICKET 284
+#define SSL_F_SSL3_OUTPUT_CERT_CHAIN 147
+#define SSL_F_SSL3_PEEK 235
+#define SSL_F_SSL3_READ_BYTES 148
+#define SSL_F_SSL3_READ_N 149
+#define SSL_F_SSL3_SEND_CERTIFICATE_REQUEST 150
+#define SSL_F_SSL3_SEND_CLIENT_CERTIFICATE 151
+#define SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE 152
+#define SSL_F_SSL3_SEND_CLIENT_VERIFY 153
+#define SSL_F_SSL3_SEND_SERVER_CERTIFICATE 154
+#define SSL_F_SSL3_SEND_SERVER_HELLO 242
+#define SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE 155
+#define SSL_F_SSL3_SETUP_BUFFERS 156
+#define SSL_F_SSL3_SETUP_KEY_BLOCK 157
+#define SSL_F_SSL3_WRITE_BYTES 158
+#define SSL_F_SSL3_WRITE_PENDING 159
+#define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT 285
+#define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT 272
+#define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK 215
+#define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK 216
+#define SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT 286
+#define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT 273
+#define SSL_F_SSL_BAD_METHOD 160
+#define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161
+#define SSL_F_SSL_CERT_DUP 221
+#define SSL_F_SSL_CERT_INST 222
+#define SSL_F_SSL_CERT_INSTANTIATE 214
+#define SSL_F_SSL_CERT_NEW 162
+#define SSL_F_SSL_CHECK_PRIVATE_KEY 163
+#define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT 274
+#define SSL_F_SSL_CIPHER_PROCESS_RULESTR 230
+#define SSL_F_SSL_CIPHER_STRENGTH_SORT 231
+#define SSL_F_SSL_CLEAR 164
+#define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD 165
+#define SSL_F_SSL_CREATE_CIPHER_LIST 166
+#define SSL_F_SSL_CTRL 232
+#define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY 168
+#define SSL_F_SSL_CTX_NEW 169
+#define SSL_F_SSL_CTX_SET_CIPHER_LIST 269
+#define SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE 278
+#define SSL_F_SSL_CTX_SET_PURPOSE 226
+#define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT 219
+#define SSL_F_SSL_CTX_SET_SSL_VERSION 170
+#define SSL_F_SSL_CTX_SET_TRUST 229
+#define SSL_F_SSL_CTX_USE_CERTIFICATE 171
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 172
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE 220
+#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 173
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY 174
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 175
+#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 176
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 177
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 178
+#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 179
+#define SSL_F_SSL_DO_HANDSHAKE 180
+#define SSL_F_SSL_GET_NEW_SESSION 181
+#define SSL_F_SSL_GET_PREV_SESSION 217
+#define SSL_F_SSL_GET_SERVER_SEND_CERT 182
+#define SSL_F_SSL_GET_SIGN_PKEY 183
+#define SSL_F_SSL_INIT_WBIO_BUFFER 184
+#define SSL_F_SSL_LOAD_CLIENT_CA_FILE 185
+#define SSL_F_SSL_NEW 186
+#define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT 287
+#define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT 290
+#define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT 289
+#define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT 291
+#define SSL_F_SSL_PEEK 270
+#define SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT 275
+#define SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT 276
+#define SSL_F_SSL_READ 223
+#define SSL_F_SSL_RSA_PRIVATE_DECRYPT 187
+#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 188
+#define SSL_F_SSL_SESSION_NEW 189
+#define SSL_F_SSL_SESSION_PRINT_FP 190
+#define SSL_F_SSL_SESS_CERT_NEW 225
+#define SSL_F_SSL_SET_CERT 191
+#define SSL_F_SSL_SET_CIPHER_LIST 271
+#define SSL_F_SSL_SET_FD 192
+#define SSL_F_SSL_SET_PKEY 193
+#define SSL_F_SSL_SET_PURPOSE 227
+#define SSL_F_SSL_SET_RFD 194
+#define SSL_F_SSL_SET_SESSION 195
+#define SSL_F_SSL_SET_SESSION_ID_CONTEXT 218
+#define SSL_F_SSL_SET_TRUST 228
+#define SSL_F_SSL_SET_WFD 196
+#define SSL_F_SSL_SHUTDOWN 224
+#define SSL_F_SSL_UNDEFINED_CONST_FUNCTION 243
+#define SSL_F_SSL_UNDEFINED_FUNCTION 197
+#define SSL_F_SSL_UNDEFINED_VOID_FUNCTION 244
+#define SSL_F_SSL_USE_CERTIFICATE 198
+#define SSL_F_SSL_USE_CERTIFICATE_ASN1 199
+#define SSL_F_SSL_USE_CERTIFICATE_FILE 200
+#define SSL_F_SSL_USE_PRIVATEKEY 201
+#define SSL_F_SSL_USE_PRIVATEKEY_ASN1 202
+#define SSL_F_SSL_USE_PRIVATEKEY_FILE 203
+#define SSL_F_SSL_USE_RSAPRIVATEKEY 204
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 205
+#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 206
+#define SSL_F_SSL_VERIFY_CERT_CHAIN 207
+#define SSL_F_SSL_WRITE 208
+#define SSL_F_TLS1_CHANGE_CIPHER_STATE 209
+#define SSL_F_TLS1_ENC 210
+#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
+#define SSL_F_WRITE_PENDING 212
+
+/* Reason codes. */
+#define SSL_R_APP_DATA_IN_HANDSHAKE 100
+#define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
+#define SSL_R_BAD_ALERT_RECORD 101
+#define SSL_R_BAD_AUTHENTICATION_TYPE 102
+#define SSL_R_BAD_CHANGE_CIPHER_SPEC 103
+#define SSL_R_BAD_CHECKSUM 104
+#define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 106
+#define SSL_R_BAD_DECOMPRESSION 107
+#define SSL_R_BAD_DH_G_LENGTH 108
+#define SSL_R_BAD_DH_PUB_KEY_LENGTH 109
+#define SSL_R_BAD_DH_P_LENGTH 110
+#define SSL_R_BAD_DIGEST_LENGTH 111
+#define SSL_R_BAD_DSA_SIGNATURE 112
+#define SSL_R_BAD_ECC_CERT 304
+#define SSL_R_BAD_ECDSA_SIGNATURE 305
+#define SSL_R_BAD_ECPOINT 306
+#define SSL_R_BAD_HELLO_REQUEST 105
+#define SSL_R_BAD_LENGTH 271
+#define SSL_R_BAD_MAC_DECODE 113
+#define SSL_R_BAD_MESSAGE_TYPE 114
+#define SSL_R_BAD_PACKET_LENGTH 115
+#define SSL_R_BAD_PROTOCOL_VERSION_NUMBER 116
+#define SSL_R_BAD_RESPONSE_ARGUMENT 117
+#define SSL_R_BAD_RSA_DECRYPT 118
+#define SSL_R_BAD_RSA_ENCRYPT 119
+#define SSL_R_BAD_RSA_E_LENGTH 120
+#define SSL_R_BAD_RSA_MODULUS_LENGTH 121
+#define SSL_R_BAD_RSA_SIGNATURE 122
+#define SSL_R_BAD_SIGNATURE 123
+#define SSL_R_BAD_SSL_FILETYPE 124
+#define SSL_R_BAD_SSL_SESSION_ID_LENGTH 125
+#define SSL_R_BAD_STATE 126
+#define SSL_R_BAD_WRITE_RETRY 127
+#define SSL_R_BIO_NOT_SET 128
+#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG 129
+#define SSL_R_BN_LIB 130
+#define SSL_R_CA_DN_LENGTH_MISMATCH 131
+#define SSL_R_CA_DN_TOO_LONG 132
+#define SSL_R_CCS_RECEIVED_EARLY 133
+#define SSL_R_CERTIFICATE_VERIFY_FAILED 134
+#define SSL_R_CERT_LENGTH_MISMATCH 135
+#define SSL_R_CHALLENGE_IS_DIFFERENT 136
+#define SSL_R_CIPHER_CODE_WRONG_LENGTH 137
+#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE 138
+#define SSL_R_CIPHER_TABLE_SRC_ERROR 139
+#define SSL_R_CLIENTHELLO_TLSEXT 157
+#define SSL_R_COMPRESSED_LENGTH_TOO_LONG 140
+#define SSL_R_COMPRESSION_FAILURE 141
+#define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE 307
+#define SSL_R_COMPRESSION_LIBRARY_ERROR 142
+#define SSL_R_CONNECTION_ID_IS_DIFFERENT 143
+#define SSL_R_CONNECTION_TYPE_NOT_SET 144
+#define SSL_R_COOKIE_MISMATCH 308
+#define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED 145
+#define SSL_R_DATA_LENGTH_TOO_LONG 146
+#define SSL_R_DECRYPTION_FAILED 147
+#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 281
+#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 148
+#define SSL_R_DIGEST_CHECK_FAILED 149
+#define SSL_R_DTLS_MESSAGE_TOO_BIG 318
+#define SSL_R_DUPLICATE_COMPRESSION_ID 309
+#define SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER 310
+#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 150
+#define SSL_R_ERROR_GENERATING_TMP_RSA_KEY 282
+#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST 151
+#define SSL_R_EXCESSIVE_MESSAGE_SIZE 152
+#define SSL_R_EXTRA_DATA_IN_MESSAGE 153
+#define SSL_R_GOT_A_FIN_BEFORE_A_CCS 154
+#define SSL_R_HTTPS_PROXY_REQUEST 155
+#define SSL_R_HTTP_REQUEST 156
+#define SSL_R_ILLEGAL_PADDING 283
+#define SSL_R_INVALID_CHALLENGE_LENGTH 158
+#define SSL_R_INVALID_COMMAND 280
+#define SSL_R_INVALID_PURPOSE 278
+#define SSL_R_INVALID_STATUS_RESPONSE 316
+#define SSL_R_INVALID_TICKET_KEYS_LENGTH 275
+#define SSL_R_INVALID_TRUST 279
+#define SSL_R_KEY_ARG_TOO_LONG 284
+#define SSL_R_KRB5 285
+#define SSL_R_KRB5_C_CC_PRINC 286
+#define SSL_R_KRB5_C_GET_CRED 287
+#define SSL_R_KRB5_C_INIT 288
+#define SSL_R_KRB5_C_MK_REQ 289
+#define SSL_R_KRB5_S_BAD_TICKET 290
+#define SSL_R_KRB5_S_INIT 291
+#define SSL_R_KRB5_S_RD_REQ 292
+#define SSL_R_KRB5_S_TKT_EXPIRED 293
+#define SSL_R_KRB5_S_TKT_NYV 294
+#define SSL_R_KRB5_S_TKT_SKEW 295
+#define SSL_R_LENGTH_MISMATCH 159
+#define SSL_R_LENGTH_TOO_SHORT 160
+#define SSL_R_LIBRARY_BUG 274
+#define SSL_R_LIBRARY_HAS_NO_CIPHERS 161
+#define SSL_R_MESSAGE_TOO_LONG 296
+#define SSL_R_MISSING_DH_DSA_CERT 162
+#define SSL_R_MISSING_DH_KEY 163
+#define SSL_R_MISSING_DH_RSA_CERT 164
+#define SSL_R_MISSING_DSA_SIGNING_CERT 165
+#define SSL_R_MISSING_EXPORT_TMP_DH_KEY 166
+#define SSL_R_MISSING_EXPORT_TMP_RSA_KEY 167
+#define SSL_R_MISSING_RSA_CERTIFICATE 168
+#define SSL_R_MISSING_RSA_ENCRYPTING_CERT 169
+#define SSL_R_MISSING_RSA_SIGNING_CERT 170
+#define SSL_R_MISSING_TMP_DH_KEY 171
+#define SSL_R_MISSING_TMP_ECDH_KEY 311
+#define SSL_R_MISSING_TMP_RSA_KEY 172
+#define SSL_R_MISSING_TMP_RSA_PKEY 173
+#define SSL_R_MISSING_VERIFY_MESSAGE 174
+#define SSL_R_MULTIPLE_SGC_RESTARTS 325
+#define SSL_R_NON_SSLV2_INITIAL_PACKET 175
+#define SSL_R_NO_CERTIFICATES_RETURNED 176
+#define SSL_R_NO_CERTIFICATE_ASSIGNED 177
+#define SSL_R_NO_CERTIFICATE_RETURNED 178
+#define SSL_R_NO_CERTIFICATE_SET 179
+#define SSL_R_NO_CERTIFICATE_SPECIFIED 180
+#define SSL_R_NO_CIPHERS_AVAILABLE 181
+#define SSL_R_NO_CIPHERS_PASSED 182
+#define SSL_R_NO_CIPHERS_SPECIFIED 183
+#define SSL_R_NO_CIPHER_LIST 184
+#define SSL_R_NO_CIPHER_MATCH 185
+#define SSL_R_NO_CLIENT_CERT_METHOD 317
+#define SSL_R_NO_CLIENT_CERT_RECEIVED 186
+#define SSL_R_NO_COMPRESSION_SPECIFIED 187
+#define SSL_R_NO_METHOD_SPECIFIED 188
+#define SSL_R_NO_PRIVATEKEY 189
+#define SSL_R_NO_PRIVATE_KEY_ASSIGNED 190
+#define SSL_R_NO_PROTOCOLS_AVAILABLE 191
+#define SSL_R_NO_PUBLICKEY 192
+#define SSL_R_NO_RENEGOTIATION 319
+#define SSL_R_NO_SHARED_CIPHER 193
+#define SSL_R_NO_VERIFY_CALLBACK 194
+#define SSL_R_NULL_SSL_CTX 195
+#define SSL_R_NULL_SSL_METHOD_PASSED 196
+#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197
+#define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE 297
+#define SSL_R_PACKET_LENGTH_TOO_LONG 198
+#define SSL_R_PARSE_TLSEXT 223
+#define SSL_R_PATH_TOO_LONG 270
+#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 199
+#define SSL_R_PEER_ERROR 200
+#define SSL_R_PEER_ERROR_CERTIFICATE 201
+#define SSL_R_PEER_ERROR_NO_CERTIFICATE 202
+#define SSL_R_PEER_ERROR_NO_CIPHER 203
+#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 204
+#define SSL_R_PRE_MAC_LENGTH_TOO_LONG 205
+#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS 206
+#define SSL_R_PROTOCOL_IS_SHUTDOWN 207
+#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR 208
+#define SSL_R_PUBLIC_KEY_IS_NOT_RSA 209
+#define SSL_R_PUBLIC_KEY_NOT_RSA 210
+#define SSL_R_READ_BIO_NOT_SET 211
+#define SSL_R_READ_TIMEOUT_EXPIRED 312
+#define SSL_R_READ_WRONG_PACKET_TYPE 212
+#define SSL_R_RECORD_LENGTH_MISMATCH 213
+#define SSL_R_RECORD_TOO_LARGE 214
+#define SSL_R_RECORD_TOO_SMALL 298
+#define SSL_R_RENEGOTIATE_EXT_TOO_LONG 320
+#define SSL_R_RENEGOTIATION_ENCODING_ERR 321
+#define SSL_R_RENEGOTIATION_MISMATCH 322
+#define SSL_R_REQUIRED_CIPHER_MISSING 215
+#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 216
+#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO 217
+#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO 218
+#define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING 324
+#define SSL_R_SERVERHELLO_TLSEXT 224
+#define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 277
+#define SSL_R_SHORT_READ 219
+#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220
+#define SSL_R_SSL23_DOING_SESSION_ID_REUSE 221
+#define SSL_R_SSL2_CONNECTION_ID_TOO_LONG 299
+#define SSL_R_SSL3_EXT_INVALID_SERVERNAME 225
+#define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE 226
+#define SSL_R_SSL3_SESSION_ID_TOO_LONG 300
+#define SSL_R_SSL3_SESSION_ID_TOO_SHORT 222
+#define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042
+#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED 1044
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 1046
+#define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE 1030
+#define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040
+#define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047
+#define SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041
+#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
+#define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043
+#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION 228
+#define SSL_R_SSL_HANDSHAKE_FAILURE 229
+#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS 230
+#define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED 301
+#define SSL_R_SSL_SESSION_ID_CONFLICT 302
+#define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG 273
+#define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH 303
+#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT 231
+#define SSL_R_TLSV1_ALERT_ACCESS_DENIED 1049
+#define SSL_R_TLSV1_ALERT_DECODE_ERROR 1050
+#define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021
+#define SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051
+#define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060
+#define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071
+#define SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080
+#define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100
+#define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070
+#define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022
+#define SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048
+#define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090
+#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 232
+#define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 227
+#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233
+#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG 234
+#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER 235
+#define SSL_R_UNABLE_TO_DECODE_DH_CERTS 236
+#define SSL_R_UNABLE_TO_DECODE_ECDH_CERTS 313
+#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY 237
+#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS 238
+#define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS 314
+#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 239
+#define SSL_R_UNABLE_TO_FIND_SSL_METHOD 240
+#define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES 241
+#define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 242
+#define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 243
+#define SSL_R_UNEXPECTED_MESSAGE 244
+#define SSL_R_UNEXPECTED_RECORD 245
+#define SSL_R_UNINITIALIZED 276
+#define SSL_R_UNKNOWN_ALERT_TYPE 246
+#define SSL_R_UNKNOWN_CERTIFICATE_TYPE 247
+#define SSL_R_UNKNOWN_CIPHER_RETURNED 248
+#define SSL_R_UNKNOWN_CIPHER_TYPE 249
+#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE 250
+#define SSL_R_UNKNOWN_PKEY_TYPE 251
+#define SSL_R_UNKNOWN_PROTOCOL 252
+#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE 253
+#define SSL_R_UNKNOWN_SSL_VERSION 254
+#define SSL_R_UNKNOWN_STATE 255
+#define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED 323
+#define SSL_R_UNSUPPORTED_CIPHER 256
+#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 257
+#define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE 315
+#define SSL_R_UNSUPPORTED_PROTOCOL 258
+#define SSL_R_UNSUPPORTED_SSL_VERSION 259
+#define SSL_R_UNSUPPORTED_STATUS_TYPE 329
+#define SSL_R_WRITE_BIO_NOT_SET 260
+#define SSL_R_WRONG_CIPHER_RETURNED 261
+#define SSL_R_WRONG_MESSAGE_TYPE 262
+#define SSL_R_WRONG_NUMBER_OF_KEY_BITS 263
+#define SSL_R_WRONG_SIGNATURE_LENGTH 264
+#define SSL_R_WRONG_SIGNATURE_SIZE 265
+#define SSL_R_WRONG_SSL_VERSION 266
+#define SSL_R_WRONG_VERSION_NUMBER 267
+#define SSL_R_X509_LIB 268
+#define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 269
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ssl2.h b/src/Mayaqua/win32_inc/openssl/ssl2.h
new file mode 100644
index 00000000..c871efec
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ssl2.h
@@ -0,0 +1,268 @@
+/* ssl/ssl2.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_SSL2_H
+#define HEADER_SSL2_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Protocol Version Codes */
+#define SSL2_VERSION 0x0002
+#define SSL2_VERSION_MAJOR 0x00
+#define SSL2_VERSION_MINOR 0x02
+/* #define SSL2_CLIENT_VERSION 0x0002 */
+/* #define SSL2_SERVER_VERSION 0x0002 */
+
+/* Protocol Message Codes */
+#define SSL2_MT_ERROR 0
+#define SSL2_MT_CLIENT_HELLO 1
+#define SSL2_MT_CLIENT_MASTER_KEY 2
+#define SSL2_MT_CLIENT_FINISHED 3
+#define SSL2_MT_SERVER_HELLO 4
+#define SSL2_MT_SERVER_VERIFY 5
+#define SSL2_MT_SERVER_FINISHED 6
+#define SSL2_MT_REQUEST_CERTIFICATE 7
+#define SSL2_MT_CLIENT_CERTIFICATE 8
+
+/* Error Message Codes */
+#define SSL2_PE_UNDEFINED_ERROR 0x0000
+#define SSL2_PE_NO_CIPHER 0x0001
+#define SSL2_PE_NO_CERTIFICATE 0x0002
+#define SSL2_PE_BAD_CERTIFICATE 0x0004
+#define SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE 0x0006
+
+/* Cipher Kind Values */
+#define SSL2_CK_NULL_WITH_MD5 0x02000000 /* v3 */
+#define SSL2_CK_RC4_128_WITH_MD5 0x02010080
+#define SSL2_CK_RC4_128_EXPORT40_WITH_MD5 0x02020080
+#define SSL2_CK_RC2_128_CBC_WITH_MD5 0x02030080
+#define SSL2_CK_RC2_128_CBC_EXPORT40_WITH_MD5 0x02040080
+#define SSL2_CK_IDEA_128_CBC_WITH_MD5 0x02050080
+#define SSL2_CK_DES_64_CBC_WITH_MD5 0x02060040
+#define SSL2_CK_DES_64_CBC_WITH_SHA 0x02060140 /* v3 */
+#define SSL2_CK_DES_192_EDE3_CBC_WITH_MD5 0x020700c0
+#define SSL2_CK_DES_192_EDE3_CBC_WITH_SHA 0x020701c0 /* v3 */
+#define SSL2_CK_RC4_64_WITH_MD5 0x02080080 /* MS hack */
+
+#define SSL2_CK_DES_64_CFB64_WITH_MD5_1 0x02ff0800 /* SSLeay */
+#define SSL2_CK_NULL 0x02ff0810 /* SSLeay */
+
+#define SSL2_TXT_DES_64_CFB64_WITH_MD5_1 "DES-CFB-M1"
+#define SSL2_TXT_NULL_WITH_MD5 "NULL-MD5"
+#define SSL2_TXT_RC4_128_WITH_MD5 "RC4-MD5"
+#define SSL2_TXT_RC4_128_EXPORT40_WITH_MD5 "EXP-RC4-MD5"
+#define SSL2_TXT_RC2_128_CBC_WITH_MD5 "RC2-CBC-MD5"
+#define SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 "EXP-RC2-CBC-MD5"
+#define SSL2_TXT_IDEA_128_CBC_WITH_MD5 "IDEA-CBC-MD5"
+#define SSL2_TXT_DES_64_CBC_WITH_MD5 "DES-CBC-MD5"
+#define SSL2_TXT_DES_64_CBC_WITH_SHA "DES-CBC-SHA"
+#define SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5 "DES-CBC3-MD5"
+#define SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA "DES-CBC3-SHA"
+#define SSL2_TXT_RC4_64_WITH_MD5 "RC4-64-MD5"
+
+#define SSL2_TXT_NULL "NULL"
+
+/* Flags for the SSL_CIPHER.algorithm2 field */
+#define SSL2_CF_5_BYTE_ENC 0x01
+#define SSL2_CF_8_BYTE_ENC 0x02
+
+/* Certificate Type Codes */
+#define SSL2_CT_X509_CERTIFICATE 0x01
+
+/* Authentication Type Code */
+#define SSL2_AT_MD5_WITH_RSA_ENCRYPTION 0x01
+
+#define SSL2_MAX_SSL_SESSION_ID_LENGTH 32
+
+/* Upper/Lower Bounds */
+#define SSL2_MAX_MASTER_KEY_LENGTH_IN_BITS 256
+#ifdef OPENSSL_SYS_MPE
+#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER 29998u
+#else
+#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER 32767u /* 2^15-1 */
+#endif
+#define SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER 16383 /* 2^14-1 */
+
+#define SSL2_CHALLENGE_LENGTH 16
+/*#define SSL2_CHALLENGE_LENGTH 32 */
+#define SSL2_MIN_CHALLENGE_LENGTH 16
+#define SSL2_MAX_CHALLENGE_LENGTH 32
+#define SSL2_CONNECTION_ID_LENGTH 16
+#define SSL2_MAX_CONNECTION_ID_LENGTH 16
+#define SSL2_SSL_SESSION_ID_LENGTH 16
+#define SSL2_MAX_CERT_CHALLENGE_LENGTH 32
+#define SSL2_MIN_CERT_CHALLENGE_LENGTH 16
+#define SSL2_MAX_KEY_MATERIAL_LENGTH 24
+
+#ifndef HEADER_SSL_LOCL_H
+#define CERT char
+#endif
+
+typedef struct ssl2_state_st
+ {
+ int three_byte_header;
+ int clear_text; /* clear text */
+ int escape; /* not used in SSLv2 */
+ int ssl2_rollback; /* used if SSLv23 rolled back to SSLv2 */
+
+ /* non-blocking io info, used to make sure the same
+ * args were passwd */
+ unsigned int wnum; /* number of bytes sent so far */
+ int wpend_tot;
+ const unsigned char *wpend_buf;
+
+ int wpend_off; /* offset to data to write */
+ int wpend_len; /* number of bytes passwd to write */
+ int wpend_ret; /* number of bytes to return to caller */
+
+ /* buffer raw data */
+ int rbuf_left;
+ int rbuf_offs;
+ unsigned char *rbuf;
+ unsigned char *wbuf;
+
+ unsigned char *write_ptr;/* used to point to the start due to
+ * 2/3 byte header. */
+
+ unsigned int padding;
+ unsigned int rlength; /* passed to ssl2_enc */
+ int ract_data_length; /* Set when things are encrypted. */
+ unsigned int wlength; /* passed to ssl2_enc */
+ int wact_data_length; /* Set when things are decrypted. */
+ unsigned char *ract_data;
+ unsigned char *wact_data;
+ unsigned char *mac_data;
+
+ unsigned char *read_key;
+ unsigned char *write_key;
+
+ /* Stuff specifically to do with this SSL session */
+ unsigned int challenge_length;
+ unsigned char challenge[SSL2_MAX_CHALLENGE_LENGTH];
+ unsigned int conn_id_length;
+ unsigned char conn_id[SSL2_MAX_CONNECTION_ID_LENGTH];
+ unsigned int key_material_length;
+ unsigned char key_material[SSL2_MAX_KEY_MATERIAL_LENGTH*2];
+
+ unsigned long read_sequence;
+ unsigned long write_sequence;
+
+ struct {
+ unsigned int conn_id_length;
+ unsigned int cert_type;
+ unsigned int cert_length;
+ unsigned int csl;
+ unsigned int clear;
+ unsigned int enc;
+ unsigned char ccl[SSL2_MAX_CERT_CHALLENGE_LENGTH];
+ unsigned int cipher_spec_length;
+ unsigned int session_id_length;
+ unsigned int clen;
+ unsigned int rlen;
+ } tmp;
+ } SSL2_STATE;
+
+/* SSLv2 */
+/* client */
+#define SSL2_ST_SEND_CLIENT_HELLO_A (0x10|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_HELLO_B (0x11|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_HELLO_A (0x20|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_HELLO_B (0x21|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_MASTER_KEY_A (0x30|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_MASTER_KEY_B (0x31|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_FINISHED_A (0x40|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_FINISHED_B (0x41|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_A (0x50|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_B (0x51|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_C (0x52|SSL_ST_CONNECT)
+#define SSL2_ST_SEND_CLIENT_CERTIFICATE_D (0x53|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_VERIFY_A (0x60|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_VERIFY_B (0x61|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_FINISHED_A (0x70|SSL_ST_CONNECT)
+#define SSL2_ST_GET_SERVER_FINISHED_B (0x71|SSL_ST_CONNECT)
+#define SSL2_ST_CLIENT_START_ENCRYPTION (0x80|SSL_ST_CONNECT)
+#define SSL2_ST_X509_GET_CLIENT_CERTIFICATE (0x90|SSL_ST_CONNECT)
+/* server */
+#define SSL2_ST_GET_CLIENT_HELLO_A (0x10|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_HELLO_B (0x11|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_HELLO_C (0x12|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_HELLO_A (0x20|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_HELLO_B (0x21|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_MASTER_KEY_A (0x30|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_MASTER_KEY_B (0x31|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_VERIFY_A (0x40|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_VERIFY_B (0x41|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_VERIFY_C (0x42|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_FINISHED_A (0x50|SSL_ST_ACCEPT)
+#define SSL2_ST_GET_CLIENT_FINISHED_B (0x51|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_FINISHED_A (0x60|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_SERVER_FINISHED_B (0x61|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_A (0x70|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_B (0x71|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_C (0x72|SSL_ST_ACCEPT)
+#define SSL2_ST_SEND_REQUEST_CERTIFICATE_D (0x73|SSL_ST_ACCEPT)
+#define SSL2_ST_SERVER_START_ENCRYPTION (0x80|SSL_ST_ACCEPT)
+#define SSL2_ST_X509_GET_SERVER_CERTIFICATE (0x90|SSL_ST_ACCEPT)
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/ssl23.h b/src/Mayaqua/win32_inc/openssl/ssl23.h
new file mode 100644
index 00000000..1a87d8cf
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ssl23.h
@@ -0,0 +1,83 @@
+/* ssl/ssl23.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_SSL23_H
+#define HEADER_SSL23_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*client */
+/* write to server */
+#define SSL23_ST_CW_CLNT_HELLO_A (0x210|SSL_ST_CONNECT)
+#define SSL23_ST_CW_CLNT_HELLO_B (0x211|SSL_ST_CONNECT)
+/* read from server */
+#define SSL23_ST_CR_SRVR_HELLO_A (0x220|SSL_ST_CONNECT)
+#define SSL23_ST_CR_SRVR_HELLO_B (0x221|SSL_ST_CONNECT)
+
+/* server */
+/* read from client */
+#define SSL23_ST_SR_CLNT_HELLO_A (0x210|SSL_ST_ACCEPT)
+#define SSL23_ST_SR_CLNT_HELLO_B (0x211|SSL_ST_ACCEPT)
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/ssl3.h b/src/Mayaqua/win32_inc/openssl/ssl3.h
new file mode 100644
index 00000000..d726b4f5
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ssl3.h
@@ -0,0 +1,585 @@
+/* ssl/ssl3.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_SSL3_H
+#define HEADER_SSL3_H
+
+#ifndef OPENSSL_NO_COMP
+#include <openssl/comp.h>
+#endif
+#include <openssl/buffer.h>
+#include <openssl/evp.h>
+#include <openssl/ssl.h>
+#include <openssl/pq_compat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Signalling cipher suite value: from draft-ietf-tls-renegotiation-03.txt */
+#define SSL3_CK_SCSV 0x030000FF
+
+#define SSL3_CK_RSA_NULL_MD5 0x03000001
+#define SSL3_CK_RSA_NULL_SHA 0x03000002
+#define SSL3_CK_RSA_RC4_40_MD5 0x03000003
+#define SSL3_CK_RSA_RC4_128_MD5 0x03000004
+#define SSL3_CK_RSA_RC4_128_SHA 0x03000005
+#define SSL3_CK_RSA_RC2_40_MD5 0x03000006
+#define SSL3_CK_RSA_IDEA_128_SHA 0x03000007
+#define SSL3_CK_RSA_DES_40_CBC_SHA 0x03000008
+#define SSL3_CK_RSA_DES_64_CBC_SHA 0x03000009
+#define SSL3_CK_RSA_DES_192_CBC3_SHA 0x0300000A
+
+#define SSL3_CK_DH_DSS_DES_40_CBC_SHA 0x0300000B
+#define SSL3_CK_DH_DSS_DES_64_CBC_SHA 0x0300000C
+#define SSL3_CK_DH_DSS_DES_192_CBC3_SHA 0x0300000D
+#define SSL3_CK_DH_RSA_DES_40_CBC_SHA 0x0300000E
+#define SSL3_CK_DH_RSA_DES_64_CBC_SHA 0x0300000F
+#define SSL3_CK_DH_RSA_DES_192_CBC3_SHA 0x03000010
+
+#define SSL3_CK_EDH_DSS_DES_40_CBC_SHA 0x03000011
+#define SSL3_CK_EDH_DSS_DES_64_CBC_SHA 0x03000012
+#define SSL3_CK_EDH_DSS_DES_192_CBC3_SHA 0x03000013
+#define SSL3_CK_EDH_RSA_DES_40_CBC_SHA 0x03000014
+#define SSL3_CK_EDH_RSA_DES_64_CBC_SHA 0x03000015
+#define SSL3_CK_EDH_RSA_DES_192_CBC3_SHA 0x03000016
+
+#define SSL3_CK_ADH_RC4_40_MD5 0x03000017
+#define SSL3_CK_ADH_RC4_128_MD5 0x03000018
+#define SSL3_CK_ADH_DES_40_CBC_SHA 0x03000019
+#define SSL3_CK_ADH_DES_64_CBC_SHA 0x0300001A
+#define SSL3_CK_ADH_DES_192_CBC_SHA 0x0300001B
+
+#define SSL3_CK_FZA_DMS_NULL_SHA 0x0300001C
+#define SSL3_CK_FZA_DMS_FZA_SHA 0x0300001D
+#if 0 /* Because it clashes with KRB5, is never used any more, and is safe
+ to remove according to David Hopwood <david.hopwood@zetnet.co.uk>
+ of the ietf-tls list */
+#define SSL3_CK_FZA_DMS_RC4_SHA 0x0300001E
+#endif
+
+/* VRS Additional Kerberos5 entries
+ */
+#define SSL3_CK_KRB5_DES_64_CBC_SHA 0x0300001E
+#define SSL3_CK_KRB5_DES_192_CBC3_SHA 0x0300001F
+#define SSL3_CK_KRB5_RC4_128_SHA 0x03000020
+#define SSL3_CK_KRB5_IDEA_128_CBC_SHA 0x03000021
+#define SSL3_CK_KRB5_DES_64_CBC_MD5 0x03000022
+#define SSL3_CK_KRB5_DES_192_CBC3_MD5 0x03000023
+#define SSL3_CK_KRB5_RC4_128_MD5 0x03000024
+#define SSL3_CK_KRB5_IDEA_128_CBC_MD5 0x03000025
+
+#define SSL3_CK_KRB5_DES_40_CBC_SHA 0x03000026
+#define SSL3_CK_KRB5_RC2_40_CBC_SHA 0x03000027
+#define SSL3_CK_KRB5_RC4_40_SHA 0x03000028
+#define SSL3_CK_KRB5_DES_40_CBC_MD5 0x03000029
+#define SSL3_CK_KRB5_RC2_40_CBC_MD5 0x0300002A
+#define SSL3_CK_KRB5_RC4_40_MD5 0x0300002B
+
+#define SSL3_TXT_RSA_NULL_MD5 "NULL-MD5"
+#define SSL3_TXT_RSA_NULL_SHA "NULL-SHA"
+#define SSL3_TXT_RSA_RC4_40_MD5 "EXP-RC4-MD5"
+#define SSL3_TXT_RSA_RC4_128_MD5 "RC4-MD5"
+#define SSL3_TXT_RSA_RC4_128_SHA "RC4-SHA"
+#define SSL3_TXT_RSA_RC2_40_MD5 "EXP-RC2-CBC-MD5"
+#define SSL3_TXT_RSA_IDEA_128_SHA "IDEA-CBC-SHA"
+#define SSL3_TXT_RSA_DES_40_CBC_SHA "EXP-DES-CBC-SHA"
+#define SSL3_TXT_RSA_DES_64_CBC_SHA "DES-CBC-SHA"
+#define SSL3_TXT_RSA_DES_192_CBC3_SHA "DES-CBC3-SHA"
+
+#define SSL3_TXT_DH_DSS_DES_40_CBC_SHA "EXP-DH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_DH_DSS_DES_64_CBC_SHA "DH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_DH_DSS_DES_192_CBC3_SHA "DH-DSS-DES-CBC3-SHA"
+#define SSL3_TXT_DH_RSA_DES_40_CBC_SHA "EXP-DH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_DH_RSA_DES_64_CBC_SHA "DH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_DH_RSA_DES_192_CBC3_SHA "DH-RSA-DES-CBC3-SHA"
+
+#define SSL3_TXT_EDH_DSS_DES_40_CBC_SHA "EXP-EDH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_EDH_DSS_DES_64_CBC_SHA "EDH-DSS-DES-CBC-SHA"
+#define SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA "EDH-DSS-DES-CBC3-SHA"
+#define SSL3_TXT_EDH_RSA_DES_40_CBC_SHA "EXP-EDH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_EDH_RSA_DES_64_CBC_SHA "EDH-RSA-DES-CBC-SHA"
+#define SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA "EDH-RSA-DES-CBC3-SHA"
+
+#define SSL3_TXT_ADH_RC4_40_MD5 "EXP-ADH-RC4-MD5"
+#define SSL3_TXT_ADH_RC4_128_MD5 "ADH-RC4-MD5"
+#define SSL3_TXT_ADH_DES_40_CBC_SHA "EXP-ADH-DES-CBC-SHA"
+#define SSL3_TXT_ADH_DES_64_CBC_SHA "ADH-DES-CBC-SHA"
+#define SSL3_TXT_ADH_DES_192_CBC_SHA "ADH-DES-CBC3-SHA"
+
+#define SSL3_TXT_FZA_DMS_NULL_SHA "FZA-NULL-SHA"
+#define SSL3_TXT_FZA_DMS_FZA_SHA "FZA-FZA-CBC-SHA"
+#define SSL3_TXT_FZA_DMS_RC4_SHA "FZA-RC4-SHA"
+
+#define SSL3_TXT_KRB5_DES_64_CBC_SHA "KRB5-DES-CBC-SHA"
+#define SSL3_TXT_KRB5_DES_192_CBC3_SHA "KRB5-DES-CBC3-SHA"
+#define SSL3_TXT_KRB5_RC4_128_SHA "KRB5-RC4-SHA"
+#define SSL3_TXT_KRB5_IDEA_128_CBC_SHA "KRB5-IDEA-CBC-SHA"
+#define SSL3_TXT_KRB5_DES_64_CBC_MD5 "KRB5-DES-CBC-MD5"
+#define SSL3_TXT_KRB5_DES_192_CBC3_MD5 "KRB5-DES-CBC3-MD5"
+#define SSL3_TXT_KRB5_RC4_128_MD5 "KRB5-RC4-MD5"
+#define SSL3_TXT_KRB5_IDEA_128_CBC_MD5 "KRB5-IDEA-CBC-MD5"
+
+#define SSL3_TXT_KRB5_DES_40_CBC_SHA "EXP-KRB5-DES-CBC-SHA"
+#define SSL3_TXT_KRB5_RC2_40_CBC_SHA "EXP-KRB5-RC2-CBC-SHA"
+#define SSL3_TXT_KRB5_RC4_40_SHA "EXP-KRB5-RC4-SHA"
+#define SSL3_TXT_KRB5_DES_40_CBC_MD5 "EXP-KRB5-DES-CBC-MD5"
+#define SSL3_TXT_KRB5_RC2_40_CBC_MD5 "EXP-KRB5-RC2-CBC-MD5"
+#define SSL3_TXT_KRB5_RC4_40_MD5 "EXP-KRB5-RC4-MD5"
+
+#define SSL3_SSL_SESSION_ID_LENGTH 32
+#define SSL3_MAX_SSL_SESSION_ID_LENGTH 32
+
+#define SSL3_MASTER_SECRET_SIZE 48
+#define SSL3_RANDOM_SIZE 32
+#define SSL3_SESSION_ID_SIZE 32
+#define SSL3_RT_HEADER_LENGTH 5
+
+/* Due to MS stuffing up, this can change.... */
+#if defined(OPENSSL_SYS_WIN16) || \
+ (defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32))
+#define SSL3_RT_MAX_EXTRA (14000)
+#else
+#define SSL3_RT_MAX_EXTRA (16384)
+#endif
+
+#define SSL3_RT_MAX_PLAIN_LENGTH 16384
+#ifdef OPENSSL_NO_COMP
+#define SSL3_RT_MAX_COMPRESSED_LENGTH SSL3_RT_MAX_PLAIN_LENGTH
+#else
+#define SSL3_RT_MAX_COMPRESSED_LENGTH (1024+SSL3_RT_MAX_PLAIN_LENGTH)
+#endif
+#define SSL3_RT_MAX_ENCRYPTED_LENGTH (1024+SSL3_RT_MAX_COMPRESSED_LENGTH)
+#define SSL3_RT_MAX_PACKET_SIZE (SSL3_RT_MAX_ENCRYPTED_LENGTH+SSL3_RT_HEADER_LENGTH)
+#define SSL3_RT_MAX_DATA_SIZE (1024*1024)
+
+#define SSL3_MD_CLIENT_FINISHED_CONST "\x43\x4C\x4E\x54"
+#define SSL3_MD_SERVER_FINISHED_CONST "\x53\x52\x56\x52"
+
+#define SSL3_VERSION 0x0300
+#define SSL3_VERSION_MAJOR 0x03
+#define SSL3_VERSION_MINOR 0x00
+
+#define SSL3_RT_CHANGE_CIPHER_SPEC 20
+#define SSL3_RT_ALERT 21
+#define SSL3_RT_HANDSHAKE 22
+#define SSL3_RT_APPLICATION_DATA 23
+
+#define SSL3_AL_WARNING 1
+#define SSL3_AL_FATAL 2
+
+#define SSL3_AD_CLOSE_NOTIFY 0
+#define SSL3_AD_UNEXPECTED_MESSAGE 10 /* fatal */
+#define SSL3_AD_BAD_RECORD_MAC 20 /* fatal */
+#define SSL3_AD_DECOMPRESSION_FAILURE 30 /* fatal */
+#define SSL3_AD_HANDSHAKE_FAILURE 40 /* fatal */
+#define SSL3_AD_NO_CERTIFICATE 41
+#define SSL3_AD_BAD_CERTIFICATE 42
+#define SSL3_AD_UNSUPPORTED_CERTIFICATE 43
+#define SSL3_AD_CERTIFICATE_REVOKED 44
+#define SSL3_AD_CERTIFICATE_EXPIRED 45
+#define SSL3_AD_CERTIFICATE_UNKNOWN 46
+#define SSL3_AD_ILLEGAL_PARAMETER 47 /* fatal */
+
+typedef struct ssl3_record_st
+ {
+/*r */ int type; /* type of record */
+/*rw*/ unsigned int length; /* How many bytes available */
+/*r */ unsigned int off; /* read/write offset into 'buf' */
+/*rw*/ unsigned char *data; /* pointer to the record data */
+/*rw*/ unsigned char *input; /* where the decode bytes are */
+/*r */ unsigned char *comp; /* only used with decompression - malloc()ed */
+/*r */ unsigned long epoch; /* epoch number, needed by DTLS1 */
+/*r */ PQ_64BIT seq_num; /* sequence number, needed by DTLS1 */
+ } SSL3_RECORD;
+
+typedef struct ssl3_buffer_st
+ {
+ unsigned char *buf; /* at least SSL3_RT_MAX_PACKET_SIZE bytes,
+ * see ssl3_setup_buffers() */
+ size_t len; /* buffer size */
+ int offset; /* where to 'copy from' */
+ int left; /* how many bytes left */
+ } SSL3_BUFFER;
+
+#define SSL3_CT_RSA_SIGN 1
+#define SSL3_CT_DSS_SIGN 2
+#define SSL3_CT_RSA_FIXED_DH 3
+#define SSL3_CT_DSS_FIXED_DH 4
+#define SSL3_CT_RSA_EPHEMERAL_DH 5
+#define SSL3_CT_DSS_EPHEMERAL_DH 6
+#define SSL3_CT_FORTEZZA_DMS 20
+/* SSL3_CT_NUMBER is used to size arrays and it must be large
+ * enough to contain all of the cert types defined either for
+ * SSLv3 and TLSv1.
+ */
+#define SSL3_CT_NUMBER 7
+
+
+#define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS 0x0001
+#define SSL3_FLAGS_DELAY_CLIENT_FINISHED 0x0002
+#define SSL3_FLAGS_POP_BUFFER 0x0004
+#define TLS1_FLAGS_TLS_PADDING_BUG 0x0008
+
+/* SSL3_FLAGS_SGC_RESTART_DONE is set when we
+ * restart a handshake because of MS SGC and so prevents us
+ * from restarting the handshake in a loop. It's reset on a
+ * renegotiation, so effectively limits the client to one restart
+ * per negotiation. This limits the possibility of a DDoS
+ * attack where the client handshakes in a loop using SGC to
+ * restart. Servers which permit renegotiation can still be
+ * effected, but we can't prevent that.
+ */
+#define SSL3_FLAGS_SGC_RESTART_DONE 0x0040
+
+typedef struct ssl3_state_st
+ {
+ long flags;
+ int delay_buf_pop_ret;
+
+ unsigned char read_sequence[8];
+ unsigned char read_mac_secret[EVP_MAX_MD_SIZE];
+ unsigned char write_sequence[8];
+ unsigned char write_mac_secret[EVP_MAX_MD_SIZE];
+
+ unsigned char server_random[SSL3_RANDOM_SIZE];
+ unsigned char client_random[SSL3_RANDOM_SIZE];
+
+ /* flags for countermeasure against known-IV weakness */
+ int need_empty_fragments;
+ int empty_fragment_done;
+
+ SSL3_BUFFER rbuf; /* read IO goes into here */
+ SSL3_BUFFER wbuf; /* write IO goes into here */
+
+ SSL3_RECORD rrec; /* each decoded record goes in here */
+ SSL3_RECORD wrec; /* goes out from here */
+
+ /* storage for Alert/Handshake protocol data received but not
+ * yet processed by ssl3_read_bytes: */
+ unsigned char alert_fragment[2];
+ unsigned int alert_fragment_len;
+ unsigned char handshake_fragment[4];
+ unsigned int handshake_fragment_len;
+
+ /* partial write - check the numbers match */
+ unsigned int wnum; /* number of bytes sent so far */
+ int wpend_tot; /* number bytes written */
+ int wpend_type;
+ int wpend_ret; /* number of bytes submitted */
+ const unsigned char *wpend_buf;
+
+ /* used during startup, digest all incoming/outgoing packets */
+ EVP_MD_CTX finish_dgst1;
+ EVP_MD_CTX finish_dgst2;
+
+ /* this is set whenerver we see a change_cipher_spec message
+ * come in when we are not looking for one */
+ int change_cipher_spec;
+
+ int warn_alert;
+ int fatal_alert;
+ /* we allow one fatal and one warning alert to be outstanding,
+ * send close alert via the warning alert */
+ int alert_dispatch;
+ unsigned char send_alert[2];
+
+ /* This flag is set when we should renegotiate ASAP, basically when
+ * there is no more data in the read or write buffers */
+ int renegotiate;
+ int total_renegotiations;
+ int num_renegotiations;
+
+ int in_read_app_data;
+
+ struct {
+ /* actually only needs to be 16+20 */
+ unsigned char cert_verify_md[EVP_MAX_MD_SIZE*2];
+
+ /* actually only need to be 16+20 for SSLv3 and 12 for TLS */
+ unsigned char finish_md[EVP_MAX_MD_SIZE*2];
+ int finish_md_len;
+ unsigned char peer_finish_md[EVP_MAX_MD_SIZE*2];
+ int peer_finish_md_len;
+
+ unsigned long message_size;
+ int message_type;
+
+ /* used to hold the new cipher we are going to use */
+ SSL_CIPHER *new_cipher;
+#ifndef OPENSSL_NO_DH
+ DH *dh;
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+ EC_KEY *ecdh; /* holds short lived ECDH key */
+#endif
+
+ /* used when SSL_ST_FLUSH_DATA is entered */
+ int next_state;
+
+ int reuse_message;
+
+ /* used for certificate requests */
+ int cert_req;
+ int ctype_num;
+ char ctype[SSL3_CT_NUMBER];
+ STACK_OF(X509_NAME) *ca_names;
+
+ int use_rsa_tmp;
+
+ int key_block_length;
+ unsigned char *key_block;
+
+ const EVP_CIPHER *new_sym_enc;
+ const EVP_MD *new_hash;
+#ifndef OPENSSL_NO_COMP
+ const SSL_COMP *new_compression;
+#else
+ char *new_compression;
+#endif
+ int cert_request;
+ } tmp;
+
+ /* Connection binding to prevent renegotiation attacks */
+ unsigned char previous_client_finished[EVP_MAX_MD_SIZE];
+ unsigned char previous_client_finished_len;
+ unsigned char previous_server_finished[EVP_MAX_MD_SIZE];
+ unsigned char previous_server_finished_len;
+ int send_connection_binding; /* TODOEKR */
+ } SSL3_STATE;
+
+
+/* SSLv3 */
+/*client */
+/* extra state */
+#define SSL3_ST_CW_FLUSH (0x100|SSL_ST_CONNECT)
+/* write to server */
+#define SSL3_ST_CW_CLNT_HELLO_A (0x110|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CLNT_HELLO_B (0x111|SSL_ST_CONNECT)
+/* read from server */
+#define SSL3_ST_CR_SRVR_HELLO_A (0x120|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SRVR_HELLO_B (0x121|SSL_ST_CONNECT)
+#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A (0x126|SSL_ST_CONNECT)
+#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B (0x127|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_A (0x130|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_B (0x131|SSL_ST_CONNECT)
+#define SSL3_ST_CR_KEY_EXCH_A (0x140|SSL_ST_CONNECT)
+#define SSL3_ST_CR_KEY_EXCH_B (0x141|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_REQ_A (0x150|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_REQ_B (0x151|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SRVR_DONE_A (0x160|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SRVR_DONE_B (0x161|SSL_ST_CONNECT)
+/* write to server */
+#define SSL3_ST_CW_CERT_A (0x170|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_B (0x171|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_C (0x172|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_D (0x173|SSL_ST_CONNECT)
+#define SSL3_ST_CW_KEY_EXCH_A (0x180|SSL_ST_CONNECT)
+#define SSL3_ST_CW_KEY_EXCH_B (0x181|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_VRFY_A (0x190|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CERT_VRFY_B (0x191|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CHANGE_A (0x1A0|SSL_ST_CONNECT)
+#define SSL3_ST_CW_CHANGE_B (0x1A1|SSL_ST_CONNECT)
+#define SSL3_ST_CW_FINISHED_A (0x1B0|SSL_ST_CONNECT)
+#define SSL3_ST_CW_FINISHED_B (0x1B1|SSL_ST_CONNECT)
+/* read from server */
+#define SSL3_ST_CR_CHANGE_A (0x1C0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CHANGE_B (0x1C1|SSL_ST_CONNECT)
+#define SSL3_ST_CR_FINISHED_A (0x1D0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_FINISHED_B (0x1D1|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SESSION_TICKET_A (0x1E0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SESSION_TICKET_B (0x1E1|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_STATUS_A (0x1F0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_STATUS_B (0x1F1|SSL_ST_CONNECT)
+
+/* server */
+/* extra state */
+#define SSL3_ST_SW_FLUSH (0x100|SSL_ST_ACCEPT)
+/* read from client */
+/* Do not change the number values, they do matter */
+#define SSL3_ST_SR_CLNT_HELLO_A (0x110|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CLNT_HELLO_B (0x111|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CLNT_HELLO_C (0x112|SSL_ST_ACCEPT)
+/* write to client */
+#define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A (0x113|SSL_ST_ACCEPT)
+#define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B (0x114|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_HELLO_REQ_A (0x120|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_HELLO_REQ_B (0x121|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_HELLO_REQ_C (0x122|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_HELLO_A (0x130|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_HELLO_B (0x131|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_A (0x140|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_B (0x141|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_KEY_EXCH_A (0x150|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_KEY_EXCH_B (0x151|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_REQ_A (0x160|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_REQ_B (0x161|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_DONE_A (0x170|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SRVR_DONE_B (0x171|SSL_ST_ACCEPT)
+/* read from client */
+#define SSL3_ST_SR_CERT_A (0x180|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CERT_B (0x181|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_KEY_EXCH_A (0x190|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_KEY_EXCH_B (0x191|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CERT_VRFY_A (0x1A0|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CERT_VRFY_B (0x1A1|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CHANGE_A (0x1B0|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CHANGE_B (0x1B1|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_FINISHED_A (0x1C0|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_FINISHED_B (0x1C1|SSL_ST_ACCEPT)
+/* write to client */
+#define SSL3_ST_SW_CHANGE_A (0x1D0|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CHANGE_B (0x1D1|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_FINISHED_A (0x1E0|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_FINISHED_B (0x1E1|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SESSION_TICKET_A (0x1F0|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SESSION_TICKET_B (0x1F1|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_STATUS_A (0x200|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_STATUS_B (0x201|SSL_ST_ACCEPT)
+
+#define SSL3_MT_HELLO_REQUEST 0
+#define SSL3_MT_CLIENT_HELLO 1
+#define SSL3_MT_SERVER_HELLO 2
+#define SSL3_MT_NEWSESSION_TICKET 4
+#define SSL3_MT_CERTIFICATE 11
+#define SSL3_MT_SERVER_KEY_EXCHANGE 12
+#define SSL3_MT_CERTIFICATE_REQUEST 13
+#define SSL3_MT_SERVER_DONE 14
+#define SSL3_MT_CERTIFICATE_VERIFY 15
+#define SSL3_MT_CLIENT_KEY_EXCHANGE 16
+#define SSL3_MT_FINISHED 20
+#define SSL3_MT_CERTIFICATE_STATUS 22
+#define DTLS1_MT_HELLO_VERIFY_REQUEST 3
+
+
+#define SSL3_MT_CCS 1
+
+/* These are used when changing over to a new cipher */
+#define SSL3_CC_READ 0x01
+#define SSL3_CC_WRITE 0x02
+#define SSL3_CC_CLIENT 0x10
+#define SSL3_CC_SERVER 0x20
+#define SSL3_CHANGE_CIPHER_CLIENT_WRITE (SSL3_CC_CLIENT|SSL3_CC_WRITE)
+#define SSL3_CHANGE_CIPHER_SERVER_READ (SSL3_CC_SERVER|SSL3_CC_READ)
+#define SSL3_CHANGE_CIPHER_CLIENT_READ (SSL3_CC_CLIENT|SSL3_CC_READ)
+#define SSL3_CHANGE_CIPHER_SERVER_WRITE (SSL3_CC_SERVER|SSL3_CC_WRITE)
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/stack.h b/src/Mayaqua/win32_inc/openssl/stack.h
new file mode 100644
index 00000000..7f3b13d2
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/stack.h
@@ -0,0 +1,109 @@
+/* crypto/stack/stack.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_STACK_H
+#define HEADER_STACK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct stack_st
+ {
+ int num;
+ char **data;
+ int sorted;
+
+ int num_alloc;
+ int (*comp)(const char * const *, const char * const *);
+ } STACK;
+
+#define M_sk_num(sk) ((sk) ? (sk)->num:-1)
+#define M_sk_value(sk,n) ((sk) ? (sk)->data[n] : NULL)
+
+int sk_num(const STACK *);
+char *sk_value(const STACK *, int);
+
+char *sk_set(STACK *, int, char *);
+
+STACK *sk_new(int (*cmp)(const char * const *, const char * const *));
+STACK *sk_new_null(void);
+void sk_free(STACK *);
+void sk_pop_free(STACK *st, void (*func)(void *));
+int sk_insert(STACK *sk,char *data,int where);
+char *sk_delete(STACK *st,int loc);
+char *sk_delete_ptr(STACK *st, char *p);
+int sk_find(STACK *st,char *data);
+int sk_find_ex(STACK *st,char *data);
+int sk_push(STACK *st,char *data);
+int sk_unshift(STACK *st,char *data);
+char *sk_shift(STACK *st);
+char *sk_pop(STACK *st);
+void sk_zero(STACK *st);
+int (*sk_set_cmp_func(STACK *sk, int (*c)(const char * const *,
+ const char * const *)))
+ (const char * const *, const char * const *);
+STACK *sk_dup(STACK *st);
+void sk_sort(STACK *st);
+int sk_is_sorted(const STACK *st);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/store.h b/src/Mayaqua/win32_inc/openssl/store.h
new file mode 100644
index 00000000..9665d0d4
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/store.h
@@ -0,0 +1,554 @@
+/* crypto/store/store.h -*- mode:C; c-file-style: "eay" -*- */
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2003.
+ */
+/* ====================================================================
+ * Copyright (c) 2003 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_STORE_H
+#define HEADER_STORE_H
+
+#include <openssl/ossl_typ.h>
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+#include <openssl/x509.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Already defined in ossl_typ.h */
+/* typedef struct store_st STORE; */
+/* typedef struct store_method_st STORE_METHOD; */
+
+
+/* All the following functions return 0, a negative number or NULL on error.
+ When everything is fine, they return a positive value or a non-NULL
+ pointer, all depending on their purpose. */
+
+/* Creators and destructor. */
+STORE *STORE_new_method(const STORE_METHOD *method);
+STORE *STORE_new_engine(ENGINE *engine);
+void STORE_free(STORE *ui);
+
+
+/* Give a user interface parametrised control commands. This can be used to
+ send down an integer, a data pointer or a function pointer, as well as
+ be used to get information from a STORE. */
+int STORE_ctrl(STORE *store, int cmd, long i, void *p, void (*f)(void));
+
+/* A control to set the directory with keys and certificates. Used by the
+ built-in directory level method. */
+#define STORE_CTRL_SET_DIRECTORY 0x0001
+/* A control to set a file to load. Used by the built-in file level method. */
+#define STORE_CTRL_SET_FILE 0x0002
+/* A control to set a configuration file to load. Can be used by any method
+ that wishes to load a configuration file. */
+#define STORE_CTRL_SET_CONF_FILE 0x0003
+/* A control to set a the section of the loaded configuration file. Can be
+ used by any method that wishes to load a configuration file. */
+#define STORE_CTRL_SET_CONF_SECTION 0x0004
+
+
+/* Some methods may use extra data */
+#define STORE_set_app_data(s,arg) STORE_set_ex_data(s,0,arg)
+#define STORE_get_app_data(s) STORE_get_ex_data(s,0)
+int STORE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int STORE_set_ex_data(STORE *r,int idx,void *arg);
+void *STORE_get_ex_data(STORE *r, int idx);
+
+/* Use specific methods instead of the built-in one */
+const STORE_METHOD *STORE_get_method(STORE *store);
+const STORE_METHOD *STORE_set_method(STORE *store, const STORE_METHOD *meth);
+
+/* The standard OpenSSL methods. */
+/* This is the in-memory method. It does everything except revoking and updating,
+ and is of course volatile. It's used by other methods that have an in-memory
+ cache. */
+const STORE_METHOD *STORE_Memory(void);
+#if 0 /* Not yet implemented */
+/* This is the directory store. It does everything except revoking and updating,
+ and uses STORE_Memory() to cache things in memory. */
+const STORE_METHOD *STORE_Directory(void);
+/* This is the file store. It does everything except revoking and updating,
+ and uses STORE_Memory() to cache things in memory. Certificates are added
+ to it with the store operation, and it will only get cached certificates. */
+const STORE_METHOD *STORE_File(void);
+#endif
+
+/* Store functions take a type code for the type of data they should store
+ or fetch */
+typedef enum STORE_object_types
+ {
+ STORE_OBJECT_TYPE_X509_CERTIFICATE= 0x01, /* X509 * */
+ STORE_OBJECT_TYPE_X509_CRL= 0x02, /* X509_CRL * */
+ STORE_OBJECT_TYPE_PRIVATE_KEY= 0x03, /* EVP_PKEY * */
+ STORE_OBJECT_TYPE_PUBLIC_KEY= 0x04, /* EVP_PKEY * */
+ STORE_OBJECT_TYPE_NUMBER= 0x05, /* BIGNUM * */
+ STORE_OBJECT_TYPE_ARBITRARY= 0x06, /* BUF_MEM * */
+ STORE_OBJECT_TYPE_NUM= 0x06 /* The amount of known
+ object types */
+ } STORE_OBJECT_TYPES;
+/* List of text strings corresponding to the object types. */
+extern const char * const STORE_object_type_string[STORE_OBJECT_TYPE_NUM+1];
+
+/* Some store functions take a parameter list. Those parameters come with
+ one of the following codes. The comments following the codes below indicate
+ what type the value should be a pointer to. */
+typedef enum STORE_params
+ {
+ STORE_PARAM_EVP_TYPE= 0x01, /* int */
+ STORE_PARAM_BITS= 0x02, /* size_t */
+ STORE_PARAM_KEY_PARAMETERS= 0x03, /* ??? */
+ STORE_PARAM_KEY_NO_PARAMETERS= 0x04, /* N/A */
+ STORE_PARAM_AUTH_PASSPHRASE= 0x05, /* char * */
+ STORE_PARAM_AUTH_KRB5_TICKET= 0x06, /* void * */
+ STORE_PARAM_TYPE_NUM= 0x06 /* The amount of known
+ parameter types */
+ } STORE_PARAM_TYPES;
+/* Parameter value sizes. -1 means unknown, anything else is the required size. */
+extern const int STORE_param_sizes[STORE_PARAM_TYPE_NUM+1];
+
+/* Store functions take attribute lists. Those attributes come with codes.
+ The comments following the codes below indicate what type the value should
+ be a pointer to. */
+typedef enum STORE_attribs
+ {
+ STORE_ATTR_END= 0x00,
+ STORE_ATTR_FRIENDLYNAME= 0x01, /* C string */
+ STORE_ATTR_KEYID= 0x02, /* 160 bit string (SHA1) */
+ STORE_ATTR_ISSUERKEYID= 0x03, /* 160 bit string (SHA1) */
+ STORE_ATTR_SUBJECTKEYID= 0x04, /* 160 bit string (SHA1) */
+ STORE_ATTR_ISSUERSERIALHASH= 0x05, /* 160 bit string (SHA1) */
+ STORE_ATTR_ISSUER= 0x06, /* X509_NAME * */
+ STORE_ATTR_SERIAL= 0x07, /* BIGNUM * */
+ STORE_ATTR_SUBJECT= 0x08, /* X509_NAME * */
+ STORE_ATTR_CERTHASH= 0x09, /* 160 bit string (SHA1) */
+ STORE_ATTR_EMAIL= 0x0a, /* C string */
+ STORE_ATTR_FILENAME= 0x0b, /* C string */
+ STORE_ATTR_TYPE_NUM= 0x0b, /* The amount of known
+ attribute types */
+ STORE_ATTR_OR= 0xff /* This is a special
+ separator, which
+ expresses the OR
+ operation. */
+ } STORE_ATTR_TYPES;
+/* Attribute value sizes. -1 means unknown, anything else is the required size. */
+extern const int STORE_attr_sizes[STORE_ATTR_TYPE_NUM+1];
+
+typedef enum STORE_certificate_status
+ {
+ STORE_X509_VALID= 0x00,
+ STORE_X509_EXPIRED= 0x01,
+ STORE_X509_SUSPENDED= 0x02,
+ STORE_X509_REVOKED= 0x03
+ } STORE_CERTIFICATE_STATUS;
+
+/* Engine store functions will return a structure that contains all the necessary
+ * information, including revokation status for certificates. This is really not
+ * needed for application authors, as the ENGINE framework functions will extract
+ * the OpenSSL-specific information when at all possible. However, for engine
+ * authors, it's crucial to know this structure. */
+typedef struct STORE_OBJECT_st
+ {
+ STORE_OBJECT_TYPES type;
+ union
+ {
+ struct
+ {
+ STORE_CERTIFICATE_STATUS status;
+ X509 *certificate;
+ } x509;
+ X509_CRL *crl;
+ EVP_PKEY *key;
+ BIGNUM *number;
+ BUF_MEM *arbitrary;
+ } data;
+ } STORE_OBJECT;
+DECLARE_STACK_OF(STORE_OBJECT)
+STORE_OBJECT *STORE_OBJECT_new(void);
+void STORE_OBJECT_free(STORE_OBJECT *data);
+
+
+
+/* The following functions handle the storage. They return 0, a negative number
+ or NULL on error, anything else on success. */
+X509 *STORE_get_certificate(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_store_certificate(STORE *e, X509 *data, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_modify_certificate(STORE *e, OPENSSL_ITEM search_attributes[],
+ OPENSSL_ITEM add_attributes[], OPENSSL_ITEM modify_attributes[],
+ OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+int STORE_revoke_certificate(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_delete_certificate(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+void *STORE_list_certificate_start(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+X509 *STORE_list_certificate_next(STORE *e, void *handle);
+int STORE_list_certificate_end(STORE *e, void *handle);
+int STORE_list_certificate_endp(STORE *e, void *handle);
+EVP_PKEY *STORE_generate_key(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+EVP_PKEY *STORE_get_private_key(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_store_private_key(STORE *e, EVP_PKEY *data,
+ OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+int STORE_modify_private_key(STORE *e, OPENSSL_ITEM search_attributes[],
+ OPENSSL_ITEM add_sttributes[], OPENSSL_ITEM modify_attributes[],
+ OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+int STORE_revoke_private_key(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_delete_private_key(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+void *STORE_list_private_key_start(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+EVP_PKEY *STORE_list_private_key_next(STORE *e, void *handle);
+int STORE_list_private_key_end(STORE *e, void *handle);
+int STORE_list_private_key_endp(STORE *e, void *handle);
+EVP_PKEY *STORE_get_public_key(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_store_public_key(STORE *e, EVP_PKEY *data, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_modify_public_key(STORE *e, OPENSSL_ITEM search_attributes[],
+ OPENSSL_ITEM add_sttributes[], OPENSSL_ITEM modify_attributes[],
+ OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+int STORE_revoke_public_key(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_delete_public_key(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+void *STORE_list_public_key_start(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+EVP_PKEY *STORE_list_public_key_next(STORE *e, void *handle);
+int STORE_list_public_key_end(STORE *e, void *handle);
+int STORE_list_public_key_endp(STORE *e, void *handle);
+X509_CRL *STORE_generate_crl(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+X509_CRL *STORE_get_crl(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_store_crl(STORE *e, X509_CRL *data, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_modify_crl(STORE *e, OPENSSL_ITEM search_attributes[],
+ OPENSSL_ITEM add_sttributes[], OPENSSL_ITEM modify_attributes[],
+ OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+int STORE_delete_crl(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+void *STORE_list_crl_start(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+X509_CRL *STORE_list_crl_next(STORE *e, void *handle);
+int STORE_list_crl_end(STORE *e, void *handle);
+int STORE_list_crl_endp(STORE *e, void *handle);
+int STORE_store_number(STORE *e, BIGNUM *data, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_modify_number(STORE *e, OPENSSL_ITEM search_attributes[],
+ OPENSSL_ITEM add_sttributes[], OPENSSL_ITEM modify_attributes[],
+ OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+BIGNUM *STORE_get_number(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_delete_number(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_store_arbitrary(STORE *e, BUF_MEM *data, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_modify_arbitrary(STORE *e, OPENSSL_ITEM search_attributes[],
+ OPENSSL_ITEM add_sttributes[], OPENSSL_ITEM modify_attributes[],
+ OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+BUF_MEM *STORE_get_arbitrary(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+int STORE_delete_arbitrary(STORE *e, OPENSSL_ITEM attributes[],
+ OPENSSL_ITEM parameters[]);
+
+
+/* Create and manipulate methods */
+STORE_METHOD *STORE_create_method(char *name);
+void STORE_destroy_method(STORE_METHOD *store_method);
+
+/* These callback types are use for store handlers */
+typedef int (*STORE_INITIALISE_FUNC_PTR)(STORE *);
+typedef void (*STORE_CLEANUP_FUNC_PTR)(STORE *);
+typedef STORE_OBJECT *(*STORE_GENERATE_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef STORE_OBJECT *(*STORE_GET_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef void *(*STORE_START_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef STORE_OBJECT *(*STORE_NEXT_OBJECT_FUNC_PTR)(STORE *, void *handle);
+typedef int (*STORE_END_OBJECT_FUNC_PTR)(STORE *, void *handle);
+typedef int (*STORE_HANDLE_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef int (*STORE_STORE_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, STORE_OBJECT *data, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef int (*STORE_MODIFY_OBJECT_FUNC_PTR)(STORE *, STORE_OBJECT_TYPES type, OPENSSL_ITEM search_attributes[], OPENSSL_ITEM add_attributes[], OPENSSL_ITEM modify_attributes[], OPENSSL_ITEM delete_attributes[], OPENSSL_ITEM parameters[]);
+typedef int (*STORE_GENERIC_FUNC_PTR)(STORE *, OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
+typedef int (*STORE_CTRL_FUNC_PTR)(STORE *, int cmd, long l, void *p, void (*f)(void));
+
+int STORE_method_set_initialise_function(STORE_METHOD *sm, STORE_INITIALISE_FUNC_PTR init_f);
+int STORE_method_set_cleanup_function(STORE_METHOD *sm, STORE_CLEANUP_FUNC_PTR clean_f);
+int STORE_method_set_generate_function(STORE_METHOD *sm, STORE_GENERATE_OBJECT_FUNC_PTR generate_f);
+int STORE_method_set_get_function(STORE_METHOD *sm, STORE_GET_OBJECT_FUNC_PTR get_f);
+int STORE_method_set_store_function(STORE_METHOD *sm, STORE_STORE_OBJECT_FUNC_PTR store_f);
+int STORE_method_set_modify_function(STORE_METHOD *sm, STORE_MODIFY_OBJECT_FUNC_PTR store_f);
+int STORE_method_set_revoke_function(STORE_METHOD *sm, STORE_HANDLE_OBJECT_FUNC_PTR revoke_f);
+int STORE_method_set_delete_function(STORE_METHOD *sm, STORE_HANDLE_OBJECT_FUNC_PTR delete_f);
+int STORE_method_set_list_start_function(STORE_METHOD *sm, STORE_START_OBJECT_FUNC_PTR list_start_f);
+int STORE_method_set_list_next_function(STORE_METHOD *sm, STORE_NEXT_OBJECT_FUNC_PTR list_next_f);
+int STORE_method_set_list_end_function(STORE_METHOD *sm, STORE_END_OBJECT_FUNC_PTR list_end_f);
+int STORE_method_set_update_store_function(STORE_METHOD *sm, STORE_GENERIC_FUNC_PTR);
+int STORE_method_set_lock_store_function(STORE_METHOD *sm, STORE_GENERIC_FUNC_PTR);
+int STORE_method_set_unlock_store_function(STORE_METHOD *sm, STORE_GENERIC_FUNC_PTR);
+int STORE_method_set_ctrl_function(STORE_METHOD *sm, STORE_CTRL_FUNC_PTR ctrl_f);
+
+STORE_INITIALISE_FUNC_PTR STORE_method_get_initialise_function(STORE_METHOD *sm);
+STORE_CLEANUP_FUNC_PTR STORE_method_get_cleanup_function(STORE_METHOD *sm);
+STORE_GENERATE_OBJECT_FUNC_PTR STORE_method_get_generate_function(STORE_METHOD *sm);
+STORE_GET_OBJECT_FUNC_PTR STORE_method_get_get_function(STORE_METHOD *sm);
+STORE_STORE_OBJECT_FUNC_PTR STORE_method_get_store_function(STORE_METHOD *sm);
+STORE_MODIFY_OBJECT_FUNC_PTR STORE_method_get_modify_function(STORE_METHOD *sm);
+STORE_HANDLE_OBJECT_FUNC_PTR STORE_method_get_revoke_function(STORE_METHOD *sm);
+STORE_HANDLE_OBJECT_FUNC_PTR STORE_method_get_delete_function(STORE_METHOD *sm);
+STORE_START_OBJECT_FUNC_PTR STORE_method_get_list_start_function(STORE_METHOD *sm);
+STORE_NEXT_OBJECT_FUNC_PTR STORE_method_get_list_next_function(STORE_METHOD *sm);
+STORE_END_OBJECT_FUNC_PTR STORE_method_get_list_end_function(STORE_METHOD *sm);
+STORE_GENERIC_FUNC_PTR STORE_method_get_update_store_function(STORE_METHOD *sm);
+STORE_GENERIC_FUNC_PTR STORE_method_get_lock_store_function(STORE_METHOD *sm);
+STORE_GENERIC_FUNC_PTR STORE_method_get_unlock_store_function(STORE_METHOD *sm);
+STORE_CTRL_FUNC_PTR STORE_method_get_ctrl_function(STORE_METHOD *sm);
+
+/* Method helper structures and functions. */
+
+/* This structure is the result of parsing through the information in a list
+ of OPENSSL_ITEMs. It stores all the necessary information in a structured
+ way.*/
+typedef struct STORE_attr_info_st STORE_ATTR_INFO;
+
+/* Parse a list of OPENSSL_ITEMs and return a pointer to a STORE_ATTR_INFO.
+ Note that we do this in the list form, since the list of OPENSSL_ITEMs can
+ come in blocks separated with STORE_ATTR_OR. Note that the value returned
+ by STORE_parse_attrs_next() must be freed with STORE_ATTR_INFO_free(). */
+void *STORE_parse_attrs_start(OPENSSL_ITEM *attributes);
+STORE_ATTR_INFO *STORE_parse_attrs_next(void *handle);
+int STORE_parse_attrs_end(void *handle);
+int STORE_parse_attrs_endp(void *handle);
+
+/* Creator and destructor */
+STORE_ATTR_INFO *STORE_ATTR_INFO_new(void);
+int STORE_ATTR_INFO_free(STORE_ATTR_INFO *attrs);
+
+/* Manipulators */
+char *STORE_ATTR_INFO_get0_cstr(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code);
+unsigned char *STORE_ATTR_INFO_get0_sha1str(STORE_ATTR_INFO *attrs,
+ STORE_ATTR_TYPES code);
+X509_NAME *STORE_ATTR_INFO_get0_dn(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code);
+BIGNUM *STORE_ATTR_INFO_get0_number(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code);
+int STORE_ATTR_INFO_set_cstr(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ char *cstr, size_t cstr_size);
+int STORE_ATTR_INFO_set_sha1str(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ unsigned char *sha1str, size_t sha1str_size);
+int STORE_ATTR_INFO_set_dn(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ X509_NAME *dn);
+int STORE_ATTR_INFO_set_number(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ BIGNUM *number);
+int STORE_ATTR_INFO_modify_cstr(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ char *cstr, size_t cstr_size);
+int STORE_ATTR_INFO_modify_sha1str(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ unsigned char *sha1str, size_t sha1str_size);
+int STORE_ATTR_INFO_modify_dn(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ X509_NAME *dn);
+int STORE_ATTR_INFO_modify_number(STORE_ATTR_INFO *attrs, STORE_ATTR_TYPES code,
+ BIGNUM *number);
+
+/* Compare on basis of a bit pattern formed by the STORE_ATTR_TYPES values
+ in each contained attribute. */
+int STORE_ATTR_INFO_compare(STORE_ATTR_INFO *a, STORE_ATTR_INFO *b);
+/* Check if the set of attributes in a is within the range of attributes
+ set in b. */
+int STORE_ATTR_INFO_in_range(STORE_ATTR_INFO *a, STORE_ATTR_INFO *b);
+/* Check if the set of attributes in a are also set in b. */
+int STORE_ATTR_INFO_in(STORE_ATTR_INFO *a, STORE_ATTR_INFO *b);
+/* Same as STORE_ATTR_INFO_in(), but also checks the attribute values. */
+int STORE_ATTR_INFO_in_ex(STORE_ATTR_INFO *a, STORE_ATTR_INFO *b);
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_STORE_strings(void);
+
+/* Error codes for the STORE functions. */
+
+/* Function codes. */
+#define STORE_F_MEM_DELETE 134
+#define STORE_F_MEM_GENERATE 135
+#define STORE_F_MEM_LIST_END 168
+#define STORE_F_MEM_LIST_NEXT 136
+#define STORE_F_MEM_LIST_START 137
+#define STORE_F_MEM_MODIFY 169
+#define STORE_F_MEM_STORE 138
+#define STORE_F_STORE_ATTR_INFO_GET0_CSTR 139
+#define STORE_F_STORE_ATTR_INFO_GET0_DN 140
+#define STORE_F_STORE_ATTR_INFO_GET0_NUMBER 141
+#define STORE_F_STORE_ATTR_INFO_GET0_SHA1STR 142
+#define STORE_F_STORE_ATTR_INFO_MODIFY_CSTR 143
+#define STORE_F_STORE_ATTR_INFO_MODIFY_DN 144
+#define STORE_F_STORE_ATTR_INFO_MODIFY_NUMBER 145
+#define STORE_F_STORE_ATTR_INFO_MODIFY_SHA1STR 146
+#define STORE_F_STORE_ATTR_INFO_SET_CSTR 147
+#define STORE_F_STORE_ATTR_INFO_SET_DN 148
+#define STORE_F_STORE_ATTR_INFO_SET_NUMBER 149
+#define STORE_F_STORE_ATTR_INFO_SET_SHA1STR 150
+#define STORE_F_STORE_CERTIFICATE 170
+#define STORE_F_STORE_CTRL 161
+#define STORE_F_STORE_DELETE_ARBITRARY 158
+#define STORE_F_STORE_DELETE_CERTIFICATE 102
+#define STORE_F_STORE_DELETE_CRL 103
+#define STORE_F_STORE_DELETE_NUMBER 104
+#define STORE_F_STORE_DELETE_PRIVATE_KEY 105
+#define STORE_F_STORE_DELETE_PUBLIC_KEY 106
+#define STORE_F_STORE_GENERATE_CRL 107
+#define STORE_F_STORE_GENERATE_KEY 108
+#define STORE_F_STORE_GET_ARBITRARY 159
+#define STORE_F_STORE_GET_CERTIFICATE 109
+#define STORE_F_STORE_GET_CRL 110
+#define STORE_F_STORE_GET_NUMBER 111
+#define STORE_F_STORE_GET_PRIVATE_KEY 112
+#define STORE_F_STORE_GET_PUBLIC_KEY 113
+#define STORE_F_STORE_LIST_CERTIFICATE_END 114
+#define STORE_F_STORE_LIST_CERTIFICATE_ENDP 153
+#define STORE_F_STORE_LIST_CERTIFICATE_NEXT 115
+#define STORE_F_STORE_LIST_CERTIFICATE_START 116
+#define STORE_F_STORE_LIST_CRL_END 117
+#define STORE_F_STORE_LIST_CRL_ENDP 154
+#define STORE_F_STORE_LIST_CRL_NEXT 118
+#define STORE_F_STORE_LIST_CRL_START 119
+#define STORE_F_STORE_LIST_PRIVATE_KEY_END 120
+#define STORE_F_STORE_LIST_PRIVATE_KEY_ENDP 155
+#define STORE_F_STORE_LIST_PRIVATE_KEY_NEXT 121
+#define STORE_F_STORE_LIST_PRIVATE_KEY_START 122
+#define STORE_F_STORE_LIST_PUBLIC_KEY_END 123
+#define STORE_F_STORE_LIST_PUBLIC_KEY_ENDP 156
+#define STORE_F_STORE_LIST_PUBLIC_KEY_NEXT 124
+#define STORE_F_STORE_LIST_PUBLIC_KEY_START 125
+#define STORE_F_STORE_MODIFY_ARBITRARY 162
+#define STORE_F_STORE_MODIFY_CERTIFICATE 163
+#define STORE_F_STORE_MODIFY_CRL 164
+#define STORE_F_STORE_MODIFY_NUMBER 165
+#define STORE_F_STORE_MODIFY_PRIVATE_KEY 166
+#define STORE_F_STORE_MODIFY_PUBLIC_KEY 167
+#define STORE_F_STORE_NEW_ENGINE 133
+#define STORE_F_STORE_NEW_METHOD 132
+#define STORE_F_STORE_PARSE_ATTRS_END 151
+#define STORE_F_STORE_PARSE_ATTRS_ENDP 172
+#define STORE_F_STORE_PARSE_ATTRS_NEXT 152
+#define STORE_F_STORE_PARSE_ATTRS_START 171
+#define STORE_F_STORE_REVOKE_CERTIFICATE 129
+#define STORE_F_STORE_REVOKE_PRIVATE_KEY 130
+#define STORE_F_STORE_REVOKE_PUBLIC_KEY 131
+#define STORE_F_STORE_STORE_ARBITRARY 157
+#define STORE_F_STORE_STORE_CERTIFICATE 100
+#define STORE_F_STORE_STORE_CRL 101
+#define STORE_F_STORE_STORE_NUMBER 126
+#define STORE_F_STORE_STORE_PRIVATE_KEY 127
+#define STORE_F_STORE_STORE_PUBLIC_KEY 128
+
+/* Reason codes. */
+#define STORE_R_ALREADY_HAS_A_VALUE 127
+#define STORE_R_FAILED_DELETING_ARBITRARY 132
+#define STORE_R_FAILED_DELETING_CERTIFICATE 100
+#define STORE_R_FAILED_DELETING_KEY 101
+#define STORE_R_FAILED_DELETING_NUMBER 102
+#define STORE_R_FAILED_GENERATING_CRL 103
+#define STORE_R_FAILED_GENERATING_KEY 104
+#define STORE_R_FAILED_GETTING_ARBITRARY 133
+#define STORE_R_FAILED_GETTING_CERTIFICATE 105
+#define STORE_R_FAILED_GETTING_KEY 106
+#define STORE_R_FAILED_GETTING_NUMBER 107
+#define STORE_R_FAILED_LISTING_CERTIFICATES 108
+#define STORE_R_FAILED_LISTING_KEYS 109
+#define STORE_R_FAILED_MODIFYING_ARBITRARY 138
+#define STORE_R_FAILED_MODIFYING_CERTIFICATE 139
+#define STORE_R_FAILED_MODIFYING_CRL 140
+#define STORE_R_FAILED_MODIFYING_NUMBER 141
+#define STORE_R_FAILED_MODIFYING_PRIVATE_KEY 142
+#define STORE_R_FAILED_MODIFYING_PUBLIC_KEY 143
+#define STORE_R_FAILED_REVOKING_CERTIFICATE 110
+#define STORE_R_FAILED_REVOKING_KEY 111
+#define STORE_R_FAILED_STORING_ARBITRARY 134
+#define STORE_R_FAILED_STORING_CERTIFICATE 112
+#define STORE_R_FAILED_STORING_KEY 113
+#define STORE_R_FAILED_STORING_NUMBER 114
+#define STORE_R_NOT_IMPLEMENTED 128
+#define STORE_R_NO_CONTROL_FUNCTION 144
+#define STORE_R_NO_DELETE_ARBITRARY_FUNCTION 135
+#define STORE_R_NO_DELETE_NUMBER_FUNCTION 115
+#define STORE_R_NO_DELETE_OBJECT_FUNCTION 116
+#define STORE_R_NO_GENERATE_CRL_FUNCTION 117
+#define STORE_R_NO_GENERATE_OBJECT_FUNCTION 118
+#define STORE_R_NO_GET_OBJECT_ARBITRARY_FUNCTION 136
+#define STORE_R_NO_GET_OBJECT_FUNCTION 119
+#define STORE_R_NO_GET_OBJECT_NUMBER_FUNCTION 120
+#define STORE_R_NO_LIST_OBJECT_ENDP_FUNCTION 131
+#define STORE_R_NO_LIST_OBJECT_END_FUNCTION 121
+#define STORE_R_NO_LIST_OBJECT_NEXT_FUNCTION 122
+#define STORE_R_NO_LIST_OBJECT_START_FUNCTION 123
+#define STORE_R_NO_MODIFY_OBJECT_FUNCTION 145
+#define STORE_R_NO_REVOKE_OBJECT_FUNCTION 124
+#define STORE_R_NO_STORE 129
+#define STORE_R_NO_STORE_OBJECT_ARBITRARY_FUNCTION 137
+#define STORE_R_NO_STORE_OBJECT_FUNCTION 125
+#define STORE_R_NO_STORE_OBJECT_NUMBER_FUNCTION 126
+#define STORE_R_NO_VALUE 130
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/symhacks.h b/src/Mayaqua/win32_inc/openssl/symhacks.h
new file mode 100644
index 00000000..d101333e
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/symhacks.h
@@ -0,0 +1,429 @@
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_SYMHACKS_H
+#define HEADER_SYMHACKS_H
+
+#include <openssl/e_os2.h>
+
+/* Hacks to solve the problem with linkers incapable of handling very long
+ symbol names. In the case of VMS, the limit is 31 characters on VMS for
+ VAX. */
+/* Note that this affects util/libeay.num and util/ssleay.num... you may
+ change those manually, but that's not recommended, as those files are
+ controlled centrally and updated on Unix, and the central definition
+ may disagree with yours, which in turn may come with shareable library
+ incompatibilities. */
+#ifdef OPENSSL_SYS_VMS
+
+/* Hack a long name in crypto/cryptlib.c */
+#undef int_CRYPTO_set_do_dynlock_callback
+#define int_CRYPTO_set_do_dynlock_callback int_CRYPTO_set_do_dynlock_cb
+
+/* Hack a long name in crypto/ex_data.c */
+#undef CRYPTO_get_ex_data_implementation
+#define CRYPTO_get_ex_data_implementation CRYPTO_get_ex_data_impl
+#undef CRYPTO_set_ex_data_implementation
+#define CRYPTO_set_ex_data_implementation CRYPTO_set_ex_data_impl
+
+/* Hack a long name in crypto/asn1/a_mbstr.c */
+#undef ASN1_STRING_set_default_mask_asc
+#define ASN1_STRING_set_default_mask_asc ASN1_STRING_set_def_mask_asc
+
+#if 0 /* No longer needed, since safestack macro magic does the job */
+/* Hack the names created with DECLARE_ASN1_SET_OF(PKCS7_SIGNER_INFO) */
+#undef i2d_ASN1_SET_OF_PKCS7_SIGNER_INFO
+#define i2d_ASN1_SET_OF_PKCS7_SIGNER_INFO i2d_ASN1_SET_OF_PKCS7_SIGINF
+#undef d2i_ASN1_SET_OF_PKCS7_SIGNER_INFO
+#define d2i_ASN1_SET_OF_PKCS7_SIGNER_INFO d2i_ASN1_SET_OF_PKCS7_SIGINF
+#endif
+
+#if 0 /* No longer needed, since safestack macro magic does the job */
+/* Hack the names created with DECLARE_ASN1_SET_OF(PKCS7_RECIP_INFO) */
+#undef i2d_ASN1_SET_OF_PKCS7_RECIP_INFO
+#define i2d_ASN1_SET_OF_PKCS7_RECIP_INFO i2d_ASN1_SET_OF_PKCS7_RECINF
+#undef d2i_ASN1_SET_OF_PKCS7_RECIP_INFO
+#define d2i_ASN1_SET_OF_PKCS7_RECIP_INFO d2i_ASN1_SET_OF_PKCS7_RECINF
+#endif
+
+#if 0 /* No longer needed, since safestack macro magic does the job */
+/* Hack the names created with DECLARE_ASN1_SET_OF(ACCESS_DESCRIPTION) */
+#undef i2d_ASN1_SET_OF_ACCESS_DESCRIPTION
+#define i2d_ASN1_SET_OF_ACCESS_DESCRIPTION i2d_ASN1_SET_OF_ACC_DESC
+#undef d2i_ASN1_SET_OF_ACCESS_DESCRIPTION
+#define d2i_ASN1_SET_OF_ACCESS_DESCRIPTION d2i_ASN1_SET_OF_ACC_DESC
+#endif
+
+/* Hack the names created with DECLARE_PEM_rw(NETSCAPE_CERT_SEQUENCE) */
+#undef PEM_read_NETSCAPE_CERT_SEQUENCE
+#define PEM_read_NETSCAPE_CERT_SEQUENCE PEM_read_NS_CERT_SEQ
+#undef PEM_write_NETSCAPE_CERT_SEQUENCE
+#define PEM_write_NETSCAPE_CERT_SEQUENCE PEM_write_NS_CERT_SEQ
+#undef PEM_read_bio_NETSCAPE_CERT_SEQUENCE
+#define PEM_read_bio_NETSCAPE_CERT_SEQUENCE PEM_read_bio_NS_CERT_SEQ
+#undef PEM_write_bio_NETSCAPE_CERT_SEQUENCE
+#define PEM_write_bio_NETSCAPE_CERT_SEQUENCE PEM_write_bio_NS_CERT_SEQ
+#undef PEM_write_cb_bio_NETSCAPE_CERT_SEQUENCE
+#define PEM_write_cb_bio_NETSCAPE_CERT_SEQUENCE PEM_write_cb_bio_NS_CERT_SEQ
+
+/* Hack the names created with DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO) */
+#undef PEM_read_PKCS8_PRIV_KEY_INFO
+#define PEM_read_PKCS8_PRIV_KEY_INFO PEM_read_P8_PRIV_KEY_INFO
+#undef PEM_write_PKCS8_PRIV_KEY_INFO
+#define PEM_write_PKCS8_PRIV_KEY_INFO PEM_write_P8_PRIV_KEY_INFO
+#undef PEM_read_bio_PKCS8_PRIV_KEY_INFO
+#define PEM_read_bio_PKCS8_PRIV_KEY_INFO PEM_read_bio_P8_PRIV_KEY_INFO
+#undef PEM_write_bio_PKCS8_PRIV_KEY_INFO
+#define PEM_write_bio_PKCS8_PRIV_KEY_INFO PEM_write_bio_P8_PRIV_KEY_INFO
+#undef PEM_write_cb_bio_PKCS8_PRIV_KEY_INFO
+#define PEM_write_cb_bio_PKCS8_PRIV_KEY_INFO PEM_wrt_cb_bio_P8_PRIV_KEY_INFO
+
+/* Hack other PEM names */
+#undef PEM_write_bio_PKCS8PrivateKey_nid
+#define PEM_write_bio_PKCS8PrivateKey_nid PEM_write_bio_PKCS8PrivKey_nid
+
+/* Hack some long X509 names */
+#undef X509_REVOKED_get_ext_by_critical
+#define X509_REVOKED_get_ext_by_critical X509_REVOKED_get_ext_by_critic
+#undef X509_policy_tree_get0_user_policies
+#define X509_policy_tree_get0_user_policies X509_pcy_tree_get0_usr_policies
+#undef X509_policy_node_get0_qualifiers
+#define X509_policy_node_get0_qualifiers X509_pcy_node_get0_qualifiers
+#undef X509_STORE_CTX_get_explicit_policy
+#define X509_STORE_CTX_get_explicit_policy X509_STORE_CTX_get_expl_policy
+#undef X509_STORE_CTX_get0_current_issuer
+#define X509_STORE_CTX_get0_current_issuer X509_STORE_CTX_get0_cur_issuer
+
+/* Hack some long CRYPTO names */
+#undef CRYPTO_set_dynlock_destroy_callback
+#define CRYPTO_set_dynlock_destroy_callback CRYPTO_set_dynlock_destroy_cb
+#undef CRYPTO_set_dynlock_create_callback
+#define CRYPTO_set_dynlock_create_callback CRYPTO_set_dynlock_create_cb
+#undef CRYPTO_set_dynlock_lock_callback
+#define CRYPTO_set_dynlock_lock_callback CRYPTO_set_dynlock_lock_cb
+#undef CRYPTO_get_dynlock_lock_callback
+#define CRYPTO_get_dynlock_lock_callback CRYPTO_get_dynlock_lock_cb
+#undef CRYPTO_get_dynlock_destroy_callback
+#define CRYPTO_get_dynlock_destroy_callback CRYPTO_get_dynlock_destroy_cb
+#undef CRYPTO_get_dynlock_create_callback
+#define CRYPTO_get_dynlock_create_callback CRYPTO_get_dynlock_create_cb
+#undef CRYPTO_set_locked_mem_ex_functions
+#define CRYPTO_set_locked_mem_ex_functions CRYPTO_set_locked_mem_ex_funcs
+#undef CRYPTO_get_locked_mem_ex_functions
+#define CRYPTO_get_locked_mem_ex_functions CRYPTO_get_locked_mem_ex_funcs
+
+/* Hack some long SSL names */
+#undef SSL_CTX_set_default_verify_paths
+#define SSL_CTX_set_default_verify_paths SSL_CTX_set_def_verify_paths
+#undef SSL_get_ex_data_X509_STORE_CTX_idx
+#define SSL_get_ex_data_X509_STORE_CTX_idx SSL_get_ex_d_X509_STORE_CTX_idx
+#undef SSL_add_file_cert_subjects_to_stack
+#define SSL_add_file_cert_subjects_to_stack SSL_add_file_cert_subjs_to_stk
+#undef SSL_add_dir_cert_subjects_to_stack
+#define SSL_add_dir_cert_subjects_to_stack SSL_add_dir_cert_subjs_to_stk
+#undef SSL_CTX_use_certificate_chain_file
+#define SSL_CTX_use_certificate_chain_file SSL_CTX_use_cert_chain_file
+#undef SSL_CTX_set_cert_verify_callback
+#define SSL_CTX_set_cert_verify_callback SSL_CTX_set_cert_verify_cb
+#undef SSL_CTX_set_default_passwd_cb_userdata
+#define SSL_CTX_set_default_passwd_cb_userdata SSL_CTX_set_def_passwd_cb_ud
+#undef SSL_COMP_get_compression_methods
+#define SSL_COMP_get_compression_methods SSL_COMP_get_compress_methods
+
+#undef ssl_add_clienthello_renegotiate_ext
+#define ssl_add_clienthello_renegotiate_ext ssl_add_clienthello_reneg_ext
+#undef ssl_add_serverhello_renegotiate_ext
+#define ssl_add_serverhello_renegotiate_ext ssl_add_serverhello_reneg_ext
+#undef ssl_parse_clienthello_renegotiate_ext
+#define ssl_parse_clienthello_renegotiate_ext ssl_parse_clienthello_reneg_ext
+#undef ssl_parse_serverhello_renegotiate_ext
+#define ssl_parse_serverhello_renegotiate_ext ssl_parse_serverhello_reneg_ext
+
+/* Hack some long ENGINE names */
+#undef ENGINE_get_default_BN_mod_exp_crt
+#define ENGINE_get_default_BN_mod_exp_crt ENGINE_get_def_BN_mod_exp_crt
+#undef ENGINE_set_default_BN_mod_exp_crt
+#define ENGINE_set_default_BN_mod_exp_crt ENGINE_set_def_BN_mod_exp_crt
+#undef ENGINE_set_load_privkey_function
+#define ENGINE_set_load_privkey_function ENGINE_set_load_privkey_fn
+#undef ENGINE_get_load_privkey_function
+#define ENGINE_get_load_privkey_function ENGINE_get_load_privkey_fn
+#undef ENGINE_set_load_ssl_client_cert_function
+#define ENGINE_set_load_ssl_client_cert_function \
+ ENGINE_set_ld_ssl_clnt_cert_fn
+#undef ENGINE_get_ssl_client_cert_function
+#define ENGINE_get_ssl_client_cert_function ENGINE_get_ssl_client_cert_fn
+
+/* Hack some long OCSP names */
+#undef OCSP_REQUEST_get_ext_by_critical
+#define OCSP_REQUEST_get_ext_by_critical OCSP_REQUEST_get_ext_by_crit
+#undef OCSP_BASICRESP_get_ext_by_critical
+#define OCSP_BASICRESP_get_ext_by_critical OCSP_BASICRESP_get_ext_by_crit
+#undef OCSP_SINGLERESP_get_ext_by_critical
+#define OCSP_SINGLERESP_get_ext_by_critical OCSP_SINGLERESP_get_ext_by_crit
+
+/* Hack some long DES names */
+#undef _ossl_old_des_ede3_cfb64_encrypt
+#define _ossl_old_des_ede3_cfb64_encrypt _ossl_odes_ede3_cfb64_encrypt
+#undef _ossl_old_des_ede3_ofb64_encrypt
+#define _ossl_old_des_ede3_ofb64_encrypt _ossl_odes_ede3_ofb64_encrypt
+
+/* Hack some long EVP names */
+#undef OPENSSL_add_all_algorithms_noconf
+#define OPENSSL_add_all_algorithms_noconf OPENSSL_add_all_algo_noconf
+#undef OPENSSL_add_all_algorithms_conf
+#define OPENSSL_add_all_algorithms_conf OPENSSL_add_all_algo_conf
+
+/* Hack some long EC names */
+#undef EC_GROUP_set_point_conversion_form
+#define EC_GROUP_set_point_conversion_form EC_GROUP_set_point_conv_form
+#undef EC_GROUP_get_point_conversion_form
+#define EC_GROUP_get_point_conversion_form EC_GROUP_get_point_conv_form
+#undef EC_GROUP_clear_free_all_extra_data
+#define EC_GROUP_clear_free_all_extra_data EC_GROUP_clr_free_all_xtra_data
+#undef EC_POINT_set_Jprojective_coordinates_GFp
+#define EC_POINT_set_Jprojective_coordinates_GFp \
+ EC_POINT_set_Jproj_coords_GFp
+#undef EC_POINT_get_Jprojective_coordinates_GFp
+#define EC_POINT_get_Jprojective_coordinates_GFp \
+ EC_POINT_get_Jproj_coords_GFp
+#undef EC_POINT_set_affine_coordinates_GFp
+#define EC_POINT_set_affine_coordinates_GFp EC_POINT_set_affine_coords_GFp
+#undef EC_POINT_get_affine_coordinates_GFp
+#define EC_POINT_get_affine_coordinates_GFp EC_POINT_get_affine_coords_GFp
+#undef EC_POINT_set_compressed_coordinates_GFp
+#define EC_POINT_set_compressed_coordinates_GFp EC_POINT_set_compr_coords_GFp
+#undef EC_POINT_set_affine_coordinates_GF2m
+#define EC_POINT_set_affine_coordinates_GF2m EC_POINT_set_affine_coords_GF2m
+#undef EC_POINT_get_affine_coordinates_GF2m
+#define EC_POINT_get_affine_coordinates_GF2m EC_POINT_get_affine_coords_GF2m
+#undef EC_POINT_set_compressed_coordinates_GF2m
+#define EC_POINT_set_compressed_coordinates_GF2m \
+ EC_POINT_set_compr_coords_GF2m
+#undef ec_GF2m_simple_group_clear_finish
+#define ec_GF2m_simple_group_clear_finish ec_GF2m_simple_grp_clr_finish
+#undef ec_GF2m_simple_group_check_discriminant
+#define ec_GF2m_simple_group_check_discriminant ec_GF2m_simple_grp_chk_discrim
+#undef ec_GF2m_simple_point_clear_finish
+#define ec_GF2m_simple_point_clear_finish ec_GF2m_simple_pt_clr_finish
+#undef ec_GF2m_simple_point_set_to_infinity
+#define ec_GF2m_simple_point_set_to_infinity ec_GF2m_simple_pt_set_to_inf
+#undef ec_GF2m_simple_points_make_affine
+#define ec_GF2m_simple_points_make_affine ec_GF2m_simple_pts_make_affine
+#undef ec_GF2m_simple_point_set_affine_coordinates
+#define ec_GF2m_simple_point_set_affine_coordinates \
+ ec_GF2m_smp_pt_set_af_coords
+#undef ec_GF2m_simple_point_get_affine_coordinates
+#define ec_GF2m_simple_point_get_affine_coordinates \
+ ec_GF2m_smp_pt_get_af_coords
+#undef ec_GF2m_simple_set_compressed_coordinates
+#define ec_GF2m_simple_set_compressed_coordinates \
+ ec_GF2m_smp_set_compr_coords
+#undef ec_GFp_simple_group_set_curve_GFp
+#define ec_GFp_simple_group_set_curve_GFp ec_GFp_simple_grp_set_curve_GFp
+#undef ec_GFp_simple_group_get_curve_GFp
+#define ec_GFp_simple_group_get_curve_GFp ec_GFp_simple_grp_get_curve_GFp
+#undef ec_GFp_simple_group_clear_finish
+#define ec_GFp_simple_group_clear_finish ec_GFp_simple_grp_clear_finish
+#undef ec_GFp_simple_group_set_generator
+#define ec_GFp_simple_group_set_generator ec_GFp_simple_grp_set_generator
+#undef ec_GFp_simple_group_get0_generator
+#define ec_GFp_simple_group_get0_generator ec_GFp_simple_grp_gt0_generator
+#undef ec_GFp_simple_group_get_cofactor
+#define ec_GFp_simple_group_get_cofactor ec_GFp_simple_grp_get_cofactor
+#undef ec_GFp_simple_point_clear_finish
+#define ec_GFp_simple_point_clear_finish ec_GFp_simple_pt_clear_finish
+#undef ec_GFp_simple_point_set_to_infinity
+#define ec_GFp_simple_point_set_to_infinity ec_GFp_simple_pt_set_to_inf
+#undef ec_GFp_simple_points_make_affine
+#define ec_GFp_simple_points_make_affine ec_GFp_simple_pts_make_affine
+#undef ec_GFp_simple_group_get_curve_GFp
+#define ec_GFp_simple_group_get_curve_GFp ec_GFp_simple_grp_get_curve_GFp
+#undef ec_GFp_simple_set_Jprojective_coordinates_GFp
+#define ec_GFp_simple_set_Jprojective_coordinates_GFp \
+ ec_GFp_smp_set_Jproj_coords_GFp
+#undef ec_GFp_simple_get_Jprojective_coordinates_GFp
+#define ec_GFp_simple_get_Jprojective_coordinates_GFp \
+ ec_GFp_smp_get_Jproj_coords_GFp
+#undef ec_GFp_simple_point_set_affine_coordinates_GFp
+#define ec_GFp_simple_point_set_affine_coordinates_GFp \
+ ec_GFp_smp_pt_set_af_coords_GFp
+#undef ec_GFp_simple_point_get_affine_coordinates_GFp
+#define ec_GFp_simple_point_get_affine_coordinates_GFp \
+ ec_GFp_smp_pt_get_af_coords_GFp
+#undef ec_GFp_simple_set_compressed_coordinates_GFp
+#define ec_GFp_simple_set_compressed_coordinates_GFp \
+ ec_GFp_smp_set_compr_coords_GFp
+#undef ec_GFp_simple_point_set_affine_coordinates
+#define ec_GFp_simple_point_set_affine_coordinates \
+ ec_GFp_smp_pt_set_af_coords
+#undef ec_GFp_simple_point_get_affine_coordinates
+#define ec_GFp_simple_point_get_affine_coordinates \
+ ec_GFp_smp_pt_get_af_coords
+#undef ec_GFp_simple_set_compressed_coordinates
+#define ec_GFp_simple_set_compressed_coordinates \
+ ec_GFp_smp_set_compr_coords
+#undef ec_GFp_simple_group_check_discriminant
+#define ec_GFp_simple_group_check_discriminant ec_GFp_simple_grp_chk_discrim
+
+/* Hack som long STORE names */
+#undef STORE_method_set_initialise_function
+#define STORE_method_set_initialise_function STORE_meth_set_initialise_fn
+#undef STORE_method_set_cleanup_function
+#define STORE_method_set_cleanup_function STORE_meth_set_cleanup_fn
+#undef STORE_method_set_generate_function
+#define STORE_method_set_generate_function STORE_meth_set_generate_fn
+#undef STORE_method_set_modify_function
+#define STORE_method_set_modify_function STORE_meth_set_modify_fn
+#undef STORE_method_set_revoke_function
+#define STORE_method_set_revoke_function STORE_meth_set_revoke_fn
+#undef STORE_method_set_delete_function
+#define STORE_method_set_delete_function STORE_meth_set_delete_fn
+#undef STORE_method_set_list_start_function
+#define STORE_method_set_list_start_function STORE_meth_set_list_start_fn
+#undef STORE_method_set_list_next_function
+#define STORE_method_set_list_next_function STORE_meth_set_list_next_fn
+#undef STORE_method_set_list_end_function
+#define STORE_method_set_list_end_function STORE_meth_set_list_end_fn
+#undef STORE_method_set_update_store_function
+#define STORE_method_set_update_store_function STORE_meth_set_update_store_fn
+#undef STORE_method_set_lock_store_function
+#define STORE_method_set_lock_store_function STORE_meth_set_lock_store_fn
+#undef STORE_method_set_unlock_store_function
+#define STORE_method_set_unlock_store_function STORE_meth_set_unlock_store_fn
+#undef STORE_method_get_initialise_function
+#define STORE_method_get_initialise_function STORE_meth_get_initialise_fn
+#undef STORE_method_get_cleanup_function
+#define STORE_method_get_cleanup_function STORE_meth_get_cleanup_fn
+#undef STORE_method_get_generate_function
+#define STORE_method_get_generate_function STORE_meth_get_generate_fn
+#undef STORE_method_get_modify_function
+#define STORE_method_get_modify_function STORE_meth_get_modify_fn
+#undef STORE_method_get_revoke_function
+#define STORE_method_get_revoke_function STORE_meth_get_revoke_fn
+#undef STORE_method_get_delete_function
+#define STORE_method_get_delete_function STORE_meth_get_delete_fn
+#undef STORE_method_get_list_start_function
+#define STORE_method_get_list_start_function STORE_meth_get_list_start_fn
+#undef STORE_method_get_list_next_function
+#define STORE_method_get_list_next_function STORE_meth_get_list_next_fn
+#undef STORE_method_get_list_end_function
+#define STORE_method_get_list_end_function STORE_meth_get_list_end_fn
+#undef STORE_method_get_update_store_function
+#define STORE_method_get_update_store_function STORE_meth_get_update_store_fn
+#undef STORE_method_get_lock_store_function
+#define STORE_method_get_lock_store_function STORE_meth_get_lock_store_fn
+#undef STORE_method_get_unlock_store_function
+#define STORE_method_get_unlock_store_function STORE_meth_get_unlock_store_fn
+
+/* Hack some long CMS names */
+#undef CMS_RecipientInfo_ktri_get0_algs
+#define CMS_RecipientInfo_ktri_get0_algs CMS_RecipInfo_ktri_get0_algs
+#undef CMS_RecipientInfo_ktri_get0_signer_id
+#define CMS_RecipientInfo_ktri_get0_signer_id CMS_RecipInfo_ktri_get0_sigr_id
+#undef CMS_OtherRevocationInfoFormat_it
+#define CMS_OtherRevocationInfoFormat_it CMS_OtherRevocInfoFormat_it
+#undef CMS_KeyAgreeRecipientIdentifier_it
+#define CMS_KeyAgreeRecipientIdentifier_it CMS_KeyAgreeRecipIdentifier_it
+#undef CMS_OriginatorIdentifierOrKey_it
+#define CMS_OriginatorIdentifierOrKey_it CMS_OriginatorIdOrKey_it
+#undef cms_SignerIdentifier_get0_signer_id
+#define cms_SignerIdentifier_get0_signer_id cms_SignerId_get0_signer_id
+
+/* Hack some long DTLS1 names */
+#undef dtls1_retransmit_buffered_messages
+#define dtls1_retransmit_buffered_messages dtls1_retransmit_buffered_msgs
+
+#endif /* defined OPENSSL_SYS_VMS */
+
+
+/* Case insensiteve linking causes problems.... */
+#if defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2)
+#undef ERR_load_CRYPTO_strings
+#define ERR_load_CRYPTO_strings ERR_load_CRYPTOlib_strings
+#undef OCSP_crlID_new
+#define OCSP_crlID_new OCSP_crlID2_new
+
+#undef d2i_ECPARAMETERS
+#define d2i_ECPARAMETERS d2i_UC_ECPARAMETERS
+#undef i2d_ECPARAMETERS
+#define i2d_ECPARAMETERS i2d_UC_ECPARAMETERS
+#undef d2i_ECPKPARAMETERS
+#define d2i_ECPKPARAMETERS d2i_UC_ECPKPARAMETERS
+#undef i2d_ECPKPARAMETERS
+#define i2d_ECPKPARAMETERS i2d_UC_ECPKPARAMETERS
+
+/* These functions do not seem to exist! However, I'm paranoid...
+ Original command in x509v3.h:
+ These functions are being redefined in another directory,
+ and clash when the linker is case-insensitive, so let's
+ hide them a little, by giving them an extra 'o' at the
+ beginning of the name... */
+#undef X509v3_cleanup_extensions
+#define X509v3_cleanup_extensions oX509v3_cleanup_extensions
+#undef X509v3_add_extension
+#define X509v3_add_extension oX509v3_add_extension
+#undef X509v3_add_netscape_extensions
+#define X509v3_add_netscape_extensions oX509v3_add_netscape_extensions
+#undef X509v3_add_standard_extensions
+#define X509v3_add_standard_extensions oX509v3_add_standard_extensions
+
+
+#endif
+
+
+#endif /* ! defined HEADER_VMS_IDHACKS_H */
+/* This one clashes with CMS_data_create */
+#undef cms_Data_create
+#define cms_Data_create priv_cms_Data_create
diff --git a/src/Mayaqua/win32_inc/openssl/tls1.h b/src/Mayaqua/win32_inc/openssl/tls1.h
new file mode 100644
index 00000000..3ae5bfc4
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/tls1.h
@@ -0,0 +1,410 @@
+/* ssl/tls1.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * ECC cipher suite support in OpenSSL originally written by
+ * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+
+#ifndef HEADER_TLS1_H
+#define HEADER_TLS1_H
+
+#include <openssl/buffer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES 0
+
+#define TLS1_VERSION 0x0301
+#define TLS1_VERSION_MAJOR 0x03
+#define TLS1_VERSION_MINOR 0x01
+
+#define TLS1_AD_DECRYPTION_FAILED 21
+#define TLS1_AD_RECORD_OVERFLOW 22
+#define TLS1_AD_UNKNOWN_CA 48 /* fatal */
+#define TLS1_AD_ACCESS_DENIED 49 /* fatal */
+#define TLS1_AD_DECODE_ERROR 50 /* fatal */
+#define TLS1_AD_DECRYPT_ERROR 51
+#define TLS1_AD_EXPORT_RESTRICTION 60 /* fatal */
+#define TLS1_AD_PROTOCOL_VERSION 70 /* fatal */
+#define TLS1_AD_INSUFFICIENT_SECURITY 71 /* fatal */
+#define TLS1_AD_INTERNAL_ERROR 80 /* fatal */
+#define TLS1_AD_USER_CANCELLED 90
+#define TLS1_AD_NO_RENEGOTIATION 100
+/* codes 110-114 are from RFC3546 */
+#define TLS1_AD_UNSUPPORTED_EXTENSION 110
+#define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111
+#define TLS1_AD_UNRECOGNIZED_NAME 112
+#define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113
+#define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114
+#define TLS1_AD_UNKNOWN_PSK_IDENTITY 115 /* fatal */
+
+/* ExtensionType values from RFC 3546 */
+#define TLSEXT_TYPE_server_name 0
+#define TLSEXT_TYPE_max_fragment_length 1
+#define TLSEXT_TYPE_client_certificate_url 2
+#define TLSEXT_TYPE_trusted_ca_keys 3
+#define TLSEXT_TYPE_truncated_hmac 4
+#define TLSEXT_TYPE_status_request 5
+#define TLSEXT_TYPE_elliptic_curves 10
+#define TLSEXT_TYPE_ec_point_formats 11
+#define TLSEXT_TYPE_session_ticket 35
+
+/* Temporary extension type */
+#define TLSEXT_TYPE_renegotiate 0xff01
+
+/* NameType value from RFC 3546 */
+#define TLSEXT_NAMETYPE_host_name 0
+/* status request value from RFC 3546 */
+#define TLSEXT_STATUSTYPE_ocsp 1
+
+#ifndef OPENSSL_NO_TLSEXT
+
+#define TLSEXT_MAXLEN_host_name 255
+
+const char *SSL_get_servername(const SSL *s, const int type) ;
+int SSL_get_servername_type(const SSL *s) ;
+
+#define SSL_set_tlsext_host_name(s,name) \
+SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name)
+
+#define SSL_set_tlsext_debug_callback(ssl, cb) \
+SSL_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_CB,(void (*)(void))cb)
+
+#define SSL_set_tlsext_debug_arg(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_ARG,0, (void *)arg)
+
+#define SSL_set_tlsext_status_type(ssl, type) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE,type, NULL)
+
+#define SSL_get_tlsext_status_exts(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg)
+
+#define SSL_set_tlsext_status_exts(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg)
+
+#define SSL_get_tlsext_status_ids(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg)
+
+#define SSL_set_tlsext_status_ids(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg)
+
+#define SSL_get_tlsext_status_ocsp_resp(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP,0, (void *)arg)
+
+#define SSL_set_tlsext_status_ocsp_resp(ssl, arg, arglen) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,arglen, (void *)arg)
+
+#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \
+SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,(void (*)(void))cb)
+
+#define SSL_TLSEXT_ERR_OK 0
+#define SSL_TLSEXT_ERR_ALERT_WARNING 1
+#define SSL_TLSEXT_ERR_ALERT_FATAL 2
+#define SSL_TLSEXT_ERR_NOACK 3
+
+#define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \
+SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0, (void *)arg)
+
+#define SSL_CTX_get_tlsext_ticket_keys(ctx, keys, keylen) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_GET_TLSEXT_TICKET_KEYS,(keylen),(keys))
+#define SSL_CTX_set_tlsext_ticket_keys(ctx, keys, keylen) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_SET_TLSEXT_TICKET_KEYS,(keylen),(keys))
+
+#define SSL_CTX_set_tlsext_status_cb(ssl, cb) \
+SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB,(void (*)(void))cb)
+
+#define SSL_CTX_set_tlsext_status_arg(ssl, arg) \
+SSL_CTX_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG,0, (void *)arg)
+
+#define SSL_CTX_set_tlsext_ticket_key_cb(ssl, cb) \
+SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
+
+#endif
+
+/* Additional TLS ciphersuites from draft-ietf-tls-56-bit-ciphersuites-00.txt
+ * (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see
+ * s3_lib.c). We actually treat them like SSL 3.0 ciphers, which we probably
+ * shouldn't. */
+#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_MD5 0x03000060
+#define TLS1_CK_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 0x03000061
+#define TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA 0x03000062
+#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA 0x03000063
+#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_SHA 0x03000064
+#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA 0x03000065
+#define TLS1_CK_DHE_DSS_WITH_RC4_128_SHA 0x03000066
+
+/* AES ciphersuites from RFC3268 */
+
+#define TLS1_CK_RSA_WITH_AES_128_SHA 0x0300002F
+#define TLS1_CK_DH_DSS_WITH_AES_128_SHA 0x03000030
+#define TLS1_CK_DH_RSA_WITH_AES_128_SHA 0x03000031
+#define TLS1_CK_DHE_DSS_WITH_AES_128_SHA 0x03000032
+#define TLS1_CK_DHE_RSA_WITH_AES_128_SHA 0x03000033
+#define TLS1_CK_ADH_WITH_AES_128_SHA 0x03000034
+
+#define TLS1_CK_RSA_WITH_AES_256_SHA 0x03000035
+#define TLS1_CK_DH_DSS_WITH_AES_256_SHA 0x03000036
+#define TLS1_CK_DH_RSA_WITH_AES_256_SHA 0x03000037
+#define TLS1_CK_DHE_DSS_WITH_AES_256_SHA 0x03000038
+#define TLS1_CK_DHE_RSA_WITH_AES_256_SHA 0x03000039
+#define TLS1_CK_ADH_WITH_AES_256_SHA 0x0300003A
+
+/* Camellia ciphersuites from RFC4132 */
+#define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000041
+#define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000042
+#define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000043
+#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000044
+#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000045
+#define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA 0x03000046
+
+#define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000084
+#define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000085
+#define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000086
+#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000087
+#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000088
+#define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA 0x03000089
+
+/* SEED ciphersuites from RFC4162 */
+#define TLS1_CK_RSA_WITH_SEED_SHA 0x03000096
+#define TLS1_CK_DH_DSS_WITH_SEED_SHA 0x03000097
+#define TLS1_CK_DH_RSA_WITH_SEED_SHA 0x03000098
+#define TLS1_CK_DHE_DSS_WITH_SEED_SHA 0x03000099
+#define TLS1_CK_DHE_RSA_WITH_SEED_SHA 0x0300009A
+#define TLS1_CK_ADH_WITH_SEED_SHA 0x0300009B
+
+/* ECC ciphersuites from draft-ietf-tls-ecc-12.txt with changes soon to be in draft 13 */
+#define TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA 0x0300C001
+#define TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA 0x0300C002
+#define TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C003
+#define TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0x0300C004
+#define TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0x0300C005
+
+#define TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA 0x0300C006
+#define TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA 0x0300C007
+#define TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C008
+#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0x0300C009
+#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0x0300C00A
+
+#define TLS1_CK_ECDH_RSA_WITH_NULL_SHA 0x0300C00B
+#define TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA 0x0300C00C
+#define TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA 0x0300C00D
+#define TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA 0x0300C00E
+#define TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA 0x0300C00F
+
+#define TLS1_CK_ECDHE_RSA_WITH_NULL_SHA 0x0300C010
+#define TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA 0x0300C011
+#define TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA 0x0300C012
+#define TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA 0x0300C013
+#define TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA 0x0300C014
+
+#define TLS1_CK_ECDH_anon_WITH_NULL_SHA 0x0300C015
+#define TLS1_CK_ECDH_anon_WITH_RC4_128_SHA 0x0300C016
+#define TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA 0x0300C017
+#define TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA 0x0300C018
+#define TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA 0x0300C019
+
+/* XXX
+ * Inconsistency alert:
+ * The OpenSSL names of ciphers with ephemeral DH here include the string
+ * "DHE", while elsewhere it has always been "EDH".
+ * (The alias for the list of all such ciphers also is "EDH".)
+ * The specifications speak of "EDH"; maybe we should allow both forms
+ * for everything. */
+#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5 "EXP1024-RC4-MD5"
+#define TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 "EXP1024-RC2-CBC-MD5"
+#define TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA "EXP1024-DES-CBC-SHA"
+#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA "EXP1024-DHE-DSS-DES-CBC-SHA"
+#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA "EXP1024-RC4-SHA"
+#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA "EXP1024-DHE-DSS-RC4-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA "DHE-DSS-RC4-SHA"
+
+/* AES ciphersuites from RFC3268 */
+#define TLS1_TXT_RSA_WITH_AES_128_SHA "AES128-SHA"
+#define TLS1_TXT_DH_DSS_WITH_AES_128_SHA "DH-DSS-AES128-SHA"
+#define TLS1_TXT_DH_RSA_WITH_AES_128_SHA "DH-RSA-AES128-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA "DHE-DSS-AES128-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA "DHE-RSA-AES128-SHA"
+#define TLS1_TXT_ADH_WITH_AES_128_SHA "ADH-AES128-SHA"
+
+#define TLS1_TXT_RSA_WITH_AES_256_SHA "AES256-SHA"
+#define TLS1_TXT_DH_DSS_WITH_AES_256_SHA "DH-DSS-AES256-SHA"
+#define TLS1_TXT_DH_RSA_WITH_AES_256_SHA "DH-RSA-AES256-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA "DHE-DSS-AES256-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA "DHE-RSA-AES256-SHA"
+#define TLS1_TXT_ADH_WITH_AES_256_SHA "ADH-AES256-SHA"
+
+/* ECC ciphersuites from draft-ietf-tls-ecc-01.txt (Mar 15, 2001) */
+#define TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA "ECDH-ECDSA-NULL-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA "ECDH-ECDSA-RC4-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA "ECDH-ECDSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA "ECDH-ECDSA-AES128-SHA"
+#define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA "ECDH-ECDSA-AES256-SHA"
+
+#define TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA "ECDHE-ECDSA-NULL-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA "ECDHE-ECDSA-RC4-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA "ECDHE-ECDSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA "ECDHE-ECDSA-AES128-SHA"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA "ECDHE-ECDSA-AES256-SHA"
+
+#define TLS1_TXT_ECDH_RSA_WITH_NULL_SHA "ECDH-RSA-NULL-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA "ECDH-RSA-RC4-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA "ECDH-RSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA "ECDH-RSA-AES128-SHA"
+#define TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA "ECDH-RSA-AES256-SHA"
+
+#define TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA "ECDHE-RSA-NULL-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA "ECDHE-RSA-RC4-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA "ECDHE-RSA-DES-CBC3-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA "ECDHE-RSA-AES128-SHA"
+#define TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA "ECDHE-RSA-AES256-SHA"
+
+#define TLS1_TXT_ECDH_anon_WITH_NULL_SHA "AECDH-NULL-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA "AECDH-RC4-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA "AECDH-DES-CBC3-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA "AECDH-AES128-SHA"
+#define TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA "AECDH-AES256-SHA"
+
+/* Camellia ciphersuites from RFC4132 */
+#define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA "CAMELLIA128-SHA"
+#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA "DH-DSS-CAMELLIA128-SHA"
+#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA "DH-RSA-CAMELLIA128-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA "DHE-DSS-CAMELLIA128-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA "DHE-RSA-CAMELLIA128-SHA"
+#define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA "ADH-CAMELLIA128-SHA"
+
+#define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA "CAMELLIA256-SHA"
+#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA "DH-DSS-CAMELLIA256-SHA"
+#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA "DH-RSA-CAMELLIA256-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA "DHE-DSS-CAMELLIA256-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA "DHE-RSA-CAMELLIA256-SHA"
+#define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA "ADH-CAMELLIA256-SHA"
+
+/* SEED ciphersuites from RFC4162 */
+#define TLS1_TXT_RSA_WITH_SEED_SHA "SEED-SHA"
+#define TLS1_TXT_DH_DSS_WITH_SEED_SHA "DH-DSS-SEED-SHA"
+#define TLS1_TXT_DH_RSA_WITH_SEED_SHA "DH-RSA-SEED-SHA"
+#define TLS1_TXT_DHE_DSS_WITH_SEED_SHA "DHE-DSS-SEED-SHA"
+#define TLS1_TXT_DHE_RSA_WITH_SEED_SHA "DHE-RSA-SEED-SHA"
+#define TLS1_TXT_ADH_WITH_SEED_SHA "ADH-SEED-SHA"
+
+#define TLS_CT_RSA_SIGN 1
+#define TLS_CT_DSS_SIGN 2
+#define TLS_CT_RSA_FIXED_DH 3
+#define TLS_CT_DSS_FIXED_DH 4
+#define TLS_CT_ECDSA_SIGN 64
+#define TLS_CT_RSA_FIXED_ECDH 65
+#define TLS_CT_ECDSA_FIXED_ECDH 66
+#define TLS_CT_NUMBER 7
+
+#define TLS1_FINISH_MAC_LENGTH 12
+
+#define TLS_MD_MAX_CONST_SIZE 20
+#define TLS_MD_CLIENT_FINISH_CONST "client finished"
+#define TLS_MD_CLIENT_FINISH_CONST_SIZE 15
+#define TLS_MD_SERVER_FINISH_CONST "server finished"
+#define TLS_MD_SERVER_FINISH_CONST_SIZE 15
+#define TLS_MD_SERVER_WRITE_KEY_CONST "server write key"
+#define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE 16
+#define TLS_MD_KEY_EXPANSION_CONST "key expansion"
+#define TLS_MD_KEY_EXPANSION_CONST_SIZE 13
+#define TLS_MD_CLIENT_WRITE_KEY_CONST "client write key"
+#define TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE 16
+#define TLS_MD_SERVER_WRITE_KEY_CONST "server write key"
+#define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE 16
+#define TLS_MD_IV_BLOCK_CONST "IV block"
+#define TLS_MD_IV_BLOCK_CONST_SIZE 8
+#define TLS_MD_MASTER_SECRET_CONST "master secret"
+#define TLS_MD_MASTER_SECRET_CONST_SIZE 13
+
+#ifdef CHARSET_EBCDIC
+#undef TLS_MD_CLIENT_FINISH_CONST
+#define TLS_MD_CLIENT_FINISH_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x66\x69\x6e\x69\x73\x68\x65\x64" /*client finished*/
+#undef TLS_MD_SERVER_FINISH_CONST
+#define TLS_MD_SERVER_FINISH_CONST "\x73\x65\x72\x76\x65\x72\x20\x66\x69\x6e\x69\x73\x68\x65\x64" /*server finished*/
+#undef TLS_MD_SERVER_WRITE_KEY_CONST
+#define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" /*server write key*/
+#undef TLS_MD_KEY_EXPANSION_CONST
+#define TLS_MD_KEY_EXPANSION_CONST "\x6b\x65\x79\x20\x65\x78\x70\x61\x6e\x73\x69\x6f\x6e" /*key expansion*/
+#undef TLS_MD_CLIENT_WRITE_KEY_CONST
+#define TLS_MD_CLIENT_WRITE_KEY_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" /*client write key*/
+#undef TLS_MD_SERVER_WRITE_KEY_CONST
+#define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" /*server write key*/
+#undef TLS_MD_IV_BLOCK_CONST
+#define TLS_MD_IV_BLOCK_CONST "\x49\x56\x20\x62\x6c\x6f\x63\x6b" /*IV block*/
+#undef TLS_MD_MASTER_SECRET_CONST
+#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+
diff --git a/src/Mayaqua/win32_inc/openssl/tmdiff.h b/src/Mayaqua/win32_inc/openssl/tmdiff.h
new file mode 100644
index 00000000..6ed309e6
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/tmdiff.h
@@ -0,0 +1,93 @@
+/* crypto/tmdiff.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* Header for dynamic hash table routines
+ * Author - Eric Young
+ */
+/* ... erm yeah, "dynamic hash tables" you say?
+ *
+ * And what would dynamic hash tables have to do with any of this code *now*?
+ * AFAICS, this code is only referenced by crypto/bn/exp.c which is an unused
+ * file that I doubt compiles any more. speed.c is the only thing that could
+ * use this (and it has nothing to do with hash tables), yet it instead has its
+ * own duplication of all this stuff and looks, if anything, more complete. See
+ * the corresponding note in apps/speed.c.
+ * The Bemused - Geoff
+ */
+
+#ifndef HEADER_TMDIFF_H
+#define HEADER_TMDIFF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ms_tm MS_TM;
+
+MS_TM *ms_time_new(void );
+void ms_time_free(MS_TM *a);
+void ms_time_get(MS_TM *a);
+double ms_time_diff(MS_TM *start, MS_TM *end);
+int ms_time_cmp(const MS_TM *ap, const MS_TM *bp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/txt_db.h b/src/Mayaqua/win32_inc/openssl/txt_db.h
new file mode 100644
index 00000000..a767e455
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/txt_db.h
@@ -0,0 +1,109 @@
+/* crypto/txt_db/txt_db.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_TXT_DB_H
+#define HEADER_TXT_DB_H
+
+#include <openssl/opensslconf.h>
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#include <openssl/stack.h>
+#include <openssl/lhash.h>
+
+#define DB_ERROR_OK 0
+#define DB_ERROR_MALLOC 1
+#define DB_ERROR_INDEX_CLASH 2
+#define DB_ERROR_INDEX_OUT_OF_RANGE 3
+#define DB_ERROR_NO_INDEX 4
+#define DB_ERROR_INSERT_INDEX_CLASH 5
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct txt_db_st
+ {
+ int num_fields;
+ STACK /* char ** */ *data;
+ LHASH **index;
+ int (**qual)(char **);
+ long error;
+ long arg1;
+ long arg2;
+ char **arg_row;
+ } TXT_DB;
+
+#ifndef OPENSSL_NO_BIO
+TXT_DB *TXT_DB_read(BIO *in, int num);
+long TXT_DB_write(BIO *out, TXT_DB *db);
+#else
+TXT_DB *TXT_DB_read(char *in, int num);
+long TXT_DB_write(char *out, TXT_DB *db);
+#endif
+int TXT_DB_create_index(TXT_DB *db,int field,int (*qual)(char **),
+ LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp);
+void TXT_DB_free(TXT_DB *db);
+char **TXT_DB_get_by_index(TXT_DB *db, int idx, char **value);
+int TXT_DB_insert(TXT_DB *db,char **value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ui.h b/src/Mayaqua/win32_inc/openssl/ui.h
new file mode 100644
index 00000000..5570e0d1
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ui.h
@@ -0,0 +1,381 @@
+/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_UI_H
+#define HEADER_UI_H
+
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/crypto.h>
+#endif
+#include <openssl/safestack.h>
+#include <openssl/ossl_typ.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Declared already in ossl_typ.h */
+/* typedef struct ui_st UI; */
+/* typedef struct ui_method_st UI_METHOD; */
+
+
+/* All the following functions return -1 or NULL on error and in some cases
+ (UI_process()) -2 if interrupted or in some other way cancelled.
+ When everything is fine, they return 0, a positive value or a non-NULL
+ pointer, all depending on their purpose. */
+
+/* Creators and destructor. */
+UI *UI_new(void);
+UI *UI_new_method(const UI_METHOD *method);
+void UI_free(UI *ui);
+
+/* The following functions are used to add strings to be printed and prompt
+ strings to prompt for data. The names are UI_{add,dup}_<function>_string
+ and UI_{add,dup}_input_boolean.
+
+ UI_{add,dup}_<function>_string have the following meanings:
+ add add a text or prompt string. The pointers given to these
+ functions are used verbatim, no copying is done.
+ dup make a copy of the text or prompt string, then add the copy
+ to the collection of strings in the user interface.
+ <function>
+ The function is a name for the functionality that the given
+ string shall be used for. It can be one of:
+ input use the string as data prompt.
+ verify use the string as verification prompt. This
+ is used to verify a previous input.
+ info use the string for informational output.
+ error use the string for error output.
+ Honestly, there's currently no difference between info and error for the
+ moment.
+
+ UI_{add,dup}_input_boolean have the same semantics for "add" and "dup",
+ and are typically used when one wants to prompt for a yes/no response.
+
+
+ All of the functions in this group take a UI and a prompt string.
+ The string input and verify addition functions also take a flag argument,
+ a buffer for the result to end up with, a minimum input size and a maximum
+ input size (the result buffer MUST be large enough to be able to contain
+ the maximum number of characters). Additionally, the verify addition
+ functions takes another buffer to compare the result against.
+ The boolean input functions take an action description string (which should
+ be safe to ignore if the expected user action is obvious, for example with
+ a dialog box with an OK button and a Cancel button), a string of acceptable
+ characters to mean OK and to mean Cancel. The two last strings are checked
+ to make sure they don't have common characters. Additionally, the same
+ flag argument as for the string input is taken, as well as a result buffer.
+ The result buffer is required to be at least one byte long. Depending on
+ the answer, the first character from the OK or the Cancel character strings
+ will be stored in the first byte of the result buffer. No NUL will be
+ added, so the result is *not* a string.
+
+ On success, the all return an index of the added information. That index
+ is usefull when retrieving results with UI_get0_result(). */
+int UI_add_input_string(UI *ui, const char *prompt, int flags,
+ char *result_buf, int minsize, int maxsize);
+int UI_dup_input_string(UI *ui, const char *prompt, int flags,
+ char *result_buf, int minsize, int maxsize);
+int UI_add_verify_string(UI *ui, const char *prompt, int flags,
+ char *result_buf, int minsize, int maxsize, const char *test_buf);
+int UI_dup_verify_string(UI *ui, const char *prompt, int flags,
+ char *result_buf, int minsize, int maxsize, const char *test_buf);
+int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc,
+ const char *ok_chars, const char *cancel_chars,
+ int flags, char *result_buf);
+int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
+ const char *ok_chars, const char *cancel_chars,
+ int flags, char *result_buf);
+int UI_add_info_string(UI *ui, const char *text);
+int UI_dup_info_string(UI *ui, const char *text);
+int UI_add_error_string(UI *ui, const char *text);
+int UI_dup_error_string(UI *ui, const char *text);
+
+/* These are the possible flags. They can be or'ed together. */
+/* Use to have echoing of input */
+#define UI_INPUT_FLAG_ECHO 0x01
+/* Use a default password. Where that password is found is completely
+ up to the application, it might for example be in the user data set
+ with UI_add_user_data(). It is not recommended to have more than
+ one input in each UI being marked with this flag, or the application
+ might get confused. */
+#define UI_INPUT_FLAG_DEFAULT_PWD 0x02
+
+/* The user of these routines may want to define flags of their own. The core
+ UI won't look at those, but will pass them on to the method routines. They
+ must use higher bits so they don't get confused with the UI bits above.
+ UI_INPUT_FLAG_USER_BASE tells which is the lowest bit to use. A good
+ example of use is this:
+
+ #define MY_UI_FLAG1 (0x01 << UI_INPUT_FLAG_USER_BASE)
+
+*/
+#define UI_INPUT_FLAG_USER_BASE 16
+
+
+/* The following function helps construct a prompt. object_desc is a
+ textual short description of the object, for example "pass phrase",
+ and object_name is the name of the object (might be a card name or
+ a file name.
+ The returned string shall always be allocated on the heap with
+ OPENSSL_malloc(), and need to be free'd with OPENSSL_free().
+
+ If the ui_method doesn't contain a pointer to a user-defined prompt
+ constructor, a default string is built, looking like this:
+
+ "Enter {object_desc} for {object_name}:"
+
+ So, if object_desc has the value "pass phrase" and object_name has
+ the value "foo.key", the resulting string is:
+
+ "Enter pass phrase for foo.key:"
+*/
+char *UI_construct_prompt(UI *ui_method,
+ const char *object_desc, const char *object_name);
+
+
+/* The following function is used to store a pointer to user-specific data.
+ Any previous such pointer will be returned and replaced.
+
+ For callback purposes, this function makes a lot more sense than using
+ ex_data, since the latter requires that different parts of OpenSSL or
+ applications share the same ex_data index.
+
+ Note that the UI_OpenSSL() method completely ignores the user data.
+ Other methods may not, however. */
+void *UI_add_user_data(UI *ui, void *user_data);
+/* We need a user data retrieving function as well. */
+void *UI_get0_user_data(UI *ui);
+
+/* Return the result associated with a prompt given with the index i. */
+const char *UI_get0_result(UI *ui, int i);
+
+/* When all strings have been added, process the whole thing. */
+int UI_process(UI *ui);
+
+/* Give a user interface parametrised control commands. This can be used to
+ send down an integer, a data pointer or a function pointer, as well as
+ be used to get information from a UI. */
+int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f)(void));
+
+/* The commands */
+/* Use UI_CONTROL_PRINT_ERRORS with the value 1 to have UI_process print the
+ OpenSSL error stack before printing any info or added error messages and
+ before any prompting. */
+#define UI_CTRL_PRINT_ERRORS 1
+/* Check if a UI_process() is possible to do again with the same instance of
+ a user interface. This makes UI_ctrl() return 1 if it is redoable, and 0
+ if not. */
+#define UI_CTRL_IS_REDOABLE 2
+
+
+/* Some methods may use extra data */
+#define UI_set_app_data(s,arg) UI_set_ex_data(s,0,arg)
+#define UI_get_app_data(s) UI_get_ex_data(s,0)
+int UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int UI_set_ex_data(UI *r,int idx,void *arg);
+void *UI_get_ex_data(UI *r, int idx);
+
+/* Use specific methods instead of the built-in one */
+void UI_set_default_method(const UI_METHOD *meth);
+const UI_METHOD *UI_get_default_method(void);
+const UI_METHOD *UI_get_method(UI *ui);
+const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth);
+
+/* The method with all the built-in thingies */
+UI_METHOD *UI_OpenSSL(void);
+
+
+/* ---------- For method writers ---------- */
+/* A method contains a number of functions that implement the low level
+ of the User Interface. The functions are:
+
+ an opener This function starts a session, maybe by opening
+ a channel to a tty, or by opening a window.
+ a writer This function is called to write a given string,
+ maybe to the tty, maybe as a field label in a
+ window.
+ a flusher This function is called to flush everything that
+ has been output so far. It can be used to actually
+ display a dialog box after it has been built.
+ a reader This function is called to read a given prompt,
+ maybe from the tty, maybe from a field in a
+ window. Note that it's called wth all string
+ structures, not only the prompt ones, so it must
+ check such things itself.
+ a closer This function closes the session, maybe by closing
+ the channel to the tty, or closing the window.
+
+ All these functions are expected to return:
+
+ 0 on error.
+ 1 on success.
+ -1 on out-of-band events, for example if some prompting has
+ been canceled (by pressing Ctrl-C, for example). This is
+ only checked when returned by the flusher or the reader.
+
+ The way this is used, the opener is first called, then the writer for all
+ strings, then the flusher, then the reader for all strings and finally the
+ closer. Note that if you want to prompt from a terminal or other command
+ line interface, the best is to have the reader also write the prompts
+ instead of having the writer do it. If you want to prompt from a dialog
+ box, the writer can be used to build up the contents of the box, and the
+ flusher to actually display the box and run the event loop until all data
+ has been given, after which the reader only grabs the given data and puts
+ them back into the UI strings.
+
+ All method functions take a UI as argument. Additionally, the writer and
+ the reader take a UI_STRING.
+*/
+
+/* The UI_STRING type is the data structure that contains all the needed info
+ about a string or a prompt, including test data for a verification prompt.
+*/
+DECLARE_STACK_OF(UI_STRING)
+typedef struct ui_string_st UI_STRING;
+
+/* The different types of strings that are currently supported.
+ This is only needed by method authors. */
+enum UI_string_types
+ {
+ UIT_NONE=0,
+ UIT_PROMPT, /* Prompt for a string */
+ UIT_VERIFY, /* Prompt for a string and verify */
+ UIT_BOOLEAN, /* Prompt for a yes/no response */
+ UIT_INFO, /* Send info to the user */
+ UIT_ERROR /* Send an error message to the user */
+ };
+
+/* Create and manipulate methods */
+UI_METHOD *UI_create_method(char *name);
+void UI_destroy_method(UI_METHOD *ui_method);
+int UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui));
+int UI_method_set_writer(UI_METHOD *method, int (*writer)(UI *ui, UI_STRING *uis));
+int UI_method_set_flusher(UI_METHOD *method, int (*flusher)(UI *ui));
+int UI_method_set_reader(UI_METHOD *method, int (*reader)(UI *ui, UI_STRING *uis));
+int UI_method_set_closer(UI_METHOD *method, int (*closer)(UI *ui));
+int (*UI_method_get_opener(UI_METHOD *method))(UI*);
+int (*UI_method_get_writer(UI_METHOD *method))(UI*,UI_STRING*);
+int (*UI_method_get_flusher(UI_METHOD *method))(UI*);
+int (*UI_method_get_reader(UI_METHOD *method))(UI*,UI_STRING*);
+int (*UI_method_get_closer(UI_METHOD *method))(UI*);
+
+/* The following functions are helpers for method writers to access relevant
+ data from a UI_STRING. */
+
+/* Return type of the UI_STRING */
+enum UI_string_types UI_get_string_type(UI_STRING *uis);
+/* Return input flags of the UI_STRING */
+int UI_get_input_flags(UI_STRING *uis);
+/* Return the actual string to output (the prompt, info or error) */
+const char *UI_get0_output_string(UI_STRING *uis);
+/* Return the optional action string to output (the boolean promtp instruction) */
+const char *UI_get0_action_string(UI_STRING *uis);
+/* Return the result of a prompt */
+const char *UI_get0_result_string(UI_STRING *uis);
+/* Return the string to test the result against. Only useful with verifies. */
+const char *UI_get0_test_string(UI_STRING *uis);
+/* Return the required minimum size of the result */
+int UI_get_result_minsize(UI_STRING *uis);
+/* Return the required maximum size of the result */
+int UI_get_result_maxsize(UI_STRING *uis);
+/* Set the result of a UI_STRING. */
+int UI_set_result(UI *ui, UI_STRING *uis, const char *result);
+
+
+/* A couple of popular utility functions */
+int UI_UTIL_read_pw_string(char *buf,int length,const char *prompt,int verify);
+int UI_UTIL_read_pw(char *buf,char *buff,int size,const char *prompt,int verify);
+
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_UI_strings(void);
+
+/* Error codes for the UI functions. */
+
+/* Function codes. */
+#define UI_F_GENERAL_ALLOCATE_BOOLEAN 108
+#define UI_F_GENERAL_ALLOCATE_PROMPT 109
+#define UI_F_GENERAL_ALLOCATE_STRING 100
+#define UI_F_UI_CTRL 111
+#define UI_F_UI_DUP_ERROR_STRING 101
+#define UI_F_UI_DUP_INFO_STRING 102
+#define UI_F_UI_DUP_INPUT_BOOLEAN 110
+#define UI_F_UI_DUP_INPUT_STRING 103
+#define UI_F_UI_DUP_VERIFY_STRING 106
+#define UI_F_UI_GET0_RESULT 107
+#define UI_F_UI_NEW_METHOD 104
+#define UI_F_UI_SET_RESULT 105
+
+/* Reason codes. */
+#define UI_R_COMMON_OK_AND_CANCEL_CHARACTERS 104
+#define UI_R_INDEX_TOO_LARGE 102
+#define UI_R_INDEX_TOO_SMALL 103
+#define UI_R_NO_RESULT_BUFFER 105
+#define UI_R_RESULT_TOO_LARGE 100
+#define UI_R_RESULT_TOO_SMALL 101
+#define UI_R_UNKNOWN_CONTROL_COMMAND 106
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/ui_compat.h b/src/Mayaqua/win32_inc/openssl/ui_compat.h
new file mode 100644
index 00000000..0209438d
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/ui_compat.h
@@ -0,0 +1,83 @@
+/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_UI_COMPAT_H
+#define HEADER_UI_COMPAT_H
+
+#include <openssl/opensslconf.h>
+#include <openssl/ui.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The following functions were previously part of the DES section,
+ and are provided here for backward compatibility reasons. */
+
+#define des_read_pw_string(b,l,p,v) \
+ _ossl_old_des_read_pw_string((b),(l),(p),(v))
+#define des_read_pw(b,bf,s,p,v) \
+ _ossl_old_des_read_pw((b),(bf),(s),(p),(v))
+
+int _ossl_old_des_read_pw_string(char *buf,int length,const char *prompt,int verify);
+int _ossl_old_des_read_pw(char *buf,char *buff,int size,const char *prompt,int verify);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/x509.h b/src/Mayaqua/win32_inc/openssl/x509.h
new file mode 100644
index 00000000..30ebe555
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/x509.h
@@ -0,0 +1,1357 @@
+/* crypto/x509/x509.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_X509_H
+#define HEADER_X509_H
+
+#include <openssl/e_os2.h>
+#include <openssl/symhacks.h>
+#ifndef OPENSSL_NO_BUFFER
+#include <openssl/buffer.h>
+#endif
+#ifndef OPENSSL_NO_EVP
+#include <openssl/evp.h>
+#endif
+#ifndef OPENSSL_NO_BIO
+#include <openssl/bio.h>
+#endif
+#include <openssl/stack.h>
+#include <openssl/asn1.h>
+#include <openssl/safestack.h>
+
+#ifndef OPENSSL_NO_EC
+#include <openssl/ec.h>
+#endif
+
+#ifndef OPENSSL_NO_ECDSA
+#include <openssl/ecdsa.h>
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+#include <openssl/ecdh.h>
+#endif
+
+#ifndef OPENSSL_NO_DEPRECATED
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#endif
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+#endif
+
+#ifndef OPENSSL_NO_SHA
+#include <openssl/sha.h>
+#endif
+#include <openssl/ossl_typ.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_SYS_WIN32
+/* Under Win32 these are defined in wincrypt.h */
+#undef X509_NAME
+#undef X509_CERT_PAIR
+#undef X509_EXTENSIONS
+#endif
+
+#define X509_FILETYPE_PEM 1
+#define X509_FILETYPE_ASN1 2
+#define X509_FILETYPE_DEFAULT 3
+
+#define X509v3_KU_DIGITAL_SIGNATURE 0x0080
+#define X509v3_KU_NON_REPUDIATION 0x0040
+#define X509v3_KU_KEY_ENCIPHERMENT 0x0020
+#define X509v3_KU_DATA_ENCIPHERMENT 0x0010
+#define X509v3_KU_KEY_AGREEMENT 0x0008
+#define X509v3_KU_KEY_CERT_SIGN 0x0004
+#define X509v3_KU_CRL_SIGN 0x0002
+#define X509v3_KU_ENCIPHER_ONLY 0x0001
+#define X509v3_KU_DECIPHER_ONLY 0x8000
+#define X509v3_KU_UNDEF 0xffff
+
+typedef struct X509_objects_st
+ {
+ int nid;
+ int (*a2i)(void);
+ int (*i2a)(void);
+ } X509_OBJECTS;
+
+struct X509_algor_st
+ {
+ ASN1_OBJECT *algorithm;
+ ASN1_TYPE *parameter;
+ } /* X509_ALGOR */;
+
+DECLARE_ASN1_SET_OF(X509_ALGOR)
+
+typedef STACK_OF(X509_ALGOR) X509_ALGORS;
+
+typedef struct X509_val_st
+ {
+ ASN1_TIME *notBefore;
+ ASN1_TIME *notAfter;
+ } X509_VAL;
+
+typedef struct X509_pubkey_st
+ {
+ X509_ALGOR *algor;
+ ASN1_BIT_STRING *public_key;
+ EVP_PKEY *pkey;
+ } X509_PUBKEY;
+
+typedef struct X509_sig_st
+ {
+ X509_ALGOR *algor;
+ ASN1_OCTET_STRING *digest;
+ } X509_SIG;
+
+typedef struct X509_name_entry_st
+ {
+ ASN1_OBJECT *object;
+ ASN1_STRING *value;
+ int set;
+ int size; /* temp variable */
+ } X509_NAME_ENTRY;
+
+DECLARE_STACK_OF(X509_NAME_ENTRY)
+DECLARE_ASN1_SET_OF(X509_NAME_ENTRY)
+
+/* we always keep X509_NAMEs in 2 forms. */
+struct X509_name_st
+ {
+ STACK_OF(X509_NAME_ENTRY) *entries;
+ int modified; /* true if 'bytes' needs to be built */
+#ifndef OPENSSL_NO_BUFFER
+ BUF_MEM *bytes;
+#else
+ char *bytes;
+#endif
+ unsigned long hash; /* Keep the hash around for lookups */
+ } /* X509_NAME */;
+
+DECLARE_STACK_OF(X509_NAME)
+
+#define X509_EX_V_NETSCAPE_HACK 0x8000
+#define X509_EX_V_INIT 0x0001
+typedef struct X509_extension_st
+ {
+ ASN1_OBJECT *object;
+ ASN1_BOOLEAN critical;
+ ASN1_OCTET_STRING *value;
+ } X509_EXTENSION;
+
+typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS;
+
+DECLARE_STACK_OF(X509_EXTENSION)
+DECLARE_ASN1_SET_OF(X509_EXTENSION)
+
+/* a sequence of these are used */
+typedef struct x509_attributes_st
+ {
+ ASN1_OBJECT *object;
+ int single; /* 0 for a set, 1 for a single item (which is wrong) */
+ union {
+ char *ptr;
+/* 0 */ STACK_OF(ASN1_TYPE) *set;
+/* 1 */ ASN1_TYPE *single;
+ } value;
+ } X509_ATTRIBUTE;
+
+DECLARE_STACK_OF(X509_ATTRIBUTE)
+DECLARE_ASN1_SET_OF(X509_ATTRIBUTE)
+
+
+typedef struct X509_req_info_st
+ {
+ ASN1_ENCODING enc;
+ ASN1_INTEGER *version;
+ X509_NAME *subject;
+ X509_PUBKEY *pubkey;
+ /* d=2 hl=2 l= 0 cons: cont: 00 */
+ STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
+ } X509_REQ_INFO;
+
+typedef struct X509_req_st
+ {
+ X509_REQ_INFO *req_info;
+ X509_ALGOR *sig_alg;
+ ASN1_BIT_STRING *signature;
+ int references;
+ } X509_REQ;
+
+typedef struct x509_cinf_st
+ {
+ ASN1_INTEGER *version; /* [ 0 ] default of v1 */
+ ASN1_INTEGER *serialNumber;
+ X509_ALGOR *signature;
+ X509_NAME *issuer;
+ X509_VAL *validity;
+ X509_NAME *subject;
+ X509_PUBKEY *key;
+ ASN1_BIT_STRING *issuerUID; /* [ 1 ] optional in v2 */
+ ASN1_BIT_STRING *subjectUID; /* [ 2 ] optional in v2 */
+ STACK_OF(X509_EXTENSION) *extensions; /* [ 3 ] optional in v3 */
+ ASN1_ENCODING enc;
+ } X509_CINF;
+
+/* This stuff is certificate "auxiliary info"
+ * it contains details which are useful in certificate
+ * stores and databases. When used this is tagged onto
+ * the end of the certificate itself
+ */
+
+typedef struct x509_cert_aux_st
+ {
+ STACK_OF(ASN1_OBJECT) *trust; /* trusted uses */
+ STACK_OF(ASN1_OBJECT) *reject; /* rejected uses */
+ ASN1_UTF8STRING *alias; /* "friendly name" */
+ ASN1_OCTET_STRING *keyid; /* key id of private key */
+ STACK_OF(X509_ALGOR) *other; /* other unspecified info */
+ } X509_CERT_AUX;
+
+struct x509_st
+ {
+ X509_CINF *cert_info;
+ X509_ALGOR *sig_alg;
+ ASN1_BIT_STRING *signature;
+ int valid;
+ int references;
+ char *name;
+ CRYPTO_EX_DATA ex_data;
+ /* These contain copies of various extension values */
+ long ex_pathlen;
+ long ex_pcpathlen;
+ unsigned long ex_flags;
+ unsigned long ex_kusage;
+ unsigned long ex_xkusage;
+ unsigned long ex_nscert;
+ ASN1_OCTET_STRING *skid;
+ struct AUTHORITY_KEYID_st *akid;
+ X509_POLICY_CACHE *policy_cache;
+#ifndef OPENSSL_NO_RFC3779
+ STACK_OF(IPAddressFamily) *rfc3779_addr;
+ struct ASIdentifiers_st *rfc3779_asid;
+#endif
+#ifndef OPENSSL_NO_SHA
+ unsigned char sha1_hash[SHA_DIGEST_LENGTH];
+#endif
+ X509_CERT_AUX *aux;
+ } /* X509 */;
+
+DECLARE_STACK_OF(X509)
+DECLARE_ASN1_SET_OF(X509)
+
+/* This is used for a table of trust checking functions */
+
+typedef struct x509_trust_st {
+ int trust;
+ int flags;
+ int (*check_trust)(struct x509_trust_st *, X509 *, int);
+ char *name;
+ int arg1;
+ void *arg2;
+} X509_TRUST;
+
+DECLARE_STACK_OF(X509_TRUST)
+
+typedef struct x509_cert_pair_st {
+ X509 *forward;
+ X509 *reverse;
+} X509_CERT_PAIR;
+
+/* standard trust ids */
+
+#define X509_TRUST_DEFAULT -1 /* Only valid in purpose settings */
+
+#define X509_TRUST_COMPAT 1
+#define X509_TRUST_SSL_CLIENT 2
+#define X509_TRUST_SSL_SERVER 3
+#define X509_TRUST_EMAIL 4
+#define X509_TRUST_OBJECT_SIGN 5
+#define X509_TRUST_OCSP_SIGN 6
+#define X509_TRUST_OCSP_REQUEST 7
+
+/* Keep these up to date! */
+#define X509_TRUST_MIN 1
+#define X509_TRUST_MAX 7
+
+
+/* trust_flags values */
+#define X509_TRUST_DYNAMIC 1
+#define X509_TRUST_DYNAMIC_NAME 2
+
+/* check_trust return codes */
+
+#define X509_TRUST_TRUSTED 1
+#define X509_TRUST_REJECTED 2
+#define X509_TRUST_UNTRUSTED 3
+
+/* Flags for X509_print_ex() */
+
+#define X509_FLAG_COMPAT 0
+#define X509_FLAG_NO_HEADER 1L
+#define X509_FLAG_NO_VERSION (1L << 1)
+#define X509_FLAG_NO_SERIAL (1L << 2)
+#define X509_FLAG_NO_SIGNAME (1L << 3)
+#define X509_FLAG_NO_ISSUER (1L << 4)
+#define X509_FLAG_NO_VALIDITY (1L << 5)
+#define X509_FLAG_NO_SUBJECT (1L << 6)
+#define X509_FLAG_NO_PUBKEY (1L << 7)
+#define X509_FLAG_NO_EXTENSIONS (1L << 8)
+#define X509_FLAG_NO_SIGDUMP (1L << 9)
+#define X509_FLAG_NO_AUX (1L << 10)
+#define X509_FLAG_NO_ATTRIBUTES (1L << 11)
+
+/* Flags specific to X509_NAME_print_ex() */
+
+/* The field separator information */
+
+#define XN_FLAG_SEP_MASK (0xf << 16)
+
+#define XN_FLAG_COMPAT 0 /* Traditional SSLeay: use old X509_NAME_print */
+#define XN_FLAG_SEP_COMMA_PLUS (1 << 16) /* RFC2253 ,+ */
+#define XN_FLAG_SEP_CPLUS_SPC (2 << 16) /* ,+ spaced: more readable */
+#define XN_FLAG_SEP_SPLUS_SPC (3 << 16) /* ;+ spaced */
+#define XN_FLAG_SEP_MULTILINE (4 << 16) /* One line per field */
+
+#define XN_FLAG_DN_REV (1 << 20) /* Reverse DN order */
+
+/* How the field name is shown */
+
+#define XN_FLAG_FN_MASK (0x3 << 21)
+
+#define XN_FLAG_FN_SN 0 /* Object short name */
+#define XN_FLAG_FN_LN (1 << 21) /* Object long name */
+#define XN_FLAG_FN_OID (2 << 21) /* Always use OIDs */
+#define XN_FLAG_FN_NONE (3 << 21) /* No field names */
+
+#define XN_FLAG_SPC_EQ (1 << 23) /* Put spaces round '=' */
+
+/* This determines if we dump fields we don't recognise:
+ * RFC2253 requires this.
+ */
+
+#define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24)
+
+#define XN_FLAG_FN_ALIGN (1 << 25) /* Align field names to 20 characters */
+
+/* Complete set of RFC2253 flags */
+
+#define XN_FLAG_RFC2253 (ASN1_STRFLGS_RFC2253 | \
+ XN_FLAG_SEP_COMMA_PLUS | \
+ XN_FLAG_DN_REV | \
+ XN_FLAG_FN_SN | \
+ XN_FLAG_DUMP_UNKNOWN_FIELDS)
+
+/* readable oneline form */
+
+#define XN_FLAG_ONELINE (ASN1_STRFLGS_RFC2253 | \
+ ASN1_STRFLGS_ESC_QUOTE | \
+ XN_FLAG_SEP_CPLUS_SPC | \
+ XN_FLAG_SPC_EQ | \
+ XN_FLAG_FN_SN)
+
+/* readable multiline form */
+
+#define XN_FLAG_MULTILINE (ASN1_STRFLGS_ESC_CTRL | \
+ ASN1_STRFLGS_ESC_MSB | \
+ XN_FLAG_SEP_MULTILINE | \
+ XN_FLAG_SPC_EQ | \
+ XN_FLAG_FN_LN | \
+ XN_FLAG_FN_ALIGN)
+
+typedef struct X509_revoked_st
+ {
+ ASN1_INTEGER *serialNumber;
+ ASN1_TIME *revocationDate;
+ STACK_OF(X509_EXTENSION) /* optional */ *extensions;
+ int sequence; /* load sequence */
+ } X509_REVOKED;
+
+DECLARE_STACK_OF(X509_REVOKED)
+DECLARE_ASN1_SET_OF(X509_REVOKED)
+
+typedef struct X509_crl_info_st
+ {
+ ASN1_INTEGER *version;
+ X509_ALGOR *sig_alg;
+ X509_NAME *issuer;
+ ASN1_TIME *lastUpdate;
+ ASN1_TIME *nextUpdate;
+ STACK_OF(X509_REVOKED) *revoked;
+ STACK_OF(X509_EXTENSION) /* [0] */ *extensions;
+ ASN1_ENCODING enc;
+ } X509_CRL_INFO;
+
+struct X509_crl_st
+ {
+ /* actual signature */
+ X509_CRL_INFO *crl;
+ X509_ALGOR *sig_alg;
+ ASN1_BIT_STRING *signature;
+ int references;
+ } /* X509_CRL */;
+
+DECLARE_STACK_OF(X509_CRL)
+DECLARE_ASN1_SET_OF(X509_CRL)
+
+typedef struct private_key_st
+ {
+ int version;
+ /* The PKCS#8 data types */
+ X509_ALGOR *enc_algor;
+ ASN1_OCTET_STRING *enc_pkey; /* encrypted pub key */
+
+ /* When decrypted, the following will not be NULL */
+ EVP_PKEY *dec_pkey;
+
+ /* used to encrypt and decrypt */
+ int key_length;
+ char *key_data;
+ int key_free; /* true if we should auto free key_data */
+
+ /* expanded version of 'enc_algor' */
+ EVP_CIPHER_INFO cipher;
+
+ int references;
+ } X509_PKEY;
+
+#ifndef OPENSSL_NO_EVP
+typedef struct X509_info_st
+ {
+ X509 *x509;
+ X509_CRL *crl;
+ X509_PKEY *x_pkey;
+
+ EVP_CIPHER_INFO enc_cipher;
+ int enc_len;
+ char *enc_data;
+
+ int references;
+ } X509_INFO;
+
+DECLARE_STACK_OF(X509_INFO)
+#endif
+
+/* The next 2 structures and their 8 routines were sent to me by
+ * Pat Richard <patr@x509.com> and are used to manipulate
+ * Netscapes spki structures - useful if you are writing a CA web page
+ */
+typedef struct Netscape_spkac_st
+ {
+ X509_PUBKEY *pubkey;
+ ASN1_IA5STRING *challenge; /* challenge sent in atlas >= PR2 */
+ } NETSCAPE_SPKAC;
+
+typedef struct Netscape_spki_st
+ {
+ NETSCAPE_SPKAC *spkac; /* signed public key and challenge */
+ X509_ALGOR *sig_algor;
+ ASN1_BIT_STRING *signature;
+ } NETSCAPE_SPKI;
+
+/* Netscape certificate sequence structure */
+typedef struct Netscape_certificate_sequence
+ {
+ ASN1_OBJECT *type;
+ STACK_OF(X509) *certs;
+ } NETSCAPE_CERT_SEQUENCE;
+
+/* Unused (and iv length is wrong)
+typedef struct CBCParameter_st
+ {
+ unsigned char iv[8];
+ } CBC_PARAM;
+*/
+
+/* Password based encryption structure */
+
+typedef struct PBEPARAM_st {
+ASN1_OCTET_STRING *salt;
+ASN1_INTEGER *iter;
+} PBEPARAM;
+
+/* Password based encryption V2 structures */
+
+typedef struct PBE2PARAM_st {
+X509_ALGOR *keyfunc;
+X509_ALGOR *encryption;
+} PBE2PARAM;
+
+typedef struct PBKDF2PARAM_st {
+ASN1_TYPE *salt; /* Usually OCTET STRING but could be anything */
+ASN1_INTEGER *iter;
+ASN1_INTEGER *keylength;
+X509_ALGOR *prf;
+} PBKDF2PARAM;
+
+
+/* PKCS#8 private key info structure */
+
+typedef struct pkcs8_priv_key_info_st
+ {
+ int broken; /* Flag for various broken formats */
+#define PKCS8_OK 0
+#define PKCS8_NO_OCTET 1
+#define PKCS8_EMBEDDED_PARAM 2
+#define PKCS8_NS_DB 3
+ ASN1_INTEGER *version;
+ X509_ALGOR *pkeyalg;
+ ASN1_TYPE *pkey; /* Should be OCTET STRING but some are broken */
+ STACK_OF(X509_ATTRIBUTE) *attributes;
+ } PKCS8_PRIV_KEY_INFO;
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <openssl/x509_vfy.h>
+#include <openssl/pkcs7.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef SSLEAY_MACROS
+#define X509_verify(a,r) ASN1_verify((int (*)())i2d_X509_CINF,a->sig_alg,\
+ a->signature,(char *)a->cert_info,r)
+#define X509_REQ_verify(a,r) ASN1_verify((int (*)())i2d_X509_REQ_INFO, \
+ a->sig_alg,a->signature,(char *)a->req_info,r)
+#define X509_CRL_verify(a,r) ASN1_verify((int (*)())i2d_X509_CRL_INFO, \
+ a->sig_alg, a->signature,(char *)a->crl,r)
+
+#define X509_sign(x,pkey,md) \
+ ASN1_sign((int (*)())i2d_X509_CINF, x->cert_info->signature, \
+ x->sig_alg, x->signature, (char *)x->cert_info,pkey,md)
+#define X509_REQ_sign(x,pkey,md) \
+ ASN1_sign((int (*)())i2d_X509_REQ_INFO,x->sig_alg, NULL, \
+ x->signature, (char *)x->req_info,pkey,md)
+#define X509_CRL_sign(x,pkey,md) \
+ ASN1_sign((int (*)())i2d_X509_CRL_INFO,x->crl->sig_alg,x->sig_alg, \
+ x->signature, (char *)x->crl,pkey,md)
+#define NETSCAPE_SPKI_sign(x,pkey,md) \
+ ASN1_sign((int (*)())i2d_NETSCAPE_SPKAC, x->sig_algor,NULL, \
+ x->signature, (char *)x->spkac,pkey,md)
+
+#define X509_dup(x509) (X509 *)ASN1_dup((int (*)())i2d_X509, \
+ (char *(*)())d2i_X509,(char *)x509)
+#define X509_ATTRIBUTE_dup(xa) (X509_ATTRIBUTE *)ASN1_dup(\
+ (int (*)())i2d_X509_ATTRIBUTE, \
+ (char *(*)())d2i_X509_ATTRIBUTE,(char *)xa)
+#define X509_EXTENSION_dup(ex) (X509_EXTENSION *)ASN1_dup( \
+ (int (*)())i2d_X509_EXTENSION, \
+ (char *(*)())d2i_X509_EXTENSION,(char *)ex)
+#define d2i_X509_fp(fp,x509) (X509 *)ASN1_d2i_fp((char *(*)())X509_new, \
+ (char *(*)())d2i_X509, (fp),(unsigned char **)(x509))
+#define i2d_X509_fp(fp,x509) ASN1_i2d_fp(i2d_X509,fp,(unsigned char *)x509)
+#define d2i_X509_bio(bp,x509) (X509 *)ASN1_d2i_bio((char *(*)())X509_new, \
+ (char *(*)())d2i_X509, (bp),(unsigned char **)(x509))
+#define i2d_X509_bio(bp,x509) ASN1_i2d_bio(i2d_X509,bp,(unsigned char *)x509)
+
+#define X509_CRL_dup(crl) (X509_CRL *)ASN1_dup((int (*)())i2d_X509_CRL, \
+ (char *(*)())d2i_X509_CRL,(char *)crl)
+#define d2i_X509_CRL_fp(fp,crl) (X509_CRL *)ASN1_d2i_fp((char *(*)()) \
+ X509_CRL_new,(char *(*)())d2i_X509_CRL, (fp),\
+ (unsigned char **)(crl))
+#define i2d_X509_CRL_fp(fp,crl) ASN1_i2d_fp(i2d_X509_CRL,fp,\
+ (unsigned char *)crl)
+#define d2i_X509_CRL_bio(bp,crl) (X509_CRL *)ASN1_d2i_bio((char *(*)()) \
+ X509_CRL_new,(char *(*)())d2i_X509_CRL, (bp),\
+ (unsigned char **)(crl))
+#define i2d_X509_CRL_bio(bp,crl) ASN1_i2d_bio(i2d_X509_CRL,bp,\
+ (unsigned char *)crl)
+
+#define PKCS7_dup(p7) (PKCS7 *)ASN1_dup((int (*)())i2d_PKCS7, \
+ (char *(*)())d2i_PKCS7,(char *)p7)
+#define d2i_PKCS7_fp(fp,p7) (PKCS7 *)ASN1_d2i_fp((char *(*)()) \
+ PKCS7_new,(char *(*)())d2i_PKCS7, (fp),\
+ (unsigned char **)(p7))
+#define i2d_PKCS7_fp(fp,p7) ASN1_i2d_fp(i2d_PKCS7,fp,\
+ (unsigned char *)p7)
+#define d2i_PKCS7_bio(bp,p7) (PKCS7 *)ASN1_d2i_bio((char *(*)()) \
+ PKCS7_new,(char *(*)())d2i_PKCS7, (bp),\
+ (unsigned char **)(p7))
+#define i2d_PKCS7_bio(bp,p7) ASN1_i2d_bio(i2d_PKCS7,bp,\
+ (unsigned char *)p7)
+
+#define X509_REQ_dup(req) (X509_REQ *)ASN1_dup((int (*)())i2d_X509_REQ, \
+ (char *(*)())d2i_X509_REQ,(char *)req)
+#define d2i_X509_REQ_fp(fp,req) (X509_REQ *)ASN1_d2i_fp((char *(*)())\
+ X509_REQ_new, (char *(*)())d2i_X509_REQ, (fp),\
+ (unsigned char **)(req))
+#define i2d_X509_REQ_fp(fp,req) ASN1_i2d_fp(i2d_X509_REQ,fp,\
+ (unsigned char *)req)
+#define d2i_X509_REQ_bio(bp,req) (X509_REQ *)ASN1_d2i_bio((char *(*)())\
+ X509_REQ_new, (char *(*)())d2i_X509_REQ, (bp),\
+ (unsigned char **)(req))
+#define i2d_X509_REQ_bio(bp,req) ASN1_i2d_bio(i2d_X509_REQ,bp,\
+ (unsigned char *)req)
+
+#define RSAPublicKey_dup(rsa) (RSA *)ASN1_dup((int (*)())i2d_RSAPublicKey, \
+ (char *(*)())d2i_RSAPublicKey,(char *)rsa)
+#define RSAPrivateKey_dup(rsa) (RSA *)ASN1_dup((int (*)())i2d_RSAPrivateKey, \
+ (char *(*)())d2i_RSAPrivateKey,(char *)rsa)
+
+#define d2i_RSAPrivateKey_fp(fp,rsa) (RSA *)ASN1_d2i_fp((char *(*)())\
+ RSA_new,(char *(*)())d2i_RSAPrivateKey, (fp), \
+ (unsigned char **)(rsa))
+#define i2d_RSAPrivateKey_fp(fp,rsa) ASN1_i2d_fp(i2d_RSAPrivateKey,fp, \
+ (unsigned char *)rsa)
+#define d2i_RSAPrivateKey_bio(bp,rsa) (RSA *)ASN1_d2i_bio((char *(*)())\
+ RSA_new,(char *(*)())d2i_RSAPrivateKey, (bp), \
+ (unsigned char **)(rsa))
+#define i2d_RSAPrivateKey_bio(bp,rsa) ASN1_i2d_bio(i2d_RSAPrivateKey,bp, \
+ (unsigned char *)rsa)
+
+#define d2i_RSAPublicKey_fp(fp,rsa) (RSA *)ASN1_d2i_fp((char *(*)())\
+ RSA_new,(char *(*)())d2i_RSAPublicKey, (fp), \
+ (unsigned char **)(rsa))
+#define i2d_RSAPublicKey_fp(fp,rsa) ASN1_i2d_fp(i2d_RSAPublicKey,fp, \
+ (unsigned char *)rsa)
+#define d2i_RSAPublicKey_bio(bp,rsa) (RSA *)ASN1_d2i_bio((char *(*)())\
+ RSA_new,(char *(*)())d2i_RSAPublicKey, (bp), \
+ (unsigned char **)(rsa))
+#define i2d_RSAPublicKey_bio(bp,rsa) ASN1_i2d_bio(i2d_RSAPublicKey,bp, \
+ (unsigned char *)rsa)
+
+#define d2i_DSAPrivateKey_fp(fp,dsa) (DSA *)ASN1_d2i_fp((char *(*)())\
+ DSA_new,(char *(*)())d2i_DSAPrivateKey, (fp), \
+ (unsigned char **)(dsa))
+#define i2d_DSAPrivateKey_fp(fp,dsa) ASN1_i2d_fp(i2d_DSAPrivateKey,fp, \
+ (unsigned char *)dsa)
+#define d2i_DSAPrivateKey_bio(bp,dsa) (DSA *)ASN1_d2i_bio((char *(*)())\
+ DSA_new,(char *(*)())d2i_DSAPrivateKey, (bp), \
+ (unsigned char **)(dsa))
+#define i2d_DSAPrivateKey_bio(bp,dsa) ASN1_i2d_bio(i2d_DSAPrivateKey,bp, \
+ (unsigned char *)dsa)
+
+#define d2i_ECPrivateKey_fp(fp,ecdsa) (EC_KEY *)ASN1_d2i_fp((char *(*)())\
+ EC_KEY_new,(char *(*)())d2i_ECPrivateKey, (fp), \
+ (unsigned char **)(ecdsa))
+#define i2d_ECPrivateKey_fp(fp,ecdsa) ASN1_i2d_fp(i2d_ECPrivateKey,fp, \
+ (unsigned char *)ecdsa)
+#define d2i_ECPrivateKey_bio(bp,ecdsa) (EC_KEY *)ASN1_d2i_bio((char *(*)())\
+ EC_KEY_new,(char *(*)())d2i_ECPrivateKey, (bp), \
+ (unsigned char **)(ecdsa))
+#define i2d_ECPrivateKey_bio(bp,ecdsa) ASN1_i2d_bio(i2d_ECPrivateKey,bp, \
+ (unsigned char *)ecdsa)
+
+#define X509_ALGOR_dup(xn) (X509_ALGOR *)ASN1_dup((int (*)())i2d_X509_ALGOR,\
+ (char *(*)())d2i_X509_ALGOR,(char *)xn)
+
+#define X509_NAME_dup(xn) (X509_NAME *)ASN1_dup((int (*)())i2d_X509_NAME, \
+ (char *(*)())d2i_X509_NAME,(char *)xn)
+#define X509_NAME_ENTRY_dup(ne) (X509_NAME_ENTRY *)ASN1_dup( \
+ (int (*)())i2d_X509_NAME_ENTRY, \
+ (char *(*)())d2i_X509_NAME_ENTRY,\
+ (char *)ne)
+
+#define X509_digest(data,type,md,len) \
+ ASN1_digest((int (*)())i2d_X509,type,(char *)data,md,len)
+#define X509_NAME_digest(data,type,md,len) \
+ ASN1_digest((int (*)())i2d_X509_NAME,type,(char *)data,md,len)
+#ifndef PKCS7_ISSUER_AND_SERIAL_digest
+#define PKCS7_ISSUER_AND_SERIAL_digest(data,type,md,len) \
+ ASN1_digest((int (*)())i2d_PKCS7_ISSUER_AND_SERIAL,type,\
+ (char *)data,md,len)
+#endif
+#endif
+
+#define X509_EXT_PACK_UNKNOWN 1
+#define X509_EXT_PACK_STRING 2
+
+#define X509_get_version(x) ASN1_INTEGER_get((x)->cert_info->version)
+/* #define X509_get_serialNumber(x) ((x)->cert_info->serialNumber) */
+#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)
+#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
+#define X509_extract_key(x) X509_get_pubkey(x) /*****/
+#define X509_REQ_get_version(x) ASN1_INTEGER_get((x)->req_info->version)
+#define X509_REQ_get_subject_name(x) ((x)->req_info->subject)
+#define X509_REQ_extract_key(a) X509_REQ_get_pubkey(a)
+#define X509_name_cmp(a,b) X509_NAME_cmp((a),(b))
+#define X509_get_signature_type(x) EVP_PKEY_type(OBJ_obj2nid((x)->sig_alg->algorithm))
+
+#define X509_CRL_get_version(x) ASN1_INTEGER_get((x)->crl->version)
+#define X509_CRL_get_lastUpdate(x) ((x)->crl->lastUpdate)
+#define X509_CRL_get_nextUpdate(x) ((x)->crl->nextUpdate)
+#define X509_CRL_get_issuer(x) ((x)->crl->issuer)
+#define X509_CRL_get_REVOKED(x) ((x)->crl->revoked)
+
+/* This one is only used so that a binary form can output, as in
+ * i2d_X509_NAME(X509_get_X509_PUBKEY(x),&buf) */
+#define X509_get_X509_PUBKEY(x) ((x)->cert_info->key)
+
+
+const char *X509_verify_cert_error_string(long n);
+
+#ifndef SSLEAY_MACROS
+#ifndef OPENSSL_NO_EVP
+int X509_verify(X509 *a, EVP_PKEY *r);
+
+int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r);
+int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r);
+int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r);
+
+NETSCAPE_SPKI * NETSCAPE_SPKI_b64_decode(const char *str, int len);
+char * NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *x);
+EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x);
+int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey);
+
+int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki);
+
+int X509_signature_print(BIO *bp,X509_ALGOR *alg, ASN1_STRING *sig);
+
+int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
+int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md);
+int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md);
+int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md);
+
+int X509_pubkey_digest(const X509 *data,const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+int X509_digest(const X509 *data,const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+int X509_CRL_digest(const X509_CRL *data,const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+int X509_REQ_digest(const X509_REQ *data,const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+int X509_NAME_digest(const X509_NAME *data,const EVP_MD *type,
+ unsigned char *md, unsigned int *len);
+#endif
+
+#ifndef OPENSSL_NO_FP_API
+X509 *d2i_X509_fp(FILE *fp, X509 **x509);
+int i2d_X509_fp(FILE *fp,X509 *x509);
+X509_CRL *d2i_X509_CRL_fp(FILE *fp,X509_CRL **crl);
+int i2d_X509_CRL_fp(FILE *fp,X509_CRL *crl);
+X509_REQ *d2i_X509_REQ_fp(FILE *fp,X509_REQ **req);
+int i2d_X509_REQ_fp(FILE *fp,X509_REQ *req);
+#ifndef OPENSSL_NO_RSA
+RSA *d2i_RSAPrivateKey_fp(FILE *fp,RSA **rsa);
+int i2d_RSAPrivateKey_fp(FILE *fp,RSA *rsa);
+RSA *d2i_RSAPublicKey_fp(FILE *fp,RSA **rsa);
+int i2d_RSAPublicKey_fp(FILE *fp,RSA *rsa);
+RSA *d2i_RSA_PUBKEY_fp(FILE *fp,RSA **rsa);
+int i2d_RSA_PUBKEY_fp(FILE *fp,RSA *rsa);
+#endif
+#ifndef OPENSSL_NO_DSA
+DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa);
+int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa);
+DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa);
+int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa);
+#endif
+#ifndef OPENSSL_NO_EC
+EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey);
+int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey);
+EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey);
+int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey);
+#endif
+X509_SIG *d2i_PKCS8_fp(FILE *fp,X509_SIG **p8);
+int i2d_PKCS8_fp(FILE *fp,X509_SIG *p8);
+PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
+ PKCS8_PRIV_KEY_INFO **p8inf);
+int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,PKCS8_PRIV_KEY_INFO *p8inf);
+int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key);
+int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey);
+EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a);
+int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey);
+EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a);
+#endif
+
+#ifndef OPENSSL_NO_BIO
+X509 *d2i_X509_bio(BIO *bp,X509 **x509);
+int i2d_X509_bio(BIO *bp,X509 *x509);
+X509_CRL *d2i_X509_CRL_bio(BIO *bp,X509_CRL **crl);
+int i2d_X509_CRL_bio(BIO *bp,X509_CRL *crl);
+X509_REQ *d2i_X509_REQ_bio(BIO *bp,X509_REQ **req);
+int i2d_X509_REQ_bio(BIO *bp,X509_REQ *req);
+#ifndef OPENSSL_NO_RSA
+RSA *d2i_RSAPrivateKey_bio(BIO *bp,RSA **rsa);
+int i2d_RSAPrivateKey_bio(BIO *bp,RSA *rsa);
+RSA *d2i_RSAPublicKey_bio(BIO *bp,RSA **rsa);
+int i2d_RSAPublicKey_bio(BIO *bp,RSA *rsa);
+RSA *d2i_RSA_PUBKEY_bio(BIO *bp,RSA **rsa);
+int i2d_RSA_PUBKEY_bio(BIO *bp,RSA *rsa);
+#endif
+#ifndef OPENSSL_NO_DSA
+DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa);
+int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa);
+DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa);
+int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa);
+#endif
+#ifndef OPENSSL_NO_EC
+EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey);
+int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *eckey);
+EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey);
+int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey);
+#endif
+X509_SIG *d2i_PKCS8_bio(BIO *bp,X509_SIG **p8);
+int i2d_PKCS8_bio(BIO *bp,X509_SIG *p8);
+PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
+ PKCS8_PRIV_KEY_INFO **p8inf);
+int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,PKCS8_PRIV_KEY_INFO *p8inf);
+int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key);
+int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey);
+EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a);
+int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey);
+EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a);
+#endif
+
+X509 *X509_dup(X509 *x509);
+X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa);
+X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex);
+X509_CRL *X509_CRL_dup(X509_CRL *crl);
+X509_REQ *X509_REQ_dup(X509_REQ *req);
+X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn);
+int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval);
+void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval,
+ X509_ALGOR *algor);
+
+X509_NAME *X509_NAME_dup(X509_NAME *xn);
+X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne);
+
+#endif /* !SSLEAY_MACROS */
+
+int X509_cmp_time(ASN1_TIME *s, time_t *t);
+int X509_cmp_current_time(ASN1_TIME *s);
+ASN1_TIME * X509_time_adj(ASN1_TIME *s, long adj, time_t *t);
+ASN1_TIME * X509_gmtime_adj(ASN1_TIME *s, long adj);
+
+const char * X509_get_default_cert_area(void );
+const char * X509_get_default_cert_dir(void );
+const char * X509_get_default_cert_file(void );
+const char * X509_get_default_cert_dir_env(void );
+const char * X509_get_default_cert_file_env(void );
+const char * X509_get_default_private_dir(void );
+
+X509_REQ * X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
+X509 * X509_REQ_to_X509(X509_REQ *r, int days,EVP_PKEY *pkey);
+
+DECLARE_ASN1_FUNCTIONS(X509_ALGOR)
+DECLARE_ASN1_ENCODE_FUNCTIONS(X509_ALGORS, X509_ALGORS, X509_ALGORS)
+DECLARE_ASN1_FUNCTIONS(X509_VAL)
+
+DECLARE_ASN1_FUNCTIONS(X509_PUBKEY)
+
+int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey);
+EVP_PKEY * X509_PUBKEY_get(X509_PUBKEY *key);
+int X509_get_pubkey_parameters(EVP_PKEY *pkey,
+ STACK_OF(X509) *chain);
+int i2d_PUBKEY(EVP_PKEY *a,unsigned char **pp);
+EVP_PKEY * d2i_PUBKEY(EVP_PKEY **a,const unsigned char **pp,
+ long length);
+#ifndef OPENSSL_NO_RSA
+int i2d_RSA_PUBKEY(RSA *a,unsigned char **pp);
+RSA * d2i_RSA_PUBKEY(RSA **a,const unsigned char **pp,
+ long length);
+#endif
+#ifndef OPENSSL_NO_DSA
+int i2d_DSA_PUBKEY(DSA *a,unsigned char **pp);
+DSA * d2i_DSA_PUBKEY(DSA **a,const unsigned char **pp,
+ long length);
+#endif
+#ifndef OPENSSL_NO_EC
+int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp);
+EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp,
+ long length);
+#endif
+
+DECLARE_ASN1_FUNCTIONS(X509_SIG)
+DECLARE_ASN1_FUNCTIONS(X509_REQ_INFO)
+DECLARE_ASN1_FUNCTIONS(X509_REQ)
+
+DECLARE_ASN1_FUNCTIONS(X509_ATTRIBUTE)
+X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value);
+
+DECLARE_ASN1_FUNCTIONS(X509_EXTENSION)
+DECLARE_ASN1_ENCODE_FUNCTIONS(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS)
+
+DECLARE_ASN1_FUNCTIONS(X509_NAME_ENTRY)
+
+DECLARE_ASN1_FUNCTIONS(X509_NAME)
+
+int X509_NAME_set(X509_NAME **xn, X509_NAME *name);
+
+DECLARE_ASN1_FUNCTIONS(X509_CINF)
+
+DECLARE_ASN1_FUNCTIONS(X509)
+DECLARE_ASN1_FUNCTIONS(X509_CERT_AUX)
+
+DECLARE_ASN1_FUNCTIONS(X509_CERT_PAIR)
+
+int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int X509_set_ex_data(X509 *r, int idx, void *arg);
+void *X509_get_ex_data(X509 *r, int idx);
+int i2d_X509_AUX(X509 *a,unsigned char **pp);
+X509 * d2i_X509_AUX(X509 **a,const unsigned char **pp,long length);
+
+int X509_alias_set1(X509 *x, unsigned char *name, int len);
+int X509_keyid_set1(X509 *x, unsigned char *id, int len);
+unsigned char * X509_alias_get0(X509 *x, int *len);
+unsigned char * X509_keyid_get0(X509 *x, int *len);
+int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int);
+int X509_TRUST_set(int *t, int trust);
+int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj);
+int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj);
+void X509_trust_clear(X509 *x);
+void X509_reject_clear(X509 *x);
+
+DECLARE_ASN1_FUNCTIONS(X509_REVOKED)
+DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO)
+DECLARE_ASN1_FUNCTIONS(X509_CRL)
+
+int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
+
+X509_PKEY * X509_PKEY_new(void );
+void X509_PKEY_free(X509_PKEY *a);
+int i2d_X509_PKEY(X509_PKEY *a,unsigned char **pp);
+X509_PKEY * d2i_X509_PKEY(X509_PKEY **a,const unsigned char **pp,long length);
+
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKI)
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKAC)
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE)
+
+#ifndef OPENSSL_NO_EVP
+X509_INFO * X509_INFO_new(void);
+void X509_INFO_free(X509_INFO *a);
+char * X509_NAME_oneline(X509_NAME *a,char *buf,int size);
+
+int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *algor1,
+ ASN1_BIT_STRING *signature,char *data,EVP_PKEY *pkey);
+
+int ASN1_digest(i2d_of_void *i2d,const EVP_MD *type,char *data,
+ unsigned char *md,unsigned int *len);
+
+int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1,
+ X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
+ char *data,EVP_PKEY *pkey, const EVP_MD *type);
+
+int ASN1_item_digest(const ASN1_ITEM *it,const EVP_MD *type,void *data,
+ unsigned char *md,unsigned int *len);
+
+int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1,
+ ASN1_BIT_STRING *signature,void *data,EVP_PKEY *pkey);
+
+int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
+ ASN1_BIT_STRING *signature,
+ void *data, EVP_PKEY *pkey, const EVP_MD *type);
+#endif
+
+int X509_set_version(X509 *x,long version);
+int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial);
+ASN1_INTEGER * X509_get_serialNumber(X509 *x);
+int X509_set_issuer_name(X509 *x, X509_NAME *name);
+X509_NAME * X509_get_issuer_name(X509 *a);
+int X509_set_subject_name(X509 *x, X509_NAME *name);
+X509_NAME * X509_get_subject_name(X509 *a);
+int X509_set_notBefore(X509 *x, ASN1_TIME *tm);
+int X509_set_notAfter(X509 *x, ASN1_TIME *tm);
+int X509_set_pubkey(X509 *x, EVP_PKEY *pkey);
+EVP_PKEY * X509_get_pubkey(X509 *x);
+ASN1_BIT_STRING * X509_get0_pubkey_bitstr(const X509 *x);
+int X509_certificate_type(X509 *x,EVP_PKEY *pubkey /* optional */);
+
+int X509_REQ_set_version(X509_REQ *x,long version);
+int X509_REQ_set_subject_name(X509_REQ *req,X509_NAME *name);
+int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey);
+EVP_PKEY * X509_REQ_get_pubkey(X509_REQ *req);
+int X509_REQ_extension_nid(int nid);
+int * X509_REQ_get_extension_nids(void);
+void X509_REQ_set_extension_nids(int *nids);
+STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req);
+int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
+ int nid);
+int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts);
+int X509_REQ_get_attr_count(const X509_REQ *req);
+int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid,
+ int lastpos);
+int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj,
+ int lastpos);
+X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc);
+X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc);
+int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr);
+int X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
+ const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes, int len);
+int X509_REQ_add1_attr_by_NID(X509_REQ *req,
+ int nid, int type,
+ const unsigned char *bytes, int len);
+int X509_REQ_add1_attr_by_txt(X509_REQ *req,
+ const char *attrname, int type,
+ const unsigned char *bytes, int len);
+
+int X509_CRL_set_version(X509_CRL *x, long version);
+int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name);
+int X509_CRL_set_lastUpdate(X509_CRL *x, ASN1_TIME *tm);
+int X509_CRL_set_nextUpdate(X509_CRL *x, ASN1_TIME *tm);
+int X509_CRL_sort(X509_CRL *crl);
+
+int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial);
+int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm);
+
+int X509_REQ_check_private_key(X509_REQ *x509,EVP_PKEY *pkey);
+
+int X509_check_private_key(X509 *x509,EVP_PKEY *pkey);
+
+int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b);
+unsigned long X509_issuer_and_serial_hash(X509 *a);
+
+int X509_issuer_name_cmp(const X509 *a, const X509 *b);
+unsigned long X509_issuer_name_hash(X509 *a);
+
+int X509_subject_name_cmp(const X509 *a, const X509 *b);
+unsigned long X509_subject_name_hash(X509 *x);
+
+int X509_cmp(const X509 *a, const X509 *b);
+int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b);
+unsigned long X509_NAME_hash(X509_NAME *x);
+
+int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b);
+#ifndef OPENSSL_NO_FP_API
+int X509_print_ex_fp(FILE *bp,X509 *x, unsigned long nmflag, unsigned long cflag);
+int X509_print_fp(FILE *bp,X509 *x);
+int X509_CRL_print_fp(FILE *bp,X509_CRL *x);
+int X509_REQ_print_fp(FILE *bp,X509_REQ *req);
+int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, unsigned long flags);
+#endif
+
+#ifndef OPENSSL_NO_BIO
+int X509_NAME_print(BIO *bp, X509_NAME *name, int obase);
+int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags);
+int X509_print_ex(BIO *bp,X509 *x, unsigned long nmflag, unsigned long cflag);
+int X509_print(BIO *bp,X509 *x);
+int X509_ocspid_print(BIO *bp,X509 *x);
+int X509_CERT_AUX_print(BIO *bp,X509_CERT_AUX *x, int indent);
+int X509_CRL_print(BIO *bp,X509_CRL *x);
+int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflag, unsigned long cflag);
+int X509_REQ_print(BIO *bp,X509_REQ *req);
+#endif
+
+int X509_NAME_entry_count(X509_NAME *name);
+int X509_NAME_get_text_by_NID(X509_NAME *name, int nid,
+ char *buf,int len);
+int X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj,
+ char *buf,int len);
+
+/* NOTE: you should be passsing -1, not 0 as lastpos. The functions that use
+ * lastpos, search after that position on. */
+int X509_NAME_get_index_by_NID(X509_NAME *name,int nid,int lastpos);
+int X509_NAME_get_index_by_OBJ(X509_NAME *name,ASN1_OBJECT *obj,
+ int lastpos);
+X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc);
+X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc);
+int X509_NAME_add_entry(X509_NAME *name,X509_NAME_ENTRY *ne,
+ int loc, int set);
+int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
+ unsigned char *bytes, int len, int loc, int set);
+int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
+ unsigned char *bytes, int len, int loc, int set);
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
+ const char *field, int type, const unsigned char *bytes, int len);
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
+ int type,unsigned char *bytes, int len);
+int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
+ const unsigned char *bytes, int len, int loc, int set);
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
+ ASN1_OBJECT *obj, int type,const unsigned char *bytes,
+ int len);
+int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne,
+ ASN1_OBJECT *obj);
+int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
+ const unsigned char *bytes, int len);
+ASN1_OBJECT * X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne);
+ASN1_STRING * X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne);
+
+int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x);
+int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x,
+ int nid, int lastpos);
+int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *x,
+ ASN1_OBJECT *obj,int lastpos);
+int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *x,
+ int crit, int lastpos);
+X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc);
+X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc);
+STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x,
+ X509_EXTENSION *ex, int loc);
+
+int X509_get_ext_count(X509 *x);
+int X509_get_ext_by_NID(X509 *x, int nid, int lastpos);
+int X509_get_ext_by_OBJ(X509 *x,ASN1_OBJECT *obj,int lastpos);
+int X509_get_ext_by_critical(X509 *x, int crit, int lastpos);
+X509_EXTENSION *X509_get_ext(X509 *x, int loc);
+X509_EXTENSION *X509_delete_ext(X509 *x, int loc);
+int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
+void * X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx);
+int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit,
+ unsigned long flags);
+
+int X509_CRL_get_ext_count(X509_CRL *x);
+int X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos);
+int X509_CRL_get_ext_by_OBJ(X509_CRL *x,ASN1_OBJECT *obj,int lastpos);
+int X509_CRL_get_ext_by_critical(X509_CRL *x, int crit, int lastpos);
+X509_EXTENSION *X509_CRL_get_ext(X509_CRL *x, int loc);
+X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc);
+int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc);
+void * X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx);
+int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit,
+ unsigned long flags);
+
+int X509_REVOKED_get_ext_count(X509_REVOKED *x);
+int X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos);
+int X509_REVOKED_get_ext_by_OBJ(X509_REVOKED *x,ASN1_OBJECT *obj,int lastpos);
+int X509_REVOKED_get_ext_by_critical(X509_REVOKED *x, int crit, int lastpos);
+X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *x, int loc);
+X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc);
+int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc);
+void * X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx);
+int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit,
+ unsigned long flags);
+
+X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex,
+ int nid, int crit, ASN1_OCTET_STRING *data);
+X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex,
+ ASN1_OBJECT *obj,int crit,ASN1_OCTET_STRING *data);
+int X509_EXTENSION_set_object(X509_EXTENSION *ex,ASN1_OBJECT *obj);
+int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit);
+int X509_EXTENSION_set_data(X509_EXTENSION *ex,
+ ASN1_OCTET_STRING *data);
+ASN1_OBJECT * X509_EXTENSION_get_object(X509_EXTENSION *ex);
+ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne);
+int X509_EXTENSION_get_critical(X509_EXTENSION *ex);
+
+int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x);
+int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
+ int lastpos);
+int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, ASN1_OBJECT *obj,
+ int lastpos);
+X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc);
+X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
+ X509_ATTRIBUTE *attr);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x,
+ const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes, int len);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x,
+ int nid, int type,
+ const unsigned char *bytes, int len);
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x,
+ const char *attrname, int type,
+ const unsigned char *bytes, int len);
+void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x,
+ ASN1_OBJECT *obj, int lastpos, int type);
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
+ int atrtype, const void *data, int len);
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
+ const ASN1_OBJECT *obj, int atrtype, const void *data, int len);
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr,
+ const char *atrname, int type, const unsigned char *bytes, int len);
+int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj);
+int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, int len);
+void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx,
+ int atrtype, void *data);
+int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr);
+ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr);
+ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx);
+
+int EVP_PKEY_get_attr_count(const EVP_PKEY *key);
+int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid,
+ int lastpos);
+int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, ASN1_OBJECT *obj,
+ int lastpos);
+X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc);
+X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc);
+int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr);
+int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key,
+ const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes, int len);
+int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key,
+ int nid, int type,
+ const unsigned char *bytes, int len);
+int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key,
+ const char *attrname, int type,
+ const unsigned char *bytes, int len);
+
+int X509_verify_cert(X509_STORE_CTX *ctx);
+
+/* lookup a cert from a X509 STACK */
+X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk,X509_NAME *name,
+ ASN1_INTEGER *serial);
+X509 *X509_find_by_subject(STACK_OF(X509) *sk,X509_NAME *name);
+
+DECLARE_ASN1_FUNCTIONS(PBEPARAM)
+DECLARE_ASN1_FUNCTIONS(PBE2PARAM)
+DECLARE_ASN1_FUNCTIONS(PBKDF2PARAM)
+
+X509_ALGOR *PKCS5_pbe_set(int alg, int iter, unsigned char *salt, int saltlen);
+X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
+ unsigned char *salt, int saltlen);
+
+/* PKCS#8 utilities */
+
+DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
+
+EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8);
+PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey);
+PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken);
+PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken);
+
+int X509_check_trust(X509 *x, int id, int flags);
+int X509_TRUST_get_count(void);
+X509_TRUST * X509_TRUST_get0(int idx);
+int X509_TRUST_get_by_id(int id);
+int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
+ char *name, int arg1, void *arg2);
+void X509_TRUST_cleanup(void);
+int X509_TRUST_get_flags(X509_TRUST *xp);
+char *X509_TRUST_get0_name(X509_TRUST *xp);
+int X509_TRUST_get_trust(X509_TRUST *xp);
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_X509_strings(void);
+
+/* Error codes for the X509 functions. */
+
+/* Function codes. */
+#define X509_F_ADD_CERT_DIR 100
+#define X509_F_BY_FILE_CTRL 101
+#define X509_F_CHECK_POLICY 145
+#define X509_F_DIR_CTRL 102
+#define X509_F_GET_CERT_BY_SUBJECT 103
+#define X509_F_NETSCAPE_SPKI_B64_DECODE 129
+#define X509_F_NETSCAPE_SPKI_B64_ENCODE 130
+#define X509_F_X509AT_ADD1_ATTR 135
+#define X509_F_X509V3_ADD_EXT 104
+#define X509_F_X509_ATTRIBUTE_CREATE_BY_NID 136
+#define X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ 137
+#define X509_F_X509_ATTRIBUTE_CREATE_BY_TXT 140
+#define X509_F_X509_ATTRIBUTE_GET0_DATA 139
+#define X509_F_X509_ATTRIBUTE_SET1_DATA 138
+#define X509_F_X509_CHECK_PRIVATE_KEY 128
+#define X509_F_X509_CRL_PRINT_FP 147
+#define X509_F_X509_EXTENSION_CREATE_BY_NID 108
+#define X509_F_X509_EXTENSION_CREATE_BY_OBJ 109
+#define X509_F_X509_GET_PUBKEY_PARAMETERS 110
+#define X509_F_X509_LOAD_CERT_CRL_FILE 132
+#define X509_F_X509_LOAD_CERT_FILE 111
+#define X509_F_X509_LOAD_CRL_FILE 112
+#define X509_F_X509_NAME_ADD_ENTRY 113
+#define X509_F_X509_NAME_ENTRY_CREATE_BY_NID 114
+#define X509_F_X509_NAME_ENTRY_CREATE_BY_TXT 131
+#define X509_F_X509_NAME_ENTRY_SET_OBJECT 115
+#define X509_F_X509_NAME_ONELINE 116
+#define X509_F_X509_NAME_PRINT 117
+#define X509_F_X509_PRINT_EX_FP 118
+#define X509_F_X509_PUBKEY_GET 119
+#define X509_F_X509_PUBKEY_SET 120
+#define X509_F_X509_REQ_CHECK_PRIVATE_KEY 144
+#define X509_F_X509_REQ_PRINT_EX 121
+#define X509_F_X509_REQ_PRINT_FP 122
+#define X509_F_X509_REQ_TO_X509 123
+#define X509_F_X509_STORE_ADD_CERT 124
+#define X509_F_X509_STORE_ADD_CRL 125
+#define X509_F_X509_STORE_CTX_GET1_ISSUER 146
+#define X509_F_X509_STORE_CTX_INIT 143
+#define X509_F_X509_STORE_CTX_NEW 142
+#define X509_F_X509_STORE_CTX_PURPOSE_INHERIT 134
+#define X509_F_X509_TO_X509_REQ 126
+#define X509_F_X509_TRUST_ADD 133
+#define X509_F_X509_TRUST_SET 141
+#define X509_F_X509_VERIFY_CERT 127
+
+/* Reason codes. */
+#define X509_R_BAD_X509_FILETYPE 100
+#define X509_R_BASE64_DECODE_ERROR 118
+#define X509_R_CANT_CHECK_DH_KEY 114
+#define X509_R_CERT_ALREADY_IN_HASH_TABLE 101
+#define X509_R_ERR_ASN1_LIB 102
+#define X509_R_INVALID_DIRECTORY 113
+#define X509_R_INVALID_FIELD_NAME 119
+#define X509_R_INVALID_TRUST 123
+#define X509_R_KEY_TYPE_MISMATCH 115
+#define X509_R_KEY_VALUES_MISMATCH 116
+#define X509_R_LOADING_CERT_DIR 103
+#define X509_R_LOADING_DEFAULTS 104
+#define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY 105
+#define X509_R_SHOULD_RETRY 106
+#define X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN 107
+#define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY 108
+#define X509_R_UNKNOWN_KEY_TYPE 117
+#define X509_R_UNKNOWN_NID 109
+#define X509_R_UNKNOWN_PURPOSE_ID 121
+#define X509_R_UNKNOWN_TRUST_ID 120
+#define X509_R_UNSUPPORTED_ALGORITHM 111
+#define X509_R_WRONG_LOOKUP_TYPE 112
+#define X509_R_WRONG_TYPE 122
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/win32_inc/openssl/x509_vfy.h b/src/Mayaqua/win32_inc/openssl/x509_vfy.h
new file mode 100644
index 00000000..921dd0aa
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/x509_vfy.h
@@ -0,0 +1,534 @@
+/* crypto/x509/x509_vfy.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_X509_H
+#include <openssl/x509.h>
+/* openssl/x509.h ends up #include-ing this file at about the only
+ * appropriate moment. */
+#endif
+
+#ifndef HEADER_X509_VFY_H
+#define HEADER_X509_VFY_H
+
+#include <openssl/opensslconf.h>
+#ifndef OPENSSL_NO_LHASH
+#include <openssl/lhash.h>
+#endif
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/symhacks.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Outer object */
+typedef struct x509_hash_dir_st
+ {
+ int num_dirs;
+ char **dirs;
+ int *dirs_type;
+ int num_dirs_alloced;
+ } X509_HASH_DIR_CTX;
+
+typedef struct x509_file_st
+ {
+ int num_paths; /* number of paths to files or directories */
+ int num_alloced;
+ char **paths; /* the list of paths or directories */
+ int *path_type;
+ } X509_CERT_FILE_CTX;
+
+/*******************************/
+/*
+SSL_CTX -> X509_STORE
+ -> X509_LOOKUP
+ ->X509_LOOKUP_METHOD
+ -> X509_LOOKUP
+ ->X509_LOOKUP_METHOD
+
+SSL -> X509_STORE_CTX
+ ->X509_STORE
+
+The X509_STORE holds the tables etc for verification stuff.
+A X509_STORE_CTX is used while validating a single certificate.
+The X509_STORE has X509_LOOKUPs for looking up certs.
+The X509_STORE then calls a function to actually verify the
+certificate chain.
+*/
+
+#define X509_LU_RETRY -1
+#define X509_LU_FAIL 0
+#define X509_LU_X509 1
+#define X509_LU_CRL 2
+#define X509_LU_PKEY 3
+
+typedef struct x509_object_st
+ {
+ /* one of the above types */
+ int type;
+ union {
+ char *ptr;
+ X509 *x509;
+ X509_CRL *crl;
+ EVP_PKEY *pkey;
+ } data;
+ } X509_OBJECT;
+
+typedef struct x509_lookup_st X509_LOOKUP;
+
+DECLARE_STACK_OF(X509_LOOKUP)
+DECLARE_STACK_OF(X509_OBJECT)
+
+/* This is a static that defines the function interface */
+typedef struct x509_lookup_method_st
+ {
+ const char *name;
+ int (*new_item)(X509_LOOKUP *ctx);
+ void (*free)(X509_LOOKUP *ctx);
+ int (*init)(X509_LOOKUP *ctx);
+ int (*shutdown)(X509_LOOKUP *ctx);
+ int (*ctrl)(X509_LOOKUP *ctx,int cmd,const char *argc,long argl,
+ char **ret);
+ int (*get_by_subject)(X509_LOOKUP *ctx,int type,X509_NAME *name,
+ X509_OBJECT *ret);
+ int (*get_by_issuer_serial)(X509_LOOKUP *ctx,int type,X509_NAME *name,
+ ASN1_INTEGER *serial,X509_OBJECT *ret);
+ int (*get_by_fingerprint)(X509_LOOKUP *ctx,int type,
+ unsigned char *bytes,int len,
+ X509_OBJECT *ret);
+ int (*get_by_alias)(X509_LOOKUP *ctx,int type,char *str,int len,
+ X509_OBJECT *ret);
+ } X509_LOOKUP_METHOD;
+
+/* This structure hold all parameters associated with a verify operation
+ * by including an X509_VERIFY_PARAM structure in related structures the
+ * parameters used can be customized
+ */
+
+typedef struct X509_VERIFY_PARAM_st
+ {
+ char *name;
+ time_t check_time; /* Time to use */
+ unsigned long inh_flags; /* Inheritance flags */
+ unsigned long flags; /* Various verify flags */
+ int purpose; /* purpose to check untrusted certificates */
+ int trust; /* trust setting to check */
+ int depth; /* Verify depth */
+ STACK_OF(ASN1_OBJECT) *policies; /* Permissible policies */
+ } X509_VERIFY_PARAM;
+
+DECLARE_STACK_OF(X509_VERIFY_PARAM)
+
+/* This is used to hold everything. It is used for all certificate
+ * validation. Once we have a certificate chain, the 'verify'
+ * function is then called to actually check the cert chain. */
+struct x509_store_st
+ {
+ /* The following is a cache of trusted certs */
+ int cache; /* if true, stash any hits */
+ STACK_OF(X509_OBJECT) *objs; /* Cache of all objects */
+
+ /* These are external lookup methods */
+ STACK_OF(X509_LOOKUP) *get_cert_methods;
+
+ X509_VERIFY_PARAM *param;
+
+ /* Callbacks for various operations */
+ int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */
+ int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */
+ int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); /* get issuers cert from ctx */
+ int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */
+ int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */
+ int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */
+ int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */
+ int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */
+ int (*cleanup)(X509_STORE_CTX *ctx);
+
+ CRYPTO_EX_DATA ex_data;
+ int references;
+ } /* X509_STORE */;
+
+int X509_STORE_set_depth(X509_STORE *store, int depth);
+
+#define X509_STORE_set_verify_cb_func(ctx,func) ((ctx)->verify_cb=(func))
+#define X509_STORE_set_verify_func(ctx,func) ((ctx)->verify=(func))
+
+/* This is the functions plus an instance of the local variables. */
+struct x509_lookup_st
+ {
+ int init; /* have we been started */
+ int skip; /* don't use us. */
+ X509_LOOKUP_METHOD *method; /* the functions */
+ char *method_data; /* method data */
+
+ X509_STORE *store_ctx; /* who owns us */
+ } /* X509_LOOKUP */;
+
+/* This is a used when verifying cert chains. Since the
+ * gathering of the cert chain can take some time (and have to be
+ * 'retried', this needs to be kept and passed around. */
+struct x509_store_ctx_st /* X509_STORE_CTX */
+ {
+ X509_STORE *ctx;
+ int current_method; /* used when looking up certs */
+
+ /* The following are set by the caller */
+ X509 *cert; /* The cert to check */
+ STACK_OF(X509) *untrusted; /* chain of X509s - untrusted - passed in */
+ STACK_OF(X509_CRL) *crls; /* set of CRLs passed in */
+
+ X509_VERIFY_PARAM *param;
+ void *other_ctx; /* Other info for use with get_issuer() */
+
+ /* Callbacks for various operations */
+ int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */
+ int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */
+ int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); /* get issuers cert from ctx */
+ int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */
+ int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */
+ int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */
+ int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */
+ int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */
+ int (*check_policy)(X509_STORE_CTX *ctx);
+ int (*cleanup)(X509_STORE_CTX *ctx);
+
+ /* The following is built up */
+ int valid; /* if 0, rebuild chain */
+ int last_untrusted; /* index of last untrusted cert */
+ STACK_OF(X509) *chain; /* chain of X509s - built up and trusted */
+ X509_POLICY_TREE *tree; /* Valid policy tree */
+
+ int explicit_policy; /* Require explicit policy value */
+
+ /* When something goes wrong, this is why */
+ int error_depth;
+ int error;
+ X509 *current_cert;
+ X509 *current_issuer; /* cert currently being tested as valid issuer */
+ X509_CRL *current_crl; /* current CRL */
+
+ CRYPTO_EX_DATA ex_data;
+ } /* X509_STORE_CTX */;
+
+void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
+
+#define X509_STORE_CTX_set_app_data(ctx,data) \
+ X509_STORE_CTX_set_ex_data(ctx,0,data)
+#define X509_STORE_CTX_get_app_data(ctx) \
+ X509_STORE_CTX_get_ex_data(ctx,0)
+
+#define X509_L_FILE_LOAD 1
+#define X509_L_ADD_DIR 2
+
+#define X509_LOOKUP_load_file(x,name,type) \
+ X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL)
+
+#define X509_LOOKUP_add_dir(x,name,type) \
+ X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL)
+
+#define X509_V_OK 0
+/* illegal error (for uninitialized values, to avoid X509_V_OK): 1 */
+
+#define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2
+#define X509_V_ERR_UNABLE_TO_GET_CRL 3
+#define X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE 4
+#define X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE 5
+#define X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY 6
+#define X509_V_ERR_CERT_SIGNATURE_FAILURE 7
+#define X509_V_ERR_CRL_SIGNATURE_FAILURE 8
+#define X509_V_ERR_CERT_NOT_YET_VALID 9
+#define X509_V_ERR_CERT_HAS_EXPIRED 10
+#define X509_V_ERR_CRL_NOT_YET_VALID 11
+#define X509_V_ERR_CRL_HAS_EXPIRED 12
+#define X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD 13
+#define X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD 14
+#define X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD 15
+#define X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD 16
+#define X509_V_ERR_OUT_OF_MEM 17
+#define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18
+#define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19
+#define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20
+#define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21
+#define X509_V_ERR_CERT_CHAIN_TOO_LONG 22
+#define X509_V_ERR_CERT_REVOKED 23
+#define X509_V_ERR_INVALID_CA 24
+#define X509_V_ERR_PATH_LENGTH_EXCEEDED 25
+#define X509_V_ERR_INVALID_PURPOSE 26
+#define X509_V_ERR_CERT_UNTRUSTED 27
+#define X509_V_ERR_CERT_REJECTED 28
+/* These are 'informational' when looking for issuer cert */
+#define X509_V_ERR_SUBJECT_ISSUER_MISMATCH 29
+#define X509_V_ERR_AKID_SKID_MISMATCH 30
+#define X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH 31
+#define X509_V_ERR_KEYUSAGE_NO_CERTSIGN 32
+
+#define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33
+#define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34
+#define X509_V_ERR_KEYUSAGE_NO_CRL_SIGN 35
+#define X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION 36
+#define X509_V_ERR_INVALID_NON_CA 37
+#define X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED 38
+#define X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE 39
+#define X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED 40
+
+#define X509_V_ERR_INVALID_EXTENSION 41
+#define X509_V_ERR_INVALID_POLICY_EXTENSION 42
+#define X509_V_ERR_NO_EXPLICIT_POLICY 43
+
+#define X509_V_ERR_UNNESTED_RESOURCE 44
+
+/* The application is not happy */
+#define X509_V_ERR_APPLICATION_VERIFICATION 50
+
+/* Certificate verify flags */
+
+/* Send issuer+subject checks to verify_cb */
+#define X509_V_FLAG_CB_ISSUER_CHECK 0x1
+/* Use check time instead of current time */
+#define X509_V_FLAG_USE_CHECK_TIME 0x2
+/* Lookup CRLs */
+#define X509_V_FLAG_CRL_CHECK 0x4
+/* Lookup CRLs for whole chain */
+#define X509_V_FLAG_CRL_CHECK_ALL 0x8
+/* Ignore unhandled critical extensions */
+#define X509_V_FLAG_IGNORE_CRITICAL 0x10
+/* Disable workarounds for broken certificates */
+#define X509_V_FLAG_X509_STRICT 0x20
+/* Enable proxy certificate validation */
+#define X509_V_FLAG_ALLOW_PROXY_CERTS 0x40
+/* Enable policy checking */
+#define X509_V_FLAG_POLICY_CHECK 0x80
+/* Policy variable require-explicit-policy */
+#define X509_V_FLAG_EXPLICIT_POLICY 0x100
+/* Policy variable inhibit-any-policy */
+#define X509_V_FLAG_INHIBIT_ANY 0x200
+/* Policy variable inhibit-policy-mapping */
+#define X509_V_FLAG_INHIBIT_MAP 0x400
+/* Notify callback that policy is OK */
+#define X509_V_FLAG_NOTIFY_POLICY 0x800
+
+/* Check selfsigned CA signature */
+#define X509_V_FLAG_CHECK_SS_SIGNATURE 0x4000
+
+#define X509_VP_FLAG_DEFAULT 0x1
+#define X509_VP_FLAG_OVERWRITE 0x2
+#define X509_VP_FLAG_RESET_FLAGS 0x4
+#define X509_VP_FLAG_LOCKED 0x8
+#define X509_VP_FLAG_ONCE 0x10
+
+/* Internal use: mask of policy related options */
+#define X509_V_FLAG_POLICY_MASK (X509_V_FLAG_POLICY_CHECK \
+ | X509_V_FLAG_EXPLICIT_POLICY \
+ | X509_V_FLAG_INHIBIT_ANY \
+ | X509_V_FLAG_INHIBIT_MAP)
+
+int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
+ X509_NAME *name);
+X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,int type,X509_NAME *name);
+X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x);
+void X509_OBJECT_up_ref_count(X509_OBJECT *a);
+void X509_OBJECT_free_contents(X509_OBJECT *a);
+X509_STORE *X509_STORE_new(void );
+void X509_STORE_free(X509_STORE *v);
+
+int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags);
+int X509_STORE_set_purpose(X509_STORE *ctx, int purpose);
+int X509_STORE_set_trust(X509_STORE *ctx, int trust);
+int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm);
+
+X509_STORE_CTX *X509_STORE_CTX_new(void);
+
+int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
+
+void X509_STORE_CTX_free(X509_STORE_CTX *ctx);
+int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store,
+ X509 *x509, STACK_OF(X509) *chain);
+void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
+void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx);
+
+X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m);
+
+X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void);
+X509_LOOKUP_METHOD *X509_LOOKUP_file(void);
+
+int X509_STORE_add_cert(X509_STORE *ctx, X509 *x);
+int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x);
+
+int X509_STORE_get_by_subject(X509_STORE_CTX *vs,int type,X509_NAME *name,
+ X509_OBJECT *ret);
+
+int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
+ long argl, char **ret);
+
+#ifndef OPENSSL_NO_STDIO
+int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type);
+int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type);
+int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type);
+#endif
+
+
+X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method);
+void X509_LOOKUP_free(X509_LOOKUP *ctx);
+int X509_LOOKUP_init(X509_LOOKUP *ctx);
+int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
+ X509_OBJECT *ret);
+int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
+ ASN1_INTEGER *serial, X509_OBJECT *ret);
+int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
+ unsigned char *bytes, int len, X509_OBJECT *ret);
+int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str,
+ int len, X509_OBJECT *ret);
+int X509_LOOKUP_shutdown(X509_LOOKUP *ctx);
+
+#ifndef OPENSSL_NO_STDIO
+int X509_STORE_load_locations (X509_STORE *ctx,
+ const char *file, const char *dir);
+int X509_STORE_set_default_paths(X509_STORE *ctx);
+#endif
+
+int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx,int idx,void *data);
+void * X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx,int idx);
+int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx);
+void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx,int s);
+int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
+X509 * X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
+STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx);
+STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx);
+void X509_STORE_CTX_set_cert(X509_STORE_CTX *c,X509 *x);
+void X509_STORE_CTX_set_chain(X509_STORE_CTX *c,STACK_OF(X509) *sk);
+void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c,STACK_OF(X509_CRL) *sk);
+int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
+int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
+int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
+ int purpose, int trust);
+void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags);
+void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags,
+ time_t t);
+void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
+ int (*verify_cb)(int, X509_STORE_CTX *));
+
+X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx);
+int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx);
+
+X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx);
+void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param);
+int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name);
+
+/* X509_VERIFY_PARAM functions */
+
+X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void);
+void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param);
+int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *to,
+ const X509_VERIFY_PARAM *from);
+int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
+ const X509_VERIFY_PARAM *from);
+int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name);
+int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags);
+int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
+ unsigned long flags);
+unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param);
+int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose);
+int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust);
+void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth);
+void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t);
+int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
+ ASN1_OBJECT *policy);
+int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
+ STACK_OF(ASN1_OBJECT) *policies);
+int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param);
+
+int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param);
+const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name);
+void X509_VERIFY_PARAM_table_cleanup(void);
+
+int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
+ STACK_OF(X509) *certs,
+ STACK_OF(ASN1_OBJECT) *policy_oids,
+ unsigned int flags);
+
+void X509_policy_tree_free(X509_POLICY_TREE *tree);
+
+int X509_policy_tree_level_count(const X509_POLICY_TREE *tree);
+X509_POLICY_LEVEL *
+ X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, int i);
+
+STACK_OF(X509_POLICY_NODE) *
+ X509_policy_tree_get0_policies(const X509_POLICY_TREE *tree);
+
+STACK_OF(X509_POLICY_NODE) *
+ X509_policy_tree_get0_user_policies(const X509_POLICY_TREE *tree);
+
+int X509_policy_level_node_count(X509_POLICY_LEVEL *level);
+
+X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i);
+
+const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node);
+
+STACK_OF(POLICYQUALINFO) *
+ X509_policy_node_get0_qualifiers(const X509_POLICY_NODE *node);
+const X509_POLICY_NODE *
+ X509_policy_node_get0_parent(const X509_POLICY_NODE *node);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/src/Mayaqua/win32_inc/openssl/x509v3.h b/src/Mayaqua/win32_inc/openssl/x509v3.h
new file mode 100644
index 00000000..c34bd6dc
--- /dev/null
+++ b/src/Mayaqua/win32_inc/openssl/x509v3.h
@@ -0,0 +1,922 @@
+/* x509v3.h */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_X509V3_H
+#define HEADER_X509V3_H
+
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+#include <openssl/conf.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward reference */
+struct v3_ext_method;
+struct v3_ext_ctx;
+
+/* Useful typedefs */
+
+typedef void * (*X509V3_EXT_NEW)(void);
+typedef void (*X509V3_EXT_FREE)(void *);
+typedef void * (*X509V3_EXT_D2I)(void *, const unsigned char ** , long);
+typedef int (*X509V3_EXT_I2D)(void *, unsigned char **);
+typedef STACK_OF(CONF_VALUE) * (*X509V3_EXT_I2V)(struct v3_ext_method *method, void *ext, STACK_OF(CONF_VALUE) *extlist);
+typedef void * (*X509V3_EXT_V2I)(struct v3_ext_method *method, struct v3_ext_ctx *ctx, STACK_OF(CONF_VALUE) *values);
+typedef char * (*X509V3_EXT_I2S)(struct v3_ext_method *method, void *ext);
+typedef void * (*X509V3_EXT_S2I)(struct v3_ext_method *method, struct v3_ext_ctx *ctx, const char *str);
+typedef int (*X509V3_EXT_I2R)(struct v3_ext_method *method, void *ext, BIO *out, int indent);
+typedef void * (*X509V3_EXT_R2I)(struct v3_ext_method *method, struct v3_ext_ctx *ctx, const char *str);
+
+/* V3 extension structure */
+
+struct v3_ext_method {
+int ext_nid;
+int ext_flags;
+/* If this is set the following four fields are ignored */
+ASN1_ITEM_EXP *it;
+/* Old style ASN1 calls */
+X509V3_EXT_NEW ext_new;
+X509V3_EXT_FREE ext_free;
+X509V3_EXT_D2I d2i;
+X509V3_EXT_I2D i2d;
+
+/* The following pair is used for string extensions */
+X509V3_EXT_I2S i2s;
+X509V3_EXT_S2I s2i;
+
+/* The following pair is used for multi-valued extensions */
+X509V3_EXT_I2V i2v;
+X509V3_EXT_V2I v2i;
+
+/* The following are used for raw extensions */
+X509V3_EXT_I2R i2r;
+X509V3_EXT_R2I r2i;
+
+void *usr_data; /* Any extension specific data */
+};
+
+typedef struct X509V3_CONF_METHOD_st {
+char * (*get_string)(void *db, char *section, char *value);
+STACK_OF(CONF_VALUE) * (*get_section)(void *db, char *section);
+void (*free_string)(void *db, char * string);
+void (*free_section)(void *db, STACK_OF(CONF_VALUE) *section);
+} X509V3_CONF_METHOD;
+
+/* Context specific info */
+struct v3_ext_ctx {
+#define CTX_TEST 0x1
+int flags;
+X509 *issuer_cert;
+X509 *subject_cert;
+X509_REQ *subject_req;
+X509_CRL *crl;
+X509V3_CONF_METHOD *db_meth;
+void *db;
+/* Maybe more here */
+};
+
+typedef struct v3_ext_method X509V3_EXT_METHOD;
+
+DECLARE_STACK_OF(X509V3_EXT_METHOD)
+
+/* ext_flags values */
+#define X509V3_EXT_DYNAMIC 0x1
+#define X509V3_EXT_CTX_DEP 0x2
+#define X509V3_EXT_MULTILINE 0x4
+
+typedef BIT_STRING_BITNAME ENUMERATED_NAMES;
+
+typedef struct BASIC_CONSTRAINTS_st {
+int ca;
+ASN1_INTEGER *pathlen;
+} BASIC_CONSTRAINTS;
+
+
+typedef struct PKEY_USAGE_PERIOD_st {
+ASN1_GENERALIZEDTIME *notBefore;
+ASN1_GENERALIZEDTIME *notAfter;
+} PKEY_USAGE_PERIOD;
+
+typedef struct otherName_st {
+ASN1_OBJECT *type_id;
+ASN1_TYPE *value;
+} OTHERNAME;
+
+typedef struct EDIPartyName_st {
+ ASN1_STRING *nameAssigner;
+ ASN1_STRING *partyName;
+} EDIPARTYNAME;
+
+typedef struct GENERAL_NAME_st {
+
+#define GEN_OTHERNAME 0
+#define GEN_EMAIL 1
+#define GEN_DNS 2
+#define GEN_X400 3
+#define GEN_DIRNAME 4
+#define GEN_EDIPARTY 5
+#define GEN_URI 6
+#define GEN_IPADD 7
+#define GEN_RID 8
+
+int type;
+union {
+ char *ptr;
+ OTHERNAME *otherName; /* otherName */
+ ASN1_IA5STRING *rfc822Name;
+ ASN1_IA5STRING *dNSName;
+ ASN1_TYPE *x400Address;
+ X509_NAME *directoryName;
+ EDIPARTYNAME *ediPartyName;
+ ASN1_IA5STRING *uniformResourceIdentifier;
+ ASN1_OCTET_STRING *iPAddress;
+ ASN1_OBJECT *registeredID;
+
+ /* Old names */
+ ASN1_OCTET_STRING *ip; /* iPAddress */
+ X509_NAME *dirn; /* dirn */
+ ASN1_IA5STRING *ia5;/* rfc822Name, dNSName, uniformResourceIdentifier */
+ ASN1_OBJECT *rid; /* registeredID */
+ ASN1_TYPE *other; /* x400Address */
+} d;
+} GENERAL_NAME;
+
+typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES;
+
+typedef struct ACCESS_DESCRIPTION_st {
+ ASN1_OBJECT *method;
+ GENERAL_NAME *location;
+} ACCESS_DESCRIPTION;
+
+typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS;
+
+typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE;
+
+DECLARE_STACK_OF(GENERAL_NAME)
+DECLARE_ASN1_SET_OF(GENERAL_NAME)
+
+DECLARE_STACK_OF(ACCESS_DESCRIPTION)
+DECLARE_ASN1_SET_OF(ACCESS_DESCRIPTION)
+
+typedef struct DIST_POINT_NAME_st {
+int type;
+union {
+ GENERAL_NAMES *fullname;
+ STACK_OF(X509_NAME_ENTRY) *relativename;
+} name;
+} DIST_POINT_NAME;
+
+typedef struct DIST_POINT_st {
+DIST_POINT_NAME *distpoint;
+ASN1_BIT_STRING *reasons;
+GENERAL_NAMES *CRLissuer;
+} DIST_POINT;
+
+typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS;
+
+DECLARE_STACK_OF(DIST_POINT)
+DECLARE_ASN1_SET_OF(DIST_POINT)
+
+typedef struct AUTHORITY_KEYID_st {
+ASN1_OCTET_STRING *keyid;
+GENERAL_NAMES *issuer;
+ASN1_INTEGER *serial;
+} AUTHORITY_KEYID;
+
+/* Strong extranet structures */
+
+typedef struct SXNET_ID_st {
+ ASN1_INTEGER *zone;
+ ASN1_OCTET_STRING *user;
+} SXNETID;
+
+DECLARE_STACK_OF(SXNETID)
+DECLARE_ASN1_SET_OF(SXNETID)
+
+typedef struct SXNET_st {
+ ASN1_INTEGER *version;
+ STACK_OF(SXNETID) *ids;
+} SXNET;
+
+typedef struct NOTICEREF_st {
+ ASN1_STRING *organization;
+ STACK_OF(ASN1_INTEGER) *noticenos;
+} NOTICEREF;
+
+typedef struct USERNOTICE_st {
+ NOTICEREF *noticeref;
+ ASN1_STRING *exptext;
+} USERNOTICE;
+
+typedef struct POLICYQUALINFO_st {
+ ASN1_OBJECT *pqualid;
+ union {
+ ASN1_IA5STRING *cpsuri;
+ USERNOTICE *usernotice;
+ ASN1_TYPE *other;
+ } d;
+} POLICYQUALINFO;
+
+DECLARE_STACK_OF(POLICYQUALINFO)
+DECLARE_ASN1_SET_OF(POLICYQUALINFO)
+
+typedef struct POLICYINFO_st {
+ ASN1_OBJECT *policyid;
+ STACK_OF(POLICYQUALINFO) *qualifiers;
+} POLICYINFO;
+
+typedef STACK_OF(POLICYINFO) CERTIFICATEPOLICIES;
+
+DECLARE_STACK_OF(POLICYINFO)
+DECLARE_ASN1_SET_OF(POLICYINFO)
+
+typedef struct POLICY_MAPPING_st {
+ ASN1_OBJECT *issuerDomainPolicy;
+ ASN1_OBJECT *subjectDomainPolicy;
+} POLICY_MAPPING;
+
+DECLARE_STACK_OF(POLICY_MAPPING)
+
+typedef STACK_OF(POLICY_MAPPING) POLICY_MAPPINGS;
+
+typedef struct GENERAL_SUBTREE_st {
+ GENERAL_NAME *base;
+ ASN1_INTEGER *minimum;
+ ASN1_INTEGER *maximum;
+} GENERAL_SUBTREE;
+
+DECLARE_STACK_OF(GENERAL_SUBTREE)
+
+typedef struct NAME_CONSTRAINTS_st {
+ STACK_OF(GENERAL_SUBTREE) *permittedSubtrees;
+ STACK_OF(GENERAL_SUBTREE) *excludedSubtrees;
+} NAME_CONSTRAINTS;
+
+typedef struct POLICY_CONSTRAINTS_st {
+ ASN1_INTEGER *requireExplicitPolicy;
+ ASN1_INTEGER *inhibitPolicyMapping;
+} POLICY_CONSTRAINTS;
+
+/* Proxy certificate structures, see RFC 3820 */
+typedef struct PROXY_POLICY_st
+ {
+ ASN1_OBJECT *policyLanguage;
+ ASN1_OCTET_STRING *policy;
+ } PROXY_POLICY;
+
+typedef struct PROXY_CERT_INFO_EXTENSION_st
+ {
+ ASN1_INTEGER *pcPathLengthConstraint;
+ PROXY_POLICY *proxyPolicy;
+ } PROXY_CERT_INFO_EXTENSION;
+
+DECLARE_ASN1_FUNCTIONS(PROXY_POLICY)
+DECLARE_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
+
+
+#define X509V3_conf_err(val) ERR_add_error_data(6, "section:", val->section, \
+",name:", val->name, ",value:", val->value);
+
+#define X509V3_set_ctx_test(ctx) \
+ X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST)
+#define X509V3_set_ctx_nodb(ctx) (ctx)->db = NULL;
+
+#define EXT_BITSTRING(nid, table) { nid, 0, ASN1_ITEM_ref(ASN1_BIT_STRING), \
+ 0,0,0,0, \
+ 0,0, \
+ (X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, \
+ (X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, \
+ NULL, NULL, \
+ table}
+
+#define EXT_IA5STRING(nid) { nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), \
+ 0,0,0,0, \
+ (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, \
+ (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, \
+ 0,0,0,0, \
+ NULL}
+
+#define EXT_END { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+
+/* X509_PURPOSE stuff */
+
+#define EXFLAG_BCONS 0x1
+#define EXFLAG_KUSAGE 0x2
+#define EXFLAG_XKUSAGE 0x4
+#define EXFLAG_NSCERT 0x8
+
+#define EXFLAG_CA 0x10
+/* Really self issued not necessarily self signed */
+#define EXFLAG_SI 0x20
+#define EXFLAG_SS 0x20
+#define EXFLAG_V1 0x40
+#define EXFLAG_INVALID 0x80
+#define EXFLAG_SET 0x100
+#define EXFLAG_CRITICAL 0x200
+#define EXFLAG_PROXY 0x400
+
+#define EXFLAG_INVALID_POLICY 0x800
+
+#define KU_DIGITAL_SIGNATURE 0x0080
+#define KU_NON_REPUDIATION 0x0040
+#define KU_KEY_ENCIPHERMENT 0x0020
+#define KU_DATA_ENCIPHERMENT 0x0010
+#define KU_KEY_AGREEMENT 0x0008
+#define KU_KEY_CERT_SIGN 0x0004
+#define KU_CRL_SIGN 0x0002
+#define KU_ENCIPHER_ONLY 0x0001
+#define KU_DECIPHER_ONLY 0x8000
+
+#define NS_SSL_CLIENT 0x80
+#define NS_SSL_SERVER 0x40
+#define NS_SMIME 0x20
+#define NS_OBJSIGN 0x10
+#define NS_SSL_CA 0x04
+#define NS_SMIME_CA 0x02
+#define NS_OBJSIGN_CA 0x01
+#define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA)
+
+#define XKU_SSL_SERVER 0x1
+#define XKU_SSL_CLIENT 0x2
+#define XKU_SMIME 0x4
+#define XKU_CODE_SIGN 0x8
+#define XKU_SGC 0x10
+#define XKU_OCSP_SIGN 0x20
+#define XKU_TIMESTAMP 0x40
+#define XKU_DVCS 0x80
+
+#define X509_PURPOSE_DYNAMIC 0x1
+#define X509_PURPOSE_DYNAMIC_NAME 0x2
+
+typedef struct x509_purpose_st {
+ int purpose;
+ int trust; /* Default trust ID */
+ int flags;
+ int (*check_purpose)(const struct x509_purpose_st *,
+ const X509 *, int);
+ char *name;
+ char *sname;
+ void *usr_data;
+} X509_PURPOSE;
+
+#define X509_PURPOSE_SSL_CLIENT 1
+#define X509_PURPOSE_SSL_SERVER 2
+#define X509_PURPOSE_NS_SSL_SERVER 3
+#define X509_PURPOSE_SMIME_SIGN 4
+#define X509_PURPOSE_SMIME_ENCRYPT 5
+#define X509_PURPOSE_CRL_SIGN 6
+#define X509_PURPOSE_ANY 7
+#define X509_PURPOSE_OCSP_HELPER 8
+
+#define X509_PURPOSE_MIN 1
+#define X509_PURPOSE_MAX 8
+
+/* Flags for X509V3_EXT_print() */
+
+#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16)
+/* Return error for unknown extensions */
+#define X509V3_EXT_DEFAULT 0
+/* Print error for unknown extensions */
+#define X509V3_EXT_ERROR_UNKNOWN (1L << 16)
+/* ASN1 parse unknown extensions */
+#define X509V3_EXT_PARSE_UNKNOWN (2L << 16)
+/* BIO_dump unknown extensions */
+#define X509V3_EXT_DUMP_UNKNOWN (3L << 16)
+
+/* Flags for X509V3_add1_i2d */
+
+#define X509V3_ADD_OP_MASK 0xfL
+#define X509V3_ADD_DEFAULT 0L
+#define X509V3_ADD_APPEND 1L
+#define X509V3_ADD_REPLACE 2L
+#define X509V3_ADD_REPLACE_EXISTING 3L
+#define X509V3_ADD_KEEP_EXISTING 4L
+#define X509V3_ADD_DELETE 5L
+#define X509V3_ADD_SILENT 0x10
+
+DECLARE_STACK_OF(X509_PURPOSE)
+
+DECLARE_ASN1_FUNCTIONS(BASIC_CONSTRAINTS)
+
+DECLARE_ASN1_FUNCTIONS(SXNET)
+DECLARE_ASN1_FUNCTIONS(SXNETID)
+
+int SXNET_add_id_asc(SXNET **psx, char *zone, char *user, int userlen);
+int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, char *user, int userlen);
+int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *izone, char *user, int userlen);
+
+ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, char *zone);
+ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone);
+ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone);
+
+DECLARE_ASN1_FUNCTIONS(AUTHORITY_KEYID)
+
+DECLARE_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD)
+
+DECLARE_ASN1_FUNCTIONS(GENERAL_NAME)
+
+
+ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
+ ASN1_BIT_STRING *bits,
+ STACK_OF(CONF_VALUE) *extlist);
+
+STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret);
+int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen);
+
+DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES)
+
+STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
+ GENERAL_NAMES *gen, STACK_OF(CONF_VALUE) *extlist);
+GENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+
+DECLARE_ASN1_FUNCTIONS(OTHERNAME)
+DECLARE_ASN1_FUNCTIONS(EDIPARTYNAME)
+
+char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *ia5);
+ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str);
+
+DECLARE_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE)
+int i2a_ACCESS_DESCRIPTION(BIO *bp, ACCESS_DESCRIPTION* a);
+
+DECLARE_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
+DECLARE_ASN1_FUNCTIONS(POLICYINFO)
+DECLARE_ASN1_FUNCTIONS(POLICYQUALINFO)
+DECLARE_ASN1_FUNCTIONS(USERNOTICE)
+DECLARE_ASN1_FUNCTIONS(NOTICEREF)
+
+DECLARE_ASN1_FUNCTIONS(CRL_DIST_POINTS)
+DECLARE_ASN1_FUNCTIONS(DIST_POINT)
+DECLARE_ASN1_FUNCTIONS(DIST_POINT_NAME)
+
+DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION)
+DECLARE_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS)
+
+DECLARE_ASN1_ITEM(POLICY_MAPPING)
+DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING)
+DECLARE_ASN1_ITEM(POLICY_MAPPINGS)
+
+DECLARE_ASN1_ITEM(GENERAL_SUBTREE)
+DECLARE_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
+
+DECLARE_ASN1_ITEM(NAME_CONSTRAINTS)
+DECLARE_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS)
+DECLARE_ASN1_ITEM(POLICY_CONSTRAINTS)
+
+#ifdef HEADER_CONF_H
+GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+ CONF_VALUE *cnf);
+GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, X509V3_EXT_METHOD *method,
+ X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc);
+void X509V3_conf_free(CONF_VALUE *val);
+
+X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, char *value);
+X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name, char *value);
+int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section, STACK_OF(X509_EXTENSION) **sk);
+int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509 *cert);
+int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_REQ *req);
+int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl);
+
+X509_EXTENSION *X509V3_EXT_conf_nid(LHASH *conf, X509V3_CTX *ctx, int ext_nid, char *value);
+X509_EXTENSION *X509V3_EXT_conf(LHASH *conf, X509V3_CTX *ctx, char *name, char *value);
+int X509V3_EXT_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509 *cert);
+int X509V3_EXT_REQ_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509_REQ *req);
+int X509V3_EXT_CRL_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl);
+
+int X509V3_add_value_bool_nf(char *name, int asn1_bool,
+ STACK_OF(CONF_VALUE) **extlist);
+int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool);
+int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint);
+void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf);
+void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH *lhash);
+#endif
+
+char * X509V3_get_string(X509V3_CTX *ctx, char *name, char *section);
+STACK_OF(CONF_VALUE) * X509V3_get_section(X509V3_CTX *ctx, char *section);
+void X509V3_string_free(X509V3_CTX *ctx, char *str);
+void X509V3_section_free( X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section);
+void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject,
+ X509_REQ *req, X509_CRL *crl, int flags);
+
+int X509V3_add_value(const char *name, const char *value,
+ STACK_OF(CONF_VALUE) **extlist);
+int X509V3_add_value_uchar(const char *name, const unsigned char *value,
+ STACK_OF(CONF_VALUE) **extlist);
+int X509V3_add_value_bool(const char *name, int asn1_bool,
+ STACK_OF(CONF_VALUE) **extlist);
+int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
+ STACK_OF(CONF_VALUE) **extlist);
+char * i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, ASN1_INTEGER *aint);
+ASN1_INTEGER * s2i_ASN1_INTEGER(X509V3_EXT_METHOD *meth, char *value);
+char * i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *meth, ASN1_ENUMERATED *aint);
+char * i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *meth, ASN1_ENUMERATED *aint);
+int X509V3_EXT_add(X509V3_EXT_METHOD *ext);
+int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist);
+int X509V3_EXT_add_alias(int nid_to, int nid_from);
+void X509V3_EXT_cleanup(void);
+
+X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext);
+X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid);
+int X509V3_add_standard_extensions(void);
+STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line);
+void *X509V3_EXT_d2i(X509_EXTENSION *ext);
+void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx);
+
+
+X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc);
+int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, int crit, unsigned long flags);
+
+char *hex_to_string(unsigned char *buffer, long len);
+unsigned char *string_to_hex(char *str, long *len);
+int name_cmp(const char *name, const char *cmp);
+
+void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
+ int ml);
+int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent);
+int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent);
+
+int X509V3_extensions_print(BIO *out, char *title, STACK_OF(X509_EXTENSION) *exts, unsigned long flag, int indent);
+
+int X509_check_ca(X509 *x);
+int X509_check_purpose(X509 *x, int id, int ca);
+int X509_supported_extension(X509_EXTENSION *ex);
+int X509_PURPOSE_set(int *p, int purpose);
+int X509_check_issued(X509 *issuer, X509 *subject);
+int X509_PURPOSE_get_count(void);
+X509_PURPOSE * X509_PURPOSE_get0(int idx);
+int X509_PURPOSE_get_by_sname(char *sname);
+int X509_PURPOSE_get_by_id(int id);
+int X509_PURPOSE_add(int id, int trust, int flags,
+ int (*ck)(const X509_PURPOSE *, const X509 *, int),
+ char *name, char *sname, void *arg);
+char *X509_PURPOSE_get0_name(X509_PURPOSE *xp);
+char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp);
+int X509_PURPOSE_get_trust(X509_PURPOSE *xp);
+void X509_PURPOSE_cleanup(void);
+int X509_PURPOSE_get_id(X509_PURPOSE *);
+
+STACK *X509_get1_email(X509 *x);
+STACK *X509_REQ_get1_email(X509_REQ *x);
+void X509_email_free(STACK *sk);
+STACK *X509_get1_ocsp(X509 *x);
+
+ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc);
+ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc);
+int a2i_ipadd(unsigned char *ipout, const char *ipasc);
+int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
+ unsigned long chtype);
+
+void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent);
+
+#ifndef OPENSSL_NO_RFC3779
+
+typedef struct ASRange_st {
+ ASN1_INTEGER *min, *max;
+} ASRange;
+
+#define ASIdOrRange_id 0
+#define ASIdOrRange_range 1
+
+typedef struct ASIdOrRange_st {
+ int type;
+ union {
+ ASN1_INTEGER *id;
+ ASRange *range;
+ } u;
+} ASIdOrRange;
+
+typedef STACK_OF(ASIdOrRange) ASIdOrRanges;
+DECLARE_STACK_OF(ASIdOrRange)
+
+#define ASIdentifierChoice_inherit 0
+#define ASIdentifierChoice_asIdsOrRanges 1
+
+typedef struct ASIdentifierChoice_st {
+ int type;
+ union {
+ ASN1_NULL *inherit;
+ ASIdOrRanges *asIdsOrRanges;
+ } u;
+} ASIdentifierChoice;
+
+typedef struct ASIdentifiers_st {
+ ASIdentifierChoice *asnum, *rdi;
+} ASIdentifiers;
+
+DECLARE_ASN1_FUNCTIONS(ASRange)
+DECLARE_ASN1_FUNCTIONS(ASIdOrRange)
+DECLARE_ASN1_FUNCTIONS(ASIdentifierChoice)
+DECLARE_ASN1_FUNCTIONS(ASIdentifiers)
+
+
+typedef struct IPAddressRange_st {
+ ASN1_BIT_STRING *min, *max;
+} IPAddressRange;
+
+#define IPAddressOrRange_addressPrefix 0
+#define IPAddressOrRange_addressRange 1
+
+typedef struct IPAddressOrRange_st {
+ int type;
+ union {
+ ASN1_BIT_STRING *addressPrefix;
+ IPAddressRange *addressRange;
+ } u;
+} IPAddressOrRange;
+
+typedef STACK_OF(IPAddressOrRange) IPAddressOrRanges;
+DECLARE_STACK_OF(IPAddressOrRange)
+
+#define IPAddressChoice_inherit 0
+#define IPAddressChoice_addressesOrRanges 1
+
+typedef struct IPAddressChoice_st {
+ int type;
+ union {
+ ASN1_NULL *inherit;
+ IPAddressOrRanges *addressesOrRanges;
+ } u;
+} IPAddressChoice;
+
+typedef struct IPAddressFamily_st {
+ ASN1_OCTET_STRING *addressFamily;
+ IPAddressChoice *ipAddressChoice;
+} IPAddressFamily;
+
+typedef STACK_OF(IPAddressFamily) IPAddrBlocks;
+DECLARE_STACK_OF(IPAddressFamily)
+
+DECLARE_ASN1_FUNCTIONS(IPAddressRange)
+DECLARE_ASN1_FUNCTIONS(IPAddressOrRange)
+DECLARE_ASN1_FUNCTIONS(IPAddressChoice)
+DECLARE_ASN1_FUNCTIONS(IPAddressFamily)
+
+/*
+ * API tag for elements of the ASIdentifer SEQUENCE.
+ */
+#define V3_ASID_ASNUM 0
+#define V3_ASID_RDI 1
+
+/*
+ * AFI values, assigned by IANA. It'd be nice to make the AFI
+ * handling code totally generic, but there are too many little things
+ * that would need to be defined for other address families for it to
+ * be worth the trouble.
+ */
+#define IANA_AFI_IPV4 1
+#define IANA_AFI_IPV6 2
+
+/*
+ * Utilities to construct and extract values from RFC3779 extensions,
+ * since some of the encodings (particularly for IP address prefixes
+ * and ranges) are a bit tedious to work with directly.
+ */
+int v3_asid_add_inherit(ASIdentifiers *asid, int which);
+int v3_asid_add_id_or_range(ASIdentifiers *asid, int which,
+ ASN1_INTEGER *min, ASN1_INTEGER *max);
+int v3_addr_add_inherit(IPAddrBlocks *addr,
+ const unsigned afi, const unsigned *safi);
+int v3_addr_add_prefix(IPAddrBlocks *addr,
+ const unsigned afi, const unsigned *safi,
+ unsigned char *a, const int prefixlen);
+int v3_addr_add_range(IPAddrBlocks *addr,
+ const unsigned afi, const unsigned *safi,
+ unsigned char *min, unsigned char *max);
+unsigned v3_addr_get_afi(const IPAddressFamily *f);
+int v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi,
+ unsigned char *min, unsigned char *max,
+ const int length);
+
+/*
+ * Canonical forms.
+ */
+int v3_asid_is_canonical(ASIdentifiers *asid);
+int v3_addr_is_canonical(IPAddrBlocks *addr);
+int v3_asid_canonize(ASIdentifiers *asid);
+int v3_addr_canonize(IPAddrBlocks *addr);
+
+/*
+ * Tests for inheritance and containment.
+ */
+int v3_asid_inherits(ASIdentifiers *asid);
+int v3_addr_inherits(IPAddrBlocks *addr);
+int v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b);
+int v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b);
+
+/*
+ * Check whether RFC 3779 extensions nest properly in chains.
+ */
+int v3_asid_validate_path(X509_STORE_CTX *);
+int v3_addr_validate_path(X509_STORE_CTX *);
+int v3_asid_validate_resource_set(STACK_OF(X509) *chain,
+ ASIdentifiers *ext,
+ int allow_inheritance);
+int v3_addr_validate_resource_set(STACK_OF(X509) *chain,
+ IPAddrBlocks *ext,
+ int allow_inheritance);
+
+#endif /* OPENSSL_NO_RFC3779 */
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_X509V3_strings(void);
+
+/* Error codes for the X509V3 functions. */
+
+/* Function codes. */
+#define X509V3_F_ASIDENTIFIERCHOICE_CANONIZE 156
+#define X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL 157
+#define X509V3_F_COPY_EMAIL 122
+#define X509V3_F_COPY_ISSUER 123
+#define X509V3_F_DO_DIRNAME 144
+#define X509V3_F_DO_EXT_CONF 124
+#define X509V3_F_DO_EXT_I2D 135
+#define X509V3_F_DO_EXT_NCONF 151
+#define X509V3_F_DO_I2V_NAME_CONSTRAINTS 148
+#define X509V3_F_HEX_TO_STRING 111
+#define X509V3_F_I2S_ASN1_ENUMERATED 121
+#define X509V3_F_I2S_ASN1_IA5STRING 149
+#define X509V3_F_I2S_ASN1_INTEGER 120
+#define X509V3_F_I2V_AUTHORITY_INFO_ACCESS 138
+#define X509V3_F_NOTICE_SECTION 132
+#define X509V3_F_NREF_NOS 133
+#define X509V3_F_POLICY_SECTION 131
+#define X509V3_F_PROCESS_PCI_VALUE 150
+#define X509V3_F_R2I_CERTPOL 130
+#define X509V3_F_R2I_PCI 155
+#define X509V3_F_S2I_ASN1_IA5STRING 100
+#define X509V3_F_S2I_ASN1_INTEGER 108
+#define X509V3_F_S2I_ASN1_OCTET_STRING 112
+#define X509V3_F_S2I_ASN1_SKEY_ID 114
+#define X509V3_F_S2I_SKEY_ID 115
+#define X509V3_F_STRING_TO_HEX 113
+#define X509V3_F_SXNET_ADD_ID_ASC 125
+#define X509V3_F_SXNET_ADD_ID_INTEGER 126
+#define X509V3_F_SXNET_ADD_ID_ULONG 127
+#define X509V3_F_SXNET_GET_ID_ASC 128
+#define X509V3_F_SXNET_GET_ID_ULONG 129
+#define X509V3_F_V2I_ASIDENTIFIERS 158
+#define X509V3_F_V2I_ASN1_BIT_STRING 101
+#define X509V3_F_V2I_AUTHORITY_INFO_ACCESS 139
+#define X509V3_F_V2I_AUTHORITY_KEYID 119
+#define X509V3_F_V2I_BASIC_CONSTRAINTS 102
+#define X509V3_F_V2I_CRLD 134
+#define X509V3_F_V2I_EXTENDED_KEY_USAGE 103
+#define X509V3_F_V2I_GENERAL_NAMES 118
+#define X509V3_F_V2I_GENERAL_NAME_EX 117
+#define X509V3_F_V2I_IPADDRBLOCKS 159
+#define X509V3_F_V2I_ISSUER_ALT 153
+#define X509V3_F_V2I_NAME_CONSTRAINTS 147
+#define X509V3_F_V2I_POLICY_CONSTRAINTS 146
+#define X509V3_F_V2I_POLICY_MAPPINGS 145
+#define X509V3_F_V2I_SUBJECT_ALT 154
+#define X509V3_F_V3_ADDR_VALIDATE_PATH_INTERNAL 160
+#define X509V3_F_V3_GENERIC_EXTENSION 116
+#define X509V3_F_X509V3_ADD1_I2D 140
+#define X509V3_F_X509V3_ADD_VALUE 105
+#define X509V3_F_X509V3_EXT_ADD 104
+#define X509V3_F_X509V3_EXT_ADD_ALIAS 106
+#define X509V3_F_X509V3_EXT_CONF 107
+#define X509V3_F_X509V3_EXT_I2D 136
+#define X509V3_F_X509V3_EXT_NCONF 152
+#define X509V3_F_X509V3_GET_SECTION 142
+#define X509V3_F_X509V3_GET_STRING 143
+#define X509V3_F_X509V3_GET_VALUE_BOOL 110
+#define X509V3_F_X509V3_PARSE_LIST 109
+#define X509V3_F_X509_PURPOSE_ADD 137
+#define X509V3_F_X509_PURPOSE_SET 141
+
+/* Reason codes. */
+#define X509V3_R_BAD_IP_ADDRESS 118
+#define X509V3_R_BAD_OBJECT 119
+#define X509V3_R_BN_DEC2BN_ERROR 100
+#define X509V3_R_BN_TO_ASN1_INTEGER_ERROR 101
+#define X509V3_R_DIRNAME_ERROR 149
+#define X509V3_R_DUPLICATE_ZONE_ID 133
+#define X509V3_R_ERROR_CONVERTING_ZONE 131
+#define X509V3_R_ERROR_CREATING_EXTENSION 144
+#define X509V3_R_ERROR_IN_EXTENSION 128
+#define X509V3_R_EXPECTED_A_SECTION_NAME 137
+#define X509V3_R_EXTENSION_EXISTS 145
+#define X509V3_R_EXTENSION_NAME_ERROR 115
+#define X509V3_R_EXTENSION_NOT_FOUND 102
+#define X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED 103
+#define X509V3_R_EXTENSION_VALUE_ERROR 116
+#define X509V3_R_ILLEGAL_EMPTY_EXTENSION 151
+#define X509V3_R_ILLEGAL_HEX_DIGIT 113
+#define X509V3_R_INCORRECT_POLICY_SYNTAX_TAG 152
+#define X509V3_R_INVALID_ASNUMBER 160
+#define X509V3_R_INVALID_ASRANGE 161
+#define X509V3_R_INVALID_BOOLEAN_STRING 104
+#define X509V3_R_INVALID_EXTENSION_STRING 105
+#define X509V3_R_INVALID_INHERITANCE 162
+#define X509V3_R_INVALID_IPADDRESS 163
+#define X509V3_R_INVALID_NAME 106
+#define X509V3_R_INVALID_NULL_ARGUMENT 107
+#define X509V3_R_INVALID_NULL_NAME 108
+#define X509V3_R_INVALID_NULL_VALUE 109
+#define X509V3_R_INVALID_NUMBER 140
+#define X509V3_R_INVALID_NUMBERS 141
+#define X509V3_R_INVALID_OBJECT_IDENTIFIER 110
+#define X509V3_R_INVALID_OPTION 138
+#define X509V3_R_INVALID_POLICY_IDENTIFIER 134
+#define X509V3_R_INVALID_PROXY_POLICY_SETTING 153
+#define X509V3_R_INVALID_PURPOSE 146
+#define X509V3_R_INVALID_SAFI 164
+#define X509V3_R_INVALID_SECTION 135
+#define X509V3_R_INVALID_SYNTAX 143
+#define X509V3_R_ISSUER_DECODE_ERROR 126
+#define X509V3_R_MISSING_VALUE 124
+#define X509V3_R_NEED_ORGANIZATION_AND_NUMBERS 142
+#define X509V3_R_NO_CONFIG_DATABASE 136
+#define X509V3_R_NO_ISSUER_CERTIFICATE 121
+#define X509V3_R_NO_ISSUER_DETAILS 127
+#define X509V3_R_NO_POLICY_IDENTIFIER 139
+#define X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED 154
+#define X509V3_R_NO_PUBLIC_KEY 114
+#define X509V3_R_NO_SUBJECT_DETAILS 125
+#define X509V3_R_ODD_NUMBER_OF_DIGITS 112
+#define X509V3_R_OPERATION_NOT_DEFINED 148
+#define X509V3_R_OTHERNAME_ERROR 147
+#define X509V3_R_POLICY_LANGUAGE_ALREADTY_DEFINED 155
+#define X509V3_R_POLICY_PATH_LENGTH 156
+#define X509V3_R_POLICY_PATH_LENGTH_ALREADTY_DEFINED 157
+#define X509V3_R_POLICY_SYNTAX_NOT_CURRENTLY_SUPPORTED 158
+#define X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY 159
+#define X509V3_R_SECTION_NOT_FOUND 150
+#define X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS 122
+#define X509V3_R_UNABLE_TO_GET_ISSUER_KEYID 123
+#define X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT 111
+#define X509V3_R_UNKNOWN_EXTENSION 129
+#define X509V3_R_UNKNOWN_EXTENSION_NAME 130
+#define X509V3_R_UNKNOWN_OPTION 120
+#define X509V3_R_UNSUPPORTED_OPTION 117
+#define X509V3_R_USER_TOO_LONG 132
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/Mayaqua/zlib/zconf.h b/src/Mayaqua/zlib/zconf.h
new file mode 100644
index 00000000..e3b0c962
--- /dev/null
+++ b/src/Mayaqua/zlib/zconf.h
@@ -0,0 +1,332 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflateParams z_deflateParams
+# define deflateBound z_deflateBound
+# define deflatePrime z_deflatePrime
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateCopy z_inflateCopy
+# define inflateReset z_inflateReset
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+# define zError z_zError
+
+# define alloc_func z_alloc_func
+# define free_func z_free_func
+# define in_func z_in_func
+# define out_func z_out_func
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
+# include <sys/types.h> /* for off_t */
+# include <unistd.h> /* for SEEK_* and off_t */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if defined(__OS400__)
+# define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+# define NO_vsnprintf
+# ifdef FAR
+# undef FAR
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(deflateBound,"DEBND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(compressBound,"CMBND")
+# pragma map(inflate_table,"INTABL")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/src/Mayaqua/zlib/zlib.h b/src/Mayaqua/zlib/zlib.h
new file mode 100644
index 00000000..62d0e467
--- /dev/null
+++ b/src/Mayaqua/zlib/zlib.h
@@ -0,0 +1,1357 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.2.3, July 18th, 2005
+
+ Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.3"
+#define ZLIB_VERNUM 0x1230
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip streams in memory as well.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ gzip header information passed to and from zlib routines. See RFC 1952
+ for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+ int text; /* true if compressed data believed to be text */
+ uLong time; /* modification time */
+ int xflags; /* extra flags (not used when writing a gzip file) */
+ int os; /* operating system */
+ Bytef *extra; /* pointer to extra field or Z_NULL if none */
+ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
+ uInt extra_max; /* space at extra (only when reading header) */
+ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
+ uInt name_max; /* space at name (only when reading header) */
+ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
+ uInt comm_max; /* space at comment (only when reading header) */
+ int hcrc; /* true if there was or will be a header crc */
+ int done; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce some
+ output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+ decide how much data to accumualte before producing output, in order to
+ maximize compression.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In particular
+ avail_in is zero after the call if enough output space has been provided
+ before the call.) Flushing may degrade compression for some compression
+ algorithms and so it should be used only when necessary.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+ avail_out is greater than six to avoid repeated flush markers due to
+ avail_out == 0 on return.
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ the value returned by deflateBound (see below). If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update strm->data_type if it can make a good guess about
+ the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
+ fatal, and deflate() can be called again with more input and more output
+ space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+ value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller. msg is set to null if there is no error
+ message. inflateInit does not perform any decompression apart from reading
+ the zlib header if present: this will be done by inflate(). (So next_in and
+ avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
+ Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
+ output as possible to the output buffer. Z_BLOCK requests that inflate() stop
+ if and when it gets to the next deflate block boundary. When decoding the
+ zlib or gzip format, this will cause inflate() to return immediately after
+ the header and before the first block. When doing a raw inflate, inflate()
+ will go ahead and process the first block, and will return when it gets to
+ the end of that block, or when it runs out of data.
+
+ The Z_BLOCK option assists in appending to or combining deflate streams.
+ Also to assist in this, on return inflate() will set strm->data_type to the
+ number of unused bits in the last byte taken from strm->next_in, plus 64
+ if inflate() is currently decoding the last block in the deflate stream,
+ plus 128 if inflate() returned immediately after decoding an end-of-block
+ code or decoding the complete header up to just before the first byte of the
+ deflate stream. The end-of-block will not be indicated until all of the
+ uncompressed data from that block has been written to strm->next_out. The
+ number of unused bits may in general be greater than seven, except when
+ bit 7 of data_type is set, in which case the number of unused bits will be
+ less than eight.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster approach
+ may be used for the single inflate() call.
+
+ In this implementation, inflate() always flushes as much output as
+ possible to the output buffer, and always uses the faster approach on the
+ first call. So the only effect of the flush parameter in this implementation
+ is on the return value of inflate(), as noted below, or when it returns early
+ because Z_BLOCK is used.
+
+ If a preset dictionary is needed after this call (see inflateSetDictionary
+ below), inflate sets strm->adler to the adler32 checksum of the dictionary
+ chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+ strm->adler to the adler32 checksum of all output produced so far (that is,
+ total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+ below. At the end of the stream, inflate() checks that its computed adler32
+ checksum is equal to that saved by the compressor and returns Z_STREAM_END
+ only if the checksum is correct.
+
+ inflate() will decompress and check either zlib-wrapped or gzip-wrapped
+ deflate data. The header type is detected automatically. Any information
+ contained in the gzip header is not retained, so applications that need that
+ information should instead use raw inflate, see inflateInit2() below, or
+ inflateBack() and perform their own processing of the gzip header and
+ trailer.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect check
+ value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+ if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+ Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+ output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+ inflate() can be called again with more input and more output space to
+ continue decompressing. If Z_DATA_ERROR is returned, the application may then
+ call inflateSync() to look for a good compression block if a partial recovery
+ of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ determines the window size. deflate() will then generate raw deflate data
+ with no zlib header or trailer, and will not compute an adler32 check value.
+
+ windowBits can also be greater than 15 for optional gzip encoding. Add
+ 16 to windowBits to write a simple gzip header and trailer around the
+ compressed data instead of a zlib wrapper. The gzip header will have no
+ file name, no extra data, no comment, no modification time (set to zero),
+ no header crc, and the operating system will be set to 255 (unknown). If a
+ gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match), or Z_RLE to limit match distances to one (run-length
+ encoding). Filtered data consists mostly of small values with a somewhat
+ random distribution. In this case, the compression algorithm is tuned to
+ compress them better. The effect of Z_FILTERED is to force more Huffman
+ coding and less string matching; it is somewhat intermediate between
+ Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
+ Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
+ parameter only affects the compression ratio but not the correctness of the
+ compressed output even if it is not set appropriately. Z_FIXED prevents the
+ use of dynamic Huffman codes, allowing for a simpler decoder for special
+ applications.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+ method). msg is set to null if there is no error message. deflateInit2 does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. This function must be called
+ immediately after deflateInit, deflateInit2 or deflateReset, before any
+ call of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size in
+ deflate or deflate2. Thus the strings most likely to be useful should be
+ put at the end of the dictionary, not at the front. In addition, the
+ current implementation of deflate will use at most the window size minus
+ 262 bytes of the provided dictionary.
+
+ Upon return of this function, strm->adler is set to the adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.) If a raw deflate was requested, then the
+ adler32 value is not computed and strm->adler is not set.
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if the compression method is bsort). deflateSetDictionary does not
+ perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+ int level,
+ int strategy));
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different
+ strategy. If the compression level is changed, the input available so far
+ is compressed with the old level (and may be flushed); the new level will
+ take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain));
+/*
+ Fine tune deflate's internal compression parameters. This should only be
+ used by someone who understands the algorithm used by zlib's deflate for
+ searching for the best matching string, and even then only by the most
+ fanatic optimizer trying to squeeze out the last compressed bit for their
+ specific input data. Read the deflate.c source code for the meaning of the
+ max_lazy, good_length, nice_length, and max_chain parameters.
+
+ deflateTune() can be called after deflateInit() or deflateInit2(), and
+ returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+ uLong sourceLen));
+/*
+ deflateBound() returns an upper bound on the compressed size after
+ deflation of sourceLen bytes. It must be called after deflateInit()
+ or deflateInit2(). This would be used to allocate an output buffer
+ for deflation in a single pass, and so would be called before deflate().
+*/
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ deflatePrime() inserts bits in the deflate output stream. The intent
+ is that this function is used to start off the deflate output with the
+ bits leftover from a previous deflate stream when appending to it. As such,
+ this function can only be used for raw deflate, and must be used before the
+ first deflate() call after a deflateInit2() or deflateReset(). bits must be
+ less than or equal to 16, and that many of the least significant bits of
+ value will be inserted in the output.
+
+ deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ deflateSetHeader() provides gzip header information for when a gzip
+ stream is requested by deflateInit2(). deflateSetHeader() may be called
+ after deflateInit2() or deflateReset() and before the first call of
+ deflate(). The text, time, os, extra field, name, and comment information
+ in the provided gz_header structure are written to the gzip header (xflag is
+ ignored -- the extra flags are set according to the compression level). The
+ caller must assure that, if not Z_NULL, name and comment are terminated with
+ a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+ available there. If hcrc is true, a gzip header crc is included. Note that
+ the current versions of the command-line version of gzip (up through version
+ 1.3.x) do not support header crc's, and will report that it is a "multi-part
+ gzip file" and give up.
+
+ If deflateSetHeader is not used, the default gzip header has text false,
+ the time set to zero, and os set to 255, with no extra, name, or comment
+ fields. The gzip header is returned to the default state by deflateReset().
+
+ deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. windowBits must be greater than or equal to the windowBits value
+ provided to deflateInit2() while compressing, or it must be equal to 15 if
+ deflateInit2() was not used. If a compressed stream with a larger window
+ size is given as input, inflate() will return with the error code
+ Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ determines the window size. inflate() will then process raw deflate data,
+ not looking for a zlib or gzip header, not generating a check value, and not
+ looking for any check values for comparison at the end of the stream. This
+ is for use with other formats that use the deflate compressed data format
+ such as zip. Those formats provide their own check values. If a custom
+ format is developed using the raw deflate format for compressed data, it is
+ recommended that a check value such as an adler32 or a crc32 be applied to
+ the uncompressed data as is done in the zlib, gzip, and zip formats. For
+ most applications, the zlib format should be used as is. Note that comments
+ above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+ windowBits can also be greater than 15 for optional gzip decoding. Add
+ 32 to windowBits to enable zlib and gzip decoding with automatic header
+ detection, or add 16 to decode only the gzip format (the zlib format will
+ return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is
+ a crc32 instead of an adler32.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
+ is set to null if there is no error message. inflateInit2 does not perform
+ any decompression apart from reading the zlib header if present: this will
+ be done by inflate(). (So next_in and avail_in may be modified, but next_out
+ and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate,
+ if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the adler32 value returned by that call of inflate.
+ The compressor and decompressor must use exactly the same dictionary (see
+ deflateSetDictionary). For raw inflate, this function can be called
+ immediately after inflateInit2() or inflateReset() and before any call of
+ inflate() to set the dictionary. The application must insure that the
+ dictionary that was used for compression is provided.
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until a full flush point (see above the
+ description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when randomly accessing a large stream. The
+ first pass through the stream can periodically record the inflate state,
+ allowing restarting inflate at those points when randomly accessing the
+ stream.
+
+ inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ This function inserts bits in the inflate input stream. The intent is
+ that this function is used to start inflating at a bit position in the
+ middle of a byte. The provided bits will be used before any bytes are used
+ from next_in. This function should only be used with raw inflate, and
+ should be used before the first inflate() call after inflateInit2() or
+ inflateReset(). bits must be less than or equal to 16, and that many of the
+ least significant bits of value will be inserted in the input.
+
+ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ inflateGetHeader() requests that gzip header information be stored in the
+ provided gz_header structure. inflateGetHeader() may be called after
+ inflateInit2() or inflateReset(), and before the first call of inflate().
+ As inflate() processes the gzip stream, head->done is zero until the header
+ is completed, at which time head->done is set to one. If a zlib stream is
+ being decoded, then head->done is set to -1 to indicate that there will be
+ no gzip header information forthcoming. Note that Z_BLOCK can be used to
+ force inflate() to return immediately after header processing is complete
+ and before any actual data is decompressed.
+
+ The text, time, xflags, and os fields are filled in with the gzip header
+ contents. hcrc is set to true if there is a header CRC. (The header CRC
+ was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+ contains the maximum number of bytes to write to extra. Once done is true,
+ extra_len contains the actual extra field length, and extra contains the
+ extra field, or that field truncated if extra_max is less than extra_len.
+ If name is not Z_NULL, then up to name_max characters are written there,
+ terminated with a zero unless the length is greater than name_max. If
+ comment is not Z_NULL, then up to comm_max characters are written there,
+ terminated with a zero unless the length is greater than comm_max. When
+ any of extra, name, or comment are not Z_NULL and the respective field is
+ not present in the header, then that field is set to Z_NULL to signal its
+ absence. This allows the use of deflateSetHeader() with the returned
+ structure to duplicate the header. However if those fields are set to
+ allocated memory, then the application will need to save those pointers
+ elsewhere so that they can be eventually freed.
+
+ If inflateGetHeader is not used, then the header information is simply
+ discarded. The header is always checked for validity, including the header
+ CRC if present. inflateReset() will reset the process to discard the header
+ information. The application would need to call inflateGetHeader() again to
+ retrieve the header from the next gzip stream.
+
+ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window));
+
+ Initialize the internal stream state for decompression using inflateBack()
+ calls. The fields zalloc, zfree and opaque in strm must be initialized
+ before the call. If zalloc and zfree are Z_NULL, then the default library-
+ derived memory allocation routines are used. windowBits is the base two
+ logarithm of the window size, in the range 8..15. window is a caller
+ supplied buffer of that size. Except for special applications where it is
+ assured that deflate was used with small window sizes, windowBits must be 15
+ and a 32K byte window must be supplied to be able to decompress general
+ deflate streams.
+
+ See inflateBack() for the usage of these routines.
+
+ inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+ the paramaters are invalid, Z_MEM_ERROR if the internal state could not
+ be allocated, or Z_VERSION_ERROR if the version of the library does not
+ match the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+ in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc));
+/*
+ inflateBack() does a raw inflate with a single call using a call-back
+ interface for input and output. This is more efficient than inflate() for
+ file i/o applications in that it avoids copying between the output and the
+ sliding window by simply making the window itself the output buffer. This
+ function trusts the application to not change the output buffer passed by
+ the output function, at least until inflateBack() returns.
+
+ inflateBackInit() must be called first to allocate the internal state
+ and to initialize the state with the user-provided window buffer.
+ inflateBack() may then be used multiple times to inflate a complete, raw
+ deflate stream with each call. inflateBackEnd() is then called to free
+ the allocated state.
+
+ A raw deflate stream is one with no zlib or gzip header or trailer.
+ This routine would normally be used in a utility that reads zip or gzip
+ files and writes out uncompressed files. The utility would decode the
+ header and process the trailer on its own, hence this routine expects
+ only the raw deflate stream to decompress. This is different from the
+ normal behavior of inflate(), which expects either a zlib or gzip header and
+ trailer around the deflate stream.
+
+ inflateBack() uses two subroutines supplied by the caller that are then
+ called by inflateBack() for input and output. inflateBack() calls those
+ routines until it reads a complete deflate stream and writes out all of the
+ uncompressed data, or until it encounters an error. The function's
+ parameters and return types are defined above in the in_func and out_func
+ typedefs. inflateBack() will call in(in_desc, &buf) which should return the
+ number of bytes of provided input, and a pointer to that input in buf. If
+ there is no input available, in() must return zero--buf is ignored in that
+ case--and inflateBack() will return a buffer error. inflateBack() will call
+ out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out()
+ should return zero on success, or non-zero on failure. If out() returns
+ non-zero, inflateBack() will return with an error. Neither in() nor out()
+ are permitted to change the contents of the window provided to
+ inflateBackInit(), which is also the buffer that out() uses to write from.
+ The length written by out() will be at most the window size. Any non-zero
+ amount of input may be provided by in().
+
+ For convenience, inflateBack() can be provided input on the first call by
+ setting strm->next_in and strm->avail_in. If that input is exhausted, then
+ in() will be called. Therefore strm->next_in must be initialized before
+ calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called
+ immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in
+ must also be initialized, and then if strm->avail_in is not zero, input will
+ initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+ The in_desc and out_desc parameters of inflateBack() is passed as the
+ first parameter of in() and out() respectively when they are called. These
+ descriptors can be optionally used to pass any information that the caller-
+ supplied in() and out() functions need to do their job.
+
+ On return, inflateBack() will set strm->next_in and strm->avail_in to
+ pass back any unused input that was provided by the last in() call. The
+ return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+ if in() or out() returned an error, Z_DATA_ERROR if there was a format
+ error in the deflate stream (in which case strm->msg is set to indicate the
+ nature of the error), or Z_STREAM_ERROR if the stream was not properly
+ initialized. In the case of Z_BUF_ERROR, an input or output error can be
+ distinguished using strm->next_in which will be Z_NULL only if in() returned
+ an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to
+ out() returning non-zero. (in() will always be called before out(), so
+ strm->next_in is assured to be defined if out() returns non-zero.) Note
+ that inflateBack() cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+ All memory allocated by inflateBackInit() is freed.
+
+ inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+ state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+ Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+ 1.0: size of uInt
+ 3.2: size of uLong
+ 5.4: size of voidpf (pointer)
+ 7.6: size of z_off_t
+
+ Compiler, assembler, and debug options:
+ 8: DEBUG
+ 9: ASMV or ASMINF -- use ASM code
+ 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+ 11: 0 (reserved)
+
+ One-time table building (smaller code, but not thread-safe if true):
+ 12: BUILDFIXED -- build static block decoding tables when needed
+ 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+ 14,15: 0 (reserved)
+
+ Library content (indicates missing functionality):
+ 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+ deflate code when not needed)
+ 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+ and decode gzip streams (to avoid linking crc code)
+ 18-19: 0 (reserved)
+
+ Operation variations (changes in library functionality):
+ 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+ 21: FASTEST -- deflate algorithm with only one, lowest compression level
+ 22,23: 0 (reserved)
+
+ The sprintf variant used by gzprintf (zero is best):
+ 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+ 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+ 26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+ Remainder:
+ 27-31: 0 (reserved)
+ */
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level and memory usage,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least the value returned
+ by compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level));
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+ compressBound() returns an upper bound on the compressed size after
+ compress() or compress2() on sourceLen bytes. It would be used before
+ a compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+ Huffman only compression as in "wb1h", or 'R' for run-length encoding
+ as in "wb1R". (See the description of deflateInit2 for more information
+ about the strategy parameter.)
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression.
+
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR). */
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+ Dynamically update the compression level or strategy. See the description
+ of deflateInit2 for the meaning of these parameters.
+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+ opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+ voidpc buf, unsigned len));
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
+/*
+ Converts, formats, and writes the args to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written (0 in case of error). The number of
+ uncompressed bytes written is limited to 4095. The caller should assure that
+ this limit is not exceeded. If it is exceeded, then gzprintf() will return
+ return an error (0) with nothing written. In this case, there may also be a
+ buffer overflow with unpredictable consequences, which is possible only if
+ zlib was compiled with the insecure functions sprintf() or vsprintf()
+ because the secure snprintf() or vsnprintf() functions were not available.
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+ Reads bytes from the compressed file until len-1 characters are read, or
+ a newline character is read and transferred to buf, or an end-of-file
+ condition is encountered. The string is then terminated with a null
+ character.
+ gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+ Writes c, converted to an unsigned char, into the compressed file.
+ gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+ Reads one byte from the compressed file. gzgetc returns this byte
+ or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+ Push one character back onto the stream to be read again later.
+ Only one character of push-back is allowed. gzungetc() returns the
+ character pushed, or -1 on failure. gzungetc() will fail if a
+ character has been pushed but not read yet, or if c is -1. The pushed
+ character will be discarded if the stream is repositioned with gzseek()
+ or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+ z_off_t offset, int whence));
+/*
+ Sets the starting position for the next gzread or gzwrite on the
+ given compressed file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
+/*
+ Rewinds the given file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
+/*
+ Returns the starting position for the next gzread or gzwrite on the
+ given compressed file. This position represents a number of bytes in the
+ uncompressed data stream.
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+ Returns 1 when EOF has previously been detected reading the given
+ input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+ Returns 1 if file is being read directly without decompression, otherwise
+ zero.
+*/
+
+ZEXTERN int ZEXPORT gzclose OF((gzFile file));
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+ Clears the error and end-of-file flags for file. This is analogous to the
+ clearerr() function in stdio. This is useful for continuing to read a gzip
+ file that is being written concurrently.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+ z_off_t len2));
+/*
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
+*/
+
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+/*
+ Update a running CRC-32 with the bytes buf[0..len-1] and return the
+ updated CRC-32. If buf is NULL, this function returns the required initial
+ value for the for the crc. Pre- and post-conditioning (one's complement) is
+ performed within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+/*
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2.
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char * ZEXPORT zError OF((int));
+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */