Example #1
0
        public DialogResult ShowDialog(out object objResult, object objConstructParam)
        {
            objResult = null;

            ProcessMessagesEx();

            // Creating a window on the new desktop spawns a CtfMon.exe child
            // process by default. On Windows Vista, this process is terminated
            // correctly when the desktop is closed. However, on Windows 7 it
            // isn't terminated (probably a bug); creating multiple desktops
            // accumulates CtfMon.exe child processes.
            ChildProcessesSnapshot cpsCtfMons = new ChildProcessesSnapshot(
                "CtfMon.exe");

            ClipboardEventChainBlocker ccb = new ClipboardEventChainBlocker();

            byte[] pbClipHash = ClipboardUtil.ComputeHash();

            SecureThreadInfo stp = new SecureThreadInfo();

            foreach (Screen sc in Screen.AllScreens)
            {
                Bitmap bmpBack = UIUtil.CreateScreenshot(sc);
                if (bmpBack != null)
                {
                    UIUtil.DimImage(bmpBack);
                }
                stp.BackgroundBitmaps.Add(bmpBack);
            }

            DialogResult dr = DialogResult.None;

            try
            {
                uint   uOrgThreadId = NativeMethods.GetCurrentThreadId();
                IntPtr pOrgDesktop  = NativeMethods.GetThreadDesktop(uOrgThreadId);

                string strName = "D" + Convert.ToBase64String(
                    CryptoRandom.Instance.GetRandomBytes(16),
                    Base64FormattingOptions.None);
                strName = strName.Replace(@"+", string.Empty);
                strName = strName.Replace(@"/", string.Empty);
                strName = strName.Replace(@"=", string.Empty);
                if (strName.Length > 15)
                {
                    strName = strName.Substring(0, 15);
                }

                NativeMethods.DesktopFlags deskFlags =
                    (NativeMethods.DesktopFlags.CreateMenu |
                     NativeMethods.DesktopFlags.CreateWindow |
                     NativeMethods.DesktopFlags.ReadObjects |
                     NativeMethods.DesktopFlags.WriteObjects |
                     NativeMethods.DesktopFlags.SwitchDesktop);

                IntPtr pNewDesktop = NativeMethods.CreateDesktop(strName,
                                                                 null, IntPtr.Zero, 0, deskFlags, IntPtr.Zero);
                if (pNewDesktop == IntPtr.Zero)
                {
                    throw new InvalidOperationException();
                }

                bool bNameSupported = NativeMethods.DesktopNameContains(pNewDesktop,
                                                                        strName).GetValueOrDefault(false);
                Debug.Assert(bNameSupported);

                stp.ThreadDesktop      = pNewDesktop;
                stp.FormConstructParam = objConstructParam;

                Thread th = new Thread(this.SecureDialogThread);
                th.CurrentCulture   = Thread.CurrentThread.CurrentCulture;
                th.CurrentUICulture = Thread.CurrentThread.CurrentUICulture;
                th.Start(stp);

                SecureThreadState st = SecureThreadState.None;
                while (st != SecureThreadState.Terminated)
                {
                    th.Join(150);

                    lock (stp) { st = stp.State; }

                    if ((st == SecureThreadState.ShowingDialog) && bNameSupported)
                    {
                        IntPtr hCurDesk = NativeMethods.OpenInputDesktop(0,
                                                                         false, NativeMethods.DesktopFlags.ReadObjects);
                        if (hCurDesk == IntPtr.Zero)
                        {
                            Debug.Assert(false); continue;
                        }
                        if (hCurDesk == pNewDesktop)
                        {
                            if (!NativeMethods.CloseDesktop(hCurDesk))
                            {
                                Debug.Assert(false);
                            }
                            continue;
                        }
                        bool?obOnSec = NativeMethods.DesktopNameContains(hCurDesk, strName);
                        if (!NativeMethods.CloseDesktop(hCurDesk))
                        {
                            Debug.Assert(false);
                        }

                        lock (stp) { st = stp.State; }                        // Update; might have changed

                        if (obOnSec.HasValue && !obOnSec.Value &&
                            (st == SecureThreadState.ShowingDialog))
                        {
                            HandleUnexpectedDesktopSwitch(pOrgDesktop, pNewDesktop, stp);
                        }
                    }
                }

                if (!NativeMethods.SwitchDesktop(pOrgDesktop))
                {
                    Debug.Assert(false);
                }
                NativeMethods.SetThreadDesktop(pOrgDesktop);

                th.Join();                 // Ensure thread terminated before closing desktop

                if (!NativeMethods.CloseDesktop(pNewDesktop))
                {
                    Debug.Assert(false);
                }
                NativeMethods.CloseDesktop(pOrgDesktop);                 // Optional

                dr        = stp.DialogResult;
                objResult = stp.ResultObject;
            }
            catch (Exception) { Debug.Assert(false); }

            byte[] pbNewClipHash = ClipboardUtil.ComputeHash();
            if ((pbClipHash != null) && (pbNewClipHash != null) &&
                !MemUtil.ArraysEqual(pbClipHash, pbNewClipHash))
            {
                ClipboardUtil.Clear();
            }
            ccb.Dispose();

            foreach (Bitmap bmpBack in stp.BackgroundBitmaps)
            {
                if (bmpBack != null)
                {
                    bmpBack.Dispose();
                }
            }
            stp.BackgroundBitmaps.Clear();

            cpsCtfMons.TerminateNewChildsAsync(4100);

            // If something failed, show the dialog on the normal desktop
            if (dr == DialogResult.None)
            {
                Form f = m_fnConstruct(objConstructParam);
                dr        = f.ShowDialog();
                objResult = m_fnResultBuilder(f);
                UIUtil.DestroyForm(f);
            }

            return(dr);
        }
Example #2
0
        public DialogResult ShowDialog(out object objResult, object objConstructParam)
        {
            objResult = null;

            ProcessMessagesEx();

            ClipboardEventChainBlocker ccb = new ClipboardEventChainBlocker();

            byte[] pbClipHash = ClipboardUtil.ComputeHash();

            Bitmap bmpBack = UIUtil.CreateScreenshot();

            if (bmpBack != null)
            {
                UIUtil.DimImage(bmpBack);
            }

            DialogResult dr = DialogResult.None;

            try
            {
                uint   uOrgThreadId = NativeMethods.GetCurrentThreadId();
                IntPtr pOrgDesktop  = NativeMethods.GetThreadDesktop(uOrgThreadId);

                string strName = "D" + Convert.ToBase64String(
                    Guid.NewGuid().ToByteArray(), Base64FormattingOptions.None);
                strName = strName.Replace(@"+", string.Empty);
                strName = strName.Replace(@"/", string.Empty);
                strName = strName.Replace(@"=", string.Empty);

                NativeMethods.DesktopFlags deskFlags =
                    NativeMethods.DesktopFlags.CreateMenu |
                    NativeMethods.DesktopFlags.CreateWindow |
                    NativeMethods.DesktopFlags.ReadObjects |
                    NativeMethods.DesktopFlags.WriteObjects |
                    NativeMethods.DesktopFlags.SwitchDesktop;

                IntPtr pNewDesktop = NativeMethods.CreateDesktop(strName,
                                                                 null, IntPtr.Zero, 0, deskFlags, IntPtr.Zero);
                if (pNewDesktop == IntPtr.Zero)
                {
                    throw new InvalidOperationException();
                }

                SecureThreadParams stp = new SecureThreadParams();
                stp.BackgroundBitmap   = bmpBack;
                stp.ThreadDesktop      = pNewDesktop;
                stp.FormConstructParam = objConstructParam;

                Thread th = new Thread(this.SecureDialogThread);
                th.CurrentCulture   = Thread.CurrentThread.CurrentCulture;
                th.CurrentUICulture = Thread.CurrentThread.CurrentUICulture;
                th.Start(stp);
                th.Join();

                if (!NativeMethods.SwitchDesktop(pOrgDesktop))
                {
                    Debug.Assert(false);
                }
                NativeMethods.SetThreadDesktop(pOrgDesktop);

                if (!NativeMethods.CloseDesktop(pNewDesktop))
                {
                    Debug.Assert(false);
                }
                NativeMethods.CloseDesktop(pOrgDesktop);

                dr        = stp.DialogResult;
                objResult = stp.ResultObject;
            }
            catch (Exception) { Debug.Assert(false); }

            byte[] pbNewClipHash = ClipboardUtil.ComputeHash();
            if ((pbClipHash != null) && (pbNewClipHash != null) &&
                !MemUtil.ArraysEqual(pbClipHash, pbNewClipHash))
            {
                ClipboardUtil.Clear();
            }
            ccb.Release();

            if (bmpBack != null)
            {
                bmpBack.Dispose();
            }

            // If something failed, show the dialog on the normal desktop
            if (dr == DialogResult.None)
            {
                Form f = m_fnConstruct(objConstructParam);
                dr        = f.ShowDialog();
                objResult = m_fnResultBuilder(f);
                UIUtil.DestroyForm(f);
            }

            return(dr);
        }