EndScene and WPF problem menu

Shout-Out

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 15 of 21
  1. #1
    !@^^@!'s Avatar Active Member
    Reputation
    23
    Join Date
    Feb 2007
    Posts
    155
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    EndScene and WPF problem

    Okay so i recently dusted off my old bot code and starting rewriting it from scratch and it seems i've run into one of the problems i had in my previous project: WPF and EndScene hooks screw shit up :<
    Basically i have a normal WPF window with nothing exciting in, just normal stuff that works just fine in a normal standalone WPF app and a EndScene and a BeginScene hook that so far does nothing but just sit there and gives me access to wow's d3d9 device using the SlimDx libary...
    For the hooking/detouring I'm using Apoc's WhiteMagic libary

    Ok time for some code:

    Main.cs
    Code:
    public class Main
        {
            private static BotBase Base = new BotBase();
    
            public static int Start()
            {
                Statics.Initialize();
                Extensions.Rebasher.Rebash(typeof (Offsets.Misc));
                Base.DefaultInitialize();
    
                HookEndScene();
    
    
                while (!Statics.Shutdown)
                {
                    System.Threading.Thread.Sleep(100);
                }
                Shutdown();
                return 0;
            }
    
            public static void HookEndScene()
            {
                EndSceneHandler = EndSceneHook;
                
                var dev = new Device(new Direct3D(), 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.HardwareVertexProcessing, new PresentParameters() { BackBufferWidth = 1, BackBufferHeight = 1 });
       
                var endsceneAdd = (IntPtr)Marshal.ReadInt32(((IntPtr)Marshal.ReadInt32(dev.ComPointer)) + 0xA8);
                
                var dele = Statics.Magic.RegisterDelegate<EndSceneDelegate>(endsceneAdd);
                
                Statics.Magic.Detours.CreateAndApply(dele, EndSceneHandler, "EndScene");
            }
    
            #region Delegates
            [UnmanagedFunctionPointer(CallingConvention.Winapi)]
            public delegate int EndSceneDelegate(IntPtr pointer);
            public static EndSceneDelegate EndSceneHandler;
            #endregion
    
            private static int EndSceneHook(IntPtr pointer)
            {
                if (Statics.Device == null)
                {
                    Statics.Device = Device.FromPointer(pointer);
                }
                else
                {
                    if (Statics.Device.ComPointer == pointer)
                    {
                        Base.PulsNow();
                    }
                }
                return (int)Statics.Magic.Detours["EndScene"].CallOriginal(pointer);
            }
    
            private static void Shutdown()
            {
                Statics.Magic.Detours["EndScene"].Remove();
            }
        }
    BotBase.cs:
    Code:
    class BotBase:Puls.Pulsator
        {
            readonly GuiManager gui = new GuiManager();
    
            protected override void OnFirstFrame()
            {
                gui.Launch();
                base.OnFirstFrame();
            }
        }
    GuiManager.cs (Just a quick mock up based on Kryso's code http://dl.dropbox.com/u/1799304/Wow/GuiThread.cs)
    Code:
    class GuiManager
        {
            Thread _thread;
            private MainView _view;
            private Application _app;
            private bool _running;
    
            public GuiManager()
            {
                _thread = new Thread(ThreadWork);    
                _thread.SetApartmentState(ApartmentState.STA);
                _thread.IsBackground = true;
            }
    
            public void Launch()
            {
                if (!_running)
                {
                    _thread.Start();
                    _running = true;
                }
            }
    
            public void Close()
            {
                
            }
    
            private void ThreadWork()
            {
                try
                {
                    _app = new Application();
                    _view = new MainView();
                    _app.Run(_view);
                }
                catch (Exception exception)
                {
                    MessageBox.Show(exception.Message);
                }
            }
    
            private void CleanUp()
            {
    
            }
        }
    Basically all i need todo to make wow crash now is to force the WPF window to rerender by resizing it or whatever...
    What exactly happens? Am I overlooking something obvious or is there a bug in Apocs lib?
    Last edited by !@^^@!; 01-08-2011 at 05:30 PM. Reason: Cleaned up the code

    EndScene and WPF problem
  2. #2
    suicidity's Avatar Contributor
    Reputation
    207
    Join Date
    Oct 2006
    Posts
    1,439
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Rendering while resizing/alt+tabbing sounds like a reset problem..


  3. #3
    caytchen's Avatar Contributor
    Reputation
    138
    Join Date
    Apr 2007
    Posts
    162
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sounds like a WPF problem. WPF doesn't play nice with injection, WoW and the new CLR hosting interfaces.

  4. #4
    adaephon's Avatar Active Member
    Reputation
    76
    Join Date
    May 2009
    Posts
    167
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    WPF renders using DirectX9, so when you force it to re-render, at a guess I'd say it might be calling your BeginScene / EndScene hooks, except the this pointer will be to WPF's 9Ex device. This means you'll be trying to run your pulse from your WPF render thread.

    [Edit] I notice you do some thread hash checking - is that trying to work out whether you're on WoW's thread / UI thread? If so, what I mentioned might not be your issue, but it seems as if you're checking that you're not on the UI thread, calling calling your PulsNow, and then calling EndScene on _mainView...so that still could cause problems, it's hard to say without seeing what _mainView.EndScene does.

    However, as suicidity mentioned, resize/alt+tab will cause a Reset, Reset fiddles with Presentation Parameters, WPF uses different PPs than WoW (and uses a 9Ex device instead of a standard if you're on Vista/7) and just in general could **** stuff up. Like caytchen said, WPF, injection, WoW etc isn't the most stable combination.
    Last edited by adaephon; 01-07-2011 at 08:59 PM.

  5. #5
    !@^^@!'s Avatar Active Member
    Reputation
    23
    Join Date
    Feb 2007
    Posts
    155
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The _mainView.EndScene was just some silly stuff i was trying out, it doesn't do anything anymore... And yes the hashing was to sort out when i'm in wow's main thread to avoid pulsing bot logic on wpf's thread wich would do silly stuff.

    Anyhow I'll see if can figure out some way to make it more stable with this knowledge however it doesn't look too good :/ I'll return if i make any progress...

    Thanks guys +rep for ya all (edit: that would be if i actually could give suicidity and adaephon rep, "spread some more to other users bla bla bla")

  6. #6
    Kryso's Avatar Active Member
    Reputation
    40
    Join Date
    Jul 2009
    Posts
    97
    Thanks G/R
    0/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    1, hook end scene before creating gui
    2, wait for first hit -> save device pointer, initialize gui
    3, execute pulse only when you get hit from wows device

    I had no other problems with wpf and I've been using it in wow and eve with success.

    Example wpf gui thread: http://dl.dropbox.com/u/1799304/Wow/GuiThread.cs
    Example hook method (note that I'm using little bit different hooks, you would have pDevice as first parameter directly - I need to retrieve it from stack manually):

    Code:
    [HandleProcessCorruptedStateExceptions]
    private static void OnFrame(IntPtr stack)
    {
        if (*(IntPtr*)(stack - 4) != pDevice && pDevice != IntPtr.Zero)
            return;
    
        if (FrameCount++ % 5 != 0)
            return;
    
        lock (SyncRoot)
        {
            try
            {
                if (startupEvent != null)
                {
                    pDevice = *(IntPtr*)(stack - 4);
                    Logger.SystemFormat("Direct3D device: {0}", pDevice.ToHexString());
    
                    startupEvent.Set();
                }
    
                if (shutdownEvent != null)
                {
                    detour.Remove();
                    shutdownEvent.Set();
                    return;
                }
    
                Logger.SystemFormat("Pulse {0}!", FrameCount);
            }
            catch (Exception e1)
            {
                Logger.Error(e1);
            }
        }
    }
    Tea and cake or death?!

  7. #7
    Robske's Avatar Contributor
    Reputation
    305
    Join Date
    May 2007
    Posts
    1,062
    Thanks G/R
    3/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I never managed to get it stable enough.

    Nowadays my wow clients communicate with a standalone wpf application through a service. It only does serves as a global setting repository and exception/log dump though, with some neat extras like a window manager. The main GUI is part of the wow client (managed DirectX). (http://dl.dropbox.com/u/2754079/Wow%...0-17-13-12.jpg)
    Last edited by Robske; 01-08-2011 at 10:33 AM.
    "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live." - Martin Golding
    "I cried a little earlier when I had to poop" - Sku

  8. #8
    !@^^@!'s Avatar Active Member
    Reputation
    23
    Join Date
    Feb 2007
    Posts
    155
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @Kryso: already doing that just with a thread hash instead wich from my logging/debugging yields the same result however what could be interresting is what OS are you running? I myself am on windows 7 64bit and i'm wondering if it has anything todo with the DeviceEx WPF uses on vista and windows 7...

    Anyhow I tried hooking the wpf's DeviceEx endscene and returning the value of that whenver endScene was called by wpf however that gave nothing and EndSceneEx was never called wich after some reading of MSDN explained why: "The IDirect3DDevice9Ex interface inherits from IDirect3DDevice9" Maybe it's a good idea to read the documentation first after all? :>

    Admittetly I'm still learning about DirectX and I'm more or less just trying out random ideas, one of them is to hook IDirect3DDevice9::Present and then store the original present flag when called from WPF and then restore them after the orginal Present have been called but i don't actually know enough about DirectX to tell if this would make any difference, anyone that can shed some more light on the topic?

  9. #9
    Kryso's Avatar Active Member
    Reputation
    40
    Join Date
    Jul 2009
    Posts
    97
    Thanks G/R
    0/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thread.GetHashCode Method (System.Threading) - The hash code is not guaranteed to be unique. Use the ManagedThreadId property if you need a unique identifier for a managed thread.

    I still feel like checking for device is better. I haven't done any in-depth digging into wpf, but I wouldn't just assume it uses only one thread. Also you are doing some voodoo at EndScene, but not at BeginScene. Next thing I don't get is what are you doing with those EndScene and BeginScene methods.. It is not enough to create windows and say "hey window, show yourself!" (at least I think showdialog doesn't create its own pump). You need message pump, for that use Application Class (System.Windows)
    Tea and cake or death?!

  10. #10
    !@^^@!'s Avatar Active Member
    Reputation
    23
    Join Date
    Feb 2007
    Posts
    155
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Okay I cleaned out all the so called "funky stuff" that, as i said, did nothing at all because it was commented out. Anyhow check the first post for the updated code...

    I did as you said Kryso and wrapped it up in a application however it's still crashing on resizing/rendering

    Edit: Also my MainView is a new window with NOTHING in it, just a completly new window created from the VS template just to be completly sure

    Edit2: More testing shows that calling InvalidateVisual(); in the window will crash wow thus it's not me doing something funky, it's WPF not playing nice with wow/injection
    Last edited by !@^^@!; 01-08-2011 at 05:29 PM.

  11. #11
    Kryso's Avatar Active Member
    Reputation
    40
    Join Date
    Jul 2009
    Posts
    97
    Thanks G/R
    0/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Oh another thing.. you need to use some hook method that supports multithreading. Apocs detour doesn't support that because CallOriginal removes and reaplies hook = there is chance that you will miss a call or rewrite instructions that are being executed.
    Tea and cake or death?!

  12. #12
    !@^^@!'s Avatar Active Member
    Reputation
    23
    Join Date
    Feb 2007
    Posts
    155
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Oh thanks, I was actually thinking about that earlier when i saw your code but shrugged at it and asumed Apoc implemented mulithreading support as the C# God he is but then again he would probably never need it and therefor know it's redundant to write code for...
    Thanks none the less, i'll go change it straight away

  13. #13
    jjaa's Avatar Contributor
    Reputation
    245
    Join Date
    Dec 2006
    Posts
    562
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    We didn't implement it because WoW is mainly single threaded. Other methods, seemed too messy in C#.

  14. #14
    Apoc's Avatar Angry Penguin
    Reputation
    1388
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hint:

    Code:
            [DllImport("kernel32.dll")]
            static extern uint GetCurrentThreadId();
            private bool IsWowMainThread()
            {
                return GetCurrentThreadId() == Process.GetCurrentProcess().Threads[0].Id;
            }
    Easiest way to tell if you're in WoW's render thread.

    Most people have ditched injected WPF, for numerous reasons.

    1) WPF uses D3D9Ex, while WoW does not.
    2) WoW uses different memory pools, which tends to crash the client when WPF uses ones it shouldn't be.
    3) WPF doesn't 'clean up' when it should. Or it cleans up at random times, when it's not expected.

    In other words; it's just not stable.

    You may be able to get away with using WoW in DX11 mode, but I haven't tested it to be completely honest.

  15. #15
    adaephon's Avatar Active Member
    Reputation
    76
    Join Date
    May 2009
    Posts
    167
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    On a very loosely related note, it is possible to inject XNA*, and there is a group working on a WPFish layout engine for XNA called XPF: Red Badger | Introducing XPF

    * I've managed to inject XNA and render with it. I still have some Reset issues, but I'm 99% sure they are not insurmountable. However, I haven't touched my code for that for a while, and now I'm running WoW in DX11 mode so I'm looking at hooking DX11 instead and thus XNA isn't appropriate...and tbh, on the 'appropriateness' scale, XNA is hovering around the 'PITA for minimal gain' end when compared to say SlimDX.

Page 1 of 2 12 LastLast

Similar Threads

  1. ascent and arcemu problem
    By trancer69 in forum WoW EMU Questions & Requests
    Replies: 8
    Last Post: 11-23-2008, 12:00 PM
  2. [Help] Some glitch and pvp problem
    By Anarchy in forum World of Warcraft Emulator Servers
    Replies: 3
    Last Post: 02-18-2008, 12:06 AM
  3. About several navicat and mysql problems
    By Ryuk in forum World of Warcraft Emulator Servers
    Replies: 0
    Last Post: 10-12-2007, 04:31 PM
  4. Head and anim problems
    By Shin92 in forum WoW ME Questions and Requests
    Replies: 0
    Last Post: 06-16-2007, 08:31 AM
  5. Windows Movie Maker and Fraps Problems
    By xlAnonym0uslx in forum World of Warcraft General
    Replies: 5
    Last Post: 02-15-2007, 06:09 AM
All times are GMT -5. The time now is 10:05 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search