mirror of
https://github.com/reactos/reactos.git
synced 2025-01-03 21:09:19 +00:00
- 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:
parent
4ee3207955
commit
c466246f9e
2 changed files with 118 additions and 150 deletions
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue