コード例 #1
0
        /////////////////////////////////////////////////////////////////////////////////

        #region AppDomain EventHandler (ProcessExit / DomainUnload)
        private static void NativeStack_Exited(
            object sender,
            EventArgs e
            )
        {
            lock (syncRoot) /* TRANSACTIONAL */
            {
                if (ThreadContextBuffer != UIntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(ConversionOps.ToIntPtr(
                                              ThreadContextBuffer));

                    ThreadContextBuffer = UIntPtr.Zero;

                    AppDomain appDomain = AppDomainOps.GetCurrent();

                    if (appDomain != null)
                    {
                        if (!AppDomainOps.IsDefault(appDomain))
                        {
                            appDomain.DomainUnload -= NativeStack_Exited;
                        }
                        else
                        {
                            appDomain.ProcessExit -= NativeStack_Exited;
                        }
                    }
                }
            }
        }
コード例 #2
0
        /////////////////////////////////////////////////////////////////////////////////

        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);
        }