mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-07 10:10:41 +03:00
7de986dcca
Buffer overread in ParseL2TPPacket() Memory corruption in IcmpParseResult Missing bounds check in ParseUDP() can lead to invalid memory access Out-of-bounds read in IPsec_PPP.c (unterminated string buffer) Overlapping parameters to memcpy() via StrToIp6() PACK ReadValue() crash vulnerability Potential use of uninitialized memory via IPToInAddr6() 4 memory leaks. While the amount of leakage is very small per time, these bugs can finally cause process crash by out of memory. So these bugs must be fixed. Memory leak in NnReadDnsRecord Memory leak in RadiusLogin() Memory leak via ParsePacketIPv4WithDummyMacHeader Remote memory leak in OpenVPN server code 1 coding improvement. This is not a bug, however, I fixed the code to avoid furture misunderstanding. RecvAll can return success on failure (leading to use of uninitialized memory) Contributors for this bugfix: - Max Planck Institute for Molecular Genetics - Guido Vranken
1733 lines
33 KiB
C
1733 lines
33 KiB
C
// SoftEther VPN Source Code - Developer Edition Master Branch
|
|
// Mayaqua Kernel
|
|
//
|
|
// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
|
|
//
|
|
// Copyright (c) Daiyuu Nobori.
|
|
// Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
|
|
// Copyright (c) SoftEther Corporation.
|
|
//
|
|
// All Rights Reserved.
|
|
//
|
|
// http://www.softether.org/
|
|
//
|
|
// Author: Daiyuu Nobori, Ph.D.
|
|
// 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 THIS SOFTWARE IN ANOTHER COUNTRY UNLESS
|
|
// YOU HAVE A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY
|
|
// CRIMINAL LAWS OR CIVIL RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS
|
|
// SOFTWARE IN OTHER COUNTRIES IS COMPLETELY AT YOUR OWN RISK. THE
|
|
// SOFTETHER VPN PROJECT HAS DEVELOPED AND DISTRIBUTED THIS SOFTWARE TO
|
|
// COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING CIVIL RIGHTS INCLUDING
|
|
// PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER COUNTRIES' LAWS OR
|
|
// CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES. WE HAVE
|
|
// NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
|
|
// INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+
|
|
// COUNTRIES AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE
|
|
// WORLD, WITH DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY
|
|
// COUNTRIES' LAWS, REGULATIONS AND CIVIL RIGHTS TO MAKE THE SOFTWARE
|
|
// COMPLY WITH ALL COUNTRIES' LAWS BY THE PROJECT. EVEN IF YOU WILL BE
|
|
// SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A PUBLIC SERVANT IN YOUR
|
|
// COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE LIABLE TO
|
|
// RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
|
|
// RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT
|
|
// JUST A STATEMENT FOR WARNING AND DISCLAIMER.
|
|
//
|
|
//
|
|
// SOURCE CODE CONTRIBUTION
|
|
// ------------------------
|
|
//
|
|
// Your contribution to SoftEther VPN Project is much appreciated.
|
|
// Please send patches to us through GitHub.
|
|
// Read the SoftEther VPN Patch Acceptance Policy in advance:
|
|
// http://www.softether.org/5-download/src/9.patch
|
|
//
|
|
//
|
|
// 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.
|
|
//
|
|
//
|
|
// NO MEMORY OR RESOURCE LEAKS
|
|
// ---------------------------
|
|
//
|
|
// The memory-leaks and resource-leaks verification under the stress
|
|
// test has been passed before release this source code.
|
|
|
|
|
|
// 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 > (MAX_VALUE_SIZE - 1))
|
|
{
|
|
// 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;
|
|
}
|
|
|
|
// Check whether the specified element exists
|
|
bool IsElement(PACK *p, char *name)
|
|
{
|
|
ELEMENT t;
|
|
ELEMENT *e;
|
|
// Validate arguments
|
|
if (p == NULL || name == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Search
|
|
StrCpy(t.name, sizeof(t.name), name);
|
|
e = Search(p->elements, &t);
|
|
|
|
if (e == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
|
|
// Check whether the specified value is existing on the Pack
|
|
bool PackIsValueExists(PACK *p, char *name)
|
|
{
|
|
// Validate arguments
|
|
if (p == NULL || name == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return IsElement(p, name);
|
|
}
|
|
|
|
// 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));
|
|
}
|
|
|
|
|