Author: fireball Date: Mon Sep 17 23:51:32 2007 New Revision: 29084
URL: http://svn.reactos.org/svn/reactos?rev=29084&view=rev Log: - 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.
Modified: trunk/reactos/lib/rtl/dos8dot3.c trunk/reactos/lib/rtl/path.c
Modified: trunk/reactos/lib/rtl/dos8dot3.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/dos8dot3.c?rev=2908... ============================================================================== --- trunk/reactos/lib/rtl/dos8dot3.c (original) +++ trunk/reactos/lib/rtl/dos8dot3.c Mon Sep 17 23:51:32 2007 @@ -238,79 +238,64 @@ IN OUT POEM_STRING AnsiName OPTIONAL, IN OUT PBOOLEAN SpacesFound OPTIONAL) { - PANSI_STRING name = AnsiName; - ANSI_STRING DummyString; - CHAR Buffer[12]; - char *str; - ULONG Length; - ULONG i; - NTSTATUS Status; - BOOLEAN HasSpace = FALSE; - BOOLEAN HasDot = FALSE; - - if (UnicodeName->Length > 24) - { - return(FALSE); /* name too long */ - } - - if (!name) - { - name = &DummyString; - name->Length = 0; - name->MaximumLength = 12; - name->Buffer = Buffer; - } - - Status = RtlUpcaseUnicodeStringToCountedOemString(name, - UnicodeName, - FALSE); - if (!NT_SUCCESS(Status)) - { - return(FALSE); - } - - Length = name->Length; - str = name->Buffer; - - if (!(Length == 1 && *str == '.') && - !(Length == 2 && *str == '.' && *(str + 1) == '.')) - { - for (i = 0; i < Length; i++, str++) - { - switch (*str) - { - case ' ': - HasSpace = TRUE; - break; - - case '.': - if ((HasDot) || /* two or more dots */ - (i == 0) || /* dot is first char */ - (i + 1 == Length) || /* dot is last char */ - (Length - i > 4) || /* more than 3 chars of extension */ - (HasDot == FALSE && i > 8)) /* name is longer than 8 chars */ - return(FALSE); - HasDot = TRUE; - break; - default: - if (RtlpIsShortIllegal(*str)) - { - return(FALSE); - } - } - } - } - - /* 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); + static const char Illegal[] = "*?<>|"+=,;[]:/\\345"; + int Dot = -1; + int i; + char Buffer[12]; + OEM_STRING OemString; + BOOLEAN GotSpace = FALSE; + + if (!AnsiName) + { + OemString.Length = sizeof(Buffer); + OemString.MaximumLength = sizeof(Buffer); + OemString.Buffer = Buffer; + AnsiName = &OemString; + } + if (RtlUpcaseUnicodeStringToCountedOemString( AnsiName, UnicodeName, FALSE ) != STATUS_SUCCESS) + return FALSE; + + if (AnsiName->Length > 12) return FALSE; + + /* a starting . is invalid, except for . and .. */ + if (AnsiName->Buffer[0] == '.') + { + if (AnsiName->Length != 1 && (AnsiName->Length != 2 || AnsiName->Buffer[1] != '.')) return FALSE; + if (SpacesFound) *SpacesFound = FALSE; + return TRUE; + } + + for (i = 0; i < AnsiName->Length; i++) + { + switch (AnsiName->Buffer[i]) + { + case ' ': + /* leading/trailing spaces not allowed */ + if (!i || i == AnsiName->Length-1 || AnsiName->Buffer[i+1] == '.') return FALSE; + GotSpace = TRUE; + break; + case '.': + if (Dot != -1) return FALSE; + Dot = i; + break; + default: + if (strchr(Illegal, AnsiName->Buffer[i])) return FALSE; + break; + } + } + /* check file part is shorter than 8, extension shorter than 3 + * dot cannot be last in string + */ + if (Dot == -1) + { + if (AnsiName->Length > 8) return FALSE; + } + else + { + if (Dot > 8 || (AnsiName->Length - Dot > 4) || Dot == AnsiName->Length - 1) return FALSE; + } + if (SpacesFound) *SpacesFound = GotSpace; + return TRUE; }
/*
Modified: trunk/reactos/lib/rtl/path.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/path.c?rev=29084&am... ============================================================================== --- trunk/reactos/lib/rtl/path.c (original) +++ trunk/reactos/lib/rtl/path.c Mon Sep 17 23:51:32 2007 @@ -91,92 +91,69 @@ * @implemented */ ULONG NTAPI -RtlIsDosDeviceName_U(PWSTR DeviceName) -{ - ULONG Type; - ULONG Length = 0; - ULONG Offset; - PWCHAR wc; - UNICODE_STRING DeviceNameU; - - if (DeviceName == NULL) - { - return 0; - } - - while (DeviceName[Length]) - { - Length++; - } - - Type = RtlDetermineDosPathNameType_U(DeviceName); - if (Type <= 1) - { - return 0; - } - - if (Type == 6) - { - DeviceNameU.Length = DeviceNameU.MaximumLength = Length * sizeof(WCHAR); - DeviceNameU.Buffer = DeviceName; - if (Length == 7 && - RtlEqualUnicodeString(&DeviceNameU, (PUNICODE_STRING)&_condev, TRUE)) - return 0x00080006; - return 0; - } - - /* name can end with ':' */ - if (Length && DeviceName[Length - 1 ] == L':') - { - Length--; - } - - /* there can be spaces or points at the end of name */ - wc = DeviceName + Length - 1; - while (Length && (*wc == L'.' || *wc == L' ')) - { - Length--; - wc--; - } - - /* let's find a beginning of name */ - wc = DeviceName + Length - 1; - while (wc > DeviceName && !IS_PATH_SEPARATOR(*(wc - 1))) - { - wc--; - } - Offset = wc - DeviceName; - Length -= Offset; - DeviceNameU.Length = DeviceNameU.MaximumLength = 3 * sizeof(WCHAR); - 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; +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; + default: + break; + } + + end = dos_name + wcslen(dos_name) - 1; + while (end >= dos_name && *end == ':') end--; /* remove all trailing ':' */ + + /* find start of file name */ + for (start = end; start >= dos_name; start--) + { + if (IS_PATH_SEPARATOR(start[0])) break; + /* check for ':' but ignore if before extension (for things like NUL:.txt) */ + if (start[0] == ':' && start[1] != '.') break; + } + start++; + + /* remove extension */ + if ((p = wcschr( start, '.' ))) + { + end = p - 1; + if (end >= dos_name && *end == ':') end--; /* remove trailing ':' before extension */ + } + /* remove trailing spaces */ + while (end >= dos_name && *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; + } + return 0; }
@@ -389,7 +366,12 @@ } /* skip to the next component */ 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) */ @@ -439,7 +421,8 @@
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)) {