示例#1
0
 /// <summary>
 /// helper method that queries Windows7 compat section in applciation EXE and returns OS compat flags from there.
 /// </summary>
 /// <returns></returns>
 private static OsCompatibilityFlags QueryStaticContext()
 {
     if (!s_staticContextCachePresent)
     {
         lock (s_staticContextCacheLock)
         {
             if (!s_staticContextCachePresent)
             {
                 if (!IsWindows7CompatibilitySupported)
                 {
                     // we cannot use the API with CompatibilityInformationInActivationContext on current OS, set as unknown
                     s_staticContextCache = OsCompatibilityFlags.Unknown;
                 }
                 else
                 {
                     s_staticContextCache = NativeMethods.QueryOsCompatibilityInformation(NativeMethods.GetModuleHandleW(null));
                 }
                 s_staticContextCachePresent = true;
             }
         }
     }
     return(s_staticContextCache);
 }
示例#2
0
 /// <summary>
 /// helper method that queries Windows7 compat section in applciation EXE and returns OS compat flags from there.
 /// </summary>
 /// <returns></returns>
 private static OsCompatibilityFlags QueryStaticContext()
 {
     if (!s_staticContextCachePresent)
     {
         lock (s_staticContextCacheLock)
         {
             if (!s_staticContextCachePresent)
             {
                 if (!IsWindows7CompatibilitySupported)
                 {
                     // we cannot use the API with CompatibilityInformationInActivationContext on current OS, set as unknown
                     s_staticContextCache = OsCompatibilityFlags.Unknown;
                 }
                 else
                 {
                     s_staticContextCache = NativeMethods.QueryOsCompatibilityInformation(NativeMethods.GetModuleHandleW(null));
                 }
                 s_staticContextCachePresent = true;
             }
         }
     }
     return s_staticContextCache;
 }
示例#3
0
        /// <summary>
        /// use this method in your tests to assert that Windows7 dynamic compat context is active. The method first checks the context, and
        /// if it is not currently active, the method raises exception.
        ///
        /// Exceptions raised:
        /// * NotSupportedException: current OS is not Windows7, nor Win2K8R2, nor later. Use IsWindows7CompatibilitySupported before!
        /// * InvalidOperationException: dynamic context for Windows7 compat mode has been deactivated. The exception includes list of modules
        ///   that might be the cause for the downgrade to happen!
        ///  * other exceptions are unwelcome
        /// </summary>
        public static void EnsureWindows7DynamicContextIsActive()
        {
            if (!IsWindows7CompatibilitySupported)
            {
                throw new NotSupportedException("Current OS does not support Win7 compat mode testing. Please use IsWindows7CompatibilitySupported before asserting");
            }

            if (IsWindows7DynamicContextActive)
            {
                // the true test passed: GetOverlappedResult behaves as expected in Win7 compat mode
                // OK to continue
                return;
            }

            // The process is not running in Windows7 compat mode, check for possible reasons.
            // The code below is for collecting troubleshooting information to be raised as InvalidOperationException to the user.

            if (!IsWindows7CompatibilityContextEnabled)
            {
                // current process has neither Windows7 compat manifest nor proper exe subversion (not compiled with WINVER >= 6.1)
                // there is no point to query other modules since QueryActCtxW (CompatibilityInformationInActivationContext)
                // returns no GUIDs in this case, even if modules do have compat manifest.
                throw new InvalidOperationException(string.Format(
                                                        "Process executable ({0}) has neither Windows7 GUID in its RT_MANIFEST nor compiled with WINVER>=6.1",
                                                        System.Diagnostics.Process.GetCurrentProcess().ProcessName));
            }

            // Process exe seems to be Win7 compatible, search for modules that are not compatible.
            // To ease on troubleshooting, collect incompatible modules list and add them to
            // exception message. This way the caller can find out which of the modules
            // downgrade the process.

            StringWriter exceptionMessage = new StringWriter();

            exceptionMessage.WriteLine(
                "The dynamic Win7 compat context for this process has been downgraded due " +
                "to one or more incompatible modules.");

            IntPtr[] modules = NativeMethods.GetModules();
            bool     incompatibleModuleDetected = false;

            for (int i = 0; i < modules.Length; i++)
            {
                IntPtr module = modules[i];
                OsCompatibilityFlags osCompatFlags = NativeMethods.QueryOsCompatibilityInformation(module);
                bool isWin7CompatModule            = (osCompatFlags & OsCompatibilityFlags.Windows7) != 0;

                if (!isWin7CompatModule)
                {
                    if (!incompatibleModuleDetected)
                    {
                        // first incompatible module
                        exceptionMessage.WriteLine("Incompatible modules list:");
                    }
                    incompatibleModuleDetected = true;

                    string moduleName = NativeMethods.GetModuleFileName(module);
                    exceptionMessage.WriteLine("Module: {0}; flags: {1}", moduleName, osCompatFlags);
                }
            }

            if (!incompatibleModuleDetected)
            {
                exceptionMessage.WriteLine("Cannot detect incompatible modules.");
            }

            // troubleshooting info is ready, raise the message to the user
            throw new InvalidOperationException(exceptionMessage.ToString());
        }
示例#4
0
        internal static OsCompatibilityFlags QueryOsCompatibilityInformation(IntPtr dllHandle)
        {
            if (Environment.OSVersion.Version < Win7_Win2K8R2_Version)
            {
                throw new NotSupportedException(
                          "CompatibilityInformationInActivationContext flag was added in Win7 and Windows 2008 R2 only. It is not supported on current OS.");
            }

            const int QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE         = 0x00000008;
            const int CompatibilityInformationInActivationContext = 6;

            IntPtr cbBuffer = IntPtr.Zero;
            bool   ret      = QueryActCtxW(
                QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE,
                dllHandle,
                IntPtr.Zero,
                CompatibilityInformationInActivationContext,
                null,
                IntPtr.Zero,
                ref cbBuffer);

            if (ret)
            {
                Debug.Assert(cbBuffer == IntPtr.Zero);
                return(OsCompatibilityFlags.None);
            }

            int status = Marshal.GetLastWin32Error();

            if (status != ERROR_INSUFFICIENT_BUFFER)
            {
                throw new Win32Exception(status);
            }

            byte[] CtxCompatInfo = new byte[cbBuffer.ToInt32()];
            ret = QueryActCtxW(
                QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE,
                dllHandle,
                IntPtr.Zero,
                CompatibilityInformationInActivationContext,
                CtxCompatInfo,
                cbBuffer,
                ref cbBuffer);
            if (!ret)
            {
                throw new Win32Exception(); // error message is taken from GetLastError
            }

            // read the compatibility information, native structures are:
            // typedef struct _ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION {
            //     DWORD                         ElementCount;
            //     COMPATIBILITY_CONTEXT_ELEMENT Elements[];
            // } ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION, *PACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION;
            // typedef struct _COMPATIBILITY_CONTEXT_ELEMENT {
            //   GUID                              Id;
            //   ACTCTX_COMPATIBILITY_ELEMENT_TYPE Type;
            // } COMPATIBILITY_CONTEXT_ELEMENT, *PCOMPATIBILITY_CONTEXT_ELEMENT;

            BinaryReader reader   = new BinaryReader(new MemoryStream(CtxCompatInfo));
            int          elmCount = 0;

            elmCount = reader.ReadInt32();

            OsCompatibilityFlags osCompatFlags = OsCompatibilityFlags.None;

            for (int i = 0; i < elmCount; i++)
            {
                Guid g = new Guid(reader.ReadBytes(16));
                ActcxCompatibilityElementType type = (ActcxCompatibilityElementType)reader.ReadInt32();
                if (type == ActcxCompatibilityElementType.OS)
                {
                    if (g == Win7Compat)
                    {
                        osCompatFlags |= OsCompatibilityFlags.Windows7;
                    }
                    else if (g == VistaCompat)
                    {
                        osCompatFlags |= OsCompatibilityFlags.Vista;
                    }
                    else
                    {
                        osCompatFlags |= OsCompatibilityFlags.Unknown;
                    }
                }
            }

            return(osCompatFlags);
        }