Index: /trunk/src/VBox/Main/include/GuestSessionImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/GuestSessionImpl.h	(revision 72069)
+++ /trunk/src/VBox/Main/include/GuestSessionImpl.h	(revision 72070)
@@ -267,5 +267,5 @@
                                           ComPtr<IProgress> &pProgress);
     int                     i_closeSession(uint32_t uFlags, uint32_t uTimeoutMS, int *pGuestRc);
-    static int              i_directoryCopyFlagFromStr(const com::Utf8Str &strFlags, DirectoryCopyFlag_T *pfFlags);
+    HRESULT                 i_directoryCopyFlagFromStr(const com::Utf8Str &strFlags, DirectoryCopyFlag_T *pfFlags);
     inline bool             i_directoryExists(uint32_t uDirID, ComObjPtr<GuestDirectory> *pDir);
     int                     i_directoryUnregister(GuestDirectory *pDirectory);
@@ -277,5 +277,5 @@
     int                     i_dispatchToObject(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
     int                     i_dispatchToThis(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
-    static int              i_fileCopyFlagFromStr(const com::Utf8Str &strFlags, FileCopyFlag_T *pfFlags);
+    HRESULT                 i_fileCopyFlagFromStr(const com::Utf8Str &strFlags, FileCopyFlag_T *pfFlags);
     inline bool             i_fileExists(uint32_t uFileID, ComObjPtr<GuestFile> *pFile);
     int                     i_fileUnregister(GuestFile *pFile);
Index: /trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp	(revision 72069)
+++ /trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp	(revision 72070)
@@ -42,4 +42,5 @@
 
 #include <iprt/cpp/utils.h> /* For unconst(). */
+#include <iprt/ctype.h>
 #include <iprt/env.h>
 #include <iprt/file.h> /* For CopyTo/From. */
@@ -871,56 +872,46 @@
  * Validates and extracts directory copy flags from a comma-separated string.
  *
- * @return VBox status code.
+ * @return COM status, error set on failure
  * @param  strFlags             String to extract flags from.
  * @param  pfFlags              Where to store the extracted (and validated) flags.
  */
-/* static */
-int GuestSession::i_directoryCopyFlagFromStr(const com::Utf8Str &strFlags, DirectoryCopyFlag_T *pfFlags)
-{
-    DirectoryCopyFlag_T fFlags = DirectoryCopyFlag_None;
+HRESULT GuestSession::i_directoryCopyFlagFromStr(const com::Utf8Str &strFlags, DirectoryCopyFlag_T *pfFlags)
+{
+    unsigned fFlags = DirectoryCopyFlag_None;
 
     /* Validate and set flags. */
-    if (strFlags.isEmpty())
-    {
-        *pfFlags = fFlags;
-        return VINF_SUCCESS;
-    }
-
-    const char *pcszNext = strFlags.c_str();
-    while (*pcszNext != '\0')
-    {
-        Utf8Str strFlag;
-        const char *pcszComma = RTStrStr(pcszNext, ",");
-        if (!pcszComma)
-            strFlag = pcszNext;
-        else
-            strFlag = Utf8Str(pcszNext, pcszComma - pcszNext);
-
-        const char *pcszEqual = RTStrStr(strFlag.c_str(), "=");
-        if (   pcszEqual
-            && pcszEqual != strFlag.c_str())
-        {
-            Utf8Str strKey(strFlag.c_str(), pcszEqual - strFlag.c_str());
-            Utf8Str strValue(strFlag.c_str() + (pcszEqual - strFlag.c_str() + 1));
-            RT_NOREF(strKey, strValue); /* We don't have any key=value pairs yet. */
-        }
-        else
-        {
-           if (strFlag == "CopyIntoExisting")
-               fFlags |= DirectoryCopyFlag_CopyIntoExisting;
-           else
-               return VERR_INVALID_PARAMETER;
-        }
-
-        if (!pcszComma)
-            pcszNext += strFlag.length();
-        else
-            pcszNext += strFlag.length() + 1;
+    if (strFlags.isNotEmpty())
+    {
+        const char *pszNext = strFlags.c_str();
+        for (;;)
+        {
+            /* Find the next keyword, ignoring all whitespace. */
+            pszNext = RTStrStripL(pszNext);
+
+            const char * const pszComma = strchr(pszNext, ',');
+            size_t cchKeyword = pszComma ? pszComma - pszNext : strlen(pszComma);
+            while (cchKeyword > 0 && RT_C_IS_SPACE(pszNext[cchKeyword - 1]))
+                cchKeyword--;
+
+            if (cchKeyword > 0)
+            {
+                /* Convert keyword to flag. */
+#define MATCH_KEYWORD(a_szKeyword) (   cchKeyword == sizeof(a_szKeyword) - 1U \
+                                    && memcmp(pszNext, a_szKeyword, sizeof(a_szKeyword) - 1U) == 0)
+                if (MATCH_KEYWORD("CopyIntoExisting"))
+                    fFlags |= (unsigned)DirectoryCopyFlag_CopyIntoExisting;
+                else
+                    return setError(E_INVALIDARG, tr("Invalid directory copy flag: %.*s"), (int)cchKeyword, pszNext);
+#undef MATCH_KEYWORD
+            }
+            if (!pszComma)
+                break;
+            pszNext = pszComma + 1;
+        }
     }
 
     if (pfFlags)
-        *pfFlags = fFlags;
-
-    return VINF_SUCCESS;
+        *pfFlags = (DirectoryCopyFlag_T)fFlags;
+    return S_OK;
 }
 
@@ -1348,60 +1339,50 @@
  * Validates and extracts file copy flags from a comma-separated string.
  *
- * @return VBox status code.
+ * @return COM status, error set on failure
  * @param  strFlags             String to extract flags from.
  * @param  pfFlags              Where to store the extracted (and validated) flags.
  */
-/* static */
-int GuestSession::i_fileCopyFlagFromStr(const com::Utf8Str &strFlags, FileCopyFlag_T *pfFlags)
-{
-    FileCopyFlag_T fFlags = FileCopyFlag_None;
+HRESULT GuestSession::i_fileCopyFlagFromStr(const com::Utf8Str &strFlags, FileCopyFlag_T *pfFlags)
+{
+    unsigned fFlags = (unsigned)FileCopyFlag_None;
 
     /* Validate and set flags. */
-    if (strFlags.isEmpty())
-    {
-        *pfFlags = fFlags;
-        return VINF_SUCCESS;
-    }
-
-    const char *pcszNext = strFlags.c_str();
-    while (*pcszNext != '\0')
-    {
-        Utf8Str strFlag;
-        const char *pcszComma = RTStrStr(pcszNext, ",");
-        if (!pcszComma)
-            strFlag = pcszNext;
-        else
-            strFlag = Utf8Str(pcszNext, pcszComma - pcszNext);
-
-        const char *pcszEqual = RTStrStr(strFlag.c_str(), "=");
-        if (   pcszEqual
-            && pcszEqual != strFlag.c_str())
-        {
-            Utf8Str strKey(strFlag.c_str(), pcszEqual - strFlag.c_str());
-            Utf8Str strValue(strFlag.c_str() + (pcszEqual - strFlag.c_str() + 1));
-            RT_NOREF(strKey, strValue); /* We don't have any key=value pairs yet. */
-        }
-        else
-        {
-            if (strFlag == "NoReplace")
-                fFlags |= FileCopyFlag_NoReplace;
-            else if (strFlag == "FollowLinks")
-                fFlags |= FileCopyFlag_FollowLinks;
-            else if (strFlag == "Update")
-                fFlags |= FileCopyFlag_Update;
-            else
-                return VERR_INVALID_PARAMETER;
-        }
-
-        if (!pcszComma)
-            pcszNext += strFlag.length();
-        else
-            pcszNext += strFlag.length() + 1;
+    if (strFlags.isNotEmpty())
+    {
+        const char *pszNext = strFlags.c_str();
+        for (;;)
+        {
+            /* Find the next keyword, ignoring all whitespace. */
+            pszNext = RTStrStripL(pszNext);
+
+            const char * const pszComma = strchr(pszNext, ',');
+            size_t cchKeyword = pszComma ? pszComma - pszNext : strlen(pszComma);
+            while (cchKeyword > 0 && RT_C_IS_SPACE(pszNext[cchKeyword - 1]))
+                cchKeyword--;
+
+            if (cchKeyword > 0)
+            {
+                /* Convert keyword to flag. */
+#define MATCH_KEYWORD(a_szKeyword) (   cchKeyword == sizeof(a_szKeyword) - 1U \
+                                    && memcmp(pszNext, a_szKeyword, sizeof(a_szKeyword) - 1U) == 0)
+                if (MATCH_KEYWORD("NoReplace"))
+                    fFlags |= (unsigned)FileCopyFlag_NoReplace;
+                else if (MATCH_KEYWORD("FollowLinks"))
+                    fFlags |= (unsigned)FileCopyFlag_FollowLinks;
+                else if (MATCH_KEYWORD("Update"))
+                    fFlags |= (unsigned)FileCopyFlag_Update;
+                else
+                    return setError(E_INVALIDARG, tr("Invalid file copy flag: %.*s"), (int)cchKeyword, pszNext);
+#undef MATCH_KEYWORD
+            }
+            if (!pszComma)
+                break;
+            pszNext = pszComma + 1;
+        }
     }
 
     if (pfFlags)
-        *pfFlags = fFlags;
-
-    return VINF_SUCCESS;
+        *pfFlags = (FileCopyFlag_T)fFlags;
+    return S_OK;
 }
 
@@ -2940,20 +2921,16 @@
         source.enmPathStyle = i_getPathStyle();
 
+        HRESULT hrc;
         if (source.enmType == FsObjType_Directory)
         {
-            int rc2 = GuestSession::i_directoryCopyFlagFromStr(*itFlags, &source.Type.Dir.fCopyFlags);
-            if (RT_FAILURE(rc2))
-                return setError(E_INVALIDARG, tr("Invalid / not (yet) implemented directory copy flags specified"));
-
+            hrc = GuestSession::i_directoryCopyFlagFromStr(*itFlags, &source.Type.Dir.fCopyFlags);
             source.Type.Dir.fRecursive = true; /* Implicit. */
         }
         else if (source.enmType == FsObjType_File)
-        {
-            int rc2 = GuestSession::i_fileCopyFlagFromStr(*itFlags, &source.Type.File.fCopyFlags);
-            if (RT_FAILURE(rc2))
-                return setError(E_NOTIMPL, tr("Invalid / not (yet) implemented file copy flag(s) specified"));
-        }
+            hrc = GuestSession::i_fileCopyFlagFromStr(*itFlags, &source.Type.File.fCopyFlags);
         else
             return setError(E_INVALIDARG, tr("Source type %d invalid / not supported"), source.enmType);
+        if (FAILED(hrc))
+            return hrc;
 
         SourceSet.push_back(source);
@@ -2998,20 +2975,16 @@
         source.enmPathStyle = i_getPathStyle();
 
+        HRESULT hrc;
         if (source.enmType == FsObjType_Directory)
         {
-            int rc2 = GuestSession::i_directoryCopyFlagFromStr(*itFlags, &source.Type.Dir.fCopyFlags);
-            if (RT_FAILURE(rc2))
-                return setError(E_INVALIDARG, tr("Invalid / not (yet) implemented directory copy flags specified"));
-
+            hrc = GuestSession::i_directoryCopyFlagFromStr(*itFlags, &source.Type.Dir.fCopyFlags);
             source.Type.Dir.fRecursive = true; /* Implicit. */
         }
         else if (source.enmType == FsObjType_File)
-        {
-            int rc2 = GuestSession::i_fileCopyFlagFromStr(*itFlags, &source.Type.File.fCopyFlags);
-            if (RT_FAILURE(rc2))
-                return setError(E_NOTIMPL, tr("Invalid / not (yet) implemented file copy flag(s) specified"));
-        }
+            hrc = GuestSession::i_fileCopyFlagFromStr(*itFlags, &source.Type.File.fCopyFlags);
         else
             return setError(E_INVALIDARG, tr("Source type %d invalid / not supported"), source.enmType);
+        if (FAILED(hrc))
+            return hrc;
 
         SourceSet.push_back(source);
