* copy vendor drop to trunk
[lab.git] / Dev / utvpn / utvpn-unix-v101-7101-public / src / Mayaqua / Pack.c
1 // SoftEther UT-VPN SourceCode\r
2 // \r
3 // Copyright (C) 2004-2010 SoftEther Corporation.\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.\r
6 // All Rights Reserved.\r
7 // \r
8 // http://utvpn.tsukuba.ac.jp/\r
9 // \r
10 // This program is free software; you can redistribute it and/or\r
11 // modify it under the terms of the GNU General Public License\r
12 // version 2 as published by the Free Software Foundation.\r
13 // \r
14 // This program is distributed in the hope that it will be useful,\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
17 // GNU General Public License for more details.\r
18 // \r
19 // You should have received a copy of the GNU General Public License version 2\r
20 // along with this program; if not, write to the Free Software\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
22 // \r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
28 // \r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって\r
32 // ホストされています。\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
34 // および、試験または研究のために利用が行われることを想定して配布\r
35 // しています。\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
37 // あります。\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
42 // に組み込みさせていただきます。\r
43 // \r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
46 // \r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
51 // ください。\r
52 // \r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
58 // 公益保護にご協力いただきますようお願い申し上げます。\r
59 // \r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
62 // を保護するための努力を行います。\r
63 // \r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
65 // 日本国内の脆弱性情報届出受付公的機関:\r
66 //         独立行政法人 情報処理推進機構\r
67 //         http://www.ipa.go.jp/security/vuln/report/\r
68 // \r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/\r
71 \r
72 // -----------------------------------------------\r
73 // [ChangeLog]\r
74 // 2010.05.20\r
75 //  新規リリース by SoftEther\r
76 // -----------------------------------------------\r
77 \r
78 // Pack.c\r
79 // データパッケージコード\r
80 \r
81 #include <stdio.h>\r
82 #include <stdlib.h>\r
83 #include <string.h>\r
84 #include <wchar.h>\r
85 #include <stdarg.h>\r
86 #include <time.h>\r
87 #include <errno.h>\r
88 #include <Mayaqua/Mayaqua.h>\r
89 \r
90 // BUF を PACK に変換\r
91 PACK *BufToPack(BUF *b)\r
92 {\r
93         PACK *p;\r
94         // 引数チェック\r
95         if (b == NULL)\r
96         {\r
97                 return NULL;\r
98         }\r
99 \r
100         p = NewPack();\r
101         if (ReadPack(b, p) == false)\r
102         {\r
103                 FreePack(p);\r
104                 return NULL;\r
105         }\r
106 \r
107         return p;\r
108 }\r
109 \r
110 // PACK を BUF に変換\r
111 BUF *PackToBuf(PACK *p)\r
112 {\r
113         BUF *b;\r
114         // 引数チェック\r
115         if (p == NULL)\r
116         {\r
117                 return NULL;\r
118         }\r
119 \r
120         b = NewBuf();\r
121         WritePack(b, p);\r
122 \r
123         return b;\r
124 }\r
125 \r
126 // PACK を読み込む\r
127 bool ReadPack(BUF *b, PACK *p)\r
128 {\r
129         UINT i, num;\r
130         // 引数チェック\r
131         if (b == NULL || p == NULL)\r
132         {\r
133                 return false;\r
134         }\r
135 \r
136         // ELEMENT 数\r
137         num = ReadBufInt(b);\r
138         if (num > MAX_ELEMENT_NUM)\r
139         {\r
140                 // 個数オーバー\r
141                 return false;\r
142         }\r
143 \r
144         // ELEMENT を読み込む\r
145         for (i = 0;i < num;i++)\r
146         {\r
147                 ELEMENT *e;\r
148                 e = ReadElement(b);\r
149                 if (AddElement(p, e) == false)\r
150                 {\r
151                         // 追加エラー\r
152                         return false;\r
153                 }\r
154         }\r
155 \r
156         return true;\r
157 }\r
158 \r
159 // PACK を書き出す\r
160 void WritePack(BUF *b, PACK *p)\r
161 {\r
162         UINT i;\r
163         // 引数チェック\r
164         if (b == NULL || p == NULL)\r
165         {\r
166                 return;\r
167         }\r
168 \r
169         // ELEMENT 数\r
170         WriteBufInt(b, LIST_NUM(p->elements));\r
171 \r
172         // ELEMENT を書き出す\r
173         for (i = 0;i < LIST_NUM(p->elements);i++)\r
174         {\r
175                 ELEMENT *e = LIST_DATA(p->elements, i);\r
176                 WriteElement(b, e);\r
177         }\r
178 }\r
179 \r
180 // ELEMENT を読み込む\r
181 ELEMENT *ReadElement(BUF *b)\r
182 {\r
183         UINT i;\r
184         char name[MAX_ELEMENT_NAME_LEN + 1];\r
185         UINT type, num_value;\r
186         VALUE **values;\r
187         ELEMENT *e;\r
188         // 引数チェック\r
189         if (b == NULL)\r
190         {\r
191                 return NULL;\r
192         }\r
193 \r
194         // 名前\r
195         if (ReadBufStr(b, name, sizeof(name)) == false)\r
196         {\r
197                 return NULL;\r
198         }\r
199 \r
200         // 項目の種類\r
201         type = ReadBufInt(b);\r
202 \r
203         // 項目数\r
204         num_value = ReadBufInt(b);\r
205         if (num_value > MAX_VALUE_NUM)\r
206         {\r
207                 // 個数オーバー\r
208                 return NULL;\r
209         }\r
210 \r
211         // VALUE\r
212         values = (VALUE **)Malloc(sizeof(VALUE *) * num_value);\r
213         for (i = 0;i < num_value;i++)\r
214         {\r
215                 values[i] = ReadValue(b, type);\r
216         }\r
217 \r
218         // ELEMENT を作成\r
219         e = NewElement(name, type, num_value, values);\r
220 \r
221         Free(values);\r
222 \r
223         return e;\r
224 }\r
225 \r
226 // ELEMENT を書き出す\r
227 void WriteElement(BUF *b, ELEMENT *e)\r
228 {\r
229         UINT i;\r
230         // 引数チェック\r
231         if (b == NULL || e == NULL)\r
232         {\r
233                 return;\r
234         }\r
235 \r
236         // 名前\r
237         WriteBufStr(b, e->name);\r
238         // 項目の種類\r
239         WriteBufInt(b, e->type);\r
240         // 項目数\r
241         WriteBufInt(b, e->num_value);\r
242         // VALUE\r
243         for (i = 0;i < e->num_value;i++)\r
244         {\r
245                 VALUE *v = e->values[i];\r
246                 WriteValue(b, v, e->type);\r
247         }\r
248 }\r
249 \r
250 // VALUE を読み込む\r
251 VALUE *ReadValue(BUF *b, UINT type)\r
252 {\r
253         UINT len;\r
254         BYTE *u;\r
255         void *data;\r
256         char *str;\r
257         wchar_t *unistr;\r
258         UINT unistr_size;\r
259         UINT size;\r
260         UINT u_size;\r
261         VALUE *v = NULL;\r
262         // 引数チェック\r
263         if (b == NULL)\r
264         {\r
265                 return NULL;\r
266         }\r
267 \r
268         // データ項目\r
269         switch (type)\r
270         {\r
271         case VALUE_INT:                 // 整数\r
272                 v = NewIntValue(ReadBufInt(b));\r
273                 break;\r
274         case VALUE_INT64:\r
275                 v = NewInt64Value(ReadBufInt64(b));\r
276                 break;\r
277         case VALUE_DATA:                // データ\r
278                 size = ReadBufInt(b);\r
279                 if (size > MAX_VALUE_SIZE)\r
280                 {\r
281                         // サイズオーバー\r
282                         break;\r
283                 }\r
284                 data = Malloc(size);\r
285                 if (ReadBuf(b, data, size) != size)\r
286                 {\r
287                         // 読み込み失敗\r
288                         Free(data);\r
289                         break;\r
290                 }\r
291                 v = NewDataValue(data, size);\r
292                 Free(data);\r
293                 break;\r
294         case VALUE_STR:                 // ANSI 文字列\r
295                 len = ReadBufInt(b);\r
296                 if ((len + 1) > MAX_VALUE_SIZE)\r
297                 {\r
298                         // サイズオーバー\r
299                         break;\r
300                 }\r
301                 str = Malloc(len + 1);\r
302                 // 文字列本体\r
303                 if (ReadBuf(b, str, len) != len)\r
304                 {\r
305                         // 読み込み失敗\r
306                         Free(str);\r
307                         break;\r
308                 }\r
309                 str[len] = 0;\r
310                 v = NewStrValue(str);\r
311                 Free(str);\r
312                 break;\r
313         case VALUE_UNISTR:              // Unicode 文字列\r
314                 u_size = ReadBufInt(b);\r
315                 if (u_size > MAX_VALUE_SIZE)\r
316                 {\r
317                         // サイズオーバー\r
318                         break;\r
319                 }\r
320                 // UTF-8 の読み込み\r
321                 u = ZeroMalloc(u_size + 1);\r
322                 if (ReadBuf(b, u, u_size) != u_size)\r
323                 {\r
324                         // 読み込み失敗\r
325                         Free(u);\r
326                         break;\r
327                 }\r
328                 // Unicode 文字列に変換\r
329                 unistr_size = CalcUtf8ToUni(u, u_size);\r
330                 if (unistr_size == 0)\r
331                 {\r
332                         Free(u);\r
333                         break;\r
334                 }\r
335                 unistr = Malloc(unistr_size);\r
336                 Utf8ToUni(unistr, unistr_size, u, u_size);\r
337                 Free(u);\r
338                 v = NewUniStrValue(unistr);\r
339                 Free(unistr);\r
340                 break;\r
341         }\r
342 \r
343         return v;\r
344 }\r
345 \r
346 // VALUE を書き出す\r
347 void WriteValue(BUF *b, VALUE *v, UINT type)\r
348 {\r
349         UINT len;\r
350         BYTE *u;\r
351         UINT u_size;\r
352         // 引数チェック\r
353         if (b == NULL || v == NULL)\r
354         {\r
355                 return;\r
356         }\r
357 \r
358         // データ項目\r
359         switch (type)\r
360         {\r
361         case VALUE_INT:                 // 整数\r
362                 WriteBufInt(b, v->IntValue);\r
363                 break;\r
364         case VALUE_INT64:               // 64 bit 整数\r
365                 WriteBufInt64(b, v->Int64Value);\r
366                 break;\r
367         case VALUE_DATA:                // データ\r
368                 // サイズ\r
369                 WriteBufInt(b, v->Size);\r
370                 // 本体\r
371                 WriteBuf(b, v->Data, v->Size);\r
372                 break;\r
373         case VALUE_STR:                 // ANSI 文字列\r
374                 len = StrLen(v->Str);\r
375                 // 長さ\r
376                 WriteBufInt(b, len);\r
377                 // 文字列本体\r
378                 WriteBuf(b, v->Str, len);\r
379                 break;\r
380         case VALUE_UNISTR:              // Unicode 文字列\r
381                 // UTF-8 に変換する\r
382                 u_size = CalcUniToUtf8(v->UniStr) + 1;\r
383                 u = ZeroMalloc(u_size);\r
384                 UniToUtf8(u, u_size, v->UniStr);\r
385                 // サイズ\r
386                 WriteBufInt(b, u_size);\r
387                 // UTF-8 文字列本体\r
388                 WriteBuf(b, u, u_size);\r
389                 Free(u);\r
390                 break;\r
391         }\r
392 }\r
393 \r
394 // データサイズの取得\r
395 UINT GetDataValueSize(ELEMENT *e, UINT index)\r
396 {\r
397         // 引数チェック\r
398         if (e == NULL)\r
399         {\r
400                 return 0;\r
401         }\r
402         if (e->values == NULL)\r
403         {\r
404                 return 0;\r
405         }\r
406         if (index >= e->num_value)\r
407         {\r
408                 return 0;\r
409         }\r
410         if (e->values[index] == NULL)\r
411         {\r
412                 return 0;\r
413         }\r
414 \r
415         return e->values[index]->Size;\r
416 }\r
417 \r
418 // データの取得\r
419 void *GetDataValue(ELEMENT *e, UINT index)\r
420 {\r
421         // 引数チェック\r
422         if (e == NULL)\r
423         {\r
424                 return NULL;\r
425         }\r
426         if (e->values == NULL)\r
427         {\r
428                 return NULL;\r
429         }\r
430         if (index >= e->num_value)\r
431         {\r
432                 return NULL;\r
433         }\r
434         if (e->values[index] == NULL)\r
435         {\r
436                 return NULL;\r
437         }\r
438 \r
439         return e->values[index]->Data;\r
440 }\r
441 \r
442 // Unicode 文字列型の取得\r
443 wchar_t *GetUniStrValue(ELEMENT *e, UINT index)\r
444 {\r
445         // 引数チェック\r
446         if (e == NULL)\r
447         {\r
448                 return 0;\r
449         }\r
450         if (index >= e->num_value)\r
451         {\r
452                 return 0;\r
453         }\r
454 \r
455         return e->values[index]->UniStr;\r
456 }\r
457 \r
458 // ANSI 文字列型の取得\r
459 char *GetStrValue(ELEMENT *e, UINT index)\r
460 {\r
461         // 引数チェック\r
462         if (e == NULL)\r
463         {\r
464                 return 0;\r
465         }\r
466         if (index >= e->num_value)\r
467         {\r
468                 return 0;\r
469         }\r
470 \r
471         return e->values[index]->Str;\r
472 }\r
473 \r
474 // 64 bit 整数型値の取得\r
475 UINT64 GetInt64Value(ELEMENT *e, UINT index)\r
476 {\r
477         // 引数チェック\r
478         if (e == NULL)\r
479         {\r
480                 return 0;\r
481         }\r
482         if (index >= e->num_value)\r
483         {\r
484                 return 0;\r
485         }\r
486 \r
487         return e->values[index]->Int64Value;\r
488 }\r
489 \r
490 // 整数型値の取得\r
491 UINT GetIntValue(ELEMENT *e, UINT index)\r
492 {\r
493         // 引数チェック\r
494         if (e == NULL)\r
495         {\r
496                 return 0;\r
497         }\r
498         if (index >= e->num_value)\r
499         {\r
500                 return 0;\r
501         }\r
502 \r
503         return e->values[index]->IntValue;\r
504 }\r
505 \r
506 // PACK のソート関数\r
507 int ComparePackName(void *p1, void *p2)\r
508 {\r
509         ELEMENT *o1, *o2;\r
510         if (p1 == NULL || p2 == NULL)\r
511         {\r
512                 return 0;\r
513         }\r
514         o1 = *(ELEMENT **)p1;\r
515         o2 = *(ELEMENT **)p2;\r
516         if (o1 == NULL || o2 == NULL)\r
517         {\r
518                 return 0;\r
519         }\r
520 \r
521         return StrCmpi(o1->name, o2->name);\r
522 }\r
523 \r
524 // VALUE の削除\r
525 void FreeValue(VALUE *v, UINT type)\r
526 {\r
527         // 引数チェック\r
528         if (v == NULL)\r
529         {\r
530                 return;\r
531         }\r
532 \r
533         switch (type)\r
534         {\r
535         case VALUE_INT:\r
536         case VALUE_INT64:\r
537                 break;\r
538         case VALUE_DATA:\r
539                 Free(v->Data);\r
540                 break;\r
541         case VALUE_STR:\r
542                 Free(v->Str);\r
543                 break;\r
544         case VALUE_UNISTR:\r
545                 Free(v->UniStr);\r
546                 break;\r
547         }\r
548 \r
549         // メモリ解放\r
550         Free(v);\r
551 }\r
552 \r
553 // Unicode 文字列型の VALUE の作成\r
554 VALUE *NewUniStrValue(wchar_t *str)\r
555 {\r
556         VALUE *v;\r
557         // 引数チェック\r
558         if (str == NULL)\r
559         {\r
560                 return NULL;\r
561         }\r
562 \r
563         // メモリ確保\r
564         v = Malloc(sizeof(VALUE));\r
565 \r
566         // 文字列コピー\r
567         v->Size = UniStrSize(str);\r
568         v->UniStr = Malloc(v->Size);\r
569         UniStrCpy(v->UniStr, v->Size, str);\r
570 \r
571         UniTrim(v->UniStr);\r
572 \r
573         return v;\r
574 }\r
575 \r
576 // ANSI 文字列型の VALUE の作成\r
577 VALUE *NewStrValue(char *str)\r
578 {\r
579         VALUE *v;\r
580         // 引数チェック\r
581         if (str == NULL)\r
582         {\r
583                 return NULL;\r
584         }\r
585 \r
586         // メモリ確保\r
587         v = Malloc(sizeof(VALUE));\r
588 \r
589         // 文字列コピー\r
590         v->Size = StrLen(str) + 1;\r
591         v->Str = Malloc(v->Size);\r
592         StrCpy(v->Str, v->Size, str);\r
593 \r
594         Trim(v->Str);\r
595 \r
596         return v;\r
597 }\r
598 \r
599 // データ型の VALUE の作成\r
600 VALUE *NewDataValue(void *data, UINT size)\r
601 {\r
602         VALUE *v;\r
603         // 引数チェック\r
604         if (data == NULL)\r
605         {\r
606                 return NULL;\r
607         }\r
608 \r
609         // メモリ確保\r
610         v = Malloc(sizeof(VALUE));\r
611 \r
612         // データコピー\r
613         v->Size = size;\r
614         v->Data = Malloc(v->Size);\r
615         Copy(v->Data, data, size);\r
616 \r
617         return v;\r
618 }\r
619 \r
620 // 64 bit 整数型の VALUE の作成\r
621 VALUE *NewInt64Value(UINT64 i)\r
622 {\r
623         VALUE *v;\r
624 \r
625         v = Malloc(sizeof(VALUE));\r
626         v->Int64Value = i;\r
627         v->Size = sizeof(UINT64);\r
628 \r
629         return v;\r
630 }\r
631 \r
632 // 整数型の VALUE の作成\r
633 VALUE *NewIntValue(UINT i)\r
634 {\r
635         VALUE *v;\r
636 \r
637         // メモリ確保\r
638         v = Malloc(sizeof(VALUE));\r
639         v->IntValue = i;\r
640         v->Size = sizeof(UINT);\r
641 \r
642         return v;\r
643 }\r
644 \r
645 // ELEMENT の削除\r
646 void FreeElement(ELEMENT *e)\r
647 {\r
648         UINT i;\r
649         // 引数チェック\r
650         if (e == NULL)\r
651         {\r
652                 return;\r
653         }\r
654 \r
655         for (i = 0;i < e->num_value;i++)\r
656         {\r
657                 FreeValue(e->values[i], e->type);\r
658         }\r
659         Free(e->values);\r
660 \r
661         Free(e);\r
662 }\r
663 \r
664 // ELEMENT の作成\r
665 ELEMENT *NewElement(char *name, UINT type, UINT num_value, VALUE **values)\r
666 {\r
667         ELEMENT *e;\r
668         UINT i;\r
669         // 引数チェック\r
670         if (name == NULL || num_value == 0 || values == NULL)\r
671         {\r
672                 return NULL;\r
673         }\r
674 \r
675         // メモリ確保\r
676         e = Malloc(sizeof(ELEMENT));\r
677         StrCpy(e->name, sizeof(e->name), name);\r
678         e->num_value = num_value;\r
679         e->type = type;\r
680 \r
681         // 要素へのポインタリストのコピー\r
682         e->values = (VALUE **)Malloc(sizeof(VALUE *) * num_value);\r
683         for (i = 0;i < e->num_value;i++)\r
684         {\r
685                 e->values[i] = values[i];\r
686         }\r
687 \r
688         return e;\r
689 }\r
690 \r
691 // PACK から ELEMENT を検索して取得\r
692 ELEMENT *GetElement(PACK *p, char *name, UINT type)\r
693 {\r
694         ELEMENT t;\r
695         ELEMENT *e;\r
696         // 引数チェック\r
697         if (p == NULL || name == NULL)\r
698         {\r
699                 return NULL;\r
700         }\r
701 \r
702         // 検索\r
703         StrCpy(t.name, sizeof(t.name), name);\r
704         e = Search(p->elements, &t);\r
705 \r
706         if (e == NULL)\r
707         {\r
708                 return NULL;\r
709         }\r
710 \r
711         // 型検査\r
712         if (type != INFINITE)\r
713         {\r
714                 if (e->type != type)\r
715                 {\r
716                         return NULL;\r
717                 }\r
718         }\r
719 \r
720         return e;\r
721 }\r
722 \r
723 // PACK から ELEMENT を削除\r
724 void DelElement(PACK *p, char *name)\r
725 {\r
726         ELEMENT *e;\r
727         // 引数チェック\r
728         if (p == NULL || name == NULL)\r
729         {\r
730                 return;\r
731         }\r
732 \r
733         e = GetElement(p, name, INFINITE);\r
734         if (e != NULL)\r
735         {\r
736                 Delete(p->elements, e);\r
737 \r
738                 FreeElement(e);\r
739         }\r
740 }\r
741 \r
742 // PACK に ELEMENT を追加\r
743 bool AddElement(PACK *p, ELEMENT *e)\r
744 {\r
745         // 引数チェック\r
746         if (p == NULL || e == NULL)\r
747         {\r
748                 return false;\r
749         }\r
750 \r
751         // サイズチェック\r
752         if (LIST_NUM(p->elements) >= MAX_ELEMENT_NUM)\r
753         {\r
754                 // これ以上追加できない\r
755                 FreeElement(e);\r
756                 return false;\r
757         }\r
758 \r
759         // 同じ名前が存在しないかどうかチェック\r
760         if (GetElement(p, e->name, INFINITE))\r
761         {\r
762                 // 存在している\r
763                 FreeElement(e);\r
764                 return false;\r
765         }\r
766 \r
767         if (e->num_value == 0)\r
768         {\r
769                 // 項目が 1 つも存在していない VALUE は追加できない\r
770                 FreeElement(e);\r
771                 return false;\r
772         }\r
773 \r
774         // 追加\r
775         Add(p->elements, e);\r
776         return true;\r
777 }\r
778 \r
779 // PACK オブジェクトの解放\r
780 void FreePack(PACK *p)\r
781 {\r
782         UINT i;\r
783         ELEMENT **elements;\r
784         // 引数チェック\r
785         if (p == NULL)\r
786         {\r
787                 return;\r
788         }\r
789 \r
790         elements = ToArray(p->elements);\r
791         for (i = 0;i < LIST_NUM(p->elements);i++)\r
792         {\r
793                 FreeElement(elements[i]);\r
794         }\r
795         Free(elements);\r
796 \r
797         ReleaseList(p->elements);\r
798         Free(p);\r
799 }\r
800 \r
801 // PACK オブジェクトの作成\r
802 PACK *NewPack()\r
803 {\r
804         PACK *p;\r
805 \r
806         // メモリ確保\r
807         p = MallocEx(sizeof(PACK), true);\r
808 \r
809         // リスト作成\r
810         p->elements = NewListFast(ComparePackName);\r
811 \r
812         return p;\r
813 }\r
814 \r
815 \r