private static string TryExpandShortFileName(ref StringBuffer outputBuffer, string originalPath) { // We guarantee we'll expand short names for paths that only partially exist. As such, we need to find the part of the path that actually does exist. To // avoid allocating like crazy we'll create only one input array and modify the contents with embedded nulls. Debug.Assert(!PathInternal.IsPartiallyQualified(outputBuffer.AsSpan()), "should have resolved by now"); // We'll have one of a few cases by now (the normalized path will have already: // // 1. Dos path (C:\) // 2. Dos UNC (\\Server\Share) // 3. Dos device path (\\.\C:\, \\?\C:\) // // We want to put the extended syntax on the front if it doesn't already have it, which may mean switching from \\.\. // // Note that we will never get \??\ here as GetFullPathName() does not recognize \??\ and will return it as C:\??\ (or whatever the current drive is). int rootLength = PathInternal.GetRootLength(outputBuffer.AsSpan()); bool isDevice = PathInternal.IsDevice(outputBuffer.AsSpan()); StringBuffer inputBuffer = new StringBuffer(0); try { bool isDosUnc = false; int rootDifference = 0; bool wasDotDevice = false; // Add the extended prefix before expanding to allow growth over MAX_PATH if (isDevice) { // We have one of the following (\\?\ or \\.\) inputBuffer.Append(ref outputBuffer); if (outputBuffer[2] == '.') { wasDotDevice = true; inputBuffer[2] = '?'; } } else { isDosUnc = !PathInternal.IsDevice(outputBuffer.AsSpan()) && outputBuffer.Length > 1 && outputBuffer[0] == '\\' && outputBuffer[1] == '\\'; rootDifference = GetInputBuffer(ref outputBuffer, isDosUnc, ref inputBuffer); } rootLength += rootDifference; int inputLength = inputBuffer.Length; bool success = false; int foundIndex = inputBuffer.Length - 1; while (!success) { uint result = Interop.Kernel32.GetLongPathNameW(inputBuffer.UnderlyingArray, outputBuffer.UnderlyingArray, (uint)outputBuffer.Capacity); // Replace any temporary null we added if (inputBuffer[foundIndex] == '\0') { inputBuffer[foundIndex] = '\\'; } if (result == 0) { // Look to see if we couldn't find the file int error = Marshal.GetLastWin32Error(); if (error != Interop.Errors.ERROR_FILE_NOT_FOUND && error != Interop.Errors.ERROR_PATH_NOT_FOUND) { // Some other failure, give up break; } // We couldn't find the path at the given index, start looking further back in the string. foundIndex--; for (; foundIndex > rootLength && inputBuffer[foundIndex] != '\\'; foundIndex--) { ; } if (foundIndex == rootLength) { // Can't trim the path back any further break; } else { // Temporarily set a null in the string to get Windows to look further up the path inputBuffer[foundIndex] = '\0'; } } else if (result > outputBuffer.Capacity) { // Not enough space. The result count for this API does not include the null terminator. outputBuffer.EnsureCapacity(checked ((int)result)); result = Interop.Kernel32.GetLongPathNameW(inputBuffer.UnderlyingArray, outputBuffer.UnderlyingArray, (uint)outputBuffer.Capacity); } else { // Found the path success = true; outputBuffer.Length = checked ((int)result); if (foundIndex < inputLength - 1) { // It was a partial find, put the non-existent part of the path back outputBuffer.Append(ref inputBuffer, foundIndex, inputBuffer.Length - foundIndex); } } } // Strip out the prefix and return the string ref StringBuffer bufferToUse = ref Choose(success, ref outputBuffer, ref inputBuffer); // Switch back from \\?\ to \\.\ if necessary if (wasDotDevice) { bufferToUse[2] = '.'; } string returnValue = null; int newLength = bufferToUse.Length - rootDifference; if (isDosUnc) { // Need to go from \\?\UNC\ to \\?\UN\\ bufferToUse[PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength] = '\\'; } // We now need to strip out any added characters at the front of the string if (bufferToUse.SubstringEquals(originalPath, rootDifference, newLength)) { // Use the original path to avoid allocating returnValue = originalPath; } else { returnValue = bufferToUse.Substring(rootDifference, newLength); } return(returnValue); }