public override unsafe void Hook()
        {
            DebugMessage("Hook: Begin");

            DebugMessage("Hook: Before device creation");
            using (var d3d = new Direct3D())
            {
                DebugMessage("Hook: Direct3D created");
                using (
                    var device = new Device(
                        d3d,
                        0,
                        DeviceType.NullReference,
                        IntPtr.Zero,
                        CreateFlags.HardwareVertexProcessing,
                        new PresentParameters {
                    BackBufferWidth = 1, BackBufferHeight = 1
                }))
                {
                    _id3DDeviceFunctionAddresses.AddRange(GetVTblAddresses(device.NativePointer, D3D9_DEVICE_METHOD_COUNT));
                }
            }

            try
            {
                using (var d3dEx = new Direct3DEx())
                {
                    DebugMessage("Hook: Try Direct3DEx...");
                    using (
                        var deviceEx = new DeviceEx(
                            d3dEx,
                            0,
                            DeviceType.NullReference,
                            IntPtr.Zero,
                            CreateFlags.HardwareVertexProcessing,
                            new PresentParameters {
                        BackBufferWidth = 1, BackBufferHeight = 1
                    },
                            new DisplayModeEx {
                        Width = 800, Height = 600
                    }))
                    {
                        _id3DDeviceFunctionAddresses.AddRange(
                            GetVTblAddresses(deviceEx.NativePointer, D3D9_DEVICE_METHOD_COUNT, D3D9Ex_DEVICE_METHOD_COUNT));
                        _supportsDirect3DEx = true;
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }

            DebugMessage("Setting up Direct3D hooks...");
            Direct3DDevice_EndSceneHook =
                new HookData <Direct3D9Device_EndSceneDelegate>(
                    _id3DDeviceFunctionAddresses[(int)Direct3DDevice9FunctionOrdinals.EndScene],
                    new Direct3D9Device_EndSceneDelegate(EndSceneHook),
                    this);

            Direct3DDevice_EndSceneHook.ReHook();
            Hooks.Add(Direct3DDevice_EndSceneHook.Hook);

            Direct3DDevice_PresentHook =
                new HookData <Direct3D9Device_PresentDelegate>(
                    _id3DDeviceFunctionAddresses[(int)Direct3DDevice9FunctionOrdinals.Present],
                    new Direct3D9Device_PresentDelegate(PresentHook),
                    this);

            Direct3DDevice_ResetHook =
                new HookData <Direct3D9Device_ResetDelegate>(
                    _id3DDeviceFunctionAddresses[(int)Direct3DDevice9FunctionOrdinals.Reset],
                    new Direct3D9Device_ResetDelegate(ResetHook),
                    this);

            if (_supportsDirect3DEx)
            {
                DebugMessage("Setting up Direct3DEx hooks...");
                Direct3DDeviceEx_PresentExHook =
                    new HookData <Direct3D9DeviceEx_PresentExDelegate>(
                        _id3DDeviceFunctionAddresses[(int)Direct3DDevice9ExFunctionOrdinals.PresentEx],
                        new Direct3D9DeviceEx_PresentExDelegate(PresentExHook),
                        this);

                Direct3DDeviceEx_ResetExHook =
                    new HookData <Direct3D9DeviceEx_ResetExDelegate>(
                        _id3DDeviceFunctionAddresses[(int)Direct3DDevice9ExFunctionOrdinals.ResetEx],
                        new Direct3D9DeviceEx_ResetExDelegate(ResetExHook),
                        this);
            }

            Direct3DDevice_ResetHook.ReHook();
            Hooks.Add(Direct3DDevice_ResetHook.Hook);

            Direct3DDevice_PresentHook.ReHook();
            Hooks.Add(Direct3DDevice_PresentHook.Hook);

            if (_supportsDirect3DEx)
            {
                Direct3DDeviceEx_PresentExHook.ReHook();
                Hooks.Add(Direct3DDeviceEx_PresentExHook.Hook);

                Direct3DDeviceEx_ResetExHook.ReHook();
                Hooks.Add(Direct3DDeviceEx_ResetExHook.Hook);
            }

            DebugMessage("Hook: End");
        }