- Change RtlIsDosDeviceName_U() implementation to a better Wine implementation

- Winesync RtlIsNameLegalDOS8Dot3()
- "ntdll_winetest.exe path" reduced to 3 failures (which happen on XP too), so considering "path" done 100% now.

svn path=/trunk/; revision=29084
This commit is contained in:
Aleksey Bragin 2007-09-17 19:51:32 +00:00
parent 4ee3207955
commit c466246f9e
2 changed files with 118 additions and 150 deletions

View file

@ -238,79 +238,64 @@ RtlIsNameLegalDOS8Dot3(IN PCUNICODE_STRING UnicodeName,
IN OUT POEM_STRING AnsiName OPTIONAL, IN OUT POEM_STRING AnsiName OPTIONAL,
IN OUT PBOOLEAN SpacesFound OPTIONAL) IN OUT PBOOLEAN SpacesFound OPTIONAL)
{ {
PANSI_STRING name = AnsiName; static const char Illegal[] = "*?<>|\"+=,;[]:/\\\345";
ANSI_STRING DummyString; int Dot = -1;
CHAR Buffer[12]; int i;
char *str; char Buffer[12];
ULONG Length; OEM_STRING OemString;
ULONG i; BOOLEAN GotSpace = FALSE;
NTSTATUS Status;
BOOLEAN HasSpace = FALSE;
BOOLEAN HasDot = FALSE;
if (UnicodeName->Length > 24) if (!AnsiName)
{ {
return(FALSE); /* name too long */ OemString.Length = sizeof(Buffer);
} OemString.MaximumLength = sizeof(Buffer);
OemString.Buffer = Buffer;
AnsiName = &OemString;
}
if (RtlUpcaseUnicodeStringToCountedOemString( AnsiName, UnicodeName, FALSE ) != STATUS_SUCCESS)
return FALSE;
if (!name) if (AnsiName->Length > 12) return FALSE;
{
name = &DummyString;
name->Length = 0;
name->MaximumLength = 12;
name->Buffer = Buffer;
}
Status = RtlUpcaseUnicodeStringToCountedOemString(name, /* a starting . is invalid, except for . and .. */
UnicodeName, if (AnsiName->Buffer[0] == '.')
FALSE); {
if (!NT_SUCCESS(Status)) if (AnsiName->Length != 1 && (AnsiName->Length != 2 || AnsiName->Buffer[1] != '.')) return FALSE;
{ if (SpacesFound) *SpacesFound = FALSE;
return(FALSE); return TRUE;
} }
Length = name->Length; for (i = 0; i < AnsiName->Length; i++)
str = name->Buffer; {
switch (AnsiName->Buffer[i])
if (!(Length == 1 && *str == '.') && {
!(Length == 2 && *str == '.' && *(str + 1) == '.')) case ' ':
{ /* leading/trailing spaces not allowed */
for (i = 0; i < Length; i++, str++) if (!i || i == AnsiName->Length-1 || AnsiName->Buffer[i+1] == '.') return FALSE;
{ GotSpace = TRUE;
switch (*str) break;
{ case '.':
case ' ': if (Dot != -1) return FALSE;
HasSpace = TRUE; Dot = i;
break; break;
default:
case '.': if (strchr(Illegal, AnsiName->Buffer[i])) return FALSE;
if ((HasDot) || /* two or more dots */ break;
(i == 0) || /* dot is first char */ }
(i + 1 == Length) || /* dot is last char */ }
(Length - i > 4) || /* more than 3 chars of extension */ /* check file part is shorter than 8, extension shorter than 3
(HasDot == FALSE && i > 8)) /* name is longer than 8 chars */ * dot cannot be last in string
return(FALSE); */
HasDot = TRUE; if (Dot == -1)
break; {
default: if (AnsiName->Length > 8) return FALSE;
if (RtlpIsShortIllegal(*str)) }
{ else
return(FALSE); {
} if (Dot > 8 || (AnsiName->Length - Dot > 4) || Dot == AnsiName->Length - 1) return FALSE;
} }
} if (SpacesFound) *SpacesFound = GotSpace;
} return TRUE;
/* Name is longer than 8 chars and does not have an extension */
if (Length > 8 && HasDot == FALSE)
{
return(FALSE);
}
if (SpacesFound)
*SpacesFound = HasSpace;
return(TRUE);
} }
/* /*

View file

@ -91,92 +91,69 @@ RtlDetermineDosPathNameType_U(PCWSTR Path)
* @implemented * @implemented
*/ */
ULONG NTAPI ULONG NTAPI
RtlIsDosDeviceName_U(PWSTR DeviceName) RtlIsDosDeviceName_U(PWSTR dos_name)
{ {
ULONG Type; static const WCHAR consoleW[] = {'\\','\\','.','\\','C','O','N',0};
ULONG Length = 0; static const WCHAR auxW[3] = {'A','U','X'};
ULONG Offset; static const WCHAR comW[3] = {'C','O','M'};
PWCHAR wc; static const WCHAR conW[3] = {'C','O','N'};
UNICODE_STRING DeviceNameU; static const WCHAR lptW[3] = {'L','P','T'};
static const WCHAR nulW[3] = {'N','U','L'};
static const WCHAR prnW[3] = {'P','R','N'};
if (DeviceName == NULL) const WCHAR *start, *end, *p;
{
return 0;
}
while (DeviceName[Length]) switch(RtlDetermineDosPathNameType_U( dos_name ))
{ {
Length++; 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;
default:
break;
}
Type = RtlDetermineDosPathNameType_U(DeviceName); end = dos_name + wcslen(dos_name) - 1;
if (Type <= 1) while (end >= dos_name && *end == ':') end--; /* remove all trailing ':' */
{
return 0;
}
if (Type == 6) /* find start of file name */
{ for (start = end; start >= dos_name; start--)
DeviceNameU.Length = DeviceNameU.MaximumLength = Length * sizeof(WCHAR); {
DeviceNameU.Buffer = DeviceName; if (IS_PATH_SEPARATOR(start[0])) break;
if (Length == 7 && /* check for ':' but ignore if before extension (for things like NUL:.txt) */
RtlEqualUnicodeString(&DeviceNameU, (PUNICODE_STRING)&_condev, TRUE)) if (start[0] == ':' && start[1] != '.') break;
return 0x00080006; }
return 0; start++;
}
/* name can end with ':' */ /* remove extension */
if (Length && DeviceName[Length - 1 ] == L':') if ((p = wcschr( start, '.' )))
{ {
Length--; end = p - 1;
} if (end >= dos_name && *end == ':') end--; /* remove trailing ':' before extension */
}
/* remove trailing spaces */
while (end >= dos_name && *end == ' ') end--;
/* there can be spaces or points at the end of name */ /* now we have a potential device name between start and end, check it */
wc = DeviceName + Length - 1; switch(end - start + 1)
while (Length && (*wc == L'.' || *wc == L' ')) {
{ case 3:
Length--; if (_wcsnicmp( start, auxW, 3 ) &&
wc--; _wcsnicmp( start, conW, 3 ) &&
} _wcsnicmp( start, nulW, 3 ) &&
_wcsnicmp( start, prnW, 3 )) break;
/* let's find a beginning of name */ return MAKELONG( 3 * sizeof(WCHAR), (start - dos_name) * sizeof(WCHAR) );
wc = DeviceName + Length - 1; case 4:
while (wc > DeviceName && !IS_PATH_SEPARATOR(*(wc - 1))) if (_wcsnicmp( start, comW, 3 ) && _wcsnicmp( start, lptW, 3 )) break;
{ if (*end <= '0' || *end > '9') break;
wc--; return MAKELONG( 4 * sizeof(WCHAR), (start - dos_name) * sizeof(WCHAR) );
} default: /* can't match anything */
Offset = wc - DeviceName; break;
Length -= Offset; }
DeviceNameU.Length = DeviceNameU.MaximumLength = 3 * sizeof(WCHAR); return 0;
DeviceNameU.Buffer = wc;
/* check for LPTx or COMx */
if (Length == 4 && wc[3] >= L'0' && wc[3] <= L'9')
{
if (wc[3] == L'0')
{
return 0;
}
if (RtlEqualUnicodeString(&DeviceNameU, (PUNICODE_STRING)&_lpt, TRUE) ||
RtlEqualUnicodeString(&DeviceNameU, (PUNICODE_STRING)&_com, TRUE))
{
return ((Offset * 2) << 16 ) | 8;
}
return 0;
}
/* check for PRN,AUX,NUL or CON */
if (Length == 3 &&
(RtlEqualUnicodeString(&DeviceNameU, (PUNICODE_STRING)&_prn, TRUE) ||
RtlEqualUnicodeString(&DeviceNameU, (PUNICODE_STRING)&_aux, TRUE) ||
RtlEqualUnicodeString(&DeviceNameU, (PUNICODE_STRING)&_nul, TRUE) ||
RtlEqualUnicodeString(&DeviceNameU, (PUNICODE_STRING)&_con, TRUE)))
{
return ((Offset * 2) << 16) | 6;
}
return 0;
} }
@ -389,7 +366,12 @@ static __inline void collapse_path( WCHAR *path, UINT mark )
} }
/* skip to the next component */ /* skip to the next component */
while (*p && *p != '\\') p++; while (*p && *p != '\\') p++;
if (*p == '\\') p++; if (*p == '\\')
{
/* remove last dot in previous dir name */
if (p > path + mark && p[-1] == '.') memmove( p-1, p, (wcslen(p) + 1) * sizeof(WCHAR) );
else p++;
}
} }
/* remove trailing spaces and dots (yes, Windows really does that, don't ask) */ /* remove trailing spaces and dots (yes, Windows really does that, don't ask) */
@ -439,7 +421,8 @@ static ULONG get_full_path_helper(
RtlAcquirePebLock(); RtlAcquirePebLock();
cd = &((PCURDIR)&NtCurrentTeb()->ProcessEnvironmentBlock->ProcessParameters->CurrentDirectory.DosPath)->DosPath; //cd = &((PCURDIR)&NtCurrentTeb()->ProcessEnvironmentBlock->ProcessParameters->CurrentDirectory.DosPath)->DosPath;
cd = &NtCurrentTeb()->ProcessEnvironmentBlock->ProcessParameters->CurrentDirectory.DosPath;
switch (type = RtlDetermineDosPathNameType_U(name)) switch (type = RtlDetermineDosPathNameType_U(name))
{ {