Exemple #1
0
        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);
            }
        }