Author: ion
Date: Fri Jul 15 13:08:43 2011
New Revision: 52687
URL:
http://svn.reactos.org/svn/reactos?rev=52687&view=rev
Log:
[RTL]: Implement RtlIsDosDeviceName_Ustr and make RtlIsDosDeviceName use it. Uses
UNICODE_STRING APIs everywhere and similar to the old implementation.
Modified:
trunk/reactos/lib/rtl/path.c
Modified: trunk/reactos/lib/rtl/path.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/path.c?rev=52687&a…
==============================================================================
--- trunk/reactos/lib/rtl/path.c [iso-8859-1] (original)
+++ trunk/reactos/lib/rtl/path.c [iso-8859-1] Fri Jul 15 13:08:43 2011
@@ -25,22 +25,18 @@
/* GLOBALS ********************************************************************/
static const WCHAR DeviceRootW[] = L"\\\\.\\";
-
static const UNICODE_STRING _condev = RTL_CONSTANT_STRING(L"\\\\.\\CON");
-
static const UNICODE_STRING _unc = RTL_CONSTANT_STRING(L"\\??\\UNC\\");
-static const UNICODE_STRING _lpt = RTL_CONSTANT_STRING(L"LPT");
-
-static const UNICODE_STRING _com = RTL_CONSTANT_STRING(L"COM");
-
-static const UNICODE_STRING _prn = RTL_CONSTANT_STRING(L"PRN");
-
-static const UNICODE_STRING _aux = RTL_CONSTANT_STRING(L"AUX");
-
-static const UNICODE_STRING _con = RTL_CONSTANT_STRING(L"CON");
-
-static const UNICODE_STRING _nul = RTL_CONSTANT_STRING(L"NUL");
+const UNICODE_STRING DeviceRootString = RTL_CONSTANT_STRING(L"\\\\.\\");
+
+const UNICODE_STRING RtlpDosLPTDevice = RTL_CONSTANT_STRING(L"LPT");
+const UNICODE_STRING RtlpDosCOMDevice = RTL_CONSTANT_STRING(L"COM");
+const UNICODE_STRING RtlpDosPRNDevice = RTL_CONSTANT_STRING(L"PRN");
+const UNICODE_STRING RtlpDosAUXDevice = RTL_CONSTANT_STRING(L"AUX");
+const UNICODE_STRING RtlpDosCONDevice = RTL_CONSTANT_STRING(L"CON");
+const UNICODE_STRING RtlpDosSlashCONDevice =
RTL_CONSTANT_STRING(L"\\\\.\\CON");
+const UNICODE_STRING RtlpDosNULDevice = RTL_CONSTANT_STRING(L"NUL");
/* FUNCTIONS *****************************************************************/
@@ -79,7 +75,6 @@
/*
* @implemented
- *
*/
ULONG
NTAPI
@@ -88,90 +83,229 @@
DPRINT("RtlDetermineDosPathNameType_U %S\n", Path);
ASSERT(Path != NULL);
+ /* Unlike the newer RtlDetermineDosPathNameType_U we assume 4 characters */
if (IS_PATH_SEPARATOR(Path[0]))
{
- if (!IS_PATH_SEPARATOR(Path[1])) return RtlPathTypeRooted; /* \xxx
*/
- if ((Path[2] != L'.') && (Path[2] != L'?')) return
RtlPathTypeUncAbsolute;/* \\xxx */
- if (IS_PATH_SEPARATOR(Path[3])) return RtlPathTypeLocalDevice; /*
\\.\xxx */
- if (Path[3]) return RtlPathTypeUncAbsolute; /*
\\.xxxx */
-
- return RtlPathTypeRootLocalDevice; /* \\.
*/
+ if (!IS_PATH_SEPARATOR(Path[1])) return RtlPathTypeRooted; /* \x
*/
+ if ((Path[2] != L'.') && (Path[2] != L'?')) return
RtlPathTypeUncAbsolute;/* \\x */
+ if (IS_PATH_SEPARATOR(Path[3])) return RtlPathTypeLocalDevice; /*
\\.\x or \\?\x */
+ if (Path[3]) return RtlPathTypeUncAbsolute; /* \\.x
or \\?x */
+ return RtlPathTypeRootLocalDevice; /* \\.
or \\? */
}
else
{
- if (!(Path[0]) || (Path[1] != L':')) return RtlPathTypeRelative;
/* xxx */
- if (IS_PATH_SEPARATOR(Path[2])) return RtlPathTypeDriveAbsolute; /*
x:\xxx */
-
- return RtlPathTypeDriveRelative; /*
x:xxx */
- }
-}
-
-
-/* returns 0 if name is not valid DOS device name, or DWORD with
- * offset in bytes to DOS device name from beginning of buffer in high word
- * and size in bytes of DOS device name in low word */
-
-/*
- * @implemented
- */
-ULONG NTAPI
-RtlIsDosDeviceName_U(PWSTR dos_name)
-{
- static const WCHAR consoleW[] =
{'\\','\\','.','\\','C','O','N',0};
- static const WCHAR auxW[3] = {'A','U','X'};
- static const WCHAR comW[3] = {'C','O','M'};
- static const WCHAR conW[3] = {'C','O','N'};
- static const WCHAR lptW[3] = {'L','P','T'};
- static const WCHAR nulW[3] = {'N','U','L'};
- static const WCHAR prnW[3] = {'P','R','N'};
-
- const WCHAR *start, *end, *p;
-
- switch(RtlDetermineDosPathNameType_U( dos_name ))
- {
- case RtlPathTypeUnknown:
- case RtlPathTypeUncAbsolute:
- return 0;
- case RtlPathTypeLocalDevice:
- if (!_wcsicmp( dos_name, consoleW ))
- return MAKELONG( sizeof(conW), 4 * sizeof(WCHAR) ); /* 4 is length of \\.\
prefix */
- return 0;
- case RtlPathTypeDriveAbsolute:
- case RtlPathTypeDriveRelative:
- start = dos_name + 2; /* skip drive letter */
- break;
- default:
- start = dos_name;
- break;
- }
-
- /* find start of file name */
- for (p = start; *p; p++) if (IS_PATH_SEPARATOR(*p)) start = p + 1;
-
- /* truncate at extension and ':' */
- for (end = start; *end; end++) if (*end == '.' || *end == ':')
break;
- end--;
-
- /* remove trailing spaces */
- while (end >= start && *end == ' ') end--;
-
- /* now we have a potential device name between start and end, check it */
- switch(end - start + 1)
- {
- case 3:
- if (_wcsnicmp( start, auxW, 3 ) &&
- _wcsnicmp( start, conW, 3 ) &&
- _wcsnicmp( start, nulW, 3 ) &&
- _wcsnicmp( start, prnW, 3 )) break;
- return MAKELONG( 3 * sizeof(WCHAR), (start - dos_name) * sizeof(WCHAR) );
- case 4:
- if (_wcsnicmp( start, comW, 3 ) && _wcsnicmp( start, lptW, 3 )) break;
- if (*end <= '0' || *end > '9') break;
- return MAKELONG( 4 * sizeof(WCHAR), (start - dos_name) * sizeof(WCHAR) );
- default: /* can't match anything */
- break;
- }
+ if (!(Path[0]) || (Path[1] != L':')) return RtlPathTypeRelative;
/* x */
+ if (IS_PATH_SEPARATOR(Path[2])) return RtlPathTypeDriveAbsolute; /* x:\
*/
+ return RtlPathTypeDriveRelative; /* x:
*/
+ }
+}
+
+/*
+ * @implemented
+ */
+RTL_PATH_TYPE
+NTAPI
+RtlDetermineDosPathNameType_Ustr(IN PCUNICODE_STRING PathString)
+{
+ PWCHAR Path = PathString->Buffer;
+ ULONG Chars = PathString->Length / sizeof(WCHAR);
+
+ /*
+ * The algorithm is similar to RtlDetermineDosPathNameType_U but here we
+ * actually check for the path length before touching the characters
+ */
+ if ((Chars < 1) || (IS_PATH_SEPARATOR(Path[0])))
+ {
+ if ((Chars < 2) || !(IS_PATH_SEPARATOR(Path[1]))) return RtlPathTypeRooted;
/* \x */
+ if ((Chars < 3) || ((Path[2] != L'.') && (Path[2] !=
L'?'))) return RtlPathTypeUncAbsolute;/* \\x */
+ if ((Chars >= 4) && (IS_PATH_SEPARATOR(Path[3]))) return
RtlPathTypeLocalDevice; /* \\.\x or \\?\x */
+ if (Chars != 3) return RtlPathTypeUncAbsolute;
/* \\.x or \\?x */
+ return RtlPathTypeRootLocalDevice;
/* \\. or \\? */
+ }
+ else
+ {
+ if ((Chars < 2) || (!(Path[0]) || (Path[1] != L':'))) return
RtlPathTypeRelative; /* x */
+ if ((Chars < 3) || (IS_PATH_SEPARATOR(Path[2]))) return
RtlPathTypeDriveAbsolute; /* x:\ */
+ return RtlPathTypeDriveRelative;
/* x: */
+ }
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+RtlIsDosDeviceName_Ustr(IN PUNICODE_STRING PathString)
+{
+ UNICODE_STRING PathCopy;
+ PWCHAR Start, End;
+ ULONG PathChars, ColonCount = 0;
+ USHORT ReturnOffset = 0, ReturnLength;
+ WCHAR c;
+
+ /* Check what type of path this is */
+ switch (RtlDetermineDosPathNameType_Ustr(PathString))
+ {
+ /* Fail for UNC or unknown paths */
+ case RtlPathTypeUnknown:
+ case RtlPathTypeUncAbsolute:
+ return 0;
+
+ /* Make special check for the CON device */
+ case RtlPathTypeLocalDevice:
+ if (RtlEqualUnicodeString(PathString, &RtlpDosSlashCONDevice, TRUE))
+ {
+ /* This should return 0x80006 */
+ return MAKELONG(RtlpDosCONDevice.Length, DeviceRootString.Length);
+ }
+ return 0;
+
+ default:
+ break;
+ }
+
+ /* Make a copy of the string */
+ PathCopy = *PathString;
+
+ /* Return if there's no characters */
+ PathChars = PathCopy.Length / sizeof(WCHAR);
+ if (!PathChars) return 0;
+
+ /* Check for drive path and truncate */
+ if (PathCopy.Buffer[PathChars - 1] == L':')
+ {
+ /* Fixup the lengths */
+ PathCopy.Length -= sizeof(WCHAR);
+ if (!--PathChars) return 0;
+
+ /* Remember this for later */
+ ColonCount = 1;
+ }
+
+ /* Check for extension or space, and truncate */
+ c = PathCopy.Buffer[PathChars - 1];
+ do
+ {
+ /* Stop if we hit a space or period */
+ if ((c != '.') && (c != ' ')) break;
+
+ /* Fixup the lengths and get the next character */
+ PathCopy.Length -= sizeof(WCHAR);
+ if (!--PathChars) c = PathCopy.Buffer[PathChars - 1];
+
+ /* Remember this for later */
+ ColonCount++;
+ } while (PathChars);
+
+ /* Anything still left? */
+ if (PathChars)
+ {
+ /* Loop from the end */
+ for (End = &PathCopy.Buffer[PathChars - 1];
+ End >= PathCopy.Buffer;
+ --End)
+ {
+ /* Check if the character is a path or drive separator */
+ c = *End;
+ if ((c == '\\') || (c == '/') || ((c == ':')
&& (End == PathCopy.Buffer + 1)))
+ {
+ /* Get the next lower case character */
+ End++;
+ c = *End | ' '; // ' ' == ('z' - 'Z')
+
+ /* Check if it's a DOS device (LPT, COM, PRN, AUX, or NUL) */
+ if ((End < &PathCopy.Buffer[PathCopy.Length / sizeof(WCHAR)])
&&
+ ((c == 'l') || (c == 'c') || (c == 'p') || (c
== 'a') || (c == 'n')))
+ {
+ /* Calculate the offset */
+ ReturnOffset = (PCHAR)End - (PCHAR)PathCopy.Buffer;
+
+ /* Build the final string */
+ PathCopy.Length -= ReturnOffset;
+ PathCopy.Length -= (ColonCount * sizeof(WCHAR));
+ PathCopy.Buffer = End;
+ break;
+ }
+ }
+
+ return 0;
+ }
+
+ /* Get the next lower case character and check if it's a DOS device */
+ c = *PathCopy.Buffer | ' '; // ' ' == ('z' -
'Z')
+ if ((c != 'l') && (c != 'c') && (c !=
'p') && (c != 'a') && (c != 'n'))
+ {
+ /* Not LPT, COM, PRN, AUX, or NUL */
+ return 0;
+ }
+ }
+
+ /* Now skip past any extra extension or drive letter characters */
+ Start = PathCopy.Buffer;
+ End = &Start[PathChars];
+ while (Start < End)
+ {
+ c = *Start;
+ if ((c == '.') || (c == ':')) break;
+ Start++;
+ }
+
+ /* And then go backwards to get rid of spaces */
+ while ((Start > PathCopy.Buffer) && (Start[-1] == ' ')) --Start;
+
+ /* Finally see how many characters are left, and that's our size */
+ PathChars = Start - PathCopy.Buffer;
+ PathCopy.Length = PathChars * sizeof(WCHAR);
+
+ /* Check if this is a COM or LPT port, which has a digit after it */
+ if ((PathChars == 4) &&
+ (iswdigit(PathCopy.Buffer[3]) && (PathCopy.Buffer[3] != '0')))
+ {
+ /* Don't compare the number part, just check for LPT or COM */
+ PathCopy.Length -= sizeof(WCHAR);
+ if ((RtlEqualUnicodeString(&PathCopy, &RtlpDosLPTDevice, TRUE)) ||
+ (RtlEqualUnicodeString(&PathCopy, &RtlpDosCOMDevice, TRUE)))
+ {
+ /* Found it */
+ ReturnLength = sizeof(L"COM1");
+ return MAKELONG(ReturnOffset, ReturnLength);
+ }
+ }
+ else if ((PathChars == 3) &&
+ ((RtlEqualUnicodeString(&PathCopy, &RtlpDosPRNDevice, TRUE)) ||
+ (RtlEqualUnicodeString(&PathCopy, &RtlpDosAUXDevice, TRUE)) ||
+ (RtlEqualUnicodeString(&PathCopy, &RtlpDosNULDevice, TRUE)) ||
+ (RtlEqualUnicodeString(&PathCopy, &RtlpDosCONDevice, TRUE))))
+ {
+ /* Otherwise this was something like AUX, NUL, PRN, or CON */
+ ReturnLength = sizeof(L"AUX");
+ return MAKELONG(ReturnOffset, ReturnLength);
+ }
+
+ /* Otherwise, this isn't a valid DOS device */
return 0;
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+RtlIsDosDeviceName_U(IN PWSTR Path)
+{
+ UNICODE_STRING PathString;
+ NTSTATUS Status;
+
+ /* Build the string */
+ Status = RtlInitUnicodeStringEx(&PathString, Path);
+ if (!NT_SUCCESS(Status)) return 0;
+
+ /*
+ * Returns 0 if name is not valid DOS device name, or DWORD with
+ * offset in bytes to DOS device name from beginning of buffer in high word
+ * and size in bytes of DOS device name in low word
+ */
+ return RtlIsDosDeviceName_Ustr(&PathString);
}
/*