internal unsafe bool TryExpandShortFileName() { if (doNotTryExpandShortFileName) { return(false); } if (useStackAlloc) { NullTerminate(); char *buffer = UnsafeGetArrayPtr(); char *shortFileNameBuffer = stackalloc char[Path.MaxPath + 1]; int r = Interop.mincore.GetLongPathNameW(buffer, shortFileNameBuffer, Path.MaxPath); // If success, the return buffer length does not account for the terminating null character. // If in-sufficient buffer, the return buffer length does account for the path + the terminating null character. // If failure, the return buffer length is zero if (r >= Path.MaxPath) { throw new PathTooLongException(SR.IO_PathTooLong); } if (r == 0) { // Note: GetLongPathName will return ERROR_INVALID_FUNCTION on a // path like \\.\PHYSICALDEVICE0 - some device driver doesn't // support GetLongPathName on that string. This behavior is // by design, according to the Core File Services team. // We also get ERROR_NOT_ENOUGH_QUOTA in SQL_CLR_STRESS runs // intermittently on paths like D:\DOCUME~1\user\LOCALS~1\Temp\ // We do not need to call GetLongPathName if we know it will fail becasue the path does not exist: int lastErr = Marshal.GetLastWin32Error(); if (lastErr == Interop.mincore.Errors.ERROR_FILE_NOT_FOUND || lastErr == Interop.mincore.Errors.ERROR_PATH_NOT_FOUND) { doNotTryExpandShortFileName = true; } return(false); } // Safe to copy as we have already done Path.MaxPath bound checking Wstrcpy(buffer, shortFileNameBuffer, r); Length = r; // We should explicitly null terminate as in some cases the long version of the path // might actually be shorter than what we started with because of Win32's normalization // Safe to write directly as bufferLength is guaranteed to be < Path.MaxPath NullTerminate(); return(true); } else { StringBuilder sb = GetStringBuilder(); String origName = sb.ToString(); String tempName = origName; bool addedPrefix = false; if (tempName.Length > Path.MaxPath) { tempName = PathInternal.AddExtendedPathPrefix(tempName); addedPrefix = true; } sb.Capacity = m_capacity; sb.Length = 0; int r = Interop.mincore.GetLongPathNameW(tempName, sb, m_capacity); if (r == 0) { // Note: GetLongPathName will return ERROR_INVALID_FUNCTION on a // path like \\.\PHYSICALDEVICE0 - some device driver doesn't // support GetLongPathName on that string. This behavior is // by design, according to the Core File Services team. // We also get ERROR_NOT_ENOUGH_QUOTA in SQL_CLR_STRESS runs // intermittently on paths like D:\DOCUME~1\user\LOCALS~1\Temp\ // We do not need to call GetLongPathName if we know it will fail becasue the path does not exist: int lastErr = Marshal.GetLastWin32Error(); if (Interop.mincore.Errors.ERROR_FILE_NOT_FOUND == lastErr || Interop.mincore.Errors.ERROR_PATH_NOT_FOUND == lastErr) { doNotTryExpandShortFileName = true; } sb.Length = 0; sb.Append(origName); return(false); } if (addedPrefix) { r -= 4; } // If success, the return buffer length does not account for the terminating null character. // If in-sufficient buffer, the return buffer length does account for the path + the terminating null character. // If failure, the return buffer length is zero if (r >= m_maxPath) { throw new PathTooLongException(SR.IO_PathTooLong); } sb = PathInternal.RemoveExtendedPathPrefix(sb); Length = sb.Length; return(true); } }