[Helix-client-dev] CR/CN: Windows-Unicode command line patches for GMPMetaEditor branch

Petar Basic <[email protected]> Fri, 15 Jan 2010 00:14:13 +0100
Newsgroups gmane.comp.multimedia.helix.devel
Message-ID <[email protected]>
Modified by: pbasic at real.com
Date: 2010/01/14
Project: GMP MetaEditor (meta3gp.exe)

Synopsis:
Windows-Unicode command line patches for GMPMetaEditor branch

Details:
1.) Adjusted string types and transfers in meta3gp project to make
possible usage of Unicode command line on Windows.

2.) Fixed code-unit counting bugs in the following routines
IsUTF8StringAsciiOnly, IsUTF16StringAsciiOnly, IsUTF32StringAsciiOnly.

Testing:
Verified operation on GMP MetaEditor on Windows XP SP2 and Solaris
5.10 Sparc via standard MetaEditor test scripts.

Files Modified:
common/util/uniconv.cpp
datatype/tools/dtdriver/apps/meta3gp/HXXmlInputParser.cpp
datatype/tools/dtdriver/apps/meta3gp/HXXmlInputParser.h
datatype/tools/dtdriver/apps/meta3gp/main.cpp

Platforms and Profiles Affected:
All

Image Size and Heap Use impact:
None

Platforms and Profiles Build Verified:
system id: win32-i386-vc7, sunos-5.10-sparc-studio11
profile: helix-client-all-defines

Platforms and Profiles Functionality Verified:
x86 Windows XP SP2
Sparc SunOS 5.10

Branch:
GMPMetaEditor

Copyright assignment:
I am a RealNetworks employee or contractor.

_______________________________________________
Helix-client-dev mailing list
[email protected]
http://lists.helixcommunity.org/mailman/listinfo/helix-client-dev
common_util.diff (application/octet-stream, 5.3 KB)
Index: uniconv.cpp
===================================================================
RCS file: /cvsroot/common/util/uniconv.cpp,v
retrieving revision 1.2
diff -d -H -w -U30 -r1.2 uniconv.cpp
--- uniconv.cpp	28 Nov 2007 18:59:47 -0000	1.2
+++ uniconv.cpp	14 Jan 2010 22:49:25 -0000
@@ -55,154 +55,169 @@
 
 
 // unicode constants
 #define UNICODE_MAX_ASCII               UINT32(0x0000007F)
 #define UNICODE_HIGH_SURROGATE_START    UINT32(0x0000D800)
 #define UNICODE_HIGH_SURROGATE_END      UINT32(0x0000DBFF)
 #define UNICODE_LOW_SURROGATE_START     UINT32(0x0000DC00)
 #define UNICODE_LOW_SURROGATE_END       UINT32(0x0000DFFF)
 #define UNICODE_SURROGATE_BASE          UINT32(0x00010000)
 #define UNICODE_REPLACEMENT_CHAR        UINT32(0x0000FFFD)
 #define UNICODE_MAX_BMP                 UINT32(0x0000FFFF)
 #define UNICODE_MAX_LEGAL               UINT32(0x0010FFFF)
 
 HXBOOL IsUTF8StringAsciiOnly(const UINT8* pCodeUnits, UINT32 uNumCodeUnits, UINT32& outNumUnits)
 {
     outNumUnits = 0;
     if(!pCodeUnits)
     {
         return TRUE;
     }
     HXBOOL bUseInputLimit = (uNumCodeUnits != MAX_UINT32) ? TRUE : FALSE;
     UINT32 remainingUnits = uNumCodeUnits;
 
     while(TRUE)
     {
         if(bUseInputLimit && !remainingUnits)
         {
             break; //source exhausted
         }
         UINT8 codeUnit = *pCodeUnits++;
+        remainingUnits--;
+
         if(codeUnit > UNICODE_MAX_ASCII)
         {
             return FALSE; //found non-ascii
         }
+
         outNumUnits++;
         if(!bUseInputLimit && !codeUnit)
         {
             break; //found 0-terminator
         }
     }
     return TRUE; //all units are ascii
 }
 
 HXBOOL IsUTF16StringAsciiOnly(const UINT16* pCodeUnits, UINT32 uNumCodeUnits,
                             HXBOOL bBigEndian, UINT32& outNumUnits)
 {
     outNumUnits = 0;
     if(!pCodeUnits)
     {
         return TRUE;
     }
     HXBOOL bUseInputLimit = (uNumCodeUnits != MAX_UINT32) ? TRUE : FALSE;
     UINT32 remainingUnits = uNumCodeUnits;
 
     while(TRUE)
     {
         if(bUseInputLimit && !remainingUnits)
         {
             break; //source exhausted
         }
-        UINT16 codeUnit = *pCodeUnits++;
-        const UINT8* pBytes = (const UINT8*)&codeUnit;
+        UINT16 codeUnit = *pCodeUnits;
+        const UINT8* pBytes = (const UINT8*)pCodeUnits;
+
+        pCodeUnits++;
+        remainingUnits--;
+
         UINT8 bytes[2];
         if(bBigEndian)
         {
             bytes[0] = pBytes[0];
             bytes[1] = pBytes[1];
         }
         else
         {
             bytes[0] = pBytes[1];
             bytes[1] = pBytes[0];
         }
+
         if((bytes[0] != 0) || (bytes[1] > UNICODE_MAX_ASCII))
         {
             return FALSE; //found non-ascii
         }
+
         outNumUnits++;
         if(!bUseInputLimit && !codeUnit)
         {
             break; //found 0-terminator
         }
     }
     return TRUE; //all units are ascii
 }
 
 HXBOOL IsUTF32StringAsciiOnly(const UINT32* pCodeUnits, UINT32 uNumCodeUnits,
                             HXBOOL bBigEndian, UINT32& outNumUnits)
 {
     outNumUnits = 0;
     if(!pCodeUnits)
     {
         return TRUE;
     }
     HXBOOL bUseInputLimit = (uNumCodeUnits != MAX_UINT32) ? TRUE : FALSE;
-    UINT32 remainingPoints = uNumCodeUnits;
+    UINT32 remainingUnits = uNumCodeUnits;
 
     while(TRUE)
     {
-        if(bUseInputLimit && !remainingPoints)
+        if(bUseInputLimit && !remainingUnits)
         {
             break; //source exhausted
         }
-        UINT32 codeUnit = *pCodeUnits++;
-        const UINT8* pBytes = (const UINT8*)&codeUnit;
+        UINT32 codeUnit = *pCodeUnits;
+        const UINT8* pBytes = (const UINT8*)pCodeUnits;
+
+        pCodeUnits++;
+        remainingUnits--;
+
         UINT8 bytes[4];
         if(bBigEndian)
         {
             bytes[0] = pBytes[0];
             bytes[1] = pBytes[1];
             bytes[2] = pBytes[2];
             bytes[3] = pBytes[3];
         }
         else
         {
             bytes[0] = pBytes[3];
             bytes[1] = pBytes[2];
             bytes[2] = pBytes[1];
             bytes[3] = pBytes[0];
         }
+
         if((bytes[0] != 0) || (bytes[1] != 0) || (bytes[2] != 0) || (bytes[3] > UNICODE_MAX_ASCII))
         {
             return FALSE; //found non-ascii
         }
+
         outNumUnits++;
         if(!bUseInputLimit && !codeUnit)
         {
             break; //found 0-terminator
         }
     }
     return TRUE; //all units are ascii
 }
 
 INT32 ConvertUTF8CodeUnitSequenceToUnicodeCodePoint(
                     UINT32& outCodePoint, UINT32& outNumConsumedCodeUnits,
                     const UINT8* pInCodeUnits, UINT32 uNumCodeUnits)
 {
     outCodePoint = 0; //set output to null-terminator for error cases
     outNumConsumedCodeUnits = 0;
 
     HXBOOL bUseUnitLimit = (uNumCodeUnits != MAX_UINT32) ? TRUE : FALSE;
     if(!pInCodeUnits || (bUseUnitLimit && uNumCodeUnits < 1))
     {
         return -1; //not enough units
     }
 
     UINT32 codeUnitSeqLen = 1;
     UINT32 codeUnit = UINT32(*pInCodeUnits);
 
     // determine length of code-unit sequence
     if(codeUnit >= UINT32(0x00) && codeUnit <= UNICODE_MAX_ASCII)
     {
         ; //codeUnitSeqLen already set to 1
     }
datatype_tools_dtdriver_apps_meta3gp.diff (application/octet-stream, 55.6 KB)
Index: HXXmlInputParser.cpp
===================================================================
RCS file: /cvsroot/datatype/tools/dtdriver/apps/meta3gp/HXXmlInputParser.cpp,v
retrieving revision 1.2
diff -d -H -w -U30 -r1.2 HXXmlInputParser.cpp
--- HXXmlInputParser.cpp	6 Jan 2010 18:04:20 -0000	1.2
+++ HXXmlInputParser.cpp	14 Jan 2010 22:53:47 -0000
@@ -15,60 +15,61 @@
  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  * RCSL for the rights, obligations and limitations governing use of the 
  * contents of the file.  
  *  
  * This file is part of the Helix DNA Technology. RealNetworks is the 
  * developer of the Original Code and owns the copyrights in the portions 
  * it created. 
  *  
  * This file, and the files included with this file, is distributed and made 
  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  * 
  * Technology Compatibility Kit Test Suite(s) Location: 
  *    http://www.helixcommunity.org/content/tck 
  * 
  * Contributor(s): 
  *  
  * ***** END LICENSE BLOCK ***** */ 
 
 
 /****************************************************************************
  *  Includes
  */
 
 
 #include "hxcom.h"
 #include "hxbuffer.h"
 #include "hxvalues.h"
+#include "hlxosstr.h"
 #include "HXXmlInputParser.h"
 
 CHXXmlInputParser::CHXXmlInputParser()
 :   m_lRefCount(0),
     m_pXMLParser(NULL),
     m_pResults(NULL),
     m_ParsingResult(HXR_OK)
 {
 }
 
 
 CHXXmlInputParser::~CHXXmlInputParser()
 {
     HX_RELEASE(m_pXMLParser);
 }
 
 
 STDMETHODIMP_(ULONG32) CHXXmlInputParser::AddRef()
 {
     return InterlockedIncrement(&m_lRefCount);
 }
 
 
 STDMETHODIMP_(ULONG32) CHXXmlInputParser::Release()
 {
     if (InterlockedDecrement(&m_lRefCount) > 0)
     {
         return m_lRefCount;
     }
     delete this;
@@ -103,69 +104,70 @@
     IHXValues* pAttributes,
     UINT32 ulLineNumber,
     UINT32 ulColumnNumber)
 {
     // add the name to the path
     m_sCurrentElementPath += "/";
     m_sCurrentElementPath += pName;
 
     return HXR_OK;
 }
 
 
 STDMETHODIMP CHXXmlInputParser::HandleEndElement(
     const char* pName,
     UINT32 ulLineNumber,
     UINT32 ulColumnNumber)
 {
     // remove name from path
     CHXString sName(pName);
     m_sCurrentElementPath = m_sCurrentElementPath.Left(m_sCurrentElementPath.GetLength() - sName.GetLength() -1);
 
     return HXR_OK;
 }
 
 
 STDMETHODIMP CHXXmlInputParser::HandleCharacterData(
     IHXBuffer* pBuffer,
     UINT32 ulLineNumber,
     UINT32 ulColumnNumber)
 {
-    // if path exists, the set its value
+    // With current parser implementation we will assume UTF8
+    EncodedString strValue((const char*)pBuffer->GetBuffer(), HX_TEXT_ENCODING_TYPE_UTF8);
 
-    CHXString strValue(pBuffer->GetBuffer());
     if (!strValue.IsEmpty())
     {
+        // copy value for known paths
         XmlPair* currentValue = m_pResults->GetAt(m_sCurrentElementPath);
         if (currentValue!=NULL)
         {
-            currentValue->xmlValue = strValue;
+            currentValue->xmlValueUTF8 = strValue;
         }
     }
     return HXR_OK;
 }
 
 
 STDMETHODIMP CHXXmlInputParser::HandleProcessingInstruction(
     const char* pTarget,
     IHXValues* pAttributes,
     UINT32 ulLineNumber,
     UINT32 ulColumnNumber)
 {
     return HXR_OK;
 }
 
 
 STDMETHODIMP CHXXmlInputParser::HandleUnparsedEntityDecl(
     const char* pEntityName,
     const char* pSystemID,
     const char* pPublicID,
     const char* pNotationName,
     UINT32 ulLineNumber,
     UINT32 ulColumnNumber)
 {
     return HXR_OK;
 }
 
 
 STDMETHODIMP CHXXmlInputParser::HandleNotationDecl(
     const char* pNotationName,
Index: HXXmlInputParser.h
===================================================================
RCS file: /cvsroot/datatype/tools/dtdriver/apps/meta3gp/HXXmlInputParser.h,v
retrieving revision 1.1.2.1
diff -d -H -w -U30 -r1.1.2.1 HXXmlInputParser.h
--- HXXmlInputParser.h	11 Jan 2010 17:52:26 -0000	1.1.2.1
+++ HXXmlInputParser.h	14 Jan 2010 22:53:47 -0000
@@ -18,109 +18,113 @@
  *  
  * This file is part of the Helix DNA Technology. RealNetworks is the 
  * developer of the Original Code and owns the copyrights in the portions 
  * it created. 
  *  
  * This file, and the files included with this file, is distributed and made 
  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  * 
  * Technology Compatibility Kit Test Suite(s) Location: 
  *    http://www.helixcommunity.org/content/tck 
  * 
  * Contributor(s): 
  *  
  * ***** END LICENSE BLOCK ***** */ 
 
 
 /****************************************************************************
  *  Includes
  */
 
 #ifndef _HXXMLINPUTPARSER_H_
 #define _HXXMLINPUTPARSER_H_
 
 #include "hxcom.h"
 #include "hxstring.h"
 #include "hxxml.h"
 #include "carray.h"
+#include "encstr.h"
 
 
 struct XmlPair
 {
-    XmlPair(const CHXString& path, const CHXString& value)
+    XmlPair(const CHXString& path, const EncodedString& valueUTF8)
         : xmlPath(path)
-        , xmlValue(value)
+        , xmlValueUTF8(valueUTF8)
     {
     }
     CHXString xmlPath;
-    CHXString xmlValue;
+    EncodedString xmlValueUTF8;
 };
 
 class CParsedXmlPairs
 {
 public:
     ~CParsedXmlPairs()
     {
         for(int i = 0; i < xmlPairs.GetSize(); i++)
         {
             delete (XmlPair*)xmlPairs.GetAt(i);
         }
     }
 
     void Add(XmlPair* pair)
     {
         xmlPairs.Add(pair);
     }
 
     XmlPair* GetAt(const CHXString& xmlPath)
     {
         for(int i = 0; i < xmlPairs.GetSize(); i++)
         {
             XmlPair *pair = (XmlPair*)xmlPairs.GetAt(i);
             if (pair->xmlPath == xmlPath)
             {
                 return pair;
             }
         }
 
         return NULL;
     }
 
     void Dump()
     {
         for(int i = 0; i < xmlPairs.GetSize(); i++)
         {
             XmlPair *pair = (XmlPair*)xmlPairs.GetAt(i);
-            printf(" Xml xpath %s contains value: %s\n", (const char*)pair->xmlPath, (const char*)pair->xmlValue);
+
+            printf("%s = [", (const char*)pair->xmlPath);
+            EncStrUtils::PrintTextUTF8(pair->xmlValueUTF8.GetData());
+            printf("].\n");
         }
     }
 
     CHXPtrArray* GetAllPairs()
     {
         return &xmlPairs;
     }
 
 private:
     CHXPtrArray xmlPairs;
 };
 
 /*
  * CHXXmlInputParser class implements XML upgrade manifest parser.
  */
 class CHXXmlInputParser : 
     public IHXXMLParserResponse
 {
 public:
     /*
      * Class constructor. Initializes a new instance of the CHXXmlInputParser class.
      */
     CHXXmlInputParser();
 
     /**************************************************************************
      *  IHXContextUser methods
      **************************************************************************/
     STDMETHOD(QueryInterface)	(THIS_
 				REFIID riid,
 				void** ppvObj);
Index: main.cpp
===================================================================
RCS file: /cvsroot/datatype/tools/dtdriver/apps/meta3gp/main.cpp,v
retrieving revision 1.7.2.1
diff -d -H -w -U30 -r1.7.2.1 main.cpp
--- main.cpp	11 Jan 2010 17:52:26 -0000	1.7.2.1
+++ main.cpp	14 Jan 2010 22:53:51 -0000
@@ -48,127 +48,121 @@
 #include "ffdriver.h"
 #include "cstrmsrt.h"
 #include "hxmemprb.h"
 #include "hxtick.h"
 #include "chxpckts.h"
 #include "pckunpck.h"
 #include "dllpath.h"
 #include "filespecutils.h"
 #include "metainfokeys.h"
 #include "uniconv.h"
 #include "proptools.h"
 #include "dllacces.h"
 #include "ihxmetaeditor.h"
 #include "HXXmlInputParser.h"
 #include "metautil.h"
 
 #include "meta3gp.ver"
 
 #ifdef HELIX_FEATURE_METAEDIT_AUDIO_HASH
 #include "mycrypt.h"
 #endif
 
 
 /****************************************************************************
  *  Meta-data command line editor.
  *  Build-time configuration options.
  */
 
 // uncomment to force usage of legacy strings on Windows
 // (only relevant for command-line argument transfer)
-//#define FORCE_LEGACY_CHAR 1
+//#define FORCE_LEGACY_CHAR_COMMAND_LINE 1
 
 // environment variable name
 #define PLUGIN_PATH_ENV_VAR_NAME "META3GP_PLUGIN_PATH"
 
 
 /****************************************************************************
  *  Component operational modes
  */
 HXBOOL g_bUseDefaultMetaEditorProcessor = FALSE;
 HXBOOL g_bUseDTDriverSynchronousMode = TRUE;
 
 
 /****************************************************************************
  *  System character type macros
  */
-#ifdef USE_WIDE_CHAR
-#undef USE_WIDE_CHAR
+#ifdef USE_WIDE_CHAR_COMMAND_LINE
+#undef USE_WIDE_CHAR_COMMAND_LINE
 #endif
 
-#if defined(_WINDOWS) && !defined(FORCE_LEGACY_CHAR)
-#define USE_WIDE_CHAR 1
+#if !defined(FORCE_LEGACY_CHAR_COMMAND_LINE) && defined(_WINDOWS)
+#define USE_WIDE_CHAR_COMMAND_LINE 1
 #endif
 
 
 #ifdef _T
 #undef _T
 #endif
 #ifdef TCHAR
 #undef TCHAR
 #endif
 #ifdef TMAIN
 #undef TMAIN
 #endif
 
 
-#ifdef USE_WIDE_CHAR
+#ifdef USE_WIDE_CHAR_COMMAND_LINE
 
 #define _T(Val) L##Val
 #define TCHAR wchar_t
 #define TMAIN wmain
 #define TCHXStringCtor(Val) CHXString((const char*)CCPFromWCharT(Val))
-#define TUTF8EncodedStringVar(VarName, Val) EncodedString VarName((const char*)::UTF8FromWCharT(Val), HX_TEXT_ENCODING_TYPE_UTF8)
 #define TUTF8EncodedStringCtor(Val) EncodedString((const char*)::UTF8FromWCharT(Val), HX_TEXT_ENCODING_TYPE_UTF8)
-#define TUTF8EncodedStringCCPVar(VarName, Val) EncodedString VarName((const char*)::UTF8FromCCP(Val), HX_TEXT_ENCODING_TYPE_UTF8)
-#define TUTF8EncodedStringCCPCtor(Val) EncodedString((const char*)::UTF8FromCCP(Val), HX_TEXT_ENCODING_TYPE_UTF8)
 
-#else //USE_WIDE_CHAR
+#else
 
 #define _T(Val) Val
 #define TCHAR char
 #define TMAIN main
 #define TCHXStringCtor(Val) CHXString(Val)
-#define TUTF8EncodedStringVar(VarName, Val) EncodedString VarName((const char*)::UTF8FromCCP(Val), HX_TEXT_ENCODING_TYPE_UTF8)
 #define TUTF8EncodedStringCtor(Val) EncodedString((const char*)::UTF8FromCCP(Val), HX_TEXT_ENCODING_TYPE_UTF8)
-#define TUTF8EncodedStringCCPVar(VarName, Val) EncodedString VarName((const char*)::UTF8FromCCP(Val), HX_TEXT_ENCODING_TYPE_UTF8)
-#define TUTF8EncodedStringCCPCtor(Val) EncodedString((const char*)::UTF8FromCCP(Val), HX_TEXT_ENCODING_TYPE_UTF8)
 
-#endif //USE_WIDE_CHAR
+#endif //USE_WIDE_CHAR_COMMAND_LINE
 
 
 /****************************************************************************
  *  Build-time messages
  */
 #ifdef _WINDOWS
 
-#ifdef USE_WIDE_CHAR
+#ifdef USE_WIDE_CHAR_COMMAND_LINE
 #   pragma message("Using wide-string command-line arguments")
 #else
 #   pragma message("Using legacy-string command-line arguments")
 #endif
 
 #endif //_WINDOWS
 
 
 /****************************************************************************
  *  DLLAccessPath Variable
  */
 ENABLE_DLLACCESS_PATHS(g_Meta3GPAccessPath);
 
 
 /****************************************************************************
  *  Defines
  */
 #define PROGRAM_NAME_STRING         "RealNetworks meta-data editor"
 #define PROGRAM_COPYRIGHT_STRING    "Copyright (c) RealNetworks 2010"
 
 // input/output control
 #ifdef _WINDOWS
 #define OPTION_STRING_ASYNCMODE      "dev-asyncmode"
 #endif //_WINDOWS
 
 #define OPTION_STRING_DEFMETAPROC    "dev-defmetaproc"
 #define OPTION_STRING_INPUTFILE      "if"
 #define OPTION_STRING_OUTPUTFILE     "of"
 #define OPTION_STRING_XMLINPUTFILE   "xmlin"
 #define OPTION_STRING_XMLOUTPUTFILE  "xmlout"
@@ -397,61 +391,61 @@
             OptionDesc* od = (OptionDesc*)descs.GetAt(i);
             if(strArg == od->GetOptionString())
             {
                 return od;
             }
         }
         return NULL;
     }
 
     OptionDesc* GetOptionDescWithPath(CHXString& strArg) const
     {
         for(int i = 0; i < descs.GetSize(); i++)
         {
             OptionDesc* od = (OptionDesc*)descs.GetAt(i);
             if(strArg == od->GetXPath())
             {
                 return od;
             }
         }
         return NULL;
     }
 
     void InitializeXmlPairs(CParsedXmlPairs *xmlPairs)
     {
         for(int i = 0; i < descs.GetSize(); i++)
         {
             OptionDesc* desc = (OptionDesc*)descs.GetAt(i);
             CHXString xpath(desc->GetXPath());
             if (!xpath.IsEmpty())
             {
-                xmlPairs->Add(new XmlPair(xpath, CHXString("")));
+                xmlPairs->Add(new XmlPair(xpath, EncodedString()));
             }
         }
     }
 
 private:
     CHXPtrArray descs;
 };
 
 void DisplayUsage(const TCHAR* argv0, OptionRegistry& optionReg)
 {
     const char* pszDbg = "";
 #if defined(DEBUG) || defined(_DEBUG)
     pszDbg = ".debug";
 #endif
 
     CHXString exeName = CHXFileSpecUtils::GetCurrentApplication().GetName();
 
     printf("\n--- %s ---\n    %s\n    Version %s%s\n\n",
             PROGRAM_NAME_STRING, PROGRAM_COPYRIGHT_STRING, TARVER_STRING_VERSION, pszDbg);
     printf("usage: %s [ -option [value]... ]...\n", (const char*)exeName);
     printf("with options:\n");
 
     optionReg.PrintColumns(2);
 }
 
 
 /****************************************************************************
 *  Asynchronous mode helpers
 */
 void SignalAsyncDriveEnd()
@@ -636,74 +630,83 @@
         {
             delete (ID3Tools::APICFrame*)a[i];
         }
         a.RemoveAll();
     }
 
     // meta-data input params
     HXBOOL ClearMetaData;
     HXBOOL ClearKeywords;
     HXBOOL ClearPictures;
     HXBOOL GenerateHash;
     UINT32 InjectedMetaFlavors;
     MetaInfo InjectedMetaInfo;
     CHXPtrArray AddedKeywords; //EncodedString pointers
     CHXPtrArray RemovedKeywords; //EncodedString pointers
     CHXPtrArray AddedPictures; //ID3Tools::APICFrame pointers
     CHXPtrArray RemovedPictures; //Integers
 
     // meta-data output storage
     MetaInfo ExtractedMetaInfo;
     MetaInfo OutboundMetaInfo;
 
 #ifdef HELIX_FEATURE_METAEDIT_AUDIO_HASH
     unsigned char SHAHash[32];
     hash_state HashState;
 #endif
 };
 
 struct InputOption
 {
-    InputOption(const CHXString& optionName, const CHXString& optionValue, const CHXString& xmlOptionValue)
+    InputOption(const CHXString& optionName, const EncodedString& optionValueUTF8, const EncodedString& xmlOptionValueUTF8)
         : OptionName(optionName)
-        , OptionValue(optionValue)
-        , XmlOptionValue(xmlOptionValue)
+        , OptionValueUTF8(optionValueUTF8)
+        , XmlOptionValueUTF8(xmlOptionValueUTF8)
     {
     }
 
-    ~InputOption()
+    // XML value has precedence over command-line value
+    const EncodedString& GetEffectiveOptionValueUTF8() const
     {
+        return XmlOptionValueUTF8.IsEmpty() ? OptionValueUTF8 : XmlOptionValueUTF8;
+    }
+
+    // XML value has precedence over command-line value
+    CHXString GetEffectiveOptionValueCCP() const
+    {
+        const EncodedString& val = GetEffectiveOptionValueUTF8();
+        return CHXString((const char*)CCPFromUTF8(val.GetData()));
     }
 
     CHXString OptionName;
-    CHXString OptionValue;
-    CHXString XmlOptionValue;
+    EncodedString OptionValueUTF8;
+    EncodedString XmlOptionValueUTF8;
 };
 
 /****************************************************************************
 *  Param extractors
 */
 enum eCommandLineProcessorPhase
 {
     CLPP_IndependentOptions = 0,
     CLPP_DependentOptions,
     CLPP_Done
 };
 
 class ArgVars
 {
 public:
     ArgVars(int argc_, TCHAR* argv_[], OptionRegistry& optionReg_)
         : argc(argc_)
         , argv(argv_)
         , argPosition(0)
         , optionReg(optionReg_)
     { }
 
     void ResetPosition(int pos = 1)
     {
         argPosition = pos;
     }
 
     HXBOOL ReachedEndPosition()
     {
         return (argPosition >= argc);
@@ -741,418 +744,410 @@
         return 0;
     }
 
     const TCHAR* CurrentArg(UINT32 offset, HXBOOL bOptional = FALSE)
     {
         int argIndex = argPosition + (int)offset;
         if(argIndex < argc)
         {
             const TCHAR* pVal = argv[argIndex];
             if(pVal && !optionReg.IsOption(pVal))
             {
                 return pVal;
             }
         }
 
         if(!bOptional)
         {
             CHXString strOption = TCHXStringCtor(CurrentOption(TRUE));
             printf("Missing argument for option: %s\n", (const char*)strOption);
         }
         return 0;
     }
 
 private:
     int argc;
     TCHAR** argv;
     int argPosition;
     OptionRegistry& optionReg;
 };
 
-void ReportUnsupportedMetaStyleOptionA(const char* optionName)
-{
-    printf("Option %s not supported in combination with specified metastyle(s)\n", optionName);
-}
-
-void ReportUnsupportedMetaStyleOptionT(const TCHAR* optionName)
-{
-    CHXString strOptionName = TCHXStringCtor(optionName);
-    ReportUnsupportedMetaStyleOptionA((const char*)strOptionName);
-}
-
-void ReportInvalidValueForOptionA(const char* optionName, const char* optionValue)
+void ReportUnsupportedMetaStyleOption(const char* optionName)
 {
-    printf("Invalid value for option %s: %s\n", optionName, optionValue);
+    printf("Option -%s not supported in combination with specified metastyle(s)\n", optionName);
 }
 
-void ReportInvalidValueForOptionT(const TCHAR* optionName, const TCHAR* optionValue)
+void ReportInvalidValueForOption(const char* optionName, const EncodedString& optionValueUTF8)
 {
-    CHXString strOptionName = TCHXStringCtor(optionName);
-    CHXString strOptionValue = TCHXStringCtor(optionValue);
-    ReportInvalidValueForOptionA((const char*)strOptionName, (const char*)strOptionValue);
+    printf("Invalid value for option -%s: ", optionName);
+    EncStrUtils::PrintTextUTF8(optionValueUTF8.GetData());
+    printf("\n");
 }
 
 HX_RESULT ProcessStringOption(bool bSkipArgOnly, InputOption* option, MetaInfo& metainfo,
                              MetaInfo::eStringMetaItem itemName, UINT32 metaFlavorFlags)
 {
-    if (option->OptionValue.IsEmpty() && option->XmlOptionValue.IsEmpty())
+    if(option->OptionValueUTF8.IsEmpty() && option->XmlOptionValueUTF8.IsEmpty())
     {
         return HXR_PARSE_ERROR;
     }
 
     if(bSkipArgOnly)
     {
         return HXR_OK;
     }
 
-    if (option->XmlOptionValue.IsEmpty())
+    if(option->XmlOptionValueUTF8.IsEmpty())
     {
         if(MetaInfo::IsItemSupportedByAnyFlavor(itemName, metaFlavorFlags))
         {
             // options are being read from the command line
-            TUTF8EncodedStringCCPVar(sVal, option->OptionValue);
+            EncodedString sVal = option->OptionValueUTF8;
 
             if(MetaInfo::IsItemValueValidForFlavors(itemName, sVal, metaFlavorFlags) &&
                 SUCCEEDED(metainfo.SetStringItem(itemName, sVal)))
             {
                 return HXR_OK;
             }
 
-            ReportInvalidValueForOptionA(option->OptionName, option->OptionValue);
+            ReportInvalidValueForOption(option->OptionName, option->OptionValueUTF8);
             return HXR_PARSE_ERROR;
         }
 
-        ReportUnsupportedMetaStyleOptionA(option->OptionName);
+        ReportUnsupportedMetaStyleOption(option->OptionName);
         return HXR_PARSE_ERROR;
     }
     else
     {
         // xml options override the command line, however, xml options can not be set using the flavor,
         // so in this case, if the xml option has value which is not valid for flavor, we'll just ignore it.
         if(!MetaInfo::IsItemSupportedByAnyFlavor(itemName, metaFlavorFlags))
         {
             return HXR_OK;
         }
 
-        TUTF8EncodedStringCCPVar(sVal, option->XmlOptionValue);
+        EncodedString sVal = option->XmlOptionValueUTF8;
 
         if(!MetaInfo::IsItemValueValidForFlavors(itemName, sVal, metaFlavorFlags))
         {
             return HXR_OK;
         }
         else 
         {
             if (SUCCEEDED(metainfo.SetStringItem(itemName, sVal)))
             {
                 return HXR_OK;
             }
         }
 
-        ReportInvalidValueForOptionA(option->OptionName, option->XmlOptionValue);
+        ReportInvalidValueForOption(option->OptionName, option->XmlOptionValueUTF8);
         return HXR_PARSE_ERROR;
     }
 }
 
 inline HX_RESULT ProcessDependentStringOption(eCommandLineProcessorPhase phase, InputOption* option,
                              MetaProcessorVars& mpVars, MetaInfo::eStringMetaItem itemName)
 {
     return ProcessStringOption((phase != CLPP_DependentOptions),
                 option, mpVars.InjectedMetaInfo, itemName, mpVars.InjectedMetaFlavors);
 }
 
 HX_RESULT ProcessUIntOption(bool bSkipArgOnly, InputOption* option, MetaInfo& metainfo,
                              MetaInfo::eUIntMetaItem itemName, UINT32 metaFlavorFlags)
 {
-    if (option->OptionValue.IsEmpty() && option->XmlOptionValue.IsEmpty())
+    if(option->OptionValueUTF8.IsEmpty() && option->XmlOptionValueUTF8.IsEmpty())
     {
         return HXR_PARSE_ERROR;
     }
 
     if(bSkipArgOnly)
     {
         return HXR_OK;
     }
 
-    if (option->XmlOptionValue.IsEmpty())
+    if(option->XmlOptionValueUTF8.IsEmpty())
     {
         if(MetaInfo::IsItemSupportedByAnyFlavor(itemName, metaFlavorFlags))
         {
             // options are being read from the command line
-            TUTF8EncodedStringCCPVar(sVal, option->OptionValue);
+            EncodedString sVal = option->OptionValueUTF8;
 
             UINT32 uVal = 0;
             if(PropTools::ExtractUInt32(uVal, sVal))
             {
                 if(MetaInfo::IsItemValueValidForFlavors(itemName, uVal, metaFlavorFlags) &&
                     SUCCEEDED(metainfo.SetUIntItem(itemName, uVal, TRUE)))
                 {
                     return HXR_OK;
                 }
             }
-            ReportInvalidValueForOptionA(option->OptionName, option->OptionValue);
+            ReportInvalidValueForOption(option->OptionName, option->OptionValueUTF8);
             return HXR_PARSE_ERROR;
         }
 
-        ReportUnsupportedMetaStyleOptionA(option->OptionName);
+        ReportUnsupportedMetaStyleOption(option->OptionName);
         return HXR_PARSE_ERROR;
     }
     else
     {
         // xml options override the command line, however, xml options can not be set using the flavor,
         // so in this case, if the xml option has value which is not valid for flavor, we'll just ignore it.
         if(!MetaInfo::IsItemSupportedByAnyFlavor(itemName, metaFlavorFlags))
         {
             return HXR_OK;
         }
 
-        TUTF8EncodedStringCCPVar(sVal, option->XmlOptionValue);
+        EncodedString sVal = option->XmlOptionValueUTF8;
 
         UINT32 uVal = 0;
         if(PropTools::ExtractUInt32(uVal, sVal))
         {
             if(!MetaInfo::IsItemValueValidForFlavors(itemName, uVal, metaFlavorFlags))
             {
                 return HXR_OK;
             }
             else 
             {
                 if (SUCCEEDED(metainfo.SetUIntItem(itemName, uVal, TRUE)))
                 {
                     return HXR_OK;
                 }
             }
         }
 
-        ReportInvalidValueForOptionA(option->OptionName, option->XmlOptionValue);
+        ReportInvalidValueForOption(option->OptionName, option->XmlOptionValueUTF8);
         return HXR_PARSE_ERROR;
     }
 }
 
 inline HX_RESULT ProcessDependentUIntOption(eCommandLineProcessorPhase phase, InputOption* option,
                              MetaProcessorVars& mpVars, MetaInfo::eUIntMetaItem itemName)
 {
     return ProcessUIntOption((phase != CLPP_DependentOptions),
                 option, mpVars.InjectedMetaInfo, itemName, mpVars.InjectedMetaFlavors);
 }
 
 HX_RESULT ProcessKeywordStringOption(bool bSkipArgOnly, InputOption* option,
                                     CHXPtrArray& aKeywords, UINT32 metaFlavorFlags)
 {
-    if(option->OptionValue.IsEmpty())
+    if(option->OptionValueUTF8.IsEmpty())
     {
         return HXR_PARSE_ERROR;
     }
 
     if(bSkipArgOnly)
     {
         return HXR_OK;
     }
 
     if(MetaInfo::IsItemSupportedByAnyFlavor(MetaInfo::ArrayMetaItem_Keywords, metaFlavorFlags))
     {
-        EncodedString* pEncStr = new TUTF8EncodedStringCCPCtor(option->OptionValue);
+        EncodedString* pEncStr = new EncodedString(option->OptionValueUTF8);
 
         if(pEncStr && MetaInfo::IsKeywordValidForFlavors(*pEncStr, metaFlavorFlags))
         {
             aKeywords.Add(pEncStr);
             return HXR_OK;
         }
 
         delete pEncStr;
 
-        ReportInvalidValueForOptionA(option->OptionName, option->OptionValue);
+        ReportInvalidValueForOption(option->OptionName, option->OptionValueUTF8);
         return HXR_PARSE_ERROR;
     }
 
-    ReportUnsupportedMetaStyleOptionA(option->OptionName);
+    ReportUnsupportedMetaStyleOption(option->OptionName);
     return HXR_PARSE_ERROR;
 }
 
 inline HX_RESULT ProcessDependentKeywordStringOption(eCommandLineProcessorPhase phase, InputOption* option,
                                     CHXPtrArray& aKeywords, UINT32 metaFlavorFlags)
 {
     return ProcessKeywordStringOption((phase != CLPP_DependentOptions),
                 option, aKeywords, metaFlavorFlags);
 }
 
 HX_RESULT ProcessXMLFileStringOption(bool bSkipArgOnly, InputOption* option, MetaInfo& metainfo,
                                     MetaInfo::eStringMetaItem itemName, UINT32 metaFlavorFlags)
 {
-    if(option->OptionValue.IsEmpty())
+    if(option->OptionValueUTF8.IsEmpty())
     {
         return HXR_PARSE_ERROR;
     }
 
     if(bSkipArgOnly)
     {
         return HXR_OK;
     }
 
     if(MetaInfo::IsItemSupportedByAnyFlavor(itemName, metaFlavorFlags))
     {
         // read-in the file contents
-        CHXString sFileName = option->OptionValue;
+        CHXString sFileName = option->GetEffectiveOptionValueCCP();
         if(!sFileName.IsEmpty())
         {
             EncodedString sXML;
             HX_RESULT retVal = MetaInfo::LoadXMLStringFromFile((const char*)sFileName, sXML);
 
             if(SUCCEEDED(retVal) &&
                MetaInfo::IsItemValueValidForFlavors(itemName, sXML, metaFlavorFlags) &&
                SUCCEEDED(metainfo.SetStringItem(itemName, sXML)))
             {
                 return HXR_OK;
             }
         }
 
-        ReportInvalidValueForOptionA(option->OptionName, option->OptionValue);
+        ReportInvalidValueForOption(option->OptionName, option->OptionValueUTF8);
         return HXR_PARSE_ERROR;
     }
 
-    ReportUnsupportedMetaStyleOptionA(option->OptionName);
+    ReportUnsupportedMetaStyleOption(option->OptionName);
     return HXR_PARSE_ERROR;
 }
 
 HX_RESULT ProcessRemovePictureOption(bool bSkipArgOnly, InputOption* option,
                                 CHXPtrArray& aRemovedPictureTypes, UINT32 metaFlavorFlags)
 {
-    if(option->OptionValue.IsEmpty())
+    if(option->OptionValueUTF8.IsEmpty())
     {
         return HXR_PARSE_ERROR;
     }
 
     if(bSkipArgOnly)
     {
         return HXR_OK;
     }
 
     if(MetaInfo::IsItemSupportedByAnyFlavor(MetaInfo::ArrayMetaItem_Pictures, metaFlavorFlags))
     {
-        TUTF8EncodedStringCCPVar(sVal, option->OptionValue);
+        EncodedString sVal = option->OptionValueUTF8;
 
         UINT32 uVal = 0;
         if(PropTools::ExtractUInt32(uVal, sVal) &&
            MetaInfo::IsAPICPictureTypeValidForFlavors(uVal, metaFlavorFlags))
         {
             aRemovedPictureTypes.AddIfUnique((void*)uVal);
             return HXR_OK;
         }
 
-        ReportInvalidValueForOptionA(option->OptionName, option->OptionValue);
+        ReportInvalidValueForOption(option->OptionName, option->OptionValueUTF8);
         return HXR_PARSE_ERROR;
     }
 
-    ReportUnsupportedMetaStyleOptionA(option->OptionName);
+    ReportUnsupportedMetaStyleOption(option->OptionName);
     return HXR_PARSE_ERROR;
 }
 
 HX_RESULT ProcessAddPictureOption(bool bSkipArgOnly, InputOption* option,
                                 CHXPtrArray& aAddedAPICFrames, UINT32 metaFlavorFlags)
 {
-    if(option->OptionValue.IsEmpty())
+    if(option->OptionValueUTF8.IsEmpty())
     {
         return HXR_PARSE_ERROR;
     }
 
     if(bSkipArgOnly)
     {
         return HXR_OK;
     }
 
     if(MetaInfo::IsItemSupportedByAnyFlavor(MetaInfo::ArrayMetaItem_Pictures, metaFlavorFlags))
     {
         ID3Tools::APICFrame* pFrame = new ID3Tools::APICFrame;
         if(!pFrame)
         {
             return HXR_OUTOFMEMORY;
         }
 
         // process image file
         HX_RESULT retVal = HXR_FAILED;
 
-        CHXString sFileName = option->OptionValue;
+        CHXString sFileName = option->GetEffectiveOptionValueCCP();
         if(!sFileName.IsEmpty())
         {
             // load image, accept only known MIME types
             retVal = pFrame->LoadPictureDataFromImageFile((const char*)sFileName, TRUE);
 
             // check if frame is acceptable
             if(SUCCEEDED(retVal))
             {
                 if(!MetaInfo::IsAPICFrameValidForFlavors(*pFrame, metaFlavorFlags))
                 {
                     retVal = HXR_FAILED;
                 }
             }
         }
 
         if(FAILED(retVal))
         {
             printf("Invalid image file for option %s: %s\n",
                     (const char*)option->OptionName, (const char*)sFileName);
         }
 
         // export frame
         if(SUCCEEDED(retVal) && pFrame)
         {
             if(!aAddedAPICFrames.AddIfUnique(pFrame))
             {
                 retVal = HXR_FAILED;
             }
         }
 
         if(FAILED(retVal))
         {
             // cleanup
             HX_DELETE(pFrame);
         }
 
         return retVal;
     }
 
-    ReportUnsupportedMetaStyleOptionA(option->OptionName);
+    ReportUnsupportedMetaStyleOption(option->OptionName);
     return HXR_PARSE_ERROR;
 }
 
-// Caller is responsible for result deallocation
-HX_RESULT CopyCCPStringOption(ArgVars& argVars, CHXString& sOut, HXBOOL bOptional = FALSE)
+HX_RESULT CopyOptionArgumentString(ArgVars& argVars, EncodedString& sOut, HXBOOL bOptional = FALSE)
 {
-    const TCHAR* pVal = argVars.CurrentArg(1, bOptional);
+    sOut.Clear();
 
-    sOut = TCHXStringCtor(pVal);
+    const TCHAR* pVal = argVars.CurrentArg(1, bOptional);
+    if(!pVal && !bOptional)
+    {
+        return HXR_PARSE_ERROR;
+    }
 
+    sOut = TUTF8EncodedStringCtor(pVal);
     argVars.MovePosition(1);
 
     return HXR_OK;
 }
 
-
 HXBOOL NeedOverwriteConfirmation(const char* pFileName, HXBOOL bOverwriteFile)
 {
     HXBOOL bNeedConfirmation = FALSE;
     if(pFileName)
     {
         if(CHXFileSpecUtils::FileExists(CHXFileSpecifier(pFileName)))
         {
             if(!bOverwriteFile)
             {
                 bNeedConfirmation = TRUE;
                 printf("Output file [%s] already exists. Use -%s option to force overwrite.\n",
                         pFileName, OPTION_STRING_OVERWRITEFILE);
             }
         }
     }
     return bNeedConfirmation;
 }
 
 
 /****************************************************************************
 *  Meta-data processor
 */
 class CProcessor : public IHXMetaDataProcessor
 {
 public:
     CProcessor(MetaProcessorVars& vars)
         : m_lRefCount(0)
         , m_vars(vars)
         , m_pContext(0)
     {
@@ -1373,181 +1368,187 @@
     {
         for(int i = 0; i < options.GetSize(); i++)
         {
             InputOption* option = (InputOption*)options.GetAt(i);
 
             if (option->OptionName == optionName)
             {
                 return option;
             }
         }
 
         return 0;
     }
 
     // Returns pointer to option
     InputOption* CurrentOption() const
     {
         if(position < options.GetSize())
         {
             return (InputOption*)options.GetAt(position);
         }
 
         return 0;
     }
 
 private:
     CHXPtrArray options;
     int position;
 };
 
-HX_RESULT ParseCCPInputOptions(ArgVars& argVars, OptionRegistry& optionReg, InputOptions& inputOptions)
+HX_RESULT ParseCommandLineInputOptions(ArgVars& argVars, OptionRegistry& optionReg, InputOptions& inputOptions)
 {
     HX_RESULT retVal = HXR_OK;
 
     for(argVars.ResetPosition(1); SUCCEEDED(retVal) && !argVars.ReachedEndPosition(); argVars.MovePosition(1))
     {
         // accept option format only
         CHXString strOption = TCHXStringCtor(argVars.CurrentOption(FALSE));
 
         if(strOption.IsEmpty())
         {
             printf("Found non-option command-line argument: %s\n",
                             (const char*)TCHXStringCtor(argVars.CurrentRawArg()));
             retVal = HXR_PARSE_ERROR;
             continue;
         }
 
-        // if option exists within options (optionRegs) in argVars
+        // check if we're looking at known option
         OptionDesc* od = optionReg.GetOptionDesc(strOption);
         if (od == NULL)
         {
             printf("Unrecognized option: -%s\n", (const char*)strOption);
             retVal = HXR_PARSE_ERROR;
             continue;
         }
 
+        EncodedString optionArgument;
+
         // get the option value and store it into inputOptions
-        if (od->GetNumberOfOptions() == 0)
-        {
-            // no parameters
-            inputOptions.Add(new InputOption(strOption, CHXString(""), CHXString("")));
-        }
-        else
+        switch(od->GetNumberOfOptions())
         {
-            CHXString optionArgument("");
-            if (od->GetNumberOfOptions() == -1)
+            case -1:
             {
                 // zero or one parameter
-                retVal = CopyCCPStringOption(argVars, optionArgument, TRUE);
+                retVal = CopyOptionArgumentString(argVars, optionArgument, TRUE);
+                break;
             }
-            else if (od->GetNumberOfOptions() == 1)
+
+            case 0:
+                // no parameters
+                break;
+
+            case 1:
             {
                 // one parameter
-                retVal = CopyCCPStringOption(argVars, optionArgument);
+                retVal = CopyOptionArgumentString(argVars, optionArgument, FALSE);
+                break;
             }
-            inputOptions.Add(new InputOption(strOption, optionArgument, CHXString("")));
+
+            default:
+                // unsupported number of option arguments
+                retVal = HXR_PARSE_ERROR;
+                break;
         }
 
+        if(SUCCEEDED(retVal))
+        {
+            inputOptions.Add(new InputOption(strOption, optionArgument, EncodedString()));
+        }
     }
 
     return retVal;
 }
 
 HX_RESULT ParseXMLInputOptions(IHXCommonClassFactory* pCommonClassFactory, CHXXmlInputParser* pInputParser, 
                                InputOption* option, CParsedXmlPairs* parsedXmlResults)
 {
-    if(option->OptionValue.IsEmpty())
+    if(option->OptionValueUTF8.IsEmpty())
     {
         return HXR_FAIL;
     }
 
-    FILE* fp = fopen(option->OptionValue, "r");
+    FILE* fp = fopen((const char*)option->GetEffectiveOptionValueCCP(), "r");
     if(fp == NULL)
     {
-        printf("Unable to open file: %s\n", (const char*)option->OptionValue);
+        printf("Unable to open file: %s\n", (const char*)option->GetEffectiveOptionValueCCP());
         return HXR_FAIL;
     }
 
     HX_RESULT retVal = HXR_OK;
     retVal = pInputParser->Start(parsedXmlResults);
 
     ULONG32 uParserBufferSize = 64 * 1024;
 
     if(SUCCEEDED(retVal))
     {
         // create temporary buffer for manifest chunks
         IHXBuffer* pBuffer = NULL;
         retVal = CreateBufferCCF(pBuffer, pCommonClassFactory);
         if(SUCCEEDED(retVal))
         {
             pBuffer->SetSize(uParserBufferSize);
 
             // read manifest, chunk by chunk
             while(true)
             {
                 size_t nItemsRead = fread(pBuffer->GetBuffer(), 1, uParserBufferSize, fp);
                 if(nItemsRead != 0)
                 {
                     if(uParserBufferSize != nItemsRead)
                     {
                         pBuffer->SetSize(nItemsRead);
                     }
 
                     // parse chunk
                     HXBOOL bIsFinal = uParserBufferSize != nItemsRead;
                     retVal = pInputParser->Parse(pBuffer, bIsFinal);
                     if(!SUCCEEDED(retVal))
                     {
                         break;
                     }
                 }
                 if(nItemsRead < uParserBufferSize)
                 {
                     break;
                 }
             }
         }
     }
 
 
     if (SUCCEEDED(retVal))
     {
         // retrieve manifest
         retVal = pInputParser->EndParse();
     }
 
-    if (SUCCEEDED(retVal))
-    {
-        parsedXmlResults->Dump();
-    }
-
     fclose(fp);
 
     return retVal;
 }
 
 /****************************************************************************
 *  Main entry point
 */
 int TMAIN(int argc, TCHAR* argv[])
 {
     // separate shell command from output
     printf("\n");
 
     // initialize variables
     CHXFileSpecifier exeFileSpec;
     UINT32 startTime = 0;
     
     DLLAccess* pDLLAccess = 0;
     FPHXMEDIAPLATFORMOPEN fpHXMediaPlatformOpen = 0;
     FPHXCREATEMEDIAPLATFORM fpHXCreateMediaPlatform = 0;
     FPHXMEDIAPLATFORMCLOSE fpHXMediaPlatformClose = 0;
 
     IHXMediaPlatform* pMediaPlatform = 0;
     IHXCommonClassFactory* pCommonClassFactory = 0;
     IHXMetaDataEditor* pEditor = 0;
     CResponse* pResponse = 0;
     CProcessor* pProcessor = 0;
     IHXValues* pOptions = 0;
 
     char pDllPath[_MAX_PATH] = {0};
@@ -1765,181 +1766,191 @@
     optionReg.Add(new OptionDesc(OPTION_STRING_DISKNUMBER, "<integer>", "update iTunes disc number", 1, "/albums/album/track/discNumber"));
     optionReg.Add(new OptionDesc(OPTION_STRING_DISKSTOTAL, "<integer>", "update iTunes disc count", 1, "/albums/album/discCount"));
     optionReg.Add(new OptionDesc());
     optionReg.Add(new OptionDesc(OPTION_STRING_RATING_ENTITY, "<4 character code>", "update 3GPP rating entity", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_RATING_CRITERIA, "<4 character code>", "update 3GPP rating criteria", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_RATING_INFO, "<string>", "update 3GPP rating info", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_CLASSIFICATION_ENTITY, "<4 character code>", "update 3GPP classification entity", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_CLASSIFICATION_TABLE, "<integer 0..65535>", "update 3GPP classification table", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_CLASSIFICATION_INFO, "<string>", "update 3GPP classification info", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_KEYWORD_ADD, "<string>", "add 3GPP keyword", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_KEYWORD_REMOVE, "<string>", "remove 3GPP keyword", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_KEYWORD_CLEAR, 0, "clear all extracted 3GPP keywords", 0));
     optionReg.Add(new OptionDesc(OPTION_STRING_LOCATION_NAME, "<string>", "update 3GPP location name", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_LOCATION_ASTRONOMICAL_BODY, "<string>", "update 3GPP location astronomical body", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_LOCATION_ADDITIONAL_NOTES, "<string>", "update 3GPP location notes", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_LOCATION_ROLE, "<integer 0..255>", "update 3GPP location role", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_LOCATION_LONGITUDE, "<decimal number>", "update 3GPP location longitude", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_LOCATION_LATITUDE, "<decimal number>", "update 3GPP location latitude", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_LOCATION_ALTITUDE, "<decimal number>", "update 3GPP location altitude", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_LANGUAGE_CODE, "<3 character code>", "ISO639.2/T language code of 3GPP metadata text", 1));
     optionReg.Add(new OptionDesc());
     
 #ifdef _WINDOWS
     optionReg.Add(new OptionDesc(OPTION_STRING_ASYNCMODE, 0, "dtdriver async mode (developer option)", 0));
 #endif //_WINDOWS
 
     optionReg.Add(new OptionDesc(OPTION_STRING_DEFMETAPROC, 0, "default meta processor (developer option)", 0));
     optionReg.Add(new OptionDesc(OPTION_STRING_HELP, 0, "display help text", 0));
     
     {
-        // parse command line parameters
+        // parse command line
         ArgVars argVars(argc, argv, optionReg);
-        retVal = ParseCCPInputOptions(argVars, optionReg, inputOptions);
+        retVal = ParseCommandLineInputOptions(argVars, optionReg, inputOptions);
 
         if (SUCCEEDED(retVal))
         {
             InputOption* optionXmlIn = inputOptions.GetOption(CHXString(OPTION_STRING_XMLINPUTFILE));
-            if (optionXmlIn && !optionXmlIn->OptionValue.IsEmpty())
+            if(optionXmlIn && !optionXmlIn->OptionValueUTF8.IsEmpty())
             {
                 // parse xml input file
+                if(SUCCEEDED(retVal))
+                {
+                    printf("Processing XML input file:\n");
+                }
+
                 CParsedXmlPairs parsedXmlResults;
                 optionReg.InitializeXmlPairs(&parsedXmlResults);
 
                 retVal = ParseXMLInputOptions(pCommonClassFactory, pInputParser, optionXmlIn, &parsedXmlResults);
 
                 if (SUCCEEDED(retVal))
                 {
                     // merge parsed results into inputOptions
                     CHXPtrArray *xmlPairs = parsedXmlResults.GetAllPairs();
                     for(int i = 0; i < xmlPairs->GetSize(); i++)
                     {
                         XmlPair *pair = (XmlPair*)xmlPairs->GetAt(i);
                         OptionDesc* optDesc = optionReg.GetOptionDescWithPath(pair->xmlPath);
 
-                        if (optDesc!=NULL && !pair->xmlValue.IsEmpty()) // we'll add them only if there exist not null element in results of parsing xml
+                        // Add only results of XML file parsing which have non-empty value.
+                        if((optDesc != NULL) && !pair->xmlValueUTF8.IsEmpty())
                         {
                             CHXString strName = optDesc->GetOptionString();
                             InputOption* inOpt = inputOptions.GetOption(strName);
+
                             if (inOpt==NULL)
                             {
-                                inputOptions.Add(new InputOption(strName, CHXString(""), pair->xmlValue));
+                                inputOptions.Add(new InputOption(strName, EncodedString(), pair->xmlValueUTF8));
                             }
                             else
                             {
-                                printf("Xml parameter is overriding input parameter: %s.\n",(const char *)strName );
-                                inOpt->XmlOptionValue = pair->xmlValue;
+                                inOpt->XmlOptionValueUTF8 = pair->xmlValueUTF8;
                             }
+
+                            printf("-%s taken from location [%s], value=[", (const char*)strName, (const char*)pair->xmlPath);
+                            EncStrUtils::PrintTextUTF8(pair->xmlValueUTF8.GetData());
+                            printf("]\n");
                         }
                     }
+
+                    printf("\n");
                 }
             }
         }
     }
 
-
     // The first phase seeks for independent arguments, the second phase seeks for dependent arguments.
     clpp = CLPP_IndependentOptions;
 
     while(SUCCEEDED(retVal) && (clpp != CLPP_Done))
     {
         for(inputOptions.ResetPosition(0); SUCCEEDED(retVal) && !inputOptions.ReachedEndPosition(); 
                 inputOptions.MovePosition(1))
         {
             InputOption* option = inputOptions.CurrentOption();
             CHXString strOption = option->OptionName;
-            CHXString strOptionValue = option->XmlOptionValue.IsEmpty()? option->OptionValue : option->XmlOptionValue;
 
             if(strOption == OPTION_STRING_HELP)
             {
                 bDisplayHelp = TRUE;
             }
 
 #ifdef _WINDOWS
             else if(strOption == OPTION_STRING_ASYNCMODE)
             {
                 g_bUseDTDriverSynchronousMode = FALSE;
             }
 #endif //_WINDOWS
 
             else if(strOption == OPTION_STRING_DEFMETAPROC)
             {
                 g_bUseDefaultMetaEditorProcessor = TRUE;
             }
             else if(strOption == OPTION_STRING_INPUTFILE)
             {
-                strInputFileName = strOptionValue;
+                strInputFileName = option->GetEffectiveOptionValueCCP();
             }
             else if(strOption == OPTION_STRING_OUTPUTFILE)
             {
-                strOutputFileName = strOptionValue;
+                strOutputFileName = option->GetEffectiveOptionValueCCP();
             }
             else if(strOption == OPTION_STRING_OVERWRITEFILE)
             {
                 bOverwriteFile = TRUE;
             }
             else if(strOption == OPTION_STRING_CLEARMETADATA)
             {
                 metaProcessorVars.ClearMetaData = TRUE;
             }
             else if(strOption == OPTION_STRING_PRINTMETADATA)
             {
                 bPrintMetaData = TRUE;
             }
             else if(strOption == OPTION_STRING_GENERATEHASH)
             {
                 metaProcessorVars.GenerateHash = TRUE;
             }
             else if(strOption == OPTION_STRING_XMLINPUTFILE)
             {
                 // do nothing, since it was already done what needs to be done
             }
             else if(strOption == OPTION_STRING_METASTYLE)
             {
-                strMetaStyleName = strOptionValue;
+                strMetaStyleName = option->GetEffectiveOptionValueCCP();
 
                 if(clpp == CLPP_IndependentOptions)
                 {
                     if(SUCCEEDED(retVal) && !strMetaStyleName.IsEmpty())
                     {
                         if(!strMetaStyleName.CompareNoCase("3gpp"))
                         {
                             metaProcessorVars.InjectedMetaFlavors |= METADATA_FLAVOR_3GPP;
                         }
                         else if(!strMetaStyleName.CompareNoCase("itunes"))
                         {
                             metaProcessorVars.InjectedMetaFlavors |= METADATA_FLAVOR_ITUNES;
                         }
                         else
                         {
                             retVal = HXR_PARSE_ERROR;
-                            ReportInvalidValueForOptionA(OPTION_STRING_METASTYLE, (const char*)strMetaStyleName);
+                            ReportInvalidValueForOption(OPTION_STRING_METASTYLE, option->GetEffectiveOptionValueUTF8());
                         }
                     }
                 }
             }
             else if(strOption == OPTION_STRING_UTF16OUTPUT)
             {
                 bUTF16Output = TRUE;
             }
             else if(strOption == OPTION_STRING_ID3V240OUTPUT)
             {
                 ulMetaDataID3VersionOutput = METADATAID3VERSION_240;
             }
             else if(strOption == OPTION_STRING_ID3V230OUTPUT)
             {
                 ulMetaDataID3VersionOutput = METADATAID3VERSION_230;
             }
             else if(strOption == OPTION_STRING_ID3V2NOOUTPUT)
             {
                 ulMetaDataID3VersionOutput = METADATAID3VERSION_NONE;
             }
             else if(strOption == OPTION_STRING_TITLE)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_Title);
             }
             else if(strOption == OPTION_STRING_ARTIST)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_Artist);
             }
@@ -1968,78 +1979,78 @@
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_Copyright);
             }
             else if(strOption == OPTION_STRING_TRACKNUMBER)
             {
                 retVal = ProcessDependentUIntOption(clpp, option,
                                     metaProcessorVars, MetaInfo::UIntMetaItem_TrackNumber);
             }
             else if(strOption == OPTION_STRING_YEAR)
             {
                 retVal = ProcessDependentUIntOption(clpp, option,
                                     metaProcessorVars, MetaInfo::UIntMetaItem_RecordingYear);
             }
             else if(strOption == OPTION_STRING_PICTURE_ADD)
             {
                 retVal = ProcessAddPictureOption((clpp != CLPP_DependentOptions),
                                     option, metaProcessorVars.AddedPictures, metaProcessorVars.InjectedMetaFlavors);
             }
             else if(strOption == OPTION_STRING_PICTURE_REMOVE)
             {
                 retVal = ProcessRemovePictureOption((clpp != CLPP_DependentOptions),
                                     option, metaProcessorVars.RemovedPictures, metaProcessorVars.InjectedMetaFlavors);
             }
             else if(strOption == OPTION_STRING_PICTURE_CLEAR)
             {
                 metaProcessorVars.ClearPictures = TRUE;
 
                 if((clpp == CLPP_DependentOptions) &&
                     !MetaInfo::IsItemSupportedByAnyFlavor(MetaInfo::ArrayMetaItem_Pictures, metaProcessorVars.InjectedMetaFlavors))
                 {
-                    ReportUnsupportedMetaStyleOptionA(OPTION_STRING_PICTURE_CLEAR);
+                    ReportUnsupportedMetaStyleOption(OPTION_STRING_PICTURE_CLEAR);
                     retVal = HXR_PARSE_ERROR;
                 }
             }
             else if(strOption == OPTION_STRING_PICTURE_EXTRACT)
             {
                 bExtractPicturesToFiles = TRUE;
-                strPictureFileNamePrefix = strOptionValue;
+                strPictureFileNamePrefix = option->GetEffectiveOptionValueCCP();
             }
             else if(strOption == OPTION_STRING_UITS_INSERT)
             {
                 retVal = ProcessXMLFileStringOption((clpp != CLPP_DependentOptions),
                                 option, metaProcessorVars.InjectedMetaInfo, MetaInfo::StringMetaItem_UITSData,
                                 metaProcessorVars.InjectedMetaFlavors);
             }
             else if(strOption == OPTION_STRING_UITS_EXTRACT)
             {
-                strUITSDataOutputFileName = strOptionValue;
+                strUITSDataOutputFileName = option->GetEffectiveOptionValueCCP();
             }
             else if(strOption == OPTION_STRING_SOFTWARE)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_GeneratorTool);
             }
             else if(strOption == OPTION_STRING_ENCODEDBY)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_EncodedBy);
             }
             else if(strOption == OPTION_STRING_GROUPING)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_Grouping);
             }
             else if(strOption == OPTION_STRING_ALBUMARTIST)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_AlbumArtist);
             }
             else if(strOption == OPTION_STRING_LYRICS)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_Lyrics);
             }
             else if(strOption == OPTION_STRING_SUBTITLE)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_TrackSubtitle);
@@ -2134,61 +2145,61 @@
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_LocationLongitude);
             }
             else if(strOption == OPTION_STRING_LOCATION_LATITUDE)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_LocationLatitude);
             }
             else if(strOption == OPTION_STRING_LOCATION_ALTITUDE)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_LocationAltitude);
             }
             else if(strOption == OPTION_STRING_KEYWORD_ADD)
             {
                 retVal = ProcessDependentKeywordStringOption(clpp, option,
                                     metaProcessorVars.AddedKeywords, metaProcessorVars.InjectedMetaFlavors);
             }
             else if(strOption == OPTION_STRING_KEYWORD_REMOVE)
             {
                 retVal = ProcessDependentKeywordStringOption(clpp, option,
                                     metaProcessorVars.RemovedKeywords, metaProcessorVars.InjectedMetaFlavors);
             }
             else if(strOption == OPTION_STRING_KEYWORD_CLEAR)
             {
                 metaProcessorVars.ClearKeywords = TRUE;
 
                 if((clpp == CLPP_DependentOptions) &&
                     !MetaInfo::IsItemSupportedByAnyFlavor(MetaInfo::ArrayMetaItem_Keywords, metaProcessorVars.InjectedMetaFlavors))
                 {
-                    ReportUnsupportedMetaStyleOptionA(OPTION_STRING_KEYWORD_CLEAR);
+                    ReportUnsupportedMetaStyleOption(OPTION_STRING_KEYWORD_CLEAR);
                     retVal = HXR_PARSE_ERROR;
                 }
             }
             else
             {
                 printf("Unrecognized option: -%s\n", (const char*)strOption);
                 retVal = HXR_PARSE_ERROR;
             }
         }
 
         // update metastyles
         if(clpp == CLPP_IndependentOptions)
         {
             // unless metastyles are explicitly specified, assume defaults according to file extension
             if((metaProcessorVars.InjectedMetaFlavors == 0) && !strOutputFileName.IsEmpty())
             {
                 CHXString sFileExt = "";
                 INT32 dotPos = strOutputFileName.ReverseFind('.');
 
                 if(dotPos >= 0)
                 {
                     UINT32 extLen = strOutputFileName.GetLength() - dotPos - 1;
                     if(extLen > 0)
                     {
                         sFileExt = strOutputFileName.Right(extLen);
                     }
                 }
 
                 if(!sFileExt.CompareNoCase("3gp"))
                 {