diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 74974c3b6f48e..65080489ad5e4 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -1334,7 +1334,7 @@ ClrDataAccess::GetMethodDescName(CLRDATA_ADDRESS methodDesc, unsigned int count, nChars > 0 && nChars <= ARRAY_SIZE(path)) { WCHAR* pFile = path + nChars - 1; - while ((pFile >= path) && (*pFile != W('\\'))) + while ((pFile >= path) && (*pFile != DIRECTORY_SEPARATOR_CHAR_W)) { pFile--; } diff --git a/src/coreclr/ildasm/dis.cpp b/src/coreclr/ildasm/dis.cpp index 81ccc1928b8ff..1221b81e8b5c6 100644 --- a/src/coreclr/ildasm/dis.cpp +++ b/src/coreclr/ildasm/dis.cpp @@ -1115,8 +1115,10 @@ BOOL Disassemble(IMDInternalImport *pImport, BYTE *ILHeader, void *GUICookie, md pFile = NULL; if(fopen_s(&pFile,szFileName,"rt") != 0) { - char* pch = strrchr(szFileName,'\\'); + char* pch = strrchr(szFileName, DIRECTORY_SEPARATOR_CHAR_A); +#ifdef HOST_WINDOWS if(pch == NULL) pch = strrchr(szFileName,':'); +#endif pFile = NULL; if(pch) fopen_s(&pFile,pch+1,"rt"); } diff --git a/src/coreclr/ildasm/dman.cpp b/src/coreclr/ildasm/dman.cpp index cee38f4488227..5c100431094c5 100644 --- a/src/coreclr/ildasm/dman.cpp +++ b/src/coreclr/ildasm/dman.cpp @@ -782,8 +782,10 @@ void DumpManifestResources(void* GUICookie) static WCHAR wzFileName[2048]; WszMultiByteToWideChar(CP_UTF8,0,g_szOutputFile,-1,wzFileName,2048); - wzName = wcsrchr(wzFileName,'\\'); + wzName = wcsrchr(wzFileName,DIRECTORY_SEPARATOR_CHAR_W); +#ifdef HOST_WINDOWS if(wzName == NULL) wzName = wcsrchr(wzFileName,':'); +#endif if (wzName == NULL) wzName = wzFileName; else wzName++; diff --git a/src/coreclr/inc/longfilepathwrappers.h b/src/coreclr/inc/longfilepathwrappers.h index 5a77cb102a57a..ee394aa0b7758 100644 --- a/src/coreclr/inc/longfilepathwrappers.h +++ b/src/coreclr/inc/longfilepathwrappers.h @@ -5,6 +5,8 @@ #define _WIN_PATH_APIS_WRAPPER_ class SString; +#ifdef HOST_WINDOWS + HMODULE LoadLibraryExWrapper( _In_ LPCWSTR lpLibFileName, @@ -35,7 +37,6 @@ GetFileAttributesExWrapper( _Out_writes_bytes_(sizeof(WIN32_FILE_ATTRIBUTE_DATA)) LPVOID lpFileInformation ); -#ifndef HOST_UNIX BOOL CopyFileExWrapper( _In_ LPCWSTR lpExistingFileName, @@ -46,7 +47,7 @@ CopyFileExWrapper( _Inout_opt_ LPBOOL pbCancel, _In_ DWORD dwCopyFlags ); -#endif //HOST_UNIX +#endif //HOST_WINDOWS DWORD SearchPathWrapper( diff --git a/src/coreclr/inc/nsutilpriv.h b/src/coreclr/inc/nsutilpriv.h index 5ea9d0eba2ed6..238b34618b661 100644 --- a/src/coreclr/inc/nsutilpriv.h +++ b/src/coreclr/inc/nsutilpriv.h @@ -208,8 +208,6 @@ void MakeNestedTypeName( // throws on out of memory #define ASSEMBLY_SEPARATOR_STR ", " #define ASSEMBLY_SEPARATOR_WSTR W(", ") #define ASSEMBLY_SEPARATOR_LEN 2 -#define BACKSLASH_CHAR '\\' -#define BACKSLASH_WCHAR W('\\') #define NESTED_SEPARATOR_CHAR '+' #define NESTED_SEPARATOR_WCHAR W('+') #define NESTED_SEPARATOR_STR "+" diff --git a/src/coreclr/inc/winwrap.h b/src/coreclr/inc/winwrap.h index 522ae3150e258..652c0b8065331 100644 --- a/src/coreclr/inc/winwrap.h +++ b/src/coreclr/inc/winwrap.h @@ -189,11 +189,17 @@ //File and Directory Functions which need special handling for LongFile Names //Note only the functions which are currently used are defined +#ifdef HOST_WINDOWS #define WszLoadLibrary LoadLibraryExWrapper #define WszLoadLibraryEx LoadLibraryExWrapper #define WszCreateFile CreateFileWrapper -#define WszGetFileAttributes GetFileAttributesWrapper #define WszGetFileAttributesEx GetFileAttributesExWrapper +#else // HOST_WINDOWS +#define WszLoadLibrary LoadLibraryW +#define WszLoadLibraryEx LoadLibraryExW +#define WszCreateFile CreateFileW +#define WszGetFileAttributesEx GetFileAttributesExW +#endif // HOST_WINDOWS //Can not use extended syntax #define WszGetFullPathName GetFullPathNameW diff --git a/src/coreclr/jit/error.cpp b/src/coreclr/jit/error.cpp index b5af43193faa5..0ca3c39f34448 100644 --- a/src/coreclr/jit/error.cpp +++ b/src/coreclr/jit/error.cpp @@ -239,7 +239,7 @@ DWORD getBreakOnBadCode() /*****************************************************************************/ void debugError(const char* msg, const char* file, unsigned line) { - const char* tail = strrchr(file, '\\'); + const char* tail = strrchr(file, DIRECTORY_SEPARATOR_CHAR_A); if (tail != nullptr) { tail = tail + 1; diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index df7834354af19..bcac8ba6b23d8 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -88,7 +88,7 @@ void Compiler::verRaiseVerifyExceptionIfNeeded(INDEBUG(const char* msg) DEBUGARG DEBUGARG(unsigned line)) { #ifdef DEBUG - const char* tail = strrchr(file, '\\'); + const char* tail = strrchr(file, DIRECTORY_SEPARATOR_CHAR_A); if (tail) { file = tail + 1; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.Unix.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.Unix.cs index 695b904825ea3..91203aff615c5 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.Unix.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.Unix.cs @@ -11,9 +11,6 @@ public static partial class NativeLibrary private static IntPtr LoadLibraryHelper(string libraryName, int _ /*flags*/, ref LoadLibErrorTracker errorTracker) { - // do the Dos/Unix conversion - libraryName = libraryName.Replace('\\', '/'); - IntPtr ret = Interop.Sys.LoadLibrary(libraryName); if (ret == IntPtr.Zero) { diff --git a/src/coreclr/pal/inc/mbusafecrt.h b/src/coreclr/pal/inc/mbusafecrt.h index cdcc2faabeed4..3ea804f09ad8a 100644 --- a/src/coreclr/pal/inc/mbusafecrt.h +++ b/src/coreclr/pal/inc/mbusafecrt.h @@ -81,7 +81,6 @@ extern errno_t _makepath_s( char* outDest, size_t inDestBufferSize, const char* extern errno_t _wmakepath_s( WCHAR* outDest, size_t inDestBufferSize, const WCHAR* inDrive, const WCHAR* inDirectory, const WCHAR* inFilename, const WCHAR* inExtension ); extern errno_t _splitpath_s( const char* inPath, char* outDrive, size_t inDriveSize, char* outDirectory, size_t inDirectorySize, char* outFilename, size_t inFilenameSize, char* outExtension, size_t inExtensionSize ); -extern errno_t _wsplitpath_s( const WCHAR* inPath, WCHAR* outDrive, size_t inDriveSize, WCHAR* outDirectory, size_t inDirectorySize, WCHAR* outFilename, size_t inFilenameSize, WCHAR* outExtension, size_t inExtensionSize ); extern int sprintf_s( char *string, size_t sizeInBytes, const char *format, ... ); diff --git a/src/coreclr/pal/inc/rt/safecrt.h b/src/coreclr/pal/inc/rt/safecrt.h index 4d9d1a176950c..007b3deae7e1d 100644 --- a/src/coreclr/pal/inc/rt/safecrt.h +++ b/src/coreclr/pal/inc/rt/safecrt.h @@ -383,7 +383,6 @@ void __cdecl _invalid_parameter(const WCHAR *_Message, const WCHAR *_FunctionNam #define _tcsnset_s _wcsnset_s #define _tcstok_s wcstok_s #define _tmakepath_s _wmakepath_s -#define _tsplitpath_s _wsplitpath_s #define _stprintf_s swprintf_s #define _tscanf_s wscanf_s #define _tsscanf_s swscanf_s @@ -1370,13 +1369,13 @@ errno_t __cdecl _wmakepath_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Dri } while (*p != 0); p = p - 1; - if (*p != L'/' && *p != L'\\') + if (*p != L'/') { if(++written >= _SizeInWords) { goto error_return; } - *d++ = L'\\'; + *d++ = L'/'; } } @@ -1432,224 +1431,6 @@ errno_t __cdecl _wmakepath_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Dri } #endif -/* _wsplitpath_s */ -_SAFECRT__EXTERN_C -errno_t __cdecl _wsplitpath_s( - const WCHAR *_Path, - WCHAR *_Drive, size_t _DriveSize, - WCHAR *_Dir, size_t _DirSize, - WCHAR *_Filename, size_t _FilenameSize, - WCHAR *_Ext, size_t _ExtSize -); - -/* no C++ overload for _wsplitpath_s */ - -#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL - -_SAFECRT__INLINE -errno_t __cdecl _wsplitpath_s( - const WCHAR *_Path, - WCHAR *_Drive, size_t _DriveSize, - WCHAR *_Dir, size_t _DirSize, - WCHAR *_Filename, size_t _FilenameSize, - WCHAR *_Ext, size_t _ExtSize -) -{ - const WCHAR *tmp; - const WCHAR *last_slash; - const WCHAR *dot; - int drive_set = 0; - size_t length = 0; - int bEinval = 0; - - /* validation section */ - _SAFECRT__VALIDATE_POINTER(_Path); - if ((_Drive == nullptr && _DriveSize != 0) || (_Drive != nullptr && _DriveSize == 0)) - { - goto error_einval; - } - if ((_Dir == nullptr && _DirSize != 0) || (_Dir != nullptr && _DirSize == 0)) - { - goto error_einval; - } - if ((_Filename == nullptr && _FilenameSize != 0) || (_Filename != nullptr && _FilenameSize == 0)) - { - goto error_einval; - } - if ((_Ext == nullptr && _ExtSize != 0) || (_Ext != nullptr && _ExtSize == 0)) - { - goto error_einval; - } - - /* check if _Path begins with the longpath prefix */ - if (_Path[0] == L'\\' && _Path[1] == L'\\' && _Path[2] == L'?' && _Path[3] == L'\\') - { - _Path += 4; - } - - /* extract drive letter and ':', if any */ - if (!drive_set) - { - size_t skip = _MAX_DRIVE - 2; - tmp = _Path; - while (skip > 0 && *tmp != 0) - { - skip--; - tmp++; - } - if (*tmp == L':') - { - if (_Drive != nullptr) - { - if (_DriveSize < _MAX_DRIVE) - { - goto error_erange; - } - wcsncpy_s(_Drive, _DriveSize, _Path, _MAX_DRIVE - 1); - } - _Path = tmp + 1; - } - else - { - if (_Drive != nullptr) - { - _SAFECRT__RESET_STRING(_Drive, _DriveSize); - } - } - } - - /* extract path string, if any. _Path now points to the first character - * of the path, if any, or the filename or extension, if no path was - * specified. Scan ahead for the last occurrence, if any, of a '/' or - * '\' path separator character. If none is found, there is no path. - * We will also note the last '.' character found, if any, to aid in - * handling the extension. - */ - last_slash = nullptr; - dot = nullptr; - tmp = _Path; - for (; *tmp != 0; ++tmp) - { - { - if (*tmp == L'/' || *tmp == L'\\') - { - /* point to one beyond for later copy */ - last_slash = tmp + 1; - } - else if (*tmp == L'.') - { - dot = tmp; - } - } - } - - if (last_slash != nullptr) - { - /* found a path - copy up through last_slash or max characters - * allowed, whichever is smaller - */ - if (_Dir != nullptr) { - length = (size_t)(last_slash - _Path); - if (_DirSize <= length) - { - goto error_erange; - } - wcsncpy_s(_Dir, _DirSize, _Path, length); - } - _Path = last_slash; - } - else - { - /* there is no path */ - if (_Dir != nullptr) - { - _SAFECRT__RESET_STRING(_Dir, _DirSize); - } - } - - /* extract file name and extension, if any. Path now points to the - * first character of the file name, if any, or the extension if no - * file name was given. Dot points to the '.' beginning the extension, - * if any. - */ - if (dot != nullptr && (dot >= _Path)) - { - /* found the marker for an extension - copy the file name up to the '.' */ - if (_Filename) - { - length = (size_t)(dot - _Path); - if (_FilenameSize <= length) - { - goto error_erange; - } - wcsncpy_s(_Filename, _FilenameSize, _Path, length); - } - /* now we can get the extension - remember that tmp still points - * to the terminating nullptr character of path. - */ - if (_Ext) - { - length = (size_t)(tmp - dot); - if (_ExtSize <= length) - { - goto error_erange; - } - wcsncpy_s(_Ext, _ExtSize, dot, length); - } - } - else - { - /* found no extension, give empty extension and copy rest of - * string into fname. - */ - if (_Filename) - { - length = (size_t)(tmp - _Path); - if (_FilenameSize <= length) - { - goto error_erange; - } - wcsncpy_s(_Filename, _FilenameSize, _Path, length); - } - if (_Ext) - { - _SAFECRT__RESET_STRING(_Ext, _ExtSize); - } - } - - return 0; - -error_einval: - bEinval = 1; - -error_erange: - if (_Drive != nullptr && _DriveSize > 0) - { - _SAFECRT__RESET_STRING(_Drive, _DriveSize); - } - if (_Dir != nullptr && _DirSize > 0) - { - _SAFECRT__RESET_STRING(_Dir, _DirSize); - } - if (_Filename != nullptr && _FilenameSize > 0) - { - _SAFECRT__RESET_STRING(_Filename, _FilenameSize); - } - if (_Ext != nullptr && _ExtSize > 0) - { - _SAFECRT__RESET_STRING(_Ext, _ExtSize); - } - - if (bEinval) - { - _SAFECRT__RETURN_EINVAL; - } - - _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Strings, _StringSizes); - /* should never happen, but compiler can't tell */ - return EINVAL; -} -#endif /* vsprintf_s */ /* diff --git a/src/coreclr/pal/src/CMakeLists.txt b/src/coreclr/pal/src/CMakeLists.txt index 9df78198ca634..d9726460ccfe4 100644 --- a/src/coreclr/pal/src/CMakeLists.txt +++ b/src/coreclr/pal/src/CMakeLists.txt @@ -201,7 +201,6 @@ set(SOURCES safecrt/wcsncpy_s.cpp safecrt/wcstok_s.cpp safecrt/wmakepath_s.cpp - safecrt/wsplitpath_s.cpp safecrt/xtoa_s.cpp safecrt/xtow_s.cpp sharedmemory/sharedmemory.cpp diff --git a/src/coreclr/pal/src/cruntime/file.cpp b/src/coreclr/pal/src/cruntime/file.cpp index c92f22af18115..a7a7a12a33375 100644 --- a/src/coreclr/pal/src/cruntime/file.cpp +++ b/src/coreclr/pal/src/cruntime/file.cpp @@ -234,8 +234,6 @@ PAL_fopen(const char * fileName, const char * mode) goto done; } - FILEDosToUnixPathA( UnixFileName ); - /*I am not checking for the case where stat fails *as fopen will handle the error more gracefully in case *UnixFileName is invalid*/ diff --git a/src/coreclr/pal/src/file/directory.cpp b/src/coreclr/pal/src/file/directory.cpp index a19e517932dd1..e30fd2d923626 100644 --- a/src/coreclr/pal/src/file/directory.cpp +++ b/src/coreclr/pal/src/file/directory.cpp @@ -131,8 +131,6 @@ RemoveDirectoryHelper ( BOOL bRet = FALSE; *dwLastError = 0; - FILEDosToUnixPathA( lpPathName ); - if ( rmdir(lpPathName) != 0 ) { TRACE("Removal of directory [%s] was unsuccessful, errno = %d.\n", @@ -415,7 +413,6 @@ CreateDirectoryA( dwLastError = ERROR_NOT_ENOUGH_MEMORY; goto done; } - FILEDosToUnixPathA( unixPathName ); // Remove any trailing slashes at the end because mkdir might not // handle them appropriately on all platforms. pathLength = strlen(unixPathName); @@ -509,7 +506,6 @@ SetCurrentDirectoryA( BOOL bRet = FALSE; DWORD dwLastError = 0; int result; - LPSTR unixPathName = NULL; PERF_ENTRY(SetCurrentDirectoryA); ENTRY("SetCurrentDirectoryA(lpPathName=%p (%s))\n", @@ -525,17 +521,8 @@ SetCurrentDirectoryA( goto done; } - unixPathName = PAL__strdup(lpPathName); - if (unixPathName == NULL ) - { - ERROR("PAL__strdup() failed\n"); - dwLastError = ERROR_NOT_ENOUGH_MEMORY; - goto done; - } - FILEDosToUnixPathA( unixPathName ); - - TRACE("Attempting to open Unix dir [%s]\n", unixPathName); - result = chdir(unixPathName); + TRACE("Attempting to open Unix dir [%s]\n", lpPathName); + result = chdir(lpPathName); if ( result == 0 ) { @@ -547,7 +534,7 @@ SetCurrentDirectoryA( { struct stat stat_data; - if ( stat( unixPathName, &stat_data) == 0 && + if ( stat( lpPathName, &stat_data) == 0 && (stat_data.st_mode & S_IFMT) == S_IFREG ) { /* Not a directory, it is a file. */ @@ -555,7 +542,7 @@ SetCurrentDirectoryA( } else { - FILEGetProperNotFoundError( unixPathName, &dwLastError ); + FILEGetProperNotFoundError( lpPathName, &dwLastError ); } TRACE("chdir() failed, path was invalid.\n"); } @@ -573,11 +560,6 @@ SetCurrentDirectoryA( SetLastError(dwLastError); } - if(unixPathName != NULL) - { - PAL_free( unixPathName ); - } - LOGEXIT("SetCurrentDirectoryA returns BOOL %d\n", bRet); PERF_EXIT(SetCurrentDirectoryA); return bRet; diff --git a/src/coreclr/pal/src/file/file.cpp b/src/coreclr/pal/src/file/file.cpp index e6e13bbc21360..a15be4dba7418 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -461,8 +461,6 @@ CorUnix::InternalCreateFile( goto done; } - FILEDosToUnixPathA( lpUnixPath ); - // Compute the absolute pathname to the file. This pathname is used // to determine if two file names represent the same file. palError = InternalCanonicalizeRealPath(lpUnixPath, lpFullUnixPath); @@ -1031,8 +1029,6 @@ DeleteFileA( goto done; } - FILEDosToUnixPathA( lpunixFileName ); - // Compute the absolute pathname to the file. This pathname is used // to determine if two file names represent the same file. palError = InternalCanonicalizeRealPath(lpunixFileName, lpFullunixFileName); @@ -1103,7 +1099,6 @@ GetFileAttributesA( struct stat stat_data; DWORD dwAttr = 0; DWORD dwLastError = 0; - PathCharString unixFileName; PERF_ENTRY(GetFileAttributesA); ENTRY("GetFileAttributesA(lpFileName=%p (%s))\n", lpFileName?lpFileName:"NULL", lpFileName?lpFileName:"NULL"); @@ -1115,18 +1110,9 @@ GetFileAttributesA( goto done; } - - if( !unixFileName.Set(lpFileName, strlen(lpFileName))) - { - dwLastError = ERROR_NOT_ENOUGH_MEMORY; - goto done; - } - - FILEDosToUnixPathA( unixFileName ); - - if ( stat(unixFileName, &stat_data) != 0 ) + if ( stat(lpFileName, &stat_data) != 0 ) { - dwLastError = FILEGetLastErrorFromErrnoAndFilename(unixFileName); + dwLastError = FILEGetLastErrorFromErrnoAndFilename(lpFileName); goto done; } @@ -1311,7 +1297,6 @@ GetFileAttributesExW( goto done; } - FILEDosToUnixPathA(name); /* do the stat */ if ( stat(name, &stat_data) != 0 ) { @@ -1386,7 +1371,6 @@ SetFileAttributesA( DWORD dwLastError = 0; BOOL bRet = FALSE; - LPSTR unixFileName = NULL; PERF_ENTRY(SetFileAttributesA); ENTRY("SetFileAttributesA(lpFileName=%p (%s), dwFileAttributes=%#x)\n", @@ -1422,19 +1406,11 @@ SetFileAttributesA( goto done; } - if ((unixFileName = strdup(lpFileName)) == NULL) - { - ERROR("strdup() failed\n"); - dwLastError = ERROR_NOT_ENOUGH_MEMORY; - goto done; - } - - FILEDosToUnixPathA( unixFileName ); - if ( stat(unixFileName, &stat_data) != 0 ) + if ( stat(lpFileName, &stat_data) != 0 ) { TRACE("stat failed on %s; errno is %d (%s)\n", - unixFileName, errno, strerror(errno)); - dwLastError = FILEGetLastErrorFromErrnoAndFilename(unixFileName); + lpFileName, errno, strerror(errno)); + dwLastError = FILEGetLastErrorFromErrnoAndFilename(lpFileName); goto done; } @@ -1470,10 +1446,10 @@ SetFileAttributesA( bRet = TRUE; if ( new_mode != stat_data.st_mode ) { - if ( chmod(unixFileName, new_mode) != 0 ) + if ( chmod(lpFileName, new_mode) != 0 ) { - ERROR("chmod(%s, %#x) failed\n", unixFileName, new_mode); - dwLastError = FILEGetLastErrorFromErrnoAndFilename(unixFileName); + ERROR("chmod(%s, %#x) failed\n", lpFileName, new_mode); + dwLastError = FILEGetLastErrorFromErrnoAndFilename(lpFileName); bRet = FALSE; } } @@ -1484,8 +1460,6 @@ SetFileAttributesA( pThread->SetLastError(dwLastError); } - free(unixFileName); - LOGEXIT("SetFileAttributesA returns BOOL %d\n", bRet); PERF_EXIT(SetFileAttributesA); return bRet; @@ -2657,16 +2631,15 @@ GetTempFileNameA( file_templatePS.CloseBuffer(length); chLastPathNameChar = file_template[strlen(file_template)-1]; - if (chLastPathNameChar != '\\' && chLastPathNameChar != '/') + if (chLastPathNameChar != '/') { - strcat_s( file_template, file_templatePS.GetSizeOf(), "\\" ); + strcat_s( file_template, file_templatePS.GetSizeOf(), "/" ); } if ( lpPrefixString ) { strncat_s( file_template, file_templatePS.GetSizeOf(), lpPrefixString, MAX_PREFIX ); } - FILEDosToUnixPathA( file_template ); strncat_s( file_template, file_templatePS.GetSizeOf(), "%.4x.TMP", MAX_SEEDSIZE ); /* Create the file. */ @@ -3017,7 +2990,6 @@ CopyFileA( DWORD dwSrcFileAttributes; struct stat SrcFileStats; - LPSTR lpUnixPath = NULL; const int buffer_size = 16*1024; char *buffer = (char*)alloca(buffer_size); DWORD bytes_read; @@ -3065,18 +3037,10 @@ CopyFileA( } /* Need to preserve the owner/group and chmod() flags */ - lpUnixPath = strdup(lpExistingFileName); - if ( lpUnixPath == NULL ) - { - ERROR("strdup() failed\n"); - pThread->SetLastError(FILEGetLastErrorFromErrno()); - goto done; - } - FILEDosToUnixPathA(lpUnixPath); - if (stat (lpUnixPath, &SrcFileStats) == -1) + if (stat (lpExistingFileName, &SrcFileStats) == -1) { ERROR("stat() failed for %s\n", lpExistingFileName); - pThread->SetLastError(FILEGetLastErrorFromErrnoAndFilename(lpUnixPath)); + pThread->SetLastError(FILEGetLastErrorFromErrnoAndFilename(lpExistingFileName)); goto done; } @@ -3094,17 +3058,6 @@ CopyFileA( goto done; } - free(lpUnixPath); - lpUnixPath = strdup(lpNewFileName); - if ( lpUnixPath == NULL ) - { - ERROR("strdup() failed\n"); - pThread->SetLastError(FILEGetLastErrorFromErrno()); - goto done; - } - FILEDosToUnixPathA( lpUnixPath ); - - // We don't set file attributes in CreateFile. The only attribute // that is reflected on disk in Unix is read-only, and we set that // here. @@ -3115,11 +3068,11 @@ CopyFileA( } /* Make sure the new file has the same chmod() flags. */ - if (chmod(lpUnixPath, SrcFileStats.st_mode & permissions) == -1) + if (chmod(lpNewFileName, SrcFileStats.st_mode & permissions) == -1) { WARN ("chmod() failed to set mode 0x%x on new file\n", SrcFileStats.st_mode & permissions); - pThread->SetLastError(FILEGetLastErrorFromErrnoAndFilename(lpUnixPath)); + pThread->SetLastError(FILEGetLastErrorFromErrnoAndFilename(lpNewFileName)); goto done; } @@ -3155,10 +3108,6 @@ CopyFileA( { CloseHandle( hDest ); } - if (lpUnixPath) - { - free(lpUnixPath); - } LOGEXIT("CopyFileA returns BOOL %d\n", bGood); PERF_EXIT(CopyFileA); diff --git a/src/coreclr/pal/src/file/find.cpp b/src/coreclr/pal/src/file/find.cpp index 8f2431abfa98c..b874885992f8c 100644 --- a/src/coreclr/pal/src/file/find.cpp +++ b/src/coreclr/pal/src/file/find.cpp @@ -177,7 +177,6 @@ FindFirstFileA( SetLastError( ERROR_INTERNAL_ERROR ); goto done; } - FILEDosToUnixPathA( lpTemp ); FILEGetProperNotFoundError( lpTemp, &dwLastError ); if ( ERROR_PATH_NOT_FOUND == dwLastError ) @@ -909,11 +908,6 @@ static BOOL FILEDosGlobA( CPalThread *pthrCurrent, goto done; } - if (Dir[0] != 0) - { - FILEDosToUnixPathA( Dir ); - } - /* The meat of the routine happens below. Basically, there are three special things to check for: diff --git a/src/coreclr/pal/src/file/path.cpp b/src/coreclr/pal/src/file/path.cpp index 5de7ce43c70ff..92383dd204ace 100644 --- a/src/coreclr/pal/src/file/path.cpp +++ b/src/coreclr/pal/src/file/path.cpp @@ -73,7 +73,7 @@ GetFullPathNameA( } /* find out if lpFileName is a partial or full path */ - if ('\\' == *lpFileName || '/' == *lpFileName) + if ('/' == *lpFileName) { fullPath = TRUE; } @@ -112,8 +112,6 @@ GetFullPathNameA( } unixPathBuf = unixPath.OpenStringBuffer(unixPath.GetCount()); - /* do conversion to Unix path */ - FILEDosToUnixPathA( unixPathBuf ); /* now we can canonicalize this */ FILECanonicalizePath(unixPathBuf); @@ -433,57 +431,6 @@ GetTempPathW( } - -/*++ -Function: - FileDosToUnixPathA - -Abstract: - Change a DOS path to a Unix path. - - Replaces '\' by '/' - -Parameter: - IN/OUT lpPath: path to be modified ---*/ -void -FILEDosToUnixPathA( - LPSTR lpPath) -{ - LPSTR p; - - TRACE("Original DOS path = [%s]\n", lpPath); - - if (!lpPath) - { - return; - } - - for (p = lpPath; *p; p++) - { - /* Replace \ with / */ - if (*p == '\\') - { - *p = '/'; - } - } - - TRACE("Resulting Unix path = [%s]\n", lpPath); -} - -void -FILEDosToUnixPathA( - PathCharString& lpPath) -{ - - SIZE_T len = lpPath.GetCount(); - LPSTR lpPathBuf = lpPath.OpenStringBuffer(len); - FILEDosToUnixPathA(lpPathBuf); - lpPath.CloseBuffer(len); - -} - - /*++ Function: FILEGetDirectoryFromFullPathA @@ -506,7 +453,7 @@ DWORD FILEGetDirectoryFromFullPathA( LPCSTR lpFullPath, /* look for the first path separator backwards */ lpDirEnd = lpFullPath + full_len - 1; - while( lpDirEnd >= lpFullPath && *lpDirEnd != '/' && *lpDirEnd != '\\') + while( lpDirEnd >= lpFullPath && *lpDirEnd != '/') --lpDirEnd; dir_len = lpDirEnd - lpFullPath + 1; /* +1 for fencepost */ @@ -734,7 +681,7 @@ SearchPathW( /* special case : if file name contains absolute path, don't search the provided path */ - if('\\' == lpFileName[0] || '/' == lpFileName[0]) + if(L'/' == lpFileName[0]) { /* Canonicalize the path to deal with back-to-back '/', etc. */ length = MAX_LONGPATH; //Use it for first try diff --git a/src/coreclr/pal/src/include/pal/file.h b/src/coreclr/pal/src/include/pal/file.h index d56d5df8b62a4..52054306cb3a6 100644 --- a/src/coreclr/pal/src/include/pal/file.h +++ b/src/coreclr/pal/src/include/pal/file.h @@ -59,19 +59,6 @@ Notes : --*/ void FILECanonicalizePath(LPSTR lpUnixPath); -/*++ -Function: - FileDosToUnixPathA - -Abstract: - Change a DOS path to a Unix path. Replace '\' by '/'. - -Parameter: - IN/OUT lpPath: path to be modified ---*/ -void -FILEDosToUnixPathA(LPSTR lpPath); - /*++ Function: FILEGetDirectoryFromFullPathA diff --git a/src/coreclr/pal/src/include/pal/file.hpp b/src/coreclr/pal/src/include/pal/file.hpp index e45607d0bc1dd..c35aa5cbeb86d 100644 --- a/src/coreclr/pal/src/include/pal/file.hpp +++ b/src/coreclr/pal/src/include/pal/file.hpp @@ -190,19 +190,6 @@ Notes : --*/ void FILECanonicalizePath(LPSTR lpUnixPath); -/*++ -Function: - FileDosToUnixPathA - -Abstract: - Change a DOS path to a Unix path. Replace '\' by '/'. - -Parameter: - IN/OUT lpPath: path to be modified ---*/ -void -FILEDosToUnixPathA(LPSTR lpPath); - /*++ Function: FILEGetDirectoryFromFullPathA diff --git a/src/coreclr/pal/src/include/pal/stackstring.hpp b/src/coreclr/pal/src/include/pal/stackstring.hpp index 38c4b84b6672c..4a27a15579c7d 100644 --- a/src/coreclr/pal/src/include/pal/stackstring.hpp +++ b/src/coreclr/pal/src/include/pal/stackstring.hpp @@ -256,6 +256,3 @@ typedef StackString PathWCharString; DWORD GetCurrentDirectoryA( PathCharString& lpBuffer); -void -FILEDosToUnixPathA( - PathCharString& lpPath); diff --git a/src/coreclr/pal/src/loader/module.cpp b/src/coreclr/pal/src/loader/module.cpp index 838fe3d793e2a..ce443f0dfc3c3 100644 --- a/src/coreclr/pal/src/loader/module.cpp +++ b/src/coreclr/pal/src/loader/module.cpp @@ -152,7 +152,6 @@ LoadLibraryExA( return nullptr; } - LPSTR lpstr = nullptr; HMODULE hModule = nullptr; PERF_ENTRY(LoadLibraryA); @@ -166,23 +165,10 @@ LoadLibraryExA( } /* do the Dos/Unix conversion on our own copy of the name */ - lpstr = strdup(lpLibFileName); - if (!lpstr) - { - ERROR("strdup failure!\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto Done; - } - FILEDosToUnixPathA(lpstr); - - hModule = LOADLoadLibrary(lpstr, TRUE); + hModule = LOADLoadLibrary(lpLibFileName, TRUE); /* let LOADLoadLibrary call SetLastError */ Done: - if (lpstr != nullptr) - { - free(lpstr); - } LOGEXIT("LoadLibraryExA returns HMODULE %p\n", hModule); PERF_EXIT(LoadLibraryExA); @@ -235,8 +221,6 @@ LoadLibraryExW( goto done; } - /* do the Dos/Unix conversion on our own copy of the name */ - FILEDosToUnixPathA(lpstr); pathstr.CloseBuffer(name_length); /* let LOADLoadLibrary call SetLastError in case of failure */ @@ -626,8 +610,6 @@ PAL_LoadLibraryDirect( goto done; } - /* do the Dos/Unix conversion on our own copy of the name */ - FILEDosToUnixPathA(lpstr); pathstr.CloseBuffer(name_length); lpcstr = FixLibCName(lpstr); diff --git a/src/coreclr/pal/src/safecrt/tmakepath_s.inl b/src/coreclr/pal/src/safecrt/tmakepath_s.inl index 53517412f75e9..aabf7ee266c10 100644 --- a/src/coreclr/pal/src/safecrt/tmakepath_s.inl +++ b/src/coreclr/pal/src/safecrt/tmakepath_s.inl @@ -48,13 +48,13 @@ errno_t __cdecl _FUNC_NAME(_Out_writes_z_(_SIZE) _CHAR *_DEST, _In_opt_ size_t _ } while (*p != 0); p--; - if (*p != _T('/') && *p != _T('\\')) + if (*p != '/') { if(++written >= _SIZE) { goto error_return; } - *d++ = _T('\\'); + *d++ = '/'; } } diff --git a/src/coreclr/pal/src/safecrt/tsplitpath_s.inl b/src/coreclr/pal/src/safecrt/tsplitpath_s.inl index 4366ec3cebbfa..c3d8b41403882 100644 --- a/src/coreclr/pal/src/safecrt/tsplitpath_s.inl +++ b/src/coreclr/pal/src/safecrt/tsplitpath_s.inl @@ -102,7 +102,7 @@ errno_t __cdecl _FUNC_NAME( tmp = _Path; for (; *tmp != 0; ++tmp) { - if (*tmp == _T('/') || *tmp == _T('\\')) + if (*tmp == '/') { /* point to one beyond for later copy */ last_slash = tmp + 1; @@ -125,16 +125,6 @@ errno_t __cdecl _FUNC_NAME( goto error_erange; } _TCSNCPY_S(_Dir, _DirSize, _Path, length); - - // Normalize the path separator - size_t iIndex; - for(iIndex = 0; iIndex < length; iIndex++) - { - if (_Dir[iIndex] == _T('\\')) - { - _Dir[iIndex] = _T('/'); - } - } } _Path = last_slash; } diff --git a/src/coreclr/pal/src/safecrt/wsplitpath_s.cpp b/src/coreclr/pal/src/safecrt/wsplitpath_s.cpp deleted file mode 100644 index 420d7134acaf1..0000000000000 --- a/src/coreclr/pal/src/safecrt/wsplitpath_s.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*** -*wsplitpath_s.c - break down path name into components -* - -* -*Purpose: -* To provide support for accessing the individual components of an -* arbitrary path name -* -*******************************************************************************/ - -#include -#include -#include -#include "internal_securecrt.h" - -#include "mbusafecrt_internal.h" - -#define _FUNC_PROLOGUE -#define _FUNC_NAME _wsplitpath_s -#define _CHAR char16_t -#define _TCSNCPY_S wcsncpy_s -#define _T(_Character) L##_Character - -#include "tsplitpath_s.inl" diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index 8f93db9f95c1d..29b82b69d383f 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -3417,8 +3417,7 @@ getFileName( NULL, 0, NULL, NULL); /* if only a file name is specified, prefix it with "./" */ - if ((*lpApplicationName != '.') && (*lpApplicationName != '/') && - (*lpApplicationName != '\\')) + if ((*lpApplicationName != '.') && (*lpApplicationName != '/')) { length += 2; lpTemp = lpPathFileName.OpenStringBuffer(length); @@ -3448,9 +3447,6 @@ getFileName( lpPathFileName.CloseBuffer(length -1); - /* Replace '\' by '/' */ - FILEDosToUnixPathA(lpTemp); - return TRUE; } else @@ -3521,8 +3517,6 @@ getFileName( /* restore last character */ *lpEnd = wcEnd; - /* Replace '\' by '/' */ - FILEDosToUnixPathA(lpFileName); if (!getPath(lpFileNamePS, lpPathFileName)) { /* file is not in the path */ diff --git a/src/coreclr/pal/tests/palsuite/common/palsuite.cpp b/src/coreclr/pal/tests/palsuite/common/palsuite.cpp index 5e02d5e709fca..f8bcb0727af17 100644 --- a/src/coreclr/pal/tests/palsuite/common/palsuite.cpp +++ b/src/coreclr/pal/tests/palsuite/common/palsuite.cpp @@ -62,7 +62,7 @@ UINT64 GetHighPrecisionTimeStamp(LARGE_INTEGER performanceFrequency) return ts.QuadPart / (performanceFrequency.QuadPart / 1000); } -static const char* rgchPathDelim = "\\"; +static const char* rgchPathDelim = "/"; int @@ -146,7 +146,7 @@ mkAbsoluteFilenameW ( DWORD dwFileLength, LPWSTR absPathName ) { - const WCHAR szPathDelimW[] = {'\\','\0'}; + const WCHAR szPathDelimW[] = {'/','\0'}; DWORD sizeDN, sizeFN, sizeAPN; diff --git a/src/coreclr/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.cpp b/src/coreclr/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.cpp index e8f481d7114e0..350d187e3950e 100644 --- a/src/coreclr/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.cpp +++ b/src/coreclr/pal/tests/palsuite/file_io/GetFullPathNameA/test3/test3.cpp @@ -35,10 +35,10 @@ PALTEST(file_io_GetFullPathNameA_test3_paltest_getfullpathnamea_test3, "file_io/ #ifdef WIN32 const char* szSeparator = "\\"; #else - const char* szSeparator = "//"; + const char* szSeparator = "/"; #endif - const char* szDotDot = "..\\"; + const char* szDotDot = "../"; const char* szFileName = "testing.tmp"; DWORD dwRc = 0; diff --git a/src/coreclr/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.cpp b/src/coreclr/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.cpp index 57fa29130c64c..2ed9e1279f487 100644 --- a/src/coreclr/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.cpp +++ b/src/coreclr/pal/tests/palsuite/file_io/GetFullPathNameW/test2/test2.cpp @@ -18,7 +18,7 @@ PALTEST(file_io_GetFullPathNameW_test2_paltest_getfullpathnamew_test2, "file_io/GetFullPathNameW/test2/paltest_getfullpathnamew_test2") { - WCHAR szwDotDot[] = {'.','.','\\','\0'}; + WCHAR szwDotDot[] = {'.','.','/','\0'}; WCHAR szwFileName[] = {'t','e','s','t','i','n','g','.','t','m','p','\0'}; DWORD dwRc = 0; diff --git a/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.cpp b/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.cpp index f1be5b6652579..02a01a4fe7534 100644 --- a/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.cpp +++ b/src/coreclr/pal/tests/palsuite/file_io/GetTempFileNameW/test1/GetTempFileNameW.cpp @@ -106,8 +106,8 @@ PALTEST(file_io_GetTempFileNameW_test1_paltest_gettempfilenamew_test1, "file_io/ WCHAR* wCurr = wTempString; memcpy(wCurr, wPath, wcslen(wPath) * sizeof(WCHAR)); wCurr += wcslen(wPath); - wcscat(wCurr, W("\\")); - wCurr += wcslen(W("\\")); + wcscat(wCurr, W("/")); + wCurr += wcslen(W("/")); wcscat(wCurr, wPrefix); if (memcmp(wTempString, wReturnedName, wcslen(wTempString)*sizeof(WCHAR)) == 0) { diff --git a/src/coreclr/tools/metainfo/mdobj.cpp b/src/coreclr/tools/metainfo/mdobj.cpp index 5bb4689410bb0..8102b95bd2d62 100644 --- a/src/coreclr/tools/metainfo/mdobj.cpp +++ b/src/coreclr/tools/metainfo/mdobj.cpp @@ -272,21 +272,26 @@ void DisplayFile(_In_z_ WCHAR* szFile, BOOL isFile, ULONG DumpFilter, _In_opt_z_ // print bar that separates different files pDisplayString("////////////////////////////////////////////////////////////////\n"); - WCHAR rcFname[_MAX_FNAME], rcExt[_MAX_EXT]; - _wsplitpath_s(szFile, NULL, 0, NULL, 0, rcFname, _MAX_FNAME, rcExt, _MAX_EXT); - sprintf_s(szString,1024,"\nFile %S%S: \n",rcFname, rcExt); + WCHAR *pExt = wcsrchr(szFile, W('.')); + WCHAR *pFname = wcsrchr(szFile, DIRECTORY_SEPARATOR_CHAR_W); + if (pFname == NULL) + { + pFname = szFile; + } + + sprintf_s(szString,1024,"\nFile %S: \n",pFname); pDisplayString(szString); if (DumpFilter & MDInfo::dumpValidate) { - if (!_wcsicmp(rcExt, OBJ_EXT_W) || !_wcsicmp(rcExt, LIB_EXT_W)) + if (pExt && (!_wcsicmp(pExt, OBJ_EXT_W) || !_wcsicmp(pExt, LIB_EXT_W))) g_ValModuleType = ValidatorModuleTypeObj; else g_ValModuleType = ValidatorModuleTypePE; } - if (!_wcsicmp(rcExt, LIB_EXT_W)) + if (pExt && !_wcsicmp(pExt, LIB_EXT_W)) DisplayArchive(szFile, DumpFilter, szObjName, pDisplayString); else { diff --git a/src/coreclr/tools/superpmi/mcs/verbmerge.cpp b/src/coreclr/tools/superpmi/mcs/verbmerge.cpp index 82af9cd63e272..68e89df2e047a 100644 --- a/src/coreclr/tools/superpmi/mcs/verbmerge.cpp +++ b/src/coreclr/tools/superpmi/mcs/verbmerge.cpp @@ -349,7 +349,7 @@ int verbMerge::AppendAllInDir(HANDLE hFileOut, { const _WIN32_FIND_DATAW& findData = fileArray[i]; LPWSTR fileFullPath = MergePathStrings(dir, findData.cFileName); - +#ifdef TARGET_WINDOWS if (wcslen(fileFullPath) > MAX_PATH) // This path is too long, use \\?\ to access it. { if (wcscmp(dir, W(".")) == 0) @@ -377,6 +377,7 @@ int verbMerge::AppendAllInDir(HANDLE hFileOut, fileFullPath = newBuffer; } +#endif // TARGET_WINDOWS // Is it zero length? If so, skip it. if ((findData.nFileSizeLow == 0) && (findData.nFileSizeHigh == 0)) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/standardpch.h b/src/coreclr/tools/superpmi/superpmi-shared/standardpch.h index c6e102f1d7d15..8c511b45e91b9 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/standardpch.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/standardpch.h @@ -82,13 +82,6 @@ #include "..\external\msvcdis\inc\disarm64.h" #endif // USE_MSVCDIS -#ifndef DIRECTORY_SEPARATOR_CHAR_A -#define DIRECTORY_SEPARATOR_CHAR_A '\\' -#endif -#ifndef DIRECTORY_SEPARATOR_STR_A -#define DIRECTORY_SEPARATOR_STR_A "\\" -#endif - #ifndef W #ifdef TARGET_UNIX #define W(str) u##str @@ -97,9 +90,27 @@ #endif // TARGET_UNIX #endif // !W +#ifdef TARGET_UNIX +#ifndef DIRECTORY_SEPARATOR_CHAR_A +#define DIRECTORY_SEPARATOR_CHAR_A '/' +#endif +#ifndef DIRECTORY_SEPARATOR_STR_A +#define DIRECTORY_SEPARATOR_STR_A "/" +#endif +#ifndef DIRECTORY_SEPARATOR_STR_W +#define DIRECTORY_SEPARATOR_STR_W W("/") +#endif +#else // TARGET_UNIX +#ifndef DIRECTORY_SEPARATOR_CHAR_A +#define DIRECTORY_SEPARATOR_CHAR_A '\\' +#endif +#ifndef DIRECTORY_SEPARATOR_STR_A +#define DIRECTORY_SEPARATOR_STR_A "\\" +#endif #ifndef DIRECTORY_SEPARATOR_STR_W #define DIRECTORY_SEPARATOR_STR_W W("\\") #endif +#endif // TARGET_UNIX #ifdef TARGET_UNIX #define PLATFORM_SHARED_LIB_SUFFIX_A PAL_SHLIB_SUFFIX diff --git a/src/coreclr/tools/superpmi/superpmi/jitdebugger.cpp b/src/coreclr/tools/superpmi/superpmi/jitdebugger.cpp index 242771fe796c8..44ddfa962c07f 100644 --- a/src/coreclr/tools/superpmi/superpmi/jitdebugger.cpp +++ b/src/coreclr/tools/superpmi/superpmi/jitdebugger.cpp @@ -155,7 +155,7 @@ HRESULT GetCurrentModuleFileName(_Out_writes_(*pcchBuffer) LPWSTR pBuffer, __ino } // Pick off the part after the path. - WCHAR* appName = wcsrchr(appPath, L'\\'); + WCHAR* appName = wcsrchr(appPath, DIRECTORY_SEPARATOR_CHAR_W); // If no backslash, use the whole name; if there is a backslash, skip it. appName = appName ? appName + 1 : appPath; diff --git a/src/coreclr/utilcode/longfilepathwrappers.cpp b/src/coreclr/utilcode/longfilepathwrappers.cpp index 41635c7084f99..3dea6ad57e8eb 100644 --- a/src/coreclr/utilcode/longfilepathwrappers.cpp +++ b/src/coreclr/utilcode/longfilepathwrappers.cpp @@ -7,221 +7,30 @@ #include "sstring.h" #include "ex.h" +#ifdef HOST_WINDOWS class LongFile { private: -#ifdef HOST_WINDOWS static const WCHAR* ExtendedPrefix; static const WCHAR* DevicePathPrefix; static const WCHAR* UNCPathPrefix; static const WCHAR* UNCExtendedPathPrefix; static const WCHAR VolumeSeparatorChar; #define UNCPATHPREFIX W("\\\\") -#endif //HOST_WINDOWS - static const WCHAR DirectorySeparatorChar; static const WCHAR AltDirectorySeparatorChar; + static const WCHAR DirectorySeparatorChar; public: - static BOOL ContainsDirectorySeparator(SString & path); static BOOL IsDirectorySeparator(WCHAR c); static BOOL IsPathNotFullyQualified(const SString & path); static HRESULT NormalizePath(SString& path); -#ifdef HOST_WINDOWS static BOOL IsExtended(const SString & path); static BOOL IsUNCExtended(const SString & path); static BOOL IsDevice(const SString & path); static void NormalizeDirectorySeparators(SString& path); -#endif }; - -HMODULE -LoadLibraryExWrapper( - LPCWSTR lpLibFileName, - HANDLE hFile, - DWORD dwFlags - ) -{ - CONTRACTL - { - NOTHROW; - } - CONTRACTL_END; - - HRESULT hr = S_OK; - HMODULE ret = NULL; - DWORD lastError = 0; - - EX_TRY - { - LongPathString path(LongPathString::Literal, lpLibFileName); - - if (LongFile::IsPathNotFullyQualified(path) || SUCCEEDED(LongFile::NormalizePath(path))) - { -#ifdef HOST_WINDOWS - LongFile::NormalizeDirectorySeparators(path); -#endif //HOST_WINDOWS - - ret = LoadLibraryExW(path.GetUnicode(), hFile, dwFlags); - } - - lastError = GetLastError(); - } - EX_CATCH_HRESULT(hr); - - if (hr != S_OK) - { - SetLastError(hr); - } - else if(ret == NULL) - { - SetLastError(lastError); - } - - return ret; -} - -HANDLE -CreateFileWrapper( - _In_ LPCWSTR lpFileName, - _In_ DWORD dwDesiredAccess, - _In_ DWORD dwShareMode, - _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, - _In_ DWORD dwCreationDisposition, - _In_ DWORD dwFlagsAndAttributes, - _In_opt_ HANDLE hTemplateFile - ) -{ - CONTRACTL - { - NOTHROW; - } - CONTRACTL_END; - - HRESULT hr = S_OK; - DWORD lastError = 0; - HANDLE ret = INVALID_HANDLE_VALUE; - - EX_TRY - { - LongPathString path(LongPathString::Literal, lpFileName); - - if (SUCCEEDED(LongFile::NormalizePath(path))) - { - ret = CreateFileW(path.GetUnicode(), - dwDesiredAccess, - dwShareMode, - lpSecurityAttributes, - dwCreationDisposition, - dwFlagsAndAttributes, - hTemplateFile); - - } - - lastError = GetLastError(); - } - EX_CATCH_HRESULT(hr); - - if (hr != S_OK ) - { - SetLastError(hr); - } - else if(ret == INVALID_HANDLE_VALUE) - { - SetLastError(lastError); - } - - return ret; -} - -DWORD -GetFileAttributesWrapper( - _In_ LPCWSTR lpFileName - ) -{ - CONTRACTL - { - NOTHROW; - } - CONTRACTL_END; - - HRESULT hr = S_OK; - DWORD ret = INVALID_FILE_ATTRIBUTES; - DWORD lastError = 0; - - EX_TRY - { - LongPathString path(LongPathString::Literal, lpFileName); - - if (SUCCEEDED(LongFile::NormalizePath(path))) - { - ret = GetFileAttributesW( - path.GetUnicode() - ); - } - - lastError = GetLastError(); - } - EX_CATCH_HRESULT(hr); - - if (hr != S_OK ) - { - SetLastError(hr); - } - else if(ret == INVALID_FILE_ATTRIBUTES) - { - SetLastError(lastError); - } - - return ret; -} - -BOOL -GetFileAttributesExWrapper( - _In_ LPCWSTR lpFileName, - _In_ GET_FILEEX_INFO_LEVELS fInfoLevelId, - _Out_writes_bytes_(sizeof(WIN32_FILE_ATTRIBUTE_DATA)) LPVOID lpFileInformation - ) -{ - CONTRACTL - { - NOTHROW; - } - CONTRACTL_END; - - HRESULT hr = S_OK; - BOOL ret = FALSE; - DWORD lastError = 0; - - EX_TRY - { - LongPathString path(LongPathString::Literal, lpFileName); - - if (SUCCEEDED(LongFile::NormalizePath(path))) - { - ret = GetFileAttributesExW( - path.GetUnicode(), - fInfoLevelId, - lpFileInformation - ); - - } - - lastError = GetLastError(); - } - EX_CATCH_HRESULT(hr); - - if (hr != S_OK ) - { - SetLastError(hr); - } - else if(ret == FALSE) - { - SetLastError(lastError); - } - - return ret; -} +#endif // HOST_WINDOWS DWORD SearchPathWrapper( @@ -245,8 +54,8 @@ SearchPathWrapper( EX_TRY { +#ifdef HOST_WINDOWS LongPathString Existingpath(LongPathString::Literal, lpPath); - if (lpPath != NULL) { if (FAILED(LongFile::NormalizePath(Existingpath))) @@ -258,6 +67,7 @@ SearchPathWrapper( lpPath = Existingpath.GetUnicode(); } } +#endif // HOST_WINDOWS if (!getPath) { @@ -474,9 +284,152 @@ DWORD WINAPI GetEnvironmentVariableWrapper( return ret; } - #ifdef HOST_WINDOWS +HMODULE +LoadLibraryExWrapper( + LPCWSTR lpLibFileName, + HANDLE hFile, + DWORD dwFlags + ) +{ + CONTRACTL + { + NOTHROW; + } + CONTRACTL_END; + + HRESULT hr = S_OK; + HMODULE ret = NULL; + DWORD lastError = 0; + + EX_TRY + { + LongPathString path(LongPathString::Literal, lpLibFileName); + + if (LongFile::IsPathNotFullyQualified(path) || SUCCEEDED(LongFile::NormalizePath(path))) + { + LongFile::NormalizeDirectorySeparators(path); + + ret = LoadLibraryExW(path.GetUnicode(), hFile, dwFlags); + } + + lastError = GetLastError(); + } + EX_CATCH_HRESULT(hr); + + if (hr != S_OK) + { + SetLastError(hr); + } + else if(ret == NULL) + { + SetLastError(lastError); + } + + return ret; +} + +HANDLE +CreateFileWrapper( + _In_ LPCWSTR lpFileName, + _In_ DWORD dwDesiredAccess, + _In_ DWORD dwShareMode, + _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, + _In_ DWORD dwCreationDisposition, + _In_ DWORD dwFlagsAndAttributes, + _In_opt_ HANDLE hTemplateFile + ) +{ + CONTRACTL + { + NOTHROW; + } + CONTRACTL_END; + + HRESULT hr = S_OK; + DWORD lastError = 0; + HANDLE ret = INVALID_HANDLE_VALUE; + + EX_TRY + { + LongPathString path(LongPathString::Literal, lpFileName); + + if (SUCCEEDED(LongFile::NormalizePath(path))) + { + ret = CreateFileW(path.GetUnicode(), + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + + } + + lastError = GetLastError(); + } + EX_CATCH_HRESULT(hr); + + if (hr != S_OK ) + { + SetLastError(hr); + } + else if(ret == INVALID_HANDLE_VALUE) + { + SetLastError(lastError); + } + + return ret; +} + +BOOL +GetFileAttributesExWrapper( + _In_ LPCWSTR lpFileName, + _In_ GET_FILEEX_INFO_LEVELS fInfoLevelId, + _Out_writes_bytes_(sizeof(WIN32_FILE_ATTRIBUTE_DATA)) LPVOID lpFileInformation + ) +{ + CONTRACTL + { + NOTHROW; + } + CONTRACTL_END; + + HRESULT hr = S_OK; + BOOL ret = FALSE; + DWORD lastError = 0; + + EX_TRY + { + LongPathString path(LongPathString::Literal, lpFileName); + + if (SUCCEEDED(LongFile::NormalizePath(path))) + { + ret = GetFileAttributesExW( + path.GetUnicode(), + fInfoLevelId, + lpFileInformation + ); + + } + + lastError = GetLastError(); + } + EX_CATCH_HRESULT(hr); + + if (hr != S_OK ) + { + SetLastError(hr); + } + else if(ret == FALSE) + { + SetLastError(lastError); + } + + return ret; +} + BOOL CopyFileExWrapper( _In_ LPCWSTR lpExistingFileName, @@ -530,12 +483,10 @@ CopyFileExWrapper( return ret; } -#endif // HOST_WINDOWS //Implementation of LongFile Helpers const WCHAR LongFile::DirectorySeparatorChar = W('\\'); const WCHAR LongFile::AltDirectorySeparatorChar = W('/'); -#ifdef HOST_WINDOWS const WCHAR LongFile::VolumeSeparatorChar = W(':'); const WCHAR* LongFile::ExtendedPrefix = W("\\\\?\\"); const WCHAR* LongFile::DevicePathPrefix = W("\\\\.\\"); @@ -682,25 +633,10 @@ HRESULT LongFile::NormalizePath(SString & path) return S_OK; } -#else -BOOL LongFile::IsPathNotFullyQualified(const SString & path) -{ - return TRUE; -} - -//Don't need to do anything For XPlat -HRESULT LongFile::NormalizePath(SString & path) -{ - return S_OK; -} -#endif //HOST_WINDOWS - -BOOL LongFile::ContainsDirectorySeparator(SString & path) -{ - return path.Find(path.Begin(), DirectorySeparatorChar) || path.Find(path.Begin(), AltDirectorySeparatorChar); -} BOOL LongFile::IsDirectorySeparator(WCHAR c) { - return c == DirectorySeparatorChar || c == AltDirectorySeparatorChar; + return c == DirectorySeparatorChar || c == AltDirectorySeparatorChar;; } + +#endif //HOST_WINDOWS diff --git a/src/coreclr/utilcode/splitpath.cpp b/src/coreclr/utilcode/splitpath.cpp index 949bf8b5dc5eb..0564990c20ff0 100644 --- a/src/coreclr/utilcode/splitpath.cpp +++ b/src/coreclr/utilcode/splitpath.cpp @@ -76,7 +76,6 @@ void SplitPathInterior( * relative path: * top\next\last\ ; or * top/next/last/ - * Mixed use of '/' and '\' within a path is also tolerated * fname: * 0 to _MAX_FNAME-1 characters not including the '.' character * ext: @@ -108,7 +107,7 @@ void SplitPathInterior( */ for (last_slash = NULL, p = (WCHAR *)wszPath; *p; p++) { - if (*p == _T('/') || *p == _T('\\')) + if (*p == DIRECTORY_SEPARATOR_CHAR_W) /* point to one beyond for later copy */ last_slash = p + 1; else if (*p == _T('.')) diff --git a/src/coreclr/vm/clrex.cpp b/src/coreclr/vm/clrex.cpp index a8440f3f927a8..2073bcaf3e391 100644 --- a/src/coreclr/vm/clrex.cpp +++ b/src/coreclr/vm/clrex.cpp @@ -1554,10 +1554,7 @@ void EEFileLoadException::SetFileName(const SString &fileName, BOOL removePath) { SString::CIterator i = fileName.End(); - if (fileName.FindBack(i, W('\\'))) - i++; - - if (fileName.FindBack(i, W('/'))) + if (fileName.FindBack(i, DIRECTORY_SEPARATOR_CHAR_W)) i++; m_name.Set(fileName, i, fileName.End()); diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index a81a2bd9f663f..0dc1e17680681 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -1940,8 +1940,10 @@ JIT_LOAD_DATA g_JitLoadData; // load a JIT from the root of the drive. // // The minimal set of characters that we must check for and exclude are: -// '\\' - (backslash) +// On all platforms: // '/' - (forward slash) +// On Windows: +// '\\' - (backslash) // ':' - (colon) // // Returns false if we find any of these characters in 'pwzJitName' @@ -1954,7 +1956,11 @@ static bool ValidateJitName(LPCWSTR pwzJitName) wchar_t curChar; do { curChar = *pCurChar; - if ((curChar == '\\') || (curChar == '/') || (curChar == ':')) + if (curChar == '/' +#ifdef TARGET_WINDOWS + || (curChar == '\\') || (curChar == ':') +#endif + ) { // Return false if we find any of these character in 'pwzJitName' return false; diff --git a/src/coreclr/vm/eeconfig.cpp b/src/coreclr/vm/eeconfig.cpp index 64df3d427f532..130bdd82f7bf7 100644 --- a/src/coreclr/vm/eeconfig.cpp +++ b/src/coreclr/vm/eeconfig.cpp @@ -388,7 +388,7 @@ HRESULT EEConfig::sync() if (WszGetModuleFileName(NULL, wszFileName) != 0) { // just keep the name - LPCWSTR pwszName = wcsrchr(wszFileName, W('\\')); + LPCWSTR pwszName = wcsrchr(wszFileName, DIRECTORY_SEPARATOR_CHAR_W); pwszName = (pwszName == NULL) ? wszFileName.GetUnicode() : (pwszName + 1); if (SString::_wcsicmp(pwszName,pszGCStressExe) == 0) diff --git a/src/coreclr/vm/gdbjit.cpp b/src/coreclr/vm/gdbjit.cpp index bea3035299d9c..0f22e98aaf5a8 100644 --- a/src/coreclr/vm/gdbjit.cpp +++ b/src/coreclr/vm/gdbjit.cpp @@ -3610,7 +3610,7 @@ const char * NotifyGdb::SplitFilename(const char* path) const char *pSlash = nullptr; for (const char *p = path; *p != '\0'; p++) { - if (*p == '/' || *p == '\\') + if (*p == DIRECTORY_SEPARATOR_CHAR_A) pSlash = p; } diff --git a/src/coreclr/vm/multicorejit.cpp b/src/coreclr/vm/multicorejit.cpp index 3526ef15c7bb6..d52d71081f804 100644 --- a/src/coreclr/vm/multicorejit.cpp +++ b/src/coreclr/vm/multicorejit.cpp @@ -995,9 +995,9 @@ HRESULT MulticoreJitRecorder::StartProfile(const WCHAR * pRoot, const WCHAR * pF // Append separator if root does not end with one unsigned len = m_fullFileName.GetCount(); - if ((len != 0) && (m_fullFileName[len - 1] != W('\\'))) + if ((len != 0) && (m_fullFileName[len - 1] != DIRECTORY_SEPARATOR_CHAR_W)) { - m_fullFileName.Append(W('\\')); + m_fullFileName.Append(DIRECTORY_SEPARATOR_CHAR_W); } m_fullFileName.Append(pFile); diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index 1f73b9122615b..0faee2e520c90 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -927,7 +927,7 @@ void PEAssembly::PathToUrl(SString &string) } #else // Unix doesn't have a distinction between a network or a local path - _ASSERTE( i[0] == W('\\') || i[0] == W('/')); + _ASSERTE(i[0] == W('/')); SString sss(SString::Literal, W("file://")); string.Insert(i, sss); string.Skip(i, sss); @@ -960,33 +960,19 @@ void PEAssembly::UrlToPath(SString &string) if (string.MatchCaseInsensitive(i, sss2)) string.Delete(i, 7); +#if !defined(TARGET_UNIX) while (string.Find(i, W('/'))) { string.Replace(i, W('\\')); } +#endif RETURN; } BOOL PEAssembly::FindLastPathSeparator(const SString &path, SString::Iterator &i) { -#ifdef TARGET_UNIX - SString::Iterator slash = i; - SString::Iterator backSlash = i; - BOOL foundSlash = path.FindBack(slash, '/'); - BOOL foundBackSlash = path.FindBack(backSlash, '\\'); - if (!foundSlash && !foundBackSlash) - return FALSE; - else if (foundSlash && !foundBackSlash) - i = slash; - else if (!foundSlash && foundBackSlash) - i = backSlash; - else - i = (backSlash > slash) ? backSlash : slash; - return TRUE; -#else - return path.FindBack(i, '\\'); -#endif //TARGET_UNIX + return path.FindBack(i, DIRECTORY_SEPARATOR_CHAR_A); } // ------------------------------------------------------------ diff --git a/src/coreclr/vm/peimage.cpp b/src/coreclr/vm/peimage.cpp index 0ef20ab146b0b..8d87ab168db86 100644 --- a/src/coreclr/vm/peimage.cpp +++ b/src/coreclr/vm/peimage.cpp @@ -170,7 +170,7 @@ CHECK PEImage::CheckCanonicalFullPath(const SString &path) MODE_ANY; } CONTRACT_CHECK_END; - +#ifdef TARGET_WINDOWS CCHECK_START { // This is not intended to be an exhaustive test, just to provide a sanity check @@ -197,19 +197,19 @@ CHECK PEImage::CheckCanonicalFullPath(const SString &path) while (i != path.End()) { // Check for multiple slashes - if(*i != '\\') + if(*i != DIRECTORY_SEPARATOR_CHAR_A) { // Check for . or .. SString sParentDir(SString::Ascii, ".."); SString sCurrentDir(SString::Ascii, "."); if ((path.Skip(i, sParentDir) || path.Skip(i, sCurrentDir)) - && (path.Match(i, '\\'))) + && (path.Match(i, DIRECTORY_SEPARATOR_CHAR_A))) { CCHECK_FAIL("Illegal . or .."); } - if (!path.Find(i, '\\')) + if (!path.Find(i, DIRECTORY_SEPARATOR_CHAR_A)) break; } @@ -217,6 +217,7 @@ CHECK PEImage::CheckCanonicalFullPath(const SString &path) } } CCHECK_END; +#endif // TARGET_WINDOWS CHECK_OK; } diff --git a/src/coreclr/vm/peimage.inl b/src/coreclr/vm/peimage.inl index 3fec6c1086e51..833d00ee230a7 100644 --- a/src/coreclr/vm/peimage.inl +++ b/src/coreclr/vm/peimage.inl @@ -78,7 +78,7 @@ inline void PEImage::SetModuleFileNameHintForDAC() { const WCHAR* pChar = pStartPath + nChars; nChars = 0; - while ((pChar >= pStartPath) && (*pChar != L'\\')) + while ((pChar >= pStartPath) && (*pChar != DIRECTORY_SEPARATOR_CHAR_W)) { pChar--; nChars++; diff --git a/src/coreclr/vm/stubgen.cpp b/src/coreclr/vm/stubgen.cpp index 74f7428928dff..3528b0656964f 100644 --- a/src/coreclr/vm/stubgen.cpp +++ b/src/coreclr/vm/stubgen.cpp @@ -44,8 +44,8 @@ void DumpIL_RemoveFullPath(SString &strTokenFormatting) { SString::Iterator lastSlash = strTokenFormatting.End() - 1; - // Find the last '\\' in the string. - while ((lastSlash != leftBracket) && (*lastSlash != '\\')) + // Find the last directory separator character ('\\' on Windows, '/' on Unix) in the string. + while ((lastSlash != leftBracket) && (*lastSlash != DIRECTORY_SEPARATOR_CHAR_A)) { --lastSlash; } diff --git a/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleExtractToSpecificPath.cs b/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleExtractToSpecificPath.cs index 8c3b8a4ee4460..36f5ec5adcfd1 100644 --- a/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleExtractToSpecificPath.cs +++ b/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleExtractToSpecificPath.cs @@ -79,6 +79,11 @@ private void Bundle_Extraction_To_Relative_Path_Succeeds(string relativePath, Bu if (relativePath == "foo/bar" && OperatingSystem.IsWindows()) return; + // Similarly on non-Windows OSes, we don't convert backslash directory separators + // to forward ones. + if (relativePath == "foo\\bar" && !OperatingSystem.IsWindows()) + return; + var fixture = sharedTestState.TestFixture.Copy(); var bundler = BundleSelfContainedApp(fixture, out var singleFile, bundleOptions); diff --git a/src/libraries/System.Runtime/tests/System/Type/TypeTests.cs b/src/libraries/System.Runtime/tests/System/Type/TypeTests.cs index 03fc052ef4a9d..7a92fc1be38b1 100644 --- a/src/libraries/System.Runtime/tests/System/Type/TypeTests.cs +++ b/src/libraries/System.Runtime/tests/System/Type/TypeTests.cs @@ -852,7 +852,7 @@ public class ContextBoundClass : ContextBoundObject static string testtype = "System.Collections.Generic.Dictionary`2[[Program, Foo], [Program, Foo]]"; private static Func assemblyloader = (aName) => aName.Name == "TestLoadAssembly" ? - Assembly.LoadFrom(@".\TestLoadAssembly.dll") : + Assembly.LoadFrom(Path.Join(".", "TestLoadAssembly.dll")) : null; private static Func typeloader = (assem, name, ignore) => assem == null ? Type.GetType(name, false, ignore) : diff --git a/src/tests/Loader/CollectibleAssemblies/ResolvedFromDifferentContext/ResolvedFromDifferentContext.cs b/src/tests/Loader/CollectibleAssemblies/ResolvedFromDifferentContext/ResolvedFromDifferentContext.cs index 18f876d521d6a..c7469d09f66be 100644 --- a/src/tests/Loader/CollectibleAssemblies/ResolvedFromDifferentContext/ResolvedFromDifferentContext.cs +++ b/src/tests/Loader/CollectibleAssemblies/ResolvedFromDifferentContext/ResolvedFromDifferentContext.cs @@ -31,7 +31,7 @@ protected override Assembly Load(AssemblyName assemblyName) { AssemblyLoadContext alc1 = new AssemblyLoadContext("Dependencies", true); Console.WriteLine($"Loading TestInterface by alc {alc1} for {(IsCollectible ? "collectible" : "non-collectible")} alc {this}"); - Assembly a = alc1.LoadFromAssemblyPath(Test.GetTestAssemblyPath(@"..\TestInterface\TestInterface.dll")); + Assembly a = alc1.LoadFromAssemblyPath(Test.GetTestAssemblyPath(Path.Join("..", "TestInterface", "TestInterface.dll"))); interfaceAssemblyRef = new WeakReference(a); return a; } @@ -56,7 +56,7 @@ private static Assembly LoadUsingResolvingEvent(bool collectibleParent) alc1 = new AssemblyLoadContext("Dependencies", true); AssemblyLoadContext alc2 = new AssemblyLoadContext("Test1", collectibleParent); alc2.Resolving += Alc2_Resolving; - Assembly assembly = alc2.LoadFromAssemblyPath(Test.GetTestAssemblyPath(@"..\TestClass\TestClass.dll")); + Assembly assembly = alc2.LoadFromAssemblyPath(Test.GetTestAssemblyPath(Path.Join("..", "TestClass", "TestClass.dll"))); Type t = assembly.GetType("TestClass.Class"); Console.WriteLine($"Type {t} obtained"); @@ -76,7 +76,7 @@ private static Assembly Alc2_Resolving(AssemblyLoadContext arg1, AssemblyName ar if (alc1 != null && arg2.Name == "TestInterface") { Console.WriteLine($"Loading TestInterface by alc {alc1} for {(arg1.IsCollectible ? "collectible" : "non-collectible")} alc {arg1}"); - Assembly a = alc1.LoadFromAssemblyPath(Test.GetTestAssemblyPath(@"..\TestInterface\TestInterface.dll")); + Assembly a = alc1.LoadFromAssemblyPath(Test.GetTestAssemblyPath(Path.Join("..", "TestInterface", "TestInterface.dll"))); interfaceAssemblyRef = new WeakReference(a); return a; } @@ -88,7 +88,7 @@ private static Assembly Alc2_Resolving(AssemblyLoadContext arg1, AssemblyName ar private static Assembly LoadUsingLoadOverride(bool collectibleParent) { TestAssemblyLoadContext alc2 = new TestAssemblyLoadContext("Test2", collectibleParent); - Assembly assembly = alc2.LoadFromAssemblyPath(Test.GetTestAssemblyPath(@"..\TestClass\TestClass.dll")); + Assembly assembly = alc2.LoadFromAssemblyPath(Test.GetTestAssemblyPath(Path.Join("..", "TestClass", "TestClass.dll"))); Type t = assembly.GetType("TestClass.Class");