[ros-diffs] [pschweitzer] 48002: [NTOSKRNL] Merging some stuff from pierre-fsd/arty-newcc branches: - Implemented FsRtlDissectDbcs(), FsRtlIsDbcsInExpression(), FsRtlIsFatDbcsLegal(), FsRtlIsHpfsDbcsLegal() - Implemented FsRtlIsNameInExpressionPrivate() - Rewritten FsRtlIsNameInExpression() - Updated comments About FsRtlIsNameInExpressionPrivate(), it comes with a fix there isn't in branch, which avoids reading string more than its own length, and this helps getting rid of a workaround later in code.

pschweitzer at svn.reactos.org pschweitzer at svn.reactos.org
Sun Jul 11 21:31:15 UTC 2010


Author: pschweitzer
Date: Sun Jul 11 21:31:14 2010
New Revision: 48002

URL: http://svn.reactos.org/svn/reactos?rev=48002&view=rev
Log:
[NTOSKRNL]
Merging some stuff from pierre-fsd/arty-newcc branches:
- Implemented FsRtlDissectDbcs(), FsRtlIsDbcsInExpression(), FsRtlIsFatDbcsLegal(), FsRtlIsHpfsDbcsLegal()
- Implemented FsRtlIsNameInExpressionPrivate()
- Rewritten FsRtlIsNameInExpression()
- Updated comments
About FsRtlIsNameInExpressionPrivate(), it comes with a fix there isn't in branch, which avoids reading string more than its own length, and this helps getting rid of a workaround later in code.

Modified:
    trunk/reactos/ntoskrnl/fsrtl/dbcsname.c
    trunk/reactos/ntoskrnl/fsrtl/name.c

Modified: trunk/reactos/ntoskrnl/fsrtl/dbcsname.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/dbcsname.c?rev=48002&r1=48001&r2=48002&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/fsrtl/dbcsname.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/fsrtl/dbcsname.c [iso-8859-1] Sun Jul 11 21:31:14 2010
@@ -4,6 +4,7 @@
  * FILE:            ntoskrnl/fsrtl/name.c
  * PURPOSE:         Provides DBCS parsing and other support routines for FSDs
  * PROGRAMMERS:     Alex Ionescu (alex.ionescu at reactos.org)
+ *                  Pierre Schweitzer (pierre.schweitzer at reactos.org) 
  */
 
 /* INCLUDES ******************************************************************/
@@ -45,19 +46,67 @@
                  OUT PANSI_STRING FirstPart,
                  OUT PANSI_STRING RemainingPart)
 {
-    KeBugCheck(FILE_SYSTEM);
+    ULONG FirstPosition, i;
+    ULONG SkipFirstSlash = 0;
+
+    /* Zero the strings before continuing */
+    RtlZeroMemory(FirstPart, sizeof(ANSI_STRING));
+    RtlZeroMemory(RemainingPart, sizeof(ANSI_STRING));
+
+    /* Just quit if the string is empty */
+    if (!Name.Length) return;
+
+    /* Find first backslash */
+    FirstPosition = Name.Length;
+    for (i = 0; i < Name.Length; i++)
+    {
+        /* First make sure the character it's not the Lead DBCS */
+        if (FsRtlIsLeadDbcsCharacter(Name.Buffer[i]))
+        {
+            i++;
+        }
+        /* If we found one... */
+        else if (Name.Buffer[i] == '\\')
+        {
+            /* If it begins string, just notice it and continue */
+            if (i == 0)
+            {
+                SkipFirstSlash = 1;
+            }
+            else
+            {
+                /* Else, save its position and break out of the loop */
+                FirstPosition = i;
+                break;
+            }
+        }
+    }
+
+    /* Set up the first result string */
+    FirstPart->Buffer = Name.Buffer + SkipFirstSlash;
+    FirstPart->Length = (FirstPosition - SkipFirstSlash);
+    FirstPart->MaximumLength = FirstPart->Length;
+
+    /* And second one, if necessary */
+    if (FirstPosition < (Name.Length))
+    {
+        RemainingPart->Buffer = Name.Buffer + FirstPosition + 1;
+        RemainingPart->Length = Name.Length - (FirstPosition + 1);
+        RemainingPart->MaximumLength = RemainingPart->Length;
+    }
 }
 
 /*++
  * @name FsRtlDoesDbcsContainWildCards
  * @implemented
  *
- * FILLME
+ * Returns TRUE if the given DbcsName contains wildcards such as *, ?, 
+ * ANSI_DOS_STAR, ANSI_DOS_DOT, and ANSI_DOS_QM
  *
  * @param Name
- *        FILLME
- *
- * @return None
+ *        The Name to check
+ *
+ * @return TRUE if there are wildcards, FALSE otherwise
  *
  * @remarks None
  *
@@ -89,17 +138,17 @@
 
 /*++
  * @name FsRtlIsDbcsInExpression
- * @unimplemented
- *
- * FILLME
+ * @implemented
+ *
+ * Check if the Name string is in the Expression string.
  *
  * @param Expression
- *        FILLME
+ *        The string in which we've to find Name. It can contains wildcards
  *
  * @param Name
- *        FILLME
- *
- * @return None
+ *        The string to find. It cannot contain wildcards.
+ *
+ * @return TRUE if Name is found in Expression, FALSE otherwise
  *
  * @remarks None
  *
@@ -109,27 +158,74 @@
 FsRtlIsDbcsInExpression(IN PANSI_STRING Expression,
                         IN PANSI_STRING Name)
 {
-    KeBugCheck(FILE_SYSTEM);
+    ULONG ExpressionPosition, NamePosition, MatchingChars = 0;
+
+    ASSERT(!FsRtlDoesDbcsContainWildCards(Name));
+
+    /* One can't be null, both can be */
+    if (!Expression->Length || !Name->Length)
+    {
+        return !(Expression->Length ^ Name->Length);
+    }
+
+    for (ExpressionPosition = 0; ExpressionPosition < Expression->Length; ExpressionPosition++)
+    {
+        if ((Expression->Buffer[ExpressionPosition] == Name->Buffer[MatchingChars]) ||
+            (Expression->Buffer[ExpressionPosition] == '?') ||
+            (Expression->Buffer[ExpressionPosition] == ANSI_DOS_QM) ||
+            (Expression->Buffer[ExpressionPosition] == ANSI_DOS_DOT &&
+            (Name->Buffer[MatchingChars] == '.' || Name->Buffer[MatchingChars] == '0')))
+        {
+            MatchingChars++;
+        }
+        else if (Expression->Buffer[ExpressionPosition] == '*')
+        {
+            MatchingChars = Name->Length;
+        }
+        else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_STAR)
+        {
+            for (NamePosition = MatchingChars; NamePosition < Name->Length; NamePosition++)
+            {
+                if (Name->Buffer[NamePosition] == '.')
+                {
+                    MatchingChars = NamePosition;
+                    break;
+                }
+            }
+        }
+        else
+        {
+            MatchingChars = 0;
+        }
+        if (MatchingChars == Name->Length)
+        {
+            return TRUE;
+        }
+    }
+
     return FALSE;
 }
 
 /*++
  * @name FsRtlIsFatDbcsLegal
- * @unimplemented
- *
- * FILLME
+ * @implemented
+ *
+ * Returns TRUE if the given DbcsName is a valid FAT filename (in 8.3)
  *
  * @param DbcsName
- *        FILLME
+ *        The filename to check. It can also contains pathname.
  *
  * @param WildCardsPermissible
- *        FILLME
+ *        If this is set to FALSE and if filename contains wildcard, the function 
+ *        will fail
  *
  * @param PathNamePermissible
- *        FILLME
+ *        If this is set to FALSE and if the filename comes with a pathname, the
+ *        function will fail
  *
  * @param LeadingBackslashPermissible
- *        FILLME
+ *        If this is set to FALSE and if the filename starts with a backslash, the
+ *        function will fail
  *
  * @return TRUE if the DbcsName is legal, FALSE otherwise
  *
@@ -143,27 +239,130 @@
                     IN BOOLEAN PathNamePermissible,
                     IN BOOLEAN LeadingBackslashPermissible)
 {
-    KeBugCheck(FILE_SYSTEM);
-    return FALSE;
+    ANSI_STRING FirstPart, RemainingPart, Name;
+    BOOLEAN LastDot;
+    ULONG i;
+
+    /* Just quit if the string is empty */
+    if (!DbcsName.Length)
+        return FALSE;
+
+    /* DbcsName wasn't supposed to be started with \ */
+    if (!LeadingBackslashPermissible && DbcsName.Buffer[0] == '\\')
+        return FALSE;
+    /* DbcsName was allowed to be started with \, but now, remove it */
+    else if (LeadingBackslashPermissible && DbcsName.Buffer[0] == '\\')
+    {
+        DbcsName.Buffer = DbcsName.Buffer + 1;
+        DbcsName.Length = DbcsName.Length - 1;
+        DbcsName.MaximumLength = DbcsName.MaximumLength - 1;
+    }
+
+    /* Extract first part of the DbcsName to work on */
+    FsRtlDissectDbcs(DbcsName, &FirstPart, &RemainingPart);
+    while (FirstPart.Length > 0)
+    {
+        /* Reset dots count */
+        LastDot = FALSE;
+
+        /* Accept special filename if wildcards are allowed */
+        if (WildCardsPermissible && (FirstPart.Length == 1 || FirstPart.Length == 2) && FirstPart.Buffer[0] == '.')
+        {
+            if (FirstPart.Length == 2)
+            {
+                if (FirstPart.Buffer[1] == '.')
+                {
+                    goto EndLoop;
+                }
+            }
+            else
+            {
+                goto EndLoop;
+            }
+        }
+
+        /* Filename must be 8.3 filename */
+        if (FirstPart.Length < 3 || FirstPart.Length > 12)
+            return FALSE;
+
+        /* Now, we will parse the filename to find everything bad in */
+        for (i = 0; i < FirstPart.Length; i++)
+        {
+            /* First make sure the character it's not the Lead DBCS */
+            if (FsRtlIsLeadDbcsCharacter(FirstPart.Buffer[i]))
+            {
+                if (i == (FirstPart.Length) - 1)
+                    return FALSE;
+                i++;
+            }
+            /* Then check for bad characters */
+            else if (!FsRtlIsAnsiCharacterLegalFat(FirstPart.Buffer[i], WildCardsPermissible))
+            {
+                return FALSE;
+            }
+            else if (FirstPart.Buffer[i] == '.')
+            {
+                /* Filename can only contain one dot */
+                if (LastDot)
+                    return FALSE;
+
+                LastDot = TRUE;
+
+                /* We mustn't have spaces before dot or at the end of the filename
+                 * and no dot at the beginning of the filename */
+                if ((i == (FirstPart.Length) - 1) || i == 0)
+                    return FALSE;
+
+                if (i > 0)
+                    if (FirstPart.Buffer[i - 1] == ' ')
+                        return FALSE;
+
+                /* Filename must be 8.3 filename and not 3.8 filename */
+                if ((FirstPart.Length - 1) - i > 3)
+                    return FALSE;
+            }
+        }
+
+        /* Filename mustn't finish with a space */
+        if (FirstPart.Buffer[FirstPart.Length - 1] == ' ')
+            return FALSE;
+
+        EndLoop:
+        /* Preparing next loop */
+        Name.Buffer = RemainingPart.Buffer;
+        Name.Length = RemainingPart.Length;
+        Name.MaximumLength = RemainingPart.MaximumLength;
+
+        /* Call once again our dissect function */
+        FsRtlDissectDbcs(Name, &FirstPart, &RemainingPart);
+
+        /* We found a pathname, it wasn't allowed */
+        if (FirstPart.Length > 0 && !PathNamePermissible)
+            return FALSE;
+    }
+    return TRUE;
 }
 
 /*++
  * @name FsRtlIsHpfsDbcsLegal
- * @unimplemented
- *
- * FILLME
+ * @implemented
+ *
+ * Returns TRUE if the given DbcsName is a valid HPFS filename
  *
  * @param DbcsName
- *        FILLME
+ *        The filename to check. It can also contains pathname.
  *
  * @param WildCardsPermissible
- *        FILLME
+ *        If this is set to FALSE and if filename contains wildcard, the function 
+ *        will fail
  *
  * @param PathNamePermissible
- *        FILLME
+ *        If this is set to FALSE and if the filename comes with a pathname, the
+ *        function will fail
  *
  * @param LeadingBackslashPermissible
- *        FILLME
+ *        If this is set to FALSE and if the filename starts with a backslash, the
+ *        function will fail
  *
  * @return TRUE if the DbcsName is legal, FALSE otherwise
  *
@@ -177,6 +376,82 @@
                      IN BOOLEAN PathNamePermissible,
                      IN BOOLEAN LeadingBackslashPermissible)
 {
-    KeBugCheck(FILE_SYSTEM);
-    return FALSE;
+    ANSI_STRING FirstPart, RemainingPart, Name;
+    ULONG i;
+
+    /* Just quit if the string is empty */
+    if (!DbcsName.Length)
+        return FALSE;
+
+    /* DbcsName wasn't supposed to be started with \ */
+    if (!LeadingBackslashPermissible && DbcsName.Buffer[0] == '\\')
+        return FALSE;
+    /* DbcsName was allowed to be started with \, but now, remove it */
+    else if (LeadingBackslashPermissible && DbcsName.Buffer[0] == '\\')
+    {
+        DbcsName.Buffer = DbcsName.Buffer + 1;
+        DbcsName.Length = DbcsName.Length - 1;
+        DbcsName.MaximumLength = DbcsName.MaximumLength - 1;
+    }
+
+    /* Extract first part of the DbcsName to work on */
+    FsRtlDissectDbcs(DbcsName, &FirstPart, &RemainingPart);
+    while (FirstPart.Length > 0)
+    {
+        /* Accept special filename if wildcards are allowed */
+        if (WildCardsPermissible && (FirstPart.Length == 1 || FirstPart.Length == 2) && FirstPart.Buffer[0] == '.')
+        {
+            if (FirstPart.Length == 2)
+            {
+                if (FirstPart.Buffer[1] == '.')
+                {
+                    goto EndLoop;
+                }
+            }
+            else
+            {
+                goto EndLoop;
+            }
+        }
+
+        /* Filename must be 255 bytes maximum */
+        if (FirstPart.Length > 255)
+            return FALSE;
+
+        /* Now, we will parse the filename to find everything bad in */
+        for (i = 0; i < FirstPart.Length; i++)
+        {
+            /* First make sure the character it's not the Lead DBCS */
+            if (FsRtlIsLeadDbcsCharacter(FirstPart.Buffer[i]))
+            {
+                if (i == (FirstPart.Length) - 1)
+                    return FALSE;
+                i++;
+            }
+            /* Then check for bad characters */
+            else if (!!FsRtlIsAnsiCharacterLegalHpfs(FirstPart.Buffer[i], WildCardsPermissible))
+            {
+                return FALSE;
+            }
+        }
+
+        /* Filename mustn't finish with a space or a dot */
+        if ((FirstPart.Buffer[FirstPart.Length - 1] == ' ') ||
+            (FirstPart.Buffer[FirstPart.Length - 1] == '.'))
+            return FALSE;
+
+        EndLoop:
+        /* Preparing next loop */
+        Name.Buffer = RemainingPart.Buffer;
+        Name.Length = RemainingPart.Length;
+        Name.MaximumLength = RemainingPart.MaximumLength;
+
+        /* Call once again our dissect function */
+        FsRtlDissectDbcs(Name, &FirstPart, &RemainingPart);
+
+        /* We found a pathname, it wasn't allowed */
+        if (FirstPart.Length > 0 && !PathNamePermissible)
+            return FALSE;
+    }
+    return TRUE;
 }

Modified: trunk/reactos/ntoskrnl/fsrtl/name.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/name.c?rev=48002&r1=48001&r2=48002&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/fsrtl/name.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/fsrtl/name.c [iso-8859-1] Sun Jul 11 21:31:14 2010
@@ -5,6 +5,7 @@
  * PURPOSE:         Provides name parsing and other support routines for FSDs
  * PROGRAMMERS:     Alex Ionescu (alex.ionescu at reactos.org)
  *                  Filip Navara (navaraf at reactos.org)
+ *                  Pierre Schweitzer (pierre.schweitzer at reactos.org) 
  */
 
 /* INCLUDES ******************************************************************/
@@ -13,27 +14,96 @@
 #define NDEBUG
 #include <debug.h>
 
+/* PRIVATE FUNCTIONS *********************************************************/
+BOOLEAN
+NTAPI
+FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
+                               IN PUNICODE_STRING Name,
+                               IN BOOLEAN IgnoreCase,
+                               IN PWCHAR UpcaseTable OPTIONAL)
+{
+    ULONG i = 0, j, k = 0;
+
+    ASSERT(!FsRtlDoesNameContainWildCards(Name));
+
+    while (i < Name->Length / sizeof(WCHAR) && k < Expression->Length / sizeof(WCHAR))
+    {
+		if ((Expression->Buffer[k] == (IgnoreCase ? UpcaseTable[Name->Buffer[i]] : Name->Buffer[i])) ||
+			(Expression->Buffer[k] == L'?') || (Expression->Buffer[k] == DOS_QM) ||
+			(Expression->Buffer[k] == DOS_DOT && (Name->Buffer[i] == L'.' || Name->Buffer[i] == L'0')))
+		{
+			i++;
+			k++;
+		}
+		else if (Expression->Buffer[k] == L'*')
+		{
+			if (k < Expression->Length / sizeof(WCHAR))
+			{
+				if (Expression->Buffer[k+1] != L'*' && Expression->Buffer[k+1] != L'?' &&
+              Expression->Buffer[k+1] != DOS_DOT && Expression->Buffer[k+1] != DOS_QM &&
+					Expression->Buffer[k+1] != DOS_STAR)
+				{
+					while ((IgnoreCase ? UpcaseTable[Name->Buffer[i]] : Name->Buffer[i]) != Expression->Buffer[k+1] &&
+						   i <= Name->Length / sizeof(WCHAR)) i++;
+				}
+				else
+				{
+					if (!(Expression->Buffer[k+1] != DOS_DOT && (Name->Buffer[i] == L'.' || Name->Buffer[i] == L'0')))
+					{
+						i++;
+					}
+				}
+			}
+			else
+			{
+				i = Name->Length / sizeof(WCHAR);
+			}
+			k++;
+		}
+		else if (Expression->Buffer[k] == DOS_STAR)
+		{
+			j = i;
+			while (j <= Name->Length / sizeof(WCHAR))
+			{
+				if (Name->Buffer[j] == L'.')
+				{
+					i = j;
+				}
+				j++;
+			}
+			k++;
+		}
+		else
+		{
+			i++;
+			k = 0;
+		}
+    }
+
+    return (k == Expression->Length / sizeof(WCHAR));
+}
+
 /* PUBLIC FUNCTIONS **********************************************************/
 
 /*++
  * @name FsRtlAreNamesEqual
  * @implemented
  *
- * FILLME
+ * Compare two strings to check if they match
  *
  * @param Name1
- *        FILLME
+ *        First unicode string to compare
  *
  * @param Name2
- *        FILLME
+ *        Second unicode string to compare
  *
  * @param IgnoreCase
- *        FILLME
+ *        If TRUE, Case will be ignored when comparing strings
  *
  * @param UpcaseTable
- *        FILLME
- *
- * @return None
+ *        Table for upcase letters. If NULL is given, system one will be used
+ *
+ * @return TRUE if the strings are equal
  *
  * @remarks From Bo Branten's ntifs.h v25.
  *
@@ -188,7 +258,7 @@
  * @name FsRtlDoesNameContainWildCards
  * @implemented
  *
- * FILLME
+ * Checks if the given string contains WildCards
  *
  * @param Name
  *        Pointer to a UNICODE_STRING containing Name to examine
@@ -224,13 +294,21 @@
  * @name FsRtlIsNameInExpression
  * @implemented
  *
- * FILLME
- *
- * @param DeviceObject
- *        FILLME
- *
- * @param Irp
- *        FILLME
+ * Check if the Name string is in the Expression string.
+ *
+ * @param Expression
+ *        The string in which we've to find Name. It can contain wildcards.
+ *        If IgnoreCase is set to TRUE, this string MUST BE uppercase. 
+ *
+ * @param Name
+ *        The string to find. It cannot contain wildcards
+ *
+ * @param IgnoreCase
+ *        If set to TRUE, case will be ignore with upcasing both strings
+ *
+ * @param UpcaseTable
+ *        If not NULL, and if IgnoreCase is set to TRUE, it will be used to
+ *        upcase the both strings 
  *
  * @return TRUE if Name is in Expression, FALSE otherwise
  *
@@ -246,80 +324,31 @@
                         IN BOOLEAN IgnoreCase,
                         IN PWCHAR UpcaseTable OPTIONAL)
 {
-    USHORT ExpressionPosition, NamePosition;
-    UNICODE_STRING TempExpression, TempName;
-
-    ExpressionPosition = 0;
-    NamePosition = 0;
-    while (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&
-        NamePosition < (Name->Length / sizeof(WCHAR)))
-    {
-        if (Expression->Buffer[ExpressionPosition] == L'*')
-        {
-            ExpressionPosition++;
-            if (ExpressionPosition == (Expression->Length / sizeof(WCHAR)))
-            {
-                return TRUE;
-            }
-            while (NamePosition < (Name->Length / sizeof(WCHAR)))
-            {
-                TempExpression.Length =
-                    TempExpression.MaximumLength =
-                    Expression->Length - (ExpressionPosition * sizeof(WCHAR));
-                TempExpression.Buffer = Expression->Buffer + ExpressionPosition;
-                TempName.Length =
-                    TempName.MaximumLength =
-                    Name->Length - (NamePosition * sizeof(WCHAR));
-                TempName.Buffer = Name->Buffer + NamePosition;
-                /* FIXME: Rewrite to get rid of recursion */
-                if (FsRtlIsNameInExpression(&TempExpression, &TempName,
-                    IgnoreCase, UpcaseTable))
-                {
-                    return TRUE;
-                }
-                NamePosition++;
-            }
-        }
-        else
-        {
-            /* FIXME: Take UpcaseTable into account! */
-            if (Expression->Buffer[ExpressionPosition] == L'?' ||
-                (IgnoreCase &&
-                RtlUpcaseUnicodeChar(Expression->Buffer[ExpressionPosition]) ==
-                RtlUpcaseUnicodeChar(Name->Buffer[NamePosition])) ||
-                (!IgnoreCase &&
-                Expression->Buffer[ExpressionPosition] ==
-                Name->Buffer[NamePosition]))
-            {
-                NamePosition++;
-                ExpressionPosition++;
-            }
-            else
-            {
-                return FALSE;
-            }
-        }
-    }
-
-    /* Handle matching of "f0_*.*" expression to "f0_000" file name. */
-    if (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&
-        Expression->Buffer[ExpressionPosition] == L'.')
-    {
-        while (ExpressionPosition < (Expression->Length / sizeof(WCHAR)) &&
-            (Expression->Buffer[ExpressionPosition] == L'.' ||
-            Expression->Buffer[ExpressionPosition] == L'*' ||
-            Expression->Buffer[ExpressionPosition] == L'?'))
-        {
-            ExpressionPosition++;
-        }
-    }
-
-    if (ExpressionPosition == (Expression->Length / sizeof(WCHAR)) &&
-        NamePosition == (Name->Length / sizeof(WCHAR)))
-    {
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
+    BOOLEAN Result;
+    NTSTATUS Status;
+    UNICODE_STRING IntName;
+
+    if (IgnoreCase && !UpcaseTable)
+    {
+        Status = RtlUpcaseUnicodeString(&IntName, Name, TRUE);
+        if (Status != STATUS_SUCCESS)
+        {
+            ExRaiseStatus(Status);
+        }
+        Name = &IntName;
+        IgnoreCase = FALSE;
+    }
+    else
+    {
+        IntName.Buffer = NULL;
+    }
+
+    Result = FsRtlIsNameInExpressionPrivate(Expression, Name, IgnoreCase, UpcaseTable);
+
+    if (IntName.Buffer != NULL)
+    {
+        RtlFreeUnicodeString(&IntName);
+    }
+
+    return Result;
+}




More information about the Ros-diffs mailing list