/////////////////////////////////////////////////////////////////////////////////////////////// public virtual StreamTranslation GetEnvironmentOutputTranslation() { CheckDisposed(); if (PlatformOps.IsWindowsOperatingSystem()) { return(StreamTranslation.protocol); /* NOTE: Always use cr/lf on windows. */ } else { return(StreamTranslation.lf); /* FIXME: Assumes Unix. */ } }
/////////////////////////////////////////////////////////////////////////////////////////////// #if WINFORMS private static void DoEvents() { try { Application.DoEvents(); } catch { if (PlatformOps.IsWindowsOperatingSystem()) { throw; } } }
/////////////////////////////////////////////////////////////////////////////////////////////// public static ReturnCode ProcessEvents( Interpreter interpreter, /* NOT USED */ ref Result error ) { try { #if NATIVE && WINDOWS // // NOTE: If this thread has a message queue and there // appears to be anything in it, process it now. // if (PlatformOps.IsWindowsOperatingSystem()) { if (HasMessageQueue( GlobalState.GetCurrentNativeThreadId(), ref error)) { uint flags = UnsafeNativeMethods.QS_ALLINPUT; if (UnsafeNativeMethods.GetQueueStatus(flags) != 0) #endif DoEvents(); #if NATIVE && WINDOWS } } else { DoEvents(); } #endif return(ReturnCode.Ok); } catch (Exception e) { if (traceException) { TraceOps.DebugTrace( e, typeof(WindowOps).Name, TracePriority.NativeError); } error = e; } return(ReturnCode.Error); }
/////////////////////////////////////////////////////////////////////// #region Private Methods private static ReturnCode IsStrongNameVerified( string fileName, bool force, ref bool returnValue, ref bool verified, ref Result error ) { if (String.IsNullOrEmpty(fileName)) { error = "invalid file name"; return(ReturnCode.Error); } #if WINDOWS && !MONO if (!PlatformOps.IsWindowsOperatingSystem()) { error = "not supported on this operating system"; return(ReturnCode.Error); } try { returnValue = UnsafeNativeMethods.StrongNameSignatureVerificationEx( fileName, force, ref verified); return(ReturnCode.Ok); } catch (Exception e) { error = e; } #else error = "not implemented"; #endif TraceOps.DebugTrace(String.Format( "IsStrongNameVerified: file {0} verification " + "failure, force = {1}, returnValue = {2}, " + "verified = {3}, error = {4}", FormatOps.WrapOrNull(fileName), force, returnValue, verified, FormatOps.WrapOrNull(error)), typeof(SecurityOps).Name, TracePriority.SecurityError); return(ReturnCode.Error); }
/////////////////////////////////////////////////////////////////////// #region Private Windows-Specific Methods #if WINDOWS private static ReturnCode WindowsIsAdministrator( ref bool administrator, ref Result error ) { try { // // NOTE: Are we running on Windows 2000 SP4 or higher? // if (PlatformOps.CheckVersion(PlatformID.Win32NT, 5, 0, 4, 0)) { // // HACK: Use a "documented" function for Windows // 2000 SP4+, Windows XP, and Vista (this // function used to be undocumented). // administrator = UnsafeNativeMethods.IsUserAnAdmin(); } else { // // HACK: Use a different undocumented function for // Windows NT and Windows 2000 RTM to SP3. // uint reserved2 = 0; administrator = UnsafeNativeMethods.IsNTAdmin( 0, ref reserved2); } return(ReturnCode.Ok); } catch (Exception e) { error = e; } TraceOps.DebugTrace(String.Format( "WindowsIsAdministrator: administrator = {0}, error = {1}", administrator, FormatOps.WrapOrNull(error)), typeof(SecurityOps).Name, TracePriority.SecurityError); return(ReturnCode.Error); }
/////////////////////////////////////////////////////////////////////// public static ReturnCode IsAdministrator( ref bool administrator, ref Result error ) { #if WINDOWS if (PlatformOps.IsWindowsOperatingSystem()) { return(WindowsIsAdministrator(ref administrator, ref error)); } #endif #if UNIX if (PlatformOps.IsUnixOperatingSystem()) { return(UnixIsAdministrator(ref administrator, ref error)); } #endif error = "unknown operating system"; return(ReturnCode.Error); }
/////////////////////////////////////////////////////////////////////// private static ReturnCode IsFileTrusted( string fileName, IntPtr fileHandle, bool userInterface, bool userPrompt, bool revocation, bool install, ref int returnValue, ref Result error ) { if (String.IsNullOrEmpty(fileName)) { error = "invalid file name"; return(ReturnCode.Error); } #if WINDOWS if (!PlatformOps.IsWindowsOperatingSystem()) { error = "not supported on this operating system"; return(ReturnCode.Error); } try { UnsafeNativeMethods.WINTRUST_FILE_INFO file = new UnsafeNativeMethods.WINTRUST_FILE_INFO(); file.cbStruct = (uint)Marshal.SizeOf( typeof(UnsafeNativeMethods.WINTRUST_FILE_INFO)); file.pcwszFilePath = fileName; file.hFile = fileHandle; file.pgKnownSubject = IntPtr.Zero; IntPtr pFile = IntPtr.Zero; try { pFile = Marshal.AllocCoTaskMem((int)file.cbStruct); if (pFile != IntPtr.Zero) { Marshal.StructureToPtr(file, pFile, false); UnsafeNativeMethods.WINTRUST_DATA winTrustData = new UnsafeNativeMethods.WINTRUST_DATA(); winTrustData.cbStruct = (uint)Marshal.SizeOf( typeof(UnsafeNativeMethods.WINTRUST_DATA)); winTrustData.pPolicyCallbackData = IntPtr.Zero; winTrustData.pSIPClientData = IntPtr.Zero; winTrustData.dwUIChoice = userInterface && userPrompt ? UnsafeNativeMethods.WTD_UI_ALL : UnsafeNativeMethods.WTD_UI_NONE; winTrustData.fdwRevocationChecks = revocation ? UnsafeNativeMethods.WTD_REVOKE_WHOLECHAIN : UnsafeNativeMethods.WTD_REVOKE_NONE; winTrustData.dwUnionChoice = UnsafeNativeMethods.WTD_CHOICE_FILE; winTrustData.pFile = pFile; winTrustData.dwStateAction = UnsafeNativeMethods.WTD_STATEACTION_IGNORE; winTrustData.hWVTStateData = IntPtr.Zero; winTrustData.pwszURLReference = null; winTrustData.dwProvFlags = UnsafeNativeMethods.WTD_SAFER_FLAG; winTrustData.dwUIContext = install ? UnsafeNativeMethods.WTD_UICONTEXT_INSTALL : UnsafeNativeMethods.WTD_UICONTEXT_EXECUTE; IntPtr hWnd = userInterface ? WindowOps.GetInteractiveHandle() : INVALID_HANDLE_VALUE; Guid actionId = GetActionId(); returnValue = UnsafeNativeMethods.WinVerifyTrust( hWnd, actionId, ref winTrustData); return(ReturnCode.Ok); } else { error = "out of memory"; } } finally { if (pFile != IntPtr.Zero) { Marshal.FreeCoTaskMem(pFile); pFile = IntPtr.Zero; } } } catch (Exception e) { error = e; } #else error = "not implemented"; #endif TraceOps.DebugTrace(String.Format( "IsFileTrusted: file {0} trust failure, " + "userInterface = {1}, revocation = {2}, " + "install = {3}, returnValue = {4}, error = {5}", FormatOps.WrapOrNull(fileName), userInterface, revocation, install, returnValue, FormatOps.WrapOrNull(error)), typeof(SecurityOps).Name, TracePriority.SecurityError); return(ReturnCode.Error); }
/////////////////////////////////////////////////////////////////// private static int GetFrameworkSetup471Value() { return(PlatformOps.IsWindows10FallCreatorsUpdate() ? FrameworkSetup471OnWindows10Value : FrameworkSetup471Value); }
/////////////////////////////////////////////////////////////////// private static int GetFrameworkSetup462Value() { return(PlatformOps.IsWindows10AnniversaryUpdate() ? FrameworkSetup462OnWindows10Value : FrameworkSetup462Value); }
/////////////////////////////////////////////////////////////////// private static int GetFrameworkSetup46Value() { return(PlatformOps.IsWindows10OrHigher() ? FrameworkSetup46OnWindows10Value : FrameworkSetup46Value); }
/////////////////////////////////////////////////////////////////// #region Framework Information Methods #if NET_40 private static int GetFrameworkSetup451Value() { return(PlatformOps.IsWindows81() ? FrameworkSetup451OnWindows81Value : FrameworkSetup451Value); }
///////////////////////////////////////////////////////////////////////////////// private static UIntPtr GetNativeRegister( IntPtr thread, uint flags, int offset, int size ) { // // NOTE: Are we able to query the thread context (i.e. we know // what platform we are on and the appropriate constants // have been setup)? // if (!CanQueryThread) { if (Interlocked.Increment(ref CannotQueryThread) == 1) { TraceOps.DebugTrace( "GetNativeRegister: cannot query thread", typeof(NativeStack).Name, TracePriority.NativeError); } return(UIntPtr.Zero); } // // NOTE: We do not allow anybody to attempt to read outside what // we think the bounds of the CONTEXT structure are. // if ((offset < 0) || (offset > (CONTEXT_SIZE - IntPtr.Size))) { return(UIntPtr.Zero); } try { lock (syncRoot) /* TRANSACTIONAL */ { // // NOTE: Perform one-time allocation of the fixed-size // thread context buffer, on demand and schedule // to have it freed prior to process exit. // if (ThreadContextBuffer == UIntPtr.Zero) { // // NOTE: Schedule the fixed-size thread context // buffer to be freed either upon the // AppDomain being unloaded (if we are not // in the default AppDomain) or when the // process exits. This should gracefully // handle both embedding and stand-alone // scenarios. // AppDomain appDomain = AppDomainOps.GetCurrent(); if (appDomain != null) { if (!AppDomainOps.IsDefault(appDomain)) { appDomain.DomainUnload += NativeStack_Exited; } else { appDomain.ProcessExit += NativeStack_Exited; } } // // NOTE: Now that we are sure that we have // succeeded in scheduling the cleanup for // this buffer, allocate it. // // NOTE: For safety, we now allocate at least a // whole page for this buffer. // // ThreadContextBuffer = ConversionOps.ToUIntPtr( // Marshal.AllocCoTaskMem((int)CONTEXT_SIZE)); // ThreadContextBuffer = ConversionOps.ToUIntPtr( Marshal.AllocCoTaskMem((int)Math.Max( CONTEXT_SIZE, PlatformOps.GetPageSize()))); } // // NOTE: Make sure we were able to allocate the // thread context buffer. // if (ThreadContextBuffer == UIntPtr.Zero) { return(UIntPtr.Zero); } // // NOTE: Internally convert our buffer UIntPtr to // IntPtr, as required by Marshal class. // This is absolutely required because // otherwise we end up calling the generic // version of the WriteInt32 and ReadInt32 // methods (that take an object instead of // an IntPtr) and getting the wrong results. // IntPtr threadContext = ConversionOps.ToIntPtr( ThreadContextBuffer); // // NOTE: Write flags that tell GetThreadContext // which fields of the thread context buffer // we would like it to populate. For now, // we mainly want to support the control // registers (primarily for ESP and EBP). // Marshal.WriteInt32( threadContext, (int)CONTEXT_FLAGS_OFFSET, (int)flags); // // NOTE: Query the Win32 API to obtain the // requested thread context. In theory, // this could fail or throw an exception // at this point. In that case, we would // return zero from this function and the // stack checking code would assume that // native stack checking is unavailable // and should not be relied upon. // if (UnsafeNativeMethods.GetThreadContext( thread, threadContext)) { if (size == IntPtr.Size) { return(ConversionOps.ToUIntPtr( Marshal.ReadIntPtr(threadContext, offset))); } else { switch (size) { case sizeof(long): { return(ConversionOps.ToUIntPtr( Marshal.ReadInt64(threadContext, offset))); } case sizeof(int): { return(ConversionOps.ToUIntPtr( Marshal.ReadInt32(threadContext, offset))); } case sizeof(short): { return(ConversionOps.ToUIntPtr( Marshal.ReadInt16(threadContext, offset))); } case sizeof(byte): { return(ConversionOps.ToUIntPtr( Marshal.ReadByte(threadContext, offset))); } } } } } } catch (Exception e) { if (Interlocked.Increment(ref ContextException) == 1) { TraceOps.DebugTrace( e, typeof(NativeStack).Name, TracePriority.NativeError); } } return(UIntPtr.Zero); }
///////////////////////////////////////////////////////////////////////////////// public static UIntPtr GetNativeStackMargin() { return(new UIntPtr( (ulong)PlatformOps.GetPageSize() * (ulong)StackMarginPages)); }
///////////////////////////////////////////////////////////////////////////////// #region Thread Context Support Methods private static void SetupThreadContextMetadata() { CanQueryThread = false; OperatingSystemId operatingSystemId = PlatformOps.GetOperatingSystemId(); switch (operatingSystemId) { case OperatingSystemId.WindowsNT: { ProcessorArchitecture processorArchitecture = PlatformOps.GetProcessorArchitecture(); switch (processorArchitecture) { case ProcessorArchitecture.Intel: case ProcessorArchitecture.IA32_on_Win64: { TebStackBaseOffset = TebStackBaseOffset32Bit; TebStackLimitOffset = TebStackLimitOffset32Bit; TebDeallocationStack = TebDeallocationStack32Bit; CONTEXT_FLAGS_OFFSET = CONTEXT_FLAGS_OFFSET_i386; CONTEXT_CONTROL = CONTEXT_CONTROL_i386; CONTEXT_SIZE = CONTEXT_SIZE_i386; CONTEXT_ESP_OFFSET = CONTEXT_ESP_OFFSET_i386; // // NOTE: Support is present in NTDLL, use the direct // (fast) method. // NtCurrentTeb = null; TraceOps.DebugTrace( "selected x86 architecture", typeof(NativeStack).Name, TracePriority.NativeDebug); CanQueryThread = true; break; } case ProcessorArchitecture.ARM: { TebStackBaseOffset = TebStackBaseOffset32Bit; TebStackLimitOffset = TebStackLimitOffset32Bit; TebDeallocationStack = TebDeallocationStack32Bit; CONTEXT_FLAGS_OFFSET = CONTEXT_FLAGS_OFFSET_ARM; CONTEXT_CONTROL = CONTEXT_CONTROL_ARM; CONTEXT_SIZE = CONTEXT_SIZE_ARM; CONTEXT_ESP_OFFSET = CONTEXT_ESP_OFFSET_ARM; // // NOTE: Native stack checking is not "officially" // supported on this architecture; however, // it may work. // NtCurrentTeb = new NtCurrentTeb(NtCurrentTebSlow); TraceOps.DebugTrace( "selected ARM architecture", typeof(NativeStack).Name, TracePriority.NativeDebug); CanQueryThread = true; break; } case ProcessorArchitecture.IA64: { TebStackBaseOffset = TebStackBaseOffset64Bit; TebStackLimitOffset = TebStackLimitOffset64Bit; TebDeallocationStack = TebDeallocationStack64Bit; CONTEXT_FLAGS_OFFSET = CONTEXT_FLAGS_OFFSET_IA64; CONTEXT_CONTROL = CONTEXT_CONTROL_IA64; CONTEXT_SIZE = CONTEXT_SIZE_IA64; CONTEXT_ESP_OFFSET = CONTEXT_ESP_OFFSET_IA64; // // NOTE: Native stack checking is not "officially" // supported on this architecture; however, // it may work. // NtCurrentTeb = new NtCurrentTeb(NtCurrentTebSlow); TraceOps.DebugTrace( "selected ia64 architecture", typeof(NativeStack).Name, TracePriority.NativeDebug); CanQueryThread = true; break; } case ProcessorArchitecture.AMD64: { TebStackBaseOffset = TebStackBaseOffset64Bit; TebStackLimitOffset = TebStackLimitOffset64Bit; TebDeallocationStack = TebDeallocationStack64Bit; CONTEXT_FLAGS_OFFSET = CONTEXT_FLAGS_OFFSET_AMD64; CONTEXT_CONTROL = CONTEXT_CONTROL_AMD64; CONTEXT_SIZE = CONTEXT_SIZE_AMD64; CONTEXT_ESP_OFFSET = CONTEXT_ESP_OFFSET_AMD64; // // HACK: Thanks for not exporting this function from // NTDLL on x64 (you know who you are). Since // support is not present in NTDLL, use the // slow method. // NtCurrentTeb = new NtCurrentTeb(NtCurrentTebSlow); TraceOps.DebugTrace( "selected x64 architecture", typeof(NativeStack).Name, TracePriority.NativeDebug); CanQueryThread = true; break; } case ProcessorArchitecture.ARM64: { TebStackBaseOffset = TebStackBaseOffset64Bit; TebStackLimitOffset = TebStackLimitOffset64Bit; TebDeallocationStack = TebDeallocationStack64Bit; CONTEXT_FLAGS_OFFSET = CONTEXT_FLAGS_OFFSET_ARM64; CONTEXT_CONTROL = CONTEXT_CONTROL_ARM64; CONTEXT_SIZE = CONTEXT_SIZE_ARM64; CONTEXT_ESP_OFFSET = CONTEXT_ESP_OFFSET_ARM64; // // NOTE: Native stack checking is not "officially" // supported on this architecture; however, // it may work. // NtCurrentTeb = new NtCurrentTeb(NtCurrentTebSlow); TraceOps.DebugTrace( "selected ARM64 architecture", typeof(NativeStack).Name, TracePriority.NativeDebug); CanQueryThread = true; break; } default: { // // NOTE: We have no idea what processor architecture // this is. Native stack checking is disabled. // TraceOps.DebugTrace(String.Format( "unknown architecture {0}", processorArchitecture), typeof(NativeStack).Name, TracePriority.NativeError); break; } } break; } default: { // // NOTE: We have no idea what operating system this is. // Native stack checking is disabled. // TraceOps.DebugTrace(String.Format( "unknown operating system {0}", operatingSystemId), typeof(NativeStack).Name, TracePriority.NativeError); break; } } }
/////////////////////////////////////////////////////////////////////// private static string GetNativeLibraryFileName( Interpreter interpreter /* NOT USED */ ) { string path = CommonOps.Environment.GetVariable( EnvVars.UtilityPath); if (!String.IsNullOrEmpty(path)) { if (File.Exists(path)) { return(path); } if (Directory.Exists(path)) { string fileName = PathOps.CombinePath( null, path, DllName.Utility); if (File.Exists(fileName)) { return(fileName); } // // TODO: Is this strictly necessary here? It is known // at this point that this file does not exist. // Setting the path here only controls the result // returned in non-strict mode (below). // path = fileName; } // // NOTE: If the environment variable was set and the utility // library could not be found, force an invalid result // to be returned. This ends up skipping the standard // automatic utility library detection logic. // lock (syncRoot) { return(strictPath ? null : path); } } // // HACK: If the processor architecture ends up being "AMD64", we // want it to be "x64" instead, to match the platform name // used by the native utility library project itself. // string processorName = PlatformOps.GetAlternateProcessorName( RuntimeOps.GetProcessorArchitecture(), true, false); if (processorName != null) { path = PathOps.CombinePath( null, GlobalState.GetAssemblyPath(), processorName, DllName.Utility); if (File.Exists(path)) { return(path); } } path = PathOps.CombinePath( null, GlobalState.GetAssemblyPath(), DllName.Utility); if (File.Exists(path)) { return(path); } lock (syncRoot) { return(strictPath ? null : path); } }
/////////////////////////////////////////////////////////////////////// public ReturnCode VerifyModule( ref Result error ) { if (String.IsNullOrEmpty(fileName)) { error = "invalid Tcl native module file name"; return(ReturnCode.Error); } if (!NativeOps.IsValidHandle(module)) { error = "invalid Tcl native module handle"; return(ReturnCode.Error); } // // HACK: We cannot actually verify the native module handle on any // non-Windows operating system. // if (!PlatformOps.IsWindowsOperatingSystem()) { return(ReturnCode.Ok); } try { IntPtr newModule = NativeOps.GetModuleHandle(fileName); if (newModule == IntPtr.Zero) { error = String.Format( "bad Tcl native module handle {0}, file name {1} is " + "no longer loaded", module, FormatOps.WrapOrNull( fileName)); TraceOps.DebugTrace(String.Format( "VerifyModule: {0}", FormatOps.WrapOrNull(error)), typeof(TclModule).Name, TracePriority.NativeError); return(ReturnCode.Error); } if (newModule != module) { // // NOTE: This situation should really never happen. If it // does, that indicates that the native Tcl module // was unloaded and then reloaded out from under the // native Tcl integration subsystem. // error = String.Format( "bad Tcl native module handle {0}, got {1} for file " + "name {2}", module, newModule, FormatOps.WrapOrNull( fileName)); TraceOps.DebugTrace(String.Format( "VerifyModule: {0}", FormatOps.WrapOrNull(error)), typeof(TclModule).Name, TracePriority.NativeError); return(ReturnCode.Error); } return(ReturnCode.Ok); } catch (Exception e) { error = e; } return(ReturnCode.Error); }
/////////////////////////////////////////////////////////////////// private static int GetFrameworkSetup461Value() { return(PlatformOps.IsWindows10NovemberUpdate() ? FrameworkSetup461OnWindows10Value : FrameworkSetup461Value); }