private static string GetModuleFileName(IntPtr handle) { char[] buffer = null; // Try increased buffer sizes if on longpath-enabled Windows for (int bufferSize = NativeMethodsShared.MAX_PATH; bufferSize <= NativeMethodsShared.MaxPath; bufferSize *= 2) { buffer = System.Buffers.ArrayPool <char> .Shared.Rent(bufferSize); try { var handleRef = new System.Runtime.InteropServices.HandleRef(buffer, handle); int pathLength = NativeMethodsShared.GetModuleFileName(handleRef, buffer, bufferSize); bool isBufferTooSmall = (uint)Marshal.GetLastWin32Error() == NativeMethodsShared.ERROR_INSUFFICIENT_BUFFER; if (pathLength != 0 && !isBufferTooSmall) { return(new string(buffer, 0, pathLength)); } } finally { System.Buffers.ArrayPool <char> .Shared.Return(buffer); } // Double check that the buffer is not insanely big ErrorUtilities.VerifyThrow(bufferSize <= int.MaxValue / 2, "Buffer size approaching int.MaxValue"); } return(string.Empty); }
private static string GetModuleFileName(IntPtr handle) { bool success = false; var buffer = new StringBuilder(); // Try increased buffer sizes if on longpath-enabled Windows for (int bufferSize = NativeMethodsShared.MAX_PATH; !success && bufferSize <= NativeMethodsShared.MaxPath; bufferSize *= 2) { buffer.EnsureCapacity(bufferSize); var handleRef = new System.Runtime.InteropServices.HandleRef(buffer, handle); int pathLength = NativeMethodsShared.GetModuleFileName(handleRef, buffer, buffer.Capacity); bool isBufferTooSmall = ((uint)Marshal.GetLastWin32Error() == NativeMethodsShared.ERROR_INSUFFICIENT_BUFFER); success = pathLength != 0 && !isBufferTooSmall; } return(success ? buffer.ToString() : string.Empty); }
/// <summary> /// Strips type library number from a type library path (for example, "ref.dll\2" becomes "ref.dll") /// </summary> /// <param name="typeLibPath">type library path with possible typelib number appended to it</param> /// <returns>proper file path to the type library</returns> internal static string StripTypeLibNumberFromPath(string typeLibPath, FileExists fileExists) { bool lastChance = false; if (typeLibPath != null && typeLibPath.Length > 0) { if (!fileExists(typeLibPath)) { // Strip the type library number int lastSlash = typeLibPath.LastIndexOf('\\'); if (lastSlash != -1) { bool allNumbers = true; for (int i = lastSlash + 1; i < typeLibPath.Length; i++) { if (!Char.IsDigit(typeLibPath[i])) { allNumbers = false; break; } } // If we had all numbers past the last slash then we're OK to strip // the type library number if (allNumbers) { typeLibPath = typeLibPath.Substring(0, lastSlash); if (!fileExists(typeLibPath)) { lastChance = true; } } else { lastChance = true; } } else { lastChance = true; } } } // If we couldn't find the path directly, we'll use the same mechanism Windows uses to find // libraries. LoadLibrary() will search all of the correct paths to find this module. We can then // use GetModuleFileName() to determine the actual path from which the module was loaded. This problem // was exposed in Vista where certain libraries are registered but are lacking paths in the registry, // so the old code would fail to find them on disk using the simplistic checks above. if (lastChance) { IntPtr libraryHandle = NativeMethodsShared.LoadLibrary(typeLibPath); if (IntPtr.Zero != libraryHandle) { try { StringBuilder sb = new StringBuilder(NativeMethodsShared.MAX_PATH); System.Runtime.InteropServices.HandleRef handleRef = new System.Runtime.InteropServices.HandleRef(sb, libraryHandle); int len = NativeMethodsShared.GetModuleFileName(handleRef, sb, sb.Capacity); if ((len != 0) && ((uint)Marshal.GetLastWin32Error() != NativeMethodsShared.ERROR_INSUFFICIENT_BUFFER)) { typeLibPath = sb.ToString(); } else { typeLibPath = ""; } } finally { NativeMethodsShared.FreeLibrary(libraryHandle); } } else { typeLibPath = ""; } } return(typeLibPath); }