Imported Upstream version 9.20
[platform/upstream/7zip.git] / CPP / 7zip / Archive / Common / HandlerOut.cpp
1 // HandlerOut.cpp\r
2 \r
3 #include "StdAfx.h"\r
4 \r
5 #include "../../../Common/StringToInt.h"\r
6 \r
7 #include "../../../Windows/PropVariant.h"\r
8 \r
9 #ifndef _7ZIP_ST\r
10 #include "../../../Windows/System.h"\r
11 #endif\r
12 \r
13 #include "../../ICoder.h"\r
14 \r
15 #include "../Common/ParseProperties.h"\r
16 \r
17 #include "HandlerOut.h"\r
18 \r
19 using namespace NWindows;\r
20 \r
21 namespace NArchive {\r
22 \r
23 static const wchar_t *kCopyMethod = L"Copy";\r
24 static const wchar_t *kLZMAMethodName = L"LZMA";\r
25 static const wchar_t *kLZMA2MethodName = L"LZMA2";\r
26 static const wchar_t *kBZip2MethodName = L"BZip2";\r
27 static const wchar_t *kPpmdMethodName = L"PPMd";\r
28 static const wchar_t *kDeflateMethodName = L"Deflate";\r
29 static const wchar_t *kDeflate64MethodName = L"Deflate64";\r
30 \r
31 static const wchar_t *kLzmaMatchFinderX1 = L"HC4";\r
32 static const wchar_t *kLzmaMatchFinderX5 = L"BT4";\r
33 \r
34 static const UInt32 kLzmaAlgoX1 = 0;\r
35 static const UInt32 kLzmaAlgoX5 = 1;\r
36 \r
37 static const UInt32 kLzmaDicSizeX1 = 1 << 16;\r
38 static const UInt32 kLzmaDicSizeX3 = 1 << 20;\r
39 static const UInt32 kLzmaDicSizeX5 = 1 << 24;\r
40 static const UInt32 kLzmaDicSizeX7 = 1 << 25;\r
41 static const UInt32 kLzmaDicSizeX9 = 1 << 26;\r
42 \r
43 static const UInt32 kLzmaFastBytesX1 = 32;\r
44 static const UInt32 kLzmaFastBytesX7 = 64;\r
45 \r
46 static const UInt32 kPpmdMemSizeX1 = (1 << 22);\r
47 static const UInt32 kPpmdMemSizeX5 = (1 << 24);\r
48 static const UInt32 kPpmdMemSizeX7 = (1 << 26);\r
49 static const UInt32 kPpmdMemSizeX9 = (192 << 20);\r
50 \r
51 static const UInt32 kPpmdOrderX1 = 4;\r
52 static const UInt32 kPpmdOrderX5 = 6;\r
53 static const UInt32 kPpmdOrderX7 = 16;\r
54 static const UInt32 kPpmdOrderX9 = 32;\r
55 \r
56 static const UInt32 kDeflateAlgoX1 = 0;\r
57 static const UInt32 kDeflateAlgoX5 = 1;\r
58 \r
59 static const UInt32 kDeflateFastBytesX1 = 32;\r
60 static const UInt32 kDeflateFastBytesX7 = 64;\r
61 static const UInt32 kDeflateFastBytesX9 = 128;\r
62 \r
63 static const UInt32 kDeflatePassesX1 = 1;\r
64 static const UInt32 kDeflatePassesX7 = 3;\r
65 static const UInt32 kDeflatePassesX9 = 10;\r
66 \r
67 static const UInt32 kBZip2NumPassesX1 = 1;\r
68 static const UInt32 kBZip2NumPassesX7 = 2;\r
69 static const UInt32 kBZip2NumPassesX9 = 7;\r
70 \r
71 static const UInt32 kBZip2DicSizeX1 = 100000;\r
72 static const UInt32 kBZip2DicSizeX3 = 500000;\r
73 static const UInt32 kBZip2DicSizeX5 = 900000;\r
74 \r
75 static const wchar_t *kDefaultMethodName = kLZMAMethodName;\r
76 \r
77 static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";\r
78 static const UInt32 kDictionaryForHeaders = 1 << 20;\r
79 static const UInt32 kNumFastBytesForHeaders = 273;\r
80 static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5;\r
81 \r
82 static bool AreEqual(const UString &methodName, const wchar_t *s)\r
83   { return (methodName.CompareNoCase(s) == 0); }\r
84 \r
85 bool COneMethodInfo::IsLzma() const\r
86 {\r
87   return\r
88     AreEqual(MethodName, kLZMAMethodName) ||\r
89     AreEqual(MethodName, kLZMA2MethodName);\r
90 }\r
91 \r
92 static inline bool IsBZip2Method(const UString &methodName)\r
93   { return AreEqual(methodName, kBZip2MethodName); }\r
94 \r
95 static inline bool IsPpmdMethod(const UString &methodName)\r
96   { return AreEqual(methodName, kPpmdMethodName); }\r
97 \r
98 static inline bool IsDeflateMethod(const UString &methodName)\r
99 {\r
100   return\r
101     AreEqual(methodName, kDeflateMethodName) ||\r
102     AreEqual(methodName, kDeflate64MethodName);\r
103 }\r
104 \r
105 struct CNameToPropID\r
106 {\r
107   PROPID PropID;\r
108   VARTYPE VarType;\r
109   const wchar_t *Name;\r
110 };\r
111 \r
112 static CNameToPropID g_NameToPropID[] =\r
113 {\r
114   { NCoderPropID::kBlockSize, VT_UI4, L"C" },\r
115   { NCoderPropID::kDictionarySize, VT_UI4, L"D" },\r
116   { NCoderPropID::kUsedMemorySize, VT_UI4, L"MEM" },\r
117 \r
118   { NCoderPropID::kOrder, VT_UI4, L"O" },\r
119   { NCoderPropID::kPosStateBits, VT_UI4, L"PB" },\r
120   { NCoderPropID::kLitContextBits, VT_UI4, L"LC" },\r
121   { NCoderPropID::kLitPosBits, VT_UI4, L"LP" },\r
122   { NCoderPropID::kEndMarker, VT_BOOL, L"eos" },\r
123 \r
124   { NCoderPropID::kNumPasses, VT_UI4, L"Pass" },\r
125   { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" },\r
126   { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" },\r
127   { NCoderPropID::kAlgorithm, VT_UI4, L"a" },\r
128   { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" },\r
129   { NCoderPropID::kNumThreads, VT_UI4, L"mt" },\r
130   { NCoderPropID::kDefaultProp, VT_UI4, L"" }\r
131 };\r
132 \r
133 static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)\r
134 {\r
135   if (varType == srcProp.vt)\r
136   {\r
137     destProp = srcProp;\r
138     return true;\r
139   }\r
140   if (varType == VT_UI1)\r
141   {\r
142     if (srcProp.vt == VT_UI4)\r
143     {\r
144       UInt32 value = srcProp.ulVal;\r
145       if (value > 0xFF)\r
146         return false;\r
147       destProp = (Byte)value;\r
148       return true;\r
149     }\r
150   }\r
151   else if (varType == VT_BOOL)\r
152   {\r
153     bool res;\r
154     if (SetBoolProperty(res, srcProp) != S_OK)\r
155       return false;\r
156     destProp = res;\r
157     return true;\r
158   }\r
159   return false;\r
160 }\r
161     \r
162 static int FindPropIdExact(const UString &name)\r
163 {\r
164   for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)\r
165     if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)\r
166       return i;\r
167   return -1;\r
168 }\r
169 \r
170 static int FindPropIdStart(const UString &name)\r
171 {\r
172   for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)\r
173   {\r
174     UString t = g_NameToPropID[i].Name;\r
175     if (t.CompareNoCase(name.Left(t.Length())) == 0)\r
176       return i;\r
177   }\r
178   return -1;\r
179 }\r
180 \r
181 static void SetMethodProp(COneMethodInfo &m, PROPID propID, const NCOM::CPropVariant &value)\r
182 {\r
183   for (int j = 0; j < m.Props.Size(); j++)\r
184     if (m.Props[j].Id == propID)\r
185       return;\r
186   CProp prop;\r
187   prop.Id = propID;\r
188   prop.Value = value;\r
189   m.Props.Add(prop);\r
190 }\r
191 \r
192 void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo\r
193     #ifndef _7ZIP_ST\r
194     , UInt32 numThreads\r
195     #endif\r
196     )\r
197 {\r
198   UInt32 level = _level;\r
199   if (oneMethodInfo.MethodName.IsEmpty())\r
200     oneMethodInfo.MethodName = kDefaultMethodName;\r
201   \r
202   if (oneMethodInfo.IsLzma())\r
203   {\r
204     UInt32 dicSize =\r
205       (level >= 9 ? kLzmaDicSizeX9 :\r
206       (level >= 7 ? kLzmaDicSizeX7 :\r
207       (level >= 5 ? kLzmaDicSizeX5 :\r
208       (level >= 3 ? kLzmaDicSizeX3 :\r
209                     kLzmaDicSizeX1))));\r
210     \r
211     UInt32 algo =\r
212       (level >= 5 ? kLzmaAlgoX5 :\r
213                     kLzmaAlgoX1);\r
214     \r
215     UInt32 fastBytes =\r
216       (level >= 7 ? kLzmaFastBytesX7 :\r
217                     kLzmaFastBytesX1);\r
218     \r
219     const wchar_t *matchFinder =\r
220       (level >= 5 ? kLzmaMatchFinderX5 :\r
221                     kLzmaMatchFinderX1);\r
222     \r
223     SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);\r
224     SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);\r
225     SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);\r
226     SetMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);\r
227     #ifndef _7ZIP_ST\r
228     SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);\r
229     #endif\r
230   }\r
231   else if (IsDeflateMethod(oneMethodInfo.MethodName))\r
232   {\r
233     UInt32 fastBytes =\r
234       (level >= 9 ? kDeflateFastBytesX9 :\r
235       (level >= 7 ? kDeflateFastBytesX7 :\r
236                     kDeflateFastBytesX1));\r
237     \r
238     UInt32 numPasses =\r
239       (level >= 9 ? kDeflatePassesX9 :\r
240       (level >= 7 ? kDeflatePassesX7 :\r
241                     kDeflatePassesX1));\r
242     \r
243     UInt32 algo =\r
244       (level >= 5 ? kDeflateAlgoX5 :\r
245                     kDeflateAlgoX1);\r
246     \r
247     SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);\r
248     SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);\r
249     SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);\r
250   }\r
251   else if (IsBZip2Method(oneMethodInfo.MethodName))\r
252   {\r
253     UInt32 numPasses =\r
254       (level >= 9 ? kBZip2NumPassesX9 :\r
255       (level >= 7 ? kBZip2NumPassesX7 :\r
256                     kBZip2NumPassesX1));\r
257     \r
258     UInt32 dicSize =\r
259       (level >= 5 ? kBZip2DicSizeX5 :\r
260       (level >= 3 ? kBZip2DicSizeX3 :\r
261                     kBZip2DicSizeX1));\r
262     \r
263     SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);\r
264     SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);\r
265     #ifndef _7ZIP_ST\r
266     SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);\r
267     #endif\r
268   }\r
269   else if (IsPpmdMethod(oneMethodInfo.MethodName))\r
270   {\r
271     UInt32 useMemSize =\r
272       (level >= 9 ? kPpmdMemSizeX9 :\r
273       (level >= 7 ? kPpmdMemSizeX7 :\r
274       (level >= 5 ? kPpmdMemSizeX5 :\r
275                     kPpmdMemSizeX1)));\r
276     \r
277     UInt32 order =\r
278       (level >= 9 ? kPpmdOrderX9 :\r
279       (level >= 7 ? kPpmdOrderX7 :\r
280       (level >= 5 ? kPpmdOrderX5 :\r
281                     kPpmdOrderX1)));\r
282     \r
283     SetMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);\r
284     SetMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);\r
285   }\r
286 }\r
287 \r
288 static void SplitParams(const UString &srcString, UStringVector &subStrings)\r
289 {\r
290   subStrings.Clear();\r
291   UString name;\r
292   int len = srcString.Length();\r
293   if (len == 0)\r
294     return;\r
295   for (int i = 0; i < len; i++)\r
296   {\r
297     wchar_t c = srcString[i];\r
298     if (c == L':')\r
299     {\r
300       subStrings.Add(name);\r
301       name.Empty();\r
302     }\r
303     else\r
304       name += c;\r
305   }\r
306   subStrings.Add(name);\r
307 }\r
308 \r
309 static void SplitParam(const UString &param, UString &name, UString &value)\r
310 {\r
311   int eqPos = param.Find(L'=');\r
312   if (eqPos >= 0)\r
313   {\r
314     name = param.Left(eqPos);\r
315     value = param.Mid(eqPos + 1);\r
316     return;\r
317   }\r
318   for(int i = 0; i < param.Length(); i++)\r
319   {\r
320     wchar_t c = param[i];\r
321     if (c >= L'0' && c <= L'9')\r
322     {\r
323       name = param.Left(i);\r
324       value = param.Mid(i);\r
325       return;\r
326     }\r
327   }\r
328   name = param;\r
329 }\r
330 \r
331 HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)\r
332 {\r
333   CProp prop;\r
334   int index = FindPropIdExact(name);\r
335   if (index < 0)\r
336     return E_INVALIDARG;\r
337   const CNameToPropID &nameToPropID = g_NameToPropID[index];\r
338   prop.Id = nameToPropID.PropID;\r
339 \r
340   if (prop.Id == NCoderPropID::kBlockSize ||\r
341       prop.Id == NCoderPropID::kDictionarySize ||\r
342       prop.Id == NCoderPropID::kUsedMemorySize)\r
343   {\r
344     UInt32 dicSize;\r
345     RINOK(ParsePropDictionaryValue(value, dicSize));\r
346     prop.Value = dicSize;\r
347   }\r
348   else\r
349   {\r
350     NCOM::CPropVariant propValue;\r
351     \r
352     if (nameToPropID.VarType == VT_BSTR)\r
353       propValue = value;\r
354     else if (nameToPropID.VarType == VT_BOOL)\r
355     {\r
356       bool res;\r
357       if (!StringToBool(value, res))\r
358         return E_INVALIDARG;\r
359       propValue = res;\r
360     }\r
361     else\r
362     {\r
363       UInt32 number;\r
364       if (ParseStringToUInt32(value, number) == value.Length())\r
365         propValue = number;\r
366       else\r
367         propValue = value;\r
368     }\r
369     \r
370     if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value))\r
371       return E_INVALIDARG;\r
372   }\r
373   oneMethodInfo.Props.Add(prop);\r
374   return S_OK;\r
375 }\r
376 \r
377 HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString)\r
378 {\r
379   UStringVector params;\r
380   SplitParams(srcString, params);\r
381   if (params.Size() > 0)\r
382     oneMethodInfo.MethodName = params[0];\r
383   for (int i = 1; i < params.Size(); i++)\r
384   {\r
385     const UString &param = params[i];\r
386     UString name, value;\r
387     SplitParam(param, name, value);\r
388     RINOK(SetParam(oneMethodInfo, name, value));\r
389   }\r
390   return S_OK;\r
391 }\r
392 \r
393 HRESULT COutHandler::SetSolidSettings(const UString &s)\r
394 {\r
395   UString s2 = s;\r
396   s2.MakeUpper();\r
397   for (int i = 0; i < s2.Length();)\r
398   {\r
399     const wchar_t *start = ((const wchar_t *)s2) + i;\r
400     const wchar_t *end;\r
401     UInt64 v = ConvertStringToUInt64(start, &end);\r
402     if (start == end)\r
403     {\r
404       if (s2[i++] != 'E')\r
405         return E_INVALIDARG;\r
406       _solidExtension = true;\r
407       continue;\r
408     }\r
409     i += (int)(end - start);\r
410     if (i == s2.Length())\r
411       return E_INVALIDARG;\r
412     wchar_t c = s2[i++];\r
413     switch(c)\r
414     {\r
415       case 'F':\r
416         if (v < 1)\r
417           v = 1;\r
418         _numSolidFiles = v;\r
419         break;\r
420       case 'B':\r
421         _numSolidBytes = v;\r
422         _numSolidBytesDefined = true;\r
423         break;\r
424       case 'K':\r
425         _numSolidBytes = (v << 10);\r
426         _numSolidBytesDefined = true;\r
427         break;\r
428       case 'M':\r
429         _numSolidBytes = (v << 20);\r
430         _numSolidBytesDefined = true;\r
431         break;\r
432       case 'G':\r
433         _numSolidBytes = (v << 30);\r
434         _numSolidBytesDefined = true;\r
435         break;\r
436       default:\r
437         return E_INVALIDARG;\r
438     }\r
439   }\r
440   return S_OK;\r
441 }\r
442 \r
443 HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value)\r
444 {\r
445   bool isSolid;\r
446   switch(value.vt)\r
447   {\r
448     case VT_EMPTY:\r
449       isSolid = true;\r
450       break;\r
451     case VT_BOOL:\r
452       isSolid = (value.boolVal != VARIANT_FALSE);\r
453       break;\r
454     case VT_BSTR:\r
455       if (StringToBool(value.bstrVal, isSolid))\r
456         break;\r
457       return SetSolidSettings(value.bstrVal);\r
458     default:\r
459       return E_INVALIDARG;\r
460   }\r
461   if (isSolid)\r
462     InitSolid();\r
463   else\r
464     _numSolidFiles = 1;\r
465   return S_OK;\r
466 }\r
467 \r
468 void COutHandler::Init()\r
469 {\r
470   _removeSfxBlock = false;\r
471   _compressHeaders = true;\r
472   _encryptHeadersSpecified = false;\r
473   _encryptHeaders = false;\r
474   \r
475   WriteCTime = false;\r
476   WriteATime = false;\r
477   WriteMTime = true;\r
478   \r
479   #ifndef _7ZIP_ST\r
480   _numThreads = NSystem::GetNumberOfProcessors();\r
481   #endif\r
482   \r
483   _level = 5;\r
484   _autoFilter = true;\r
485   _volumeMode = false;\r
486   _crcSize = 4;\r
487   InitSolid();\r
488 }\r
489 \r
490 void COutHandler::BeforeSetProperty()\r
491 {\r
492   Init();\r
493   #ifndef _7ZIP_ST\r
494   numProcessors = NSystem::GetNumberOfProcessors();\r
495   #endif\r
496 \r
497   mainDicSize = 0xFFFFFFFF;\r
498   mainDicMethodIndex = 0xFFFFFFFF;\r
499   minNumber = 0;\r
500   _crcSize = 4;\r
501 }\r
502 \r
503 HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)\r
504 {\r
505   UString name = nameSpec;\r
506   name.MakeUpper();\r
507   if (name.IsEmpty())\r
508     return E_INVALIDARG;\r
509   \r
510   if (name[0] == 'X')\r
511   {\r
512     name.Delete(0);\r
513     _level = 9;\r
514     return ParsePropValue(name, value, _level);\r
515   }\r
516   \r
517   if (name[0] == L'S')\r
518   {\r
519     name.Delete(0);\r
520     if (name.IsEmpty())\r
521       return SetSolidSettings(value);\r
522     if (value.vt != VT_EMPTY)\r
523       return E_INVALIDARG;\r
524     return SetSolidSettings(name);\r
525   }\r
526   \r
527   if (name == L"CRC")\r
528   {\r
529     _crcSize = 4;\r
530     name.Delete(0, 3);\r
531     return ParsePropValue(name, value, _crcSize);\r
532   }\r
533   \r
534   UInt32 number;\r
535   int index = ParseStringToUInt32(name, number);\r
536   UString realName = name.Mid(index);\r
537   if (index == 0)\r
538   {\r
539     if(name.Left(2).CompareNoCase(L"MT") == 0)\r
540     {\r
541       #ifndef _7ZIP_ST\r
542       RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));\r
543       #endif\r
544       return S_OK;\r
545     }\r
546     if (name.CompareNoCase(L"RSFX") == 0)  return SetBoolProperty(_removeSfxBlock, value);\r
547     if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value);\r
548     if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value);\r
549     if (name.CompareNoCase(L"HCF") == 0)\r
550     {\r
551       bool compressHeadersFull = true;\r
552       RINOK(SetBoolProperty(compressHeadersFull, value));\r
553       if (!compressHeadersFull)\r
554         return E_INVALIDARG;\r
555       return S_OK;\r
556     }\r
557     if (name.CompareNoCase(L"HE") == 0)\r
558     {\r
559       RINOK(SetBoolProperty(_encryptHeaders, value));\r
560       _encryptHeadersSpecified = true;\r
561       return S_OK;\r
562     }\r
563     if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCTime, value);\r
564     if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteATime, value);\r
565     if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteMTime, value);\r
566     if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value);\r
567     number = 0;\r
568   }\r
569   if (number > 10000)\r
570     return E_FAIL;\r
571   if (number < minNumber)\r
572     return E_INVALIDARG;\r
573   number -= minNumber;\r
574   for(int j = _methods.Size(); j <= (int)number; j++)\r
575   {\r
576     COneMethodInfo oneMethodInfo;\r
577     _methods.Add(oneMethodInfo);\r
578   }\r
579   \r
580   COneMethodInfo &oneMethodInfo = _methods[number];\r
581   \r
582   if (realName.Length() == 0)\r
583   {\r
584     if (value.vt != VT_BSTR)\r
585       return E_INVALIDARG;\r
586     \r
587     RINOK(SetParams(oneMethodInfo, value.bstrVal));\r
588   }\r
589   else\r
590   {\r
591     int index = FindPropIdStart(realName);\r
592     if (index < 0)\r
593       return E_INVALIDARG;\r
594     const CNameToPropID &nameToPropID = g_NameToPropID[index];\r
595     CProp prop;\r
596     prop.Id = nameToPropID.PropID;\r
597 \r
598     if (prop.Id == NCoderPropID::kBlockSize ||\r
599         prop.Id == NCoderPropID::kDictionarySize ||\r
600         prop.Id == NCoderPropID::kUsedMemorySize)\r
601     {\r
602       UInt32 dicSize;\r
603       RINOK(ParsePropDictionaryValue(realName.Mid(MyStringLen(nameToPropID.Name)), value, dicSize));\r
604       prop.Value = dicSize;\r
605       if (number <= mainDicMethodIndex)\r
606         mainDicSize = dicSize;\r
607     }\r
608     else\r
609     {\r
610       int index = FindPropIdExact(realName);\r
611       if (index < 0)\r
612         return E_INVALIDARG;\r
613       const CNameToPropID &nameToPropID = g_NameToPropID[index];\r
614       prop.Id = nameToPropID.PropID;\r
615       if (!ConvertProperty(value, nameToPropID.VarType, prop.Value))\r
616         return E_INVALIDARG;\r
617     }\r
618     oneMethodInfo.Props.Add(prop);\r
619   }\r
620   return S_OK;\r
621 }\r
622 \r
623 }\r