1 // Copyright (c) Microsoft. All rights reserved. 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 4 using System; 5 using System.IO; 6 using System.Text; 7 using System.Runtime.InteropServices; 8 9 namespace Microsoft.Build.BuildEngine.Shared 10 { 11 /// <summary> 12 /// Interop methods. 13 /// </summary> 14 /// <owner>LukaszG</owner> 15 internal static class NativeMethods 16 { 17 #region Constants 18 19 internal const uint ERROR_INSUFFICIENT_BUFFER = 0x8007007A; 20 internal const uint STARTUP_LOADER_SAFEMODE = 0x10; 21 internal const uint S_OK = 0x0; 22 internal const uint RUNTIME_INFO_DONT_SHOW_ERROR_DIALOG = 0x40; 23 internal const uint FILE_TYPE_CHAR = 0x0002; 24 internal const Int32 STD_OUTPUT_HANDLE = -11; 25 26 private const string kernel32Dll = "kernel32.dll"; 27 private const string mscoreeDLL = "mscoree.dll"; 28 29 internal static HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero); 30 31 internal static IntPtr NullIntPtr = new IntPtr(0); 32 #endregion 33 34 #region Member data 35 36 /// <summary> 37 /// Default buffer size to use when dealing with the Windows API. 38 /// </summary> 39 /// <remarks> 40 /// This member is intentionally not a constant because we want to allow 41 /// unit tests to change it. 42 /// </remarks> 43 internal static int MAX_PATH = 260; 44 45 #endregion 46 47 #region Wrapper methods 48 49 /// <summary> 50 /// Looks for the given file in the system path i.e. all locations in 51 /// the %PATH% environment variable. 52 /// </summary> 53 /// <param name="filename"></param> 54 /// <returns>The location of the file, or null if file not found.</returns> FindOnPath(string filename)55 internal static string FindOnPath(string filename) 56 { 57 StringBuilder pathBuilder = new StringBuilder(MAX_PATH + 1); 58 string pathToFile = null; 59 60 // we may need to make two attempts because there's a small chance 61 // the buffer may not be sized correctly the first time 62 for (int i = 0; i < 2; i++) 63 { 64 uint result = SearchPath 65 ( 66 null /* search the system path */, 67 filename /* look for this file */, 68 null /* don't add an extra extension to the filename when searching */, 69 pathBuilder.Capacity /* size of buffer */, 70 pathBuilder /* buffer to write path into */, 71 null /* don't want pointer to filename in the return path */ 72 ); 73 74 // if the buffer is not big enough 75 if (result > pathBuilder.Capacity) 76 { 77 ErrorUtilities.VerifyThrow(i == 0, "We should not have to resize the buffer twice."); 78 79 // resize the buffer and try again 80 pathBuilder.Capacity = (int)result; 81 } 82 else if (result > 0) 83 { 84 // file was found, so don't make another attempt 85 pathToFile = pathBuilder.ToString(); 86 break; 87 } 88 else 89 { 90 // file was not found, so quit 91 break; 92 } 93 } 94 95 return pathToFile; 96 } 97 98 #endregion 99 100 #region PInvoke 101 102 /// <summary> 103 /// Gets the current OEM code page which is used by console apps 104 /// (as opposed to the Windows/ANSI code page used by the normal people) 105 /// Basically for each ANSI code page (set in Regional settings) there's a corresponding OEM code page 106 /// that needs to be used for instance when writing to batch files 107 /// </summary> 108 /// <owner>LukaszG</owner> 109 [DllImport(kernel32Dll)] GetOEMCP()110 internal static extern int GetOEMCP(); 111 112 113 [DllImport(kernel32Dll, SetLastError = true, CharSet = CharSet.Unicode)] SearchPath( string path, string fileName, string extension, int numBufferChars, StringBuilder buffer, int[] filePart )114 private static extern uint SearchPath 115 ( 116 string path, 117 string fileName, 118 string extension, 119 int numBufferChars, 120 StringBuilder buffer, 121 int[] filePart 122 ); 123 124 125 [DllImport("kernel32.dll", PreserveSig = true, SetLastError = true)] 126 [return: MarshalAs(UnmanagedType.Bool)] FreeLibrary([In] IntPtr module)127 internal static extern bool FreeLibrary([In] IntPtr module); 128 129 [DllImport("kernel32.dll", PreserveSig = true, BestFitMapping = false, ThrowOnUnmappableChar = true, CharSet = CharSet.Ansi, SetLastError = true)] GetProcAddress(IntPtr module, string procName)130 internal static extern IntPtr GetProcAddress(IntPtr module, string procName); 131 132 [DllImport("kernel32.dll", CharSet = CharSet.Unicode, PreserveSig = true, SetLastError = true)] LoadLibrary(string fileName)133 internal static extern IntPtr LoadLibrary(string fileName); 134 135 [DllImport(mscoreeDLL, SetLastError = true, CharSet = CharSet.Unicode)] GetRequestedRuntimeInfo(String pExe, String pwszVersion, String pConfigurationFile, uint startupFlags, uint runtimeInfoFlags, StringBuilder pDirectory, int dwDirectory, out uint dwDirectoryLength, StringBuilder pVersion, int cchBuffer, out uint dwlength)136 internal static extern uint GetRequestedRuntimeInfo(String pExe, 137 String pwszVersion, 138 String pConfigurationFile, 139 uint startupFlags, 140 uint runtimeInfoFlags, 141 StringBuilder pDirectory, 142 int dwDirectory, 143 out uint dwDirectoryLength, 144 StringBuilder pVersion, 145 int cchBuffer, 146 out uint dwlength); 147 148 /// <summary> 149 /// Gets the fully qualified filename of the currently executing .exe 150 /// </summary> 151 [DllImport(kernel32Dll, SetLastError=true, CharSet = CharSet.Unicode)] GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length)152 internal static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length); 153 154 [DllImport("kernel32.dll")] GetStdHandle(int nStdHandle)155 internal static extern IntPtr GetStdHandle(int nStdHandle); 156 157 [DllImport("kernel32.dll")] GetFileType(IntPtr hFile)158 internal static extern uint GetFileType(IntPtr hFile); 159 160 [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] GetCurrentDirectory(int nBufferLength, StringBuilder lpBuffer)161 internal static extern int GetCurrentDirectory(int nBufferLength, StringBuilder lpBuffer); 162 163 #endregion 164 } 165 } 166