MinHook - API Hooking Library

Post your working scripts, libraries and tools for AHK v1.1 and older
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

MinHook - API Hooking Library

11 Aug 2018, 06:59

An AHK wrapper for MinHook.

Example 1 - Hook MessageBoxW

Code: Select all

#Include <MinHook>

hook1 := New MinHook("user32.dll", "MessageBoxW", "MessageBoxW_Hook")

hook1.Enable()
MsgBox, 64, Hello, World

hook1.Disable()
MsgBox, 64, Hello, I'm back.

hook1 := "" ; Remove hook

MessageBoxW_Hook(hWnd, lpText, lpCaption, uType) {
	global hook1
	return DllCall(hook1.original, "ptr", hWnd, "str", "Hooked!", "ptr", lpCaption, "uint", 48)
}
Example 2 - Set value for input file type in webbrowser control
Example 3 - Hook another process using HotkeyIt's InjectAhkDll and AutoHotkey.dll
Example 4 - InjectAhkDll (hook address).ahk
Example 5 - Change GUI class name.ahk
Example 6 - Change GUI class name (Memory).ahk

Download
Last edited by tmplinshi on 17 Aug 2019, 19:02, edited 2 times in total.
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: MinHook - API Hooking Library

11 Aug 2018, 14:56

Hi, tmplinshi, how do I handle

Code: Select all

#Include <MinHook>
? I can see that AutoHotkey_H lists its license on the github page, and found a program or two that use the DLL, but I don't find a library MinHook.ahk anywhere.
Edit: :facepalm: Wow. I don't know how much more obvious it could have been. :facepalm:
Sorry.
Regards,
burque505
Edit: That's really classy, tmplinshi, thank you. That will doubtless come in handy. I had to pull _Struct.ahk and sizeof.ahk out of the Lib folder because I already had them in my main Lib folder. Everything works great, ex. 3 works with AHK_H 1.1.29.01 v002.
Thanks again!
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: MinHook - API Hooking Library

13 Aug 2018, 23:41

excellent

tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Update to v1.1 (2018-8-16)

16 Aug 2018, 01:29

  • The module dll will now unload when the hook removed. (Except for standard DLL - User32.dll, Kernel32.dll, ComCtl32.dll, or Gdi32.dll)
  • Added more directories to search for MinHook.dll. You can place Minhook.dll in one of the following directories:
    • WorkingDir
    • WorkingDir\MinHook\x32 and/or WorkingDir\MinHook\x64
    • Minhook.ahk Directory
    • Minhook.ahk Directory\MinHook\x32 and/or Minhook.ahk Directory\MinHook\x64
feiyue
Posts: 348
Joined: 08 Aug 2014, 04:08

Re: MinHook - API Hooking Library

16 Aug 2018, 03:56

Hi tmplinshi, This is a very useful script! thanks for sharing! :wave:

I think Example2 needs to modify one line (Otherwise I can't see the effect.):

Example2 - GetOpenFileNameW.ahk
return DllCall(hook1.original, "ptr", ofn), hook1 := ""
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: MinHook - API Hooking Library

16 Aug 2018, 06:46

feiyue wrote:I think Example2 needs to modify one line (Otherwise I can't see the effect.):

Example2 - GetOpenFileNameW.ahk
return DllCall(hook1.original, "ptr", ofn), hook1 := ""
But then a window will popup, which was the Example2 trying to avoid. :)
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: MinHook - API Hooking Library

27 Jan 2019, 19:25

tmplinshi, do not You know how can I hook directx endscene method, as it written here:
http://spazzarama.com/2010/03/29/screen-capture-with-direct3d-api-hooks
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: MinHook - API Hooking Library

29 Jan 2019, 07:01

@malcev too complex for me.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: MinHook - API Hooking Library

30 Jan 2019, 06:33

I have done like this, I can hook endscene method but program hangs after that.
Do not know why.
Here is 32 bit program (do not need install):
https://files.fm/u/xast7cz4
Inject autohotkey.dll like this:

Code: Select all

f11::
WinGet, PID, PID, A
FileRead,HookScript,minhook.ahk
rThread:=""
rThread:=InjectAhkDll(PID,A_ScriptDir "\AutoHotkey.dll", HookScript)
return
minhook.ahk:

Code: Select all

#Persistent
SetWorkingDir %A_ScriptDir%
d3d := Direct3DCreate9(D3D_SDK_VERSION := 32) 
VarSetCapacity(D3DPRESENT_PARAMETERS, 48+2*A_PtrSize, 0) 
NumPut(1, D3DPRESENT_PARAMETERS, 0)   ; BackBufferWidth
NumPut(1, D3DPRESENT_PARAMETERS, 4)   ; BackBufferHeight
NumPut(1, D3DPRESENT_PARAMETERS, 24)   ; D3DSWAPEFFECT_DISCARD
NumPut(1, D3DPRESENT_PARAMETERS, 24+2*A_PtrSize)   ; Windowed
IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT := 0, D3DDEVTYPE_HAL := 1, 0, D3DCREATE_HARDWARE_VERTEXPROCESSING := 0x00000040, &D3DPRESENT_PARAMETERS, device)
EndScene := NumGet(NumGet(device+0)+42*A_PtrSize) 
Release(device)
Release(d3d)

MinhookDll := "MinHook.dll"
MinHook_Init(MinhookDll)
MH_CreateHook(EndScene, cbAddr := RegisterCallback("EndScene_Hook", "F"))
MH_EnableHook()
return

EndScene_Hook(device)
{
   msgbox hook
}


Direct3DCreate9(SDKVersion)
{
   if !DllCall("GetModuleHandle","str","d3d9", "PTR")
   {
      MsgBox, 16, Error, d3d9 failed.
      ExitApp
   }
   return DllCall("d3d9\Direct3DCreate9", "uint", SDKVersion)
}

IDirect3D9_CreateDevice(this,Adapter,DeviceType,hFocusWindow,BehaviorFlags,pPresentationParameters,ByRef ppReturnedDeviceInterface)
{
   hr := DllCall(NumGet(NumGet(this+0)+16*A_PtrSize),"ptr",this,"uint",Adapter,"uint",DeviceType,"ptr",hFocusWindow,"uint",BehaviorFlags,"ptr",pPresentationParameters,"ptr*",ppReturnedDeviceInterface)
   if hr
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

Release(this)
{
   return DllCall(NumGet(NumGet(this+0)+2*A_PtrSize), "ptr", this)
}

_Error(val)
{
   msgbox % val
   ExitApp
}


MinHook_Init(MinhookDll)
{
   Static h
   If Not h
   {
      h:=DllCall("LoadLibrary","Str",MinhookDll, "Ptr")
      MH_Initialize()
   }
}

; Creates a Hook for the specified target function, in disabled state.
; Parameters:
;   pTarget    [in]  A pointer to the target function, which will be
;                    overridden by the detour function.
;   pDetour    [in]  A pointer to the detour function, which will override
;                    the target function.
;   ppOriginal [out] A pointer to the trampoline function, which will be
;                    used to call the original target function.
;                    This parameter can be NULL.
MH_CreateHook(pTarget, pDetour, ByRef ppOriginal := 0) {
	return DllCall("MinHook\MH_CreateHook"
	               , "ptr", pTarget
	               , "ptr", pDetour
	               , "uptr*", ppOriginal )
}

; Initialize the MinHook library. You must call this function EXACTLY ONCE
; at the beginning of your program.
MH_Initialize() {
	return DllCall("MinHook\MH_Initialize")
}

; Uninitialize the MinHook library. You must call this function EXACTLY
; ONCE at the end of your program.
MH_Uninitialize() {
	return DllCall("MinHook\MH_Uninitialize")
}

; Removes an already created hook.
; Parameters:
;   pTarget [in] A pointer to the target function.
MH_RemoveHook(pTarget) {
	return DllCall("MinHook\MH_RemoveHook", "ptr", pTarget)
}

/*
	#define MH_ALL_HOOKS NULL
*/

; Enables an already created hook.
; Parameters:
;   pTarget [in] A pointer to the target function.
;                If this parameter is MH_ALL_HOOKS, all created hooks are
;                enabled in one go.
MH_EnableHook(pTarget := 0) {
	return DllCall("MinHook\MH_EnableHook", "ptr", pTarget)
}

; Disables an already created hook.
; Parameters:
;   pTarget [in] A pointer to the target function.
;                If this parameter is MH_ALL_HOOKS, all created hooks are
;                disabled in one go.
MH_DisableHook(pTarget := 0) {
	return DllCall("MinHook\MH_DisableHook", "ptr", pTarget)
}
Galaxis
Posts: 73
Joined: 04 Feb 2016, 20:09

Re: MinHook - API Hooking Library

07 Feb 2019, 17:42

tmplinshi wrote:
11 Aug 2018, 06:59
An AHK wrapper for MinHook.

Example 1 - Hook MessageBoxW

Code: Select all

#Include <MinHook>

hook1 := New MinHook("user32.dll", "MessageBoxW", "MessageBoxW_Hook")

hook1.Enable()
MsgBox, 64, Hello, World

hook1.Disable()
MsgBox, 64, Hello, I'm back.

hook1 := "" ; Remove hook

MessageBoxW_Hook(hWnd, lpText, lpCaption, uType) {
	global hook1
	return DllCall(hook1.original, "ptr", hWnd, "str", "Hooked!", "ptr", lpCaption, "uint", 48)
}

Can you provide an example of hooking a function in a FPS game (ie. player ammo) ?
Or an example of hooking a specific pointer address in game memory.
Or finds what writes to this address, like in Cheat Engine.
Galaxis
Posts: 73
Joined: 04 Feb 2016, 20:09

Re: MinHook - API Hooking Library

10 Feb 2019, 11:01

Galaxis wrote:
07 Feb 2019, 17:42
tmplinshi wrote:
11 Aug 2018, 06:59
An AHK wrapper for MinHook.

Example 1 - Hook MessageBoxW

Code: Select all

#Include <MinHook>

hook1 := New MinHook("user32.dll", "MessageBoxW", "MessageBoxW_Hook")

hook1.Enable()
MsgBox, 64, Hello, World

hook1.Disable()
MsgBox, 64, Hello, I'm back.

hook1 := "" ; Remove hook

MessageBoxW_Hook(hWnd, lpText, lpCaption, uType) {
	global hook1
	return DllCall(hook1.original, "ptr", hWnd, "str", "Hooked!", "ptr", lpCaption, "uint", 48)
}

Can you provide an example of hooking a function in a FPS game (ie. player ammo) ?
Or an example of hooking a specific pointer address in game memory.
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: MinHook - API Hooking Library

10 Feb 2019, 12:23

Hi Galaxis, i'm not sure but see "Example 4" that i just added.
Galaxis
Posts: 73
Joined: 04 Feb 2016, 20:09

Re: MinHook - API Hooking Library

21 Feb 2019, 07:56

malcev wrote:
27 Jan 2019, 19:25
tmplinshi, do not You know how can I hook directx endscene method, as it written here:
http://spazzarama.com/2010/03/29/screen-capture-with-direct3d-api-hooks
I want to hook DX11 =)
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: MinHook - API Hooking Library

11 Jun 2019, 04:05

I tried to hook DX9 of GFXTest32.exe, but process crashes.
I tried to run it suspended, hook it and after that resume - but nothing helps.
My be somebody can solve it.
To test it just run inject.ahk.
Attachments
hook.zip
(569.26 KiB) Downloaded 191 times
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: MinHook - API Hooking Library

17 Aug 2019, 19:12

Update:

Added 2 more examples:
  • Example 5 - Change GUI class name.ahk
  • Example 6 - Change GUI class name (Memory).ahk
Example 6 can embed MinHook.dll to the compiled exe. It uses HotkeyIt's _MemoryLibrary, _Struct and sizeof.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: MinHook - API Hooking Library

02 Oct 2019, 13:21

Just tried to hook DirectX 11::.
This example add "Hello, World!" to target program.
inject.ahk runs target program in suspended mode, then injects autohotkey.dll in target program and executes minhook.ahk.
minhook.ahk hooks IDXGISwapChain_Present and IDXGISwapChain_ResizeBuffers and add text in target program with FW1FontWrapper.dll.
FW1FontWrapper.dll does not work properly with unity engine games running in full-screen mode.
dll and target program in attachment.
inject.ahk (change TargetProgram with Yours)

Code: Select all

TargetProgram := "GFXTest.exe"
AutoHotkeyDll := "AutoHotkey.dll"
HookFile := "minhook.ahk"



array := {"TargetProgram": TargetProgram, "AutoHotkey.dll": AutoHotkeyDll, "HookFile": HookFile}
For key, value in array
{
   if !FileExist(value)
   {
      msgbox %value% does not exist
      ExitApp
   }
   if (key = "HookFile")
      Continue
   oFile := FileOpen(value, "r")
   oFile.Seek(0x3c)
   oFile.Seek(oFile.ReadInt()+4)
   machineType := oFile.ReadUShort()
   oFile.Close()
   if (machineType = 0x14c) and (A_PtrSize = 8)
   {
      msgbox %key% 32 bit, but AutoHotkey.exe 64 bit
      ExitApp
   }
   if ((machineType = 0x8664) or (machineType = 0x200)) and (A_PtrSize = 4)
   {
      msgbox %key% 64 bit, but AutoHotkey.exe 32 bit
      ExitApp
   }
}


#Persistent
VarSetCapacity(StartupInfo, size := 9*A_PtrSize + 32, 0)
NumPut(size, StartupInfo)
VarSetCapacity(ProcessInfo, 2*A_PtrSize + 8, 0)
DllCall("CreateProcess", "ptr", 0, "str", TargetProgram, "ptr", 0, "ptr", 0, "int", 0, "int", CREATE_SUSPENDED := 4, "ptr", 0, "ptr", 0, "ptr", &StartupInfo, "ptr", &ProcessInfo)
DllCall("CloseHandle", Ptr, hThread := NumGet(ProcessInfo))
DllCall("CloseHandle", Ptr, hProcess := NumGet(&ProcessInfo + A_PtrSize))
PID := NumGet(&ProcessInfo + 2*A_PtrSize, "UInt")
rThread:=""
rThread:=InjectAhkDll(pid, AutoHotkeyDll,, 1)
h := DllCall("OpenProcess", "uint", PROCESS_ALL_ACCESS := 0x1F0FFF, "int", 0, "uint", PID, "ptr")
DllCall("ntdll.dll\NtResumeProcess", "ptr", h)
DllCall("CloseHandle", "ptr", h)
FileRead,HookScript, %HookFile%
rThread.Exec(HookScript)
return



InjectAhkDll(PID,dll:="AutoHotkey64.dll",script:=0, deleteThread := false)
{
   static PROCESS_ALL_ACCESS:=0x1F0FFF,MEM_COMMIT := 0x1000,MEM_RELEASE:=0x8000,PAGE_EXECUTE_READWRITE:=64
   ,hKernel32:=DllCall("LoadLibrary","Str","kernel32.dll","PTR"),LoadLibraryA:=DllCall("GetProcAddress","PTR",hKernel32,"AStr","LoadLibraryA","PTR")
   ,FreeLibrary:=DllCall("GetProcAddress","PTR",hKernel32,"AStr","FreeLibrary","PTR")
   ,TH32CS_SNAPMODULE:=0x00000008,INVALID_HANDLE_VALUE:=-1
   ,MAX_PATH:=260,MAX_MODULE_NAME32:=255,ModuleName:="",init:=VarSetCapacity(ModuleName,MAX_PATH*(A_IsUnicode?2:1))
   base:= deleteThread ? {__Call:"InjectAhkDll",__Delete:"InjectAhkDll"} : {__Call:"InjectAhkDll"}

   if IsObject(PID)
   {
      if (dll!="Exec" && script)
         return "Only Exec method can be used here!"

      hProc := DllCall("OpenProcess", "UInt", PROCESS_ALL_ACCESS, "Int",0, "UInt", PID.PID,"PTR")
      if !hProc
         return "Could not open process for PID: " PID.PID

      if (!script) ; Free Library in remote process (object is being deleted)
      {
         ; Terminate the thread in ahkdll
         hThread := DllCall("CreateRemoteThread", "PTR", hProc, "PTR", 0, "PTR", 0, "PTR", PID.ahkTerminate, "PTR", 0, "UInt", 0, "PTR", 0,"PTR")
         DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
         ,DllCall("CloseHandle", "PTR", hThread)

         ; Free library in remote process
         hThread := DllCall("CreateRemoteThread", "PTR", hProc, "UInt", 0, "UInt", 0, "PTR", FreeLibrary, "PTR", PID.hModule, "UInt", 0, "UInt", 0,"PTR")
         DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
         ,DllCall("CloseHandle", "PTR", hThread),DllCall("CloseHandle", "PTR", hProc)
         return
      }

      nScriptLength := VarSetCapacity(nScript, (StrLen(script)+1)*(A_IsUnicode?2:1), 0)
      ,StrPut(script,&nScript)

      ; Reserve memory in remote process where our script will be saved
      if !pBufferRemote := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nScriptLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
         return "Could not reseve memory for process"
      ,DllCall("CloseHandle", "PTR", hProc)

      ; Write script to remote process memory
      DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferRemote, "Ptr", &nScript, "PTR", nScriptLength, "Ptr", 0)

      ; Start execution of code
      hThread := DllCall("CreateRemoteThread", "PTR", hProc, "PTR", 0, "PTR", 0, "PTR", PID.ahkExec, "PTR", pBufferRemote, "UInt", 0, "PTR", 0,"PTR")
      if !hThread
      {
         DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nScriptLength,MEM_RELEASE)
         ,DllCall("CloseHandle", "PTR", hProc)
         return "Could not execute script in remote process"
      }

      ; Wait for thread to finish
      DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)

      ; Get Exit code returned by ahkExec (1 = script could be executed / 0 = script could not be executed)
      DllCall("GetExitCodeThread", "PTR", hThread, "UIntP", lpExitCode)
      if !lpExitCode
         return "Could not execute script in remote process"

      DllCall("CloseHandle", "PTR", hThread)
      ,DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nScriptLength,MEM_RELEASE)
      ,DllCall("CloseHandle", "PTR", hProc)
      return
   }
   else if !hDll:=DllCall("LoadLibrary","Str",dll,"PTR")
      return "Could not find " dll " library", DllCall("CloseHandle", "PTR", hProc)
   else
   {
      hProc := DllCall("OpenProcess","UInt", PROCESS_ALL_ACCESS, "Int",0,"UInt", DllCall("GetCurrentProcessId"),"PTR")
      DllCall("GetModuleFileName","PTR",hDll,"PTR",&ModuleName,"UInt",MAX_PATH)
      DllCall("CloseHandle","PTR",hProc)
   }
   ; Open Process to PID
   hProc := DllCall("OpenProcess", "UInt", PROCESS_ALL_ACCESS, "Int",0, "UInt", PID,"PTR")
   if !hProc
      return "Could not open process for PID: " PID
   
   Loop, Files, %dll%, F
      dll := A_LoopFileLongPath
   ; Reserve some memory and write dll path (ANSI)
   nDirLength := VarSetCapacity(nDir, StrLen(dll)+1, 0)
   ,StrPut(dll,&nDir,"CP0")

   ; Reserve memory in remote process
   if !pBufferRemote := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nDirLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
      return "Could not reseve memory for process", DllCall("CloseHandle", "PTR", hProc)

   ; Write dll path to remote process memory
   DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferRemote, "Ptr", &nDir, "PTR", nDirLength, "Ptr", 0)

   ; Start new thread loading our dll

   hThread:=DllCall("CreateRemoteThread","PTR",hProc,"PTR",0,"PTR",0,"PTR",LoadLibraryA,"PTR",pBufferRemote,"UInt",0,"PTR",0,"PTR")
   if !hThread
   {
      DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,"Uint",MEM_RELEASE)
      ,DllCall("CloseHandle", "PTR", hProc)
      return "Could not load " dll " in remote process"
   }
   ; Wait for thread to finish
   DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)

   ; Get Exit code returned by thread (HMODULE for our dll)
   DllCall("GetExitCodeThread", "PTR", hThread, "UInt*", hModule)

   ; Close Thread
   DllCall("CloseHandle", "PTR", hThread)

   if (A_PtrSize=8)
   { ; use different method to retrieve base address because GetExitCodeThread returns DWORD only
      hModule:=0,VarSetCapacity(me32, (A_PtrSize=8?48:32)+(A_IsUnicode?1032:516), 0) ;W:1080:1064, A:564:548
      ;  Take a snapshot of all modules in the specified process.
      hModuleSnap := DllCall("CreateToolhelp32Snapshot","UInt", TH32CS_SNAPMODULE,"UInt", PID, "PTR" )
      if ( hModuleSnap != INVALID_HANDLE_VALUE )
      {
         ; reset hModule and set the size of the structure before using it.
         NumPut((A_PtrSize=8?48:32)+(A_IsUnicode?1032:516), &me32, 0, "UInt") ;dwSize  ;W:1080:1064, A:564:548
         ;  Retrieve information about the first module,
         ;  and exit if unsuccessful
         if ( !DllCall("Module32First" (A_IsUnicode?"W":""),"PTR", hModuleSnap,"PTR", &me32 ) )
         {
            ; Free memory used for passing dll path to remote thread
            DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
            ,DllCall("CloseHandle","PTR", hModuleSnap ) ; Must clean up the snapshot object!
            return false
         }
         ;  Now walk the module list of the process,and display information about each module
         while(A_Index=1 || DllCall("Module32Next" (A_IsUnicode?"W":""),"PTR",hModuleSnap,"PTR", &me32 ) )
            if (StrGet(&me32+(A_PtrSize=8?48:32)+(A_IsUnicode?512:256))=dll) ;szExePath ;W:560:544, A:304:288
            {
               hModule := NumGet(me32, A_PtrSize=8?40:28, "Ptr") ;hModule
               break
            }
         DllCall("CloseHandle","PTR",hModuleSnap) ; clean up
      }
   }

   hDll:=DllCall("LoadLibrary","Str",dll,"PTR")

   ; Calculate pointer to ahkdll and ahkExec functions
   ahktextdll:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahktextdll","PTR")-hDll
   ahkExec:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahkExec","PTR")-hDll
   ahkTerminate:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahkTerminate","PTR")-hDll

   if script
   {
      nScriptLength := VarSetCapacity(nScript, (StrLen(script)+1)*(A_IsUnicode?2:1), 0)
      ,StrPut(script,&nScript)
      ; Reserve memory in remote process where our script will be saved
      if !pBufferScript := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nScriptLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
         return "Could not reseve memory for process"
      ,DllCall("CloseHandle", "PTR", hProc)

      ; Write script to remote process memory
      DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferScript, "Ptr", &nScript, "PTR", nScriptLength, "Ptr", 0)
   }
   else
      pBufferScript:=0

   ; Run ahkdll function in remote thread
   hThread := DllCall("CreateRemoteThread","PTR",hProc,"PTR",0,"PTR",0,"PTR",ahktextdll,"PTR",pBufferScript,"PTR",0,"UInt",0,"PTR")
   if !hThread
   { ; could not start ahkdll in remote process
      ; Free memory used for passing dll path to remote thread
      DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
      DllCall("CloseHandle", "PTR", hProc)
      return "Could not start ahkdll in remote process"
   }
   DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
   DllCall("GetExitCodeThread", "PTR", hThread, "UIntP", lpExitCode)

   ; Release memory and handles
   DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
   DllCall("CloseHandle", "PTR", hThread)
   DllCall("CloseHandle", "PTR", hProc)

   if !lpExitCode ; thread could not be created.
      return "Could not create a thread in remote process"

   return {PID:PID,hModule:hModule,ahkExec:ahkExec,ahkTerminate:ahkTerminate,base:base}
}
minhook.ahk (change TargetWinTitle with Yours)

Code: Select all

TargetWinTitle := "ahk_class gfx_test"
MinhookDll := "MinHook.dll"
Global FW1FontWrapperDll := "FW1FontWrapper.dll"
Global IDXGISwapChain_Present_Original, IDXGISwapChain_ResizeBuffers_Original, ResolutionChanged, widthChanged, heightChanged



array := {"MinHook.dll": MinhookDll, "FW1FontWrapper.dll": FW1FontWrapperDll}
For key, value in array
{
   if !FileExist(value)
   {
      msgbox %value% does not exist
      ExitApp
   }
   oFile := FileOpen(value, "r")
   oFile.Seek(0x3c)
   oFile.Seek(oFile.ReadInt()+4)
   machineType := oFile.ReadUShort()
   oFile.Close()
   if (machineType = 0x14c) and (A_PtrSize = 8)
   {
      msgbox %key% 32 bit, but AutoHotkey.exe 64 bit
      ExitApp
   }
   if ((machineType = 0x8664) or (machineType = 0x200)) and (A_PtrSize = 4)
   {
      msgbox %key% 64 bit, but AutoHotkey.exe 32 bit
      ExitApp
   }
}

WinWait, % TargetWinTitle
hwnd := WinExist(TargetWinTitle)
SetWorkingDir %A_ScriptDir%
LoadDll()

VarSetCapacity(SwapChainDesc, 48+A_PtrSize*3, 0)
NumPut(60, SwapChainDesc, 8, "uint")   ; DXGI_MODE_DESC DXGI_RATIONAL Numerator
NumPut(1, SwapChainDesc, 12, "uint")   ; DXGI_MODE_DESC DXGI_RATIONAL Denominator
NumPut(DXGI_FORMAT_R8G8B8A8_UNORM := 28, SwapChainDesc, 16, "uint")   ; DXGI_MODE_DESC Format
NumPut(1, SwapChainDesc, 28, "uint")   ; DXGI_SAMPLE_DESC count
NumPut(DXGI_USAGE_RENDER_TARGET_OUTPUT := 32, SwapChainDesc, 36, "uint")   ; BufferUsage
NumPut(1, SwapChainDesc, 40, "uint")   ; BufferCount
NumPut(hwnd, SwapChainDesc, 40+A_PtrSize, "ptr")   ; OutputWindow
NumPut(1, SwapChainDesc, 40+2*A_PtrSize, "int")   ; Windowed
NumPut(DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH := 2, SwapChainDesc, 48+2*A_PtrSize, "uint")   ; Flags

VarSetCapacity(D3D_FEATURE_LEVEL, 4, 0)
NumPut(D3D_FEATURE_LEVEL_11_0 := 0xb000, D3D_FEATURE_LEVEL, 0, "uint")
D3D11CreateDeviceAndSwapChain(0, D3D_DRIVER_TYPE_HARDWARE := 1, 0, 0, &D3D_FEATURE_LEVEL, 1, D3D11_SDK_VERSION := 7, &SwapChainDesc, IDXGI_SwapChain, ID3D11Device, 0, ID3D11DeviceContext)
IDXGISwapChain_Present := IDXGISwapChain_Present_Get(IDXGI_SwapChain)
IDXGISwapChain_ResizeBuffers := IDXGISwapChain_ResizeBuffers_Get(IDXGI_SwapChain)
Release(IDXGI_SwapChain)
Release(ID3D11DeviceContext)
Release(ID3D11Device)
IDXGI_SwapChain := ID3D11DeviceContext := ID3D11Device := ""

MinHook_Init(MinhookDll)
MH_CreateHook(IDXGISwapChain_Present, RegisterCallback("IDXGISwapChain_Present_Hook", "F"), IDXGISwapChain_Present_Original)
MH_CreateHook(IDXGISwapChain_ResizeBuffers, RegisterCallback("IDXGISwapChain_ResizeBuffers_Hook", "F"), IDXGISwapChain_ResizeBuffers_Original)
MH_EnableHook()
return


IDXGISwapChain_Present_Hook(SwapChain, SyncInterval, Flags)
{
   Critical
   static Init, iFontWrapper, ImmediateContext, ResolutionOK, width, height
   if (ResolutionChanged = 1)
      ResolutionOk := ResolutionChanged := "", width := widthChanged, height := heightChanged
   if (ResolutionOK = "")
   {
      if ImmediateContext
      {
         Release(ImmediateContext)
         ImmediateContext := ""
      }
      IDXGISwapChain_GetDevice(SwapChain, ID3D11Device)
      ID3D11Device_GetImmediateContext(ID3D11Device, ImmediateContext)
      if (Init = "")
      {
         if (width = "")
         {
            VarSetCapacity(SwapChainDesc, 48+A_PtrSize*3, 0)
            IDXGISwapChain_GetDesc(SwapChain, &SwapChainDesc)
            width := NumGet(SwapChainDesc, 0, "uint")
            height := NumGet(SwapChainDesc, 4, "uint")
         }
         FW1CreateFactory(pFW1Factory)
         iFW1Factory := FW1Factory_Query(pFW1Factory)
         IFW1Factory_CreateFontWrapper(iFW1Factory, ID3D11Device, "Arial", pFontWrapper)
         iFontWrapper := FW1FontWrapper_Query(pFontWrapper)
         ObjRelease(iFW1Factory)
         iFW1Factory := ""
         Init := 1
      }
      ResolutionOK := 1
   }
   IFW1FontWrapper_DrawString(iFontWrapper, ImmediateContext, "Hello, World!", width*0.1, width/2, height/2, 0xFFFFFFFF, 0x1|0x4|0x800)   ; FW1_CENTER|FW1_VCENTER|FW1_RESTORESTATE
   DllCall(IDXGISwapChain_Present_Original, "ptr", SwapChain, "uint", SyncInterval, "uint", Flags)
   return 
}

IDXGISwapChain_ResizeBuffers_Hook(SwapChain, BufferCount, SwapChainWidth, SwapChainHeight, NewFormatBuf, SwapChainFlags)
{
   widthChanged := SwapChainWidth, heightChanged := SwapChainHeight
   ResolutionChanged := 1
   DllCall(IDXGISwapChain_ResizeBuffers_Original, "ptr", SwapChain, "uint", BufferCount, "uint", SwapChainWidth, "uint", SwapChainHeight, "uint", NewFormatBuf, "uint", SwapChainFlags)
   return 
}



LoadDll()
{
   if !DllCall("GetModuleHandle","str","DXGI", "ptr")
   {
      MsgBox, 16, Error, DXGI failed.
      ExitApp
   }
   if !DllCall("GetModuleHandle","str","D3D11", "ptr")
   {
      MsgBox, 16, Error, D3D11 failed.
      ExitApp
   }
   if !DllCall("GetModuleHandle","str","FW1FontWrapper")
      DllCall("LoadLibrary","Str", FW1FontWrapperDll, "ptr")
   return
}


FW1CreateFactory(ByRef ppFactory)
{
   hr := DllCall(FW1FontWrapperDll "\FW1CreateFactory", "uint", FW1_VERSION := 0x110f, "ptr*", ppFactory)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

FW1Factory_Query(pFactory)
{ 
   hr := ComObjQuery(pFactory, "{8004DB2B-B5F9-4420-A6A2-E17E15E4C336}")
   if !hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   return hr
}

IFW1Factory_CreateFontWrapper(this, pDevice, pszFontFamily, ByRef ppFontWrapper)
{
   hr := DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "ptr", pDevice, "str", pszFontFamily, "ptr*", ppFontWrapper)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

FW1FontWrapper_Query(pFontWrapper)
{ 
   hr := ComObjQuery(pFontWrapper, "{83347A5C-B0B1-460e-A35C-427E8B85F9F4}")
   if !hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   return hr
}

IFW1FontWrapper_DrawString(this, pContext, pszString, FontSize, X, Y, Color, Flags)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this, "ptr", pContext, "str", pszString, "float", FontSize, "float", X, "float", Y, "uint", Color, "uint", Flags)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}



D3D11CreateDeviceAndSwapChain(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, SwapChainDesc, ByRef ppSwapChain, ByRef ppDevice, pFeatureLevel, ByRef ppImmediateContext)
{
   hr := DllCall("D3D11\D3D11CreateDeviceAndSwapChain", "ptr", pAdapter, "int", DriverType, "ptr", Software, "uint", Flags, "ptr", pFeatureLevels, "uint", FeatureLevels, "uint", SDKVersion, "ptr", SwapChainDesc, "ptr*", ppSwapChain, "ptr*", ppDevice, "ptr", pFeatureLevel, "ptr*", ppImmediateContext)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGISwapChain_GetDevice(this, ByRef ppDevice)
{
   GUID(riid, "{db6f6ddb-ac77-4e88-8253-819df9bbf140}")
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", &riid, "ptr*", ppDevice)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11Device_GetImmediateContext(this, ByRef ppImmediateContext)
{
   DllCall(NumGet(NumGet(this+0)+40*A_PtrSize), "ptr", this, "ptr*", ppImmediateContext)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGISwapChain_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), "ptr", this, "ptr", pDesc)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGISwapChain_Present_Get(this)
{
   return NumGet(NumGet(this+0)+8*A_PtrSize)
}

IDXGISwapChain_ResizeBuffers_Get(this)
{
   return NumGet(NumGet(this+0)+13*A_PtrSize)
}

Release(this)
{
   DllCall(NumGet(NumGet(this+0)+2*A_PtrSize), "ptr", this)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

GUID(ByRef GUID, sGUID)
{
    VarSetCapacity(GUID, 16, 0)
    return DllCall("ole32\CLSIDFromString", "WStr", sGUID, "Ptr", &GUID) >= 0 ? &GUID : ""
}

_Error(val)
{
   msgbox % val
   ExitApp
}


MinHook_Init(MinhookDll)
{
   Static h
   If Not h
   {
      h:=DllCall("LoadLibrary","Str",MinhookDll, "Ptr")
      MH_Initialize()
   }
}

; Creates a Hook for the specified target function, in disabled state.
; Parameters:
;   pTarget    [in]  A pointer to the target function, which will be
;                    overridden by the detour function.
;   pDetour    [in]  A pointer to the detour function, which will override
;                    the target function.
;   ppOriginal [out] A pointer to the trampoline function, which will be
;                    used to call the original target function.
;                    This parameter can be NULL.
MH_CreateHook(pTarget, pDetour, ByRef ppOriginal := 0) {
	return DllCall("MinHook\MH_CreateHook"
	               , "ptr", pTarget
	               , "ptr", pDetour
	               , "uptr*", ppOriginal )
}

; Initialize the MinHook library. You must call this function EXACTLY ONCE
; at the beginning of your program.
MH_Initialize() {
	return DllCall("MinHook\MH_Initialize")
}

; Uninitialize the MinHook library. You must call this function EXACTLY
; ONCE at the end of your program.
MH_Uninitialize() {
	return DllCall("MinHook\MH_Uninitialize")
}

; Removes an already created hook.
; Parameters:
;   pTarget [in] A pointer to the target function.
MH_RemoveHook(pTarget) {
	return DllCall("MinHook\MH_RemoveHook", "ptr", pTarget)
}

/*
	#define MH_ALL_HOOKS NULL
*/

; Enables an already created hook.
; Parameters:
;   pTarget [in] A pointer to the target function.
;                If this parameter is MH_ALL_HOOKS, all created hooks are
;                enabled in one go.
MH_EnableHook(pTarget := 0) {
	return DllCall("MinHook\MH_EnableHook", "ptr", pTarget)
}

; Disables an already created hook.
; Parameters:
;   pTarget [in] A pointer to the target function.
;                If this parameter is MH_ALL_HOOKS, all created hooks are
;                disabled in one go.
MH_DisableHook(pTarget := 0) {
	return DllCall("MinHook\MH_DisableHook", "ptr", pTarget)
}
The next code captures screen from back buffer of directx11 programs.
f11 - saves 1 picture.
f12 - start/stop capture series of pictures with given framerate.
I do not test it on programs which have multi-sampled texture, because I do not have them, therefore I am not sure about this part of code:

Code: Select all

      else
      {
         item := 0
         loop % ArraySize
         {
            level := 0
            loop % MipLevels
            {
               index := D3D11CalcSubresource(level, item, MipLevels)
               ID3D11DeviceContext_ResolveSubresource(ImmediateContext, temp_texture, index, BackBuffer, index, fmt)
               level++
            }
            item++
         }
         ID3D11DeviceContext_CopyResource(ImmediateContext, staging_texture, temp_texture)
      }
You can uncomment this ; msgbox multisampling to check if your BackBuffer is multi-sampled.

inject.ahk

Code: Select all

TargetProgram := "GFXTest.exe"
AutoHotkeyDll := "AutoHotkey.dll"
HookFile := "minhook.ahk"



array := {"TargetProgram": TargetProgram, "AutoHotkey.dll": AutoHotkeyDll, "HookFile": HookFile}
For key, value in array
{
   if !FileExist(value)
   {
      msgbox %value% does not exist
      ExitApp
   }
   if (key = "HookFile")
      Continue
   oFile := FileOpen(value, "r")
   oFile.Seek(0x3c)
   oFile.Seek(oFile.ReadInt()+4)
   machineType := oFile.ReadUShort()
   oFile.Close()
   if (machineType = 0x14c) and (A_PtrSize = 8)
   {
      msgbox %key% 32 bit, but AutoHotkey.exe 64 bit
      ExitApp
   }
   if ((machineType = 0x8664) or (machineType = 0x200)) and (A_PtrSize = 4)
   {
      msgbox %key% 64 bit, but AutoHotkey.exe 32 bit
      ExitApp
   }
}


#Persistent
#UseHook
VarSetCapacity(StartupInfo, size := 9*A_PtrSize + 32, 0)
NumPut(size, StartupInfo)
VarSetCapacity(ProcessInfo, 2*A_PtrSize + 8, 0)
DllCall("CreateProcess", "ptr", 0, "str", TargetProgram, "ptr", 0, "ptr", 0, "int", 0, "int", CREATE_SUSPENDED := 4, "ptr", 0, "ptr", 0, "ptr", &StartupInfo, "ptr", &ProcessInfo)
DllCall("CloseHandle", Ptr, hThread := NumGet(ProcessInfo))
DllCall("CloseHandle", Ptr, hProcess := NumGet(&ProcessInfo + A_PtrSize))
PID := NumGet(&ProcessInfo + 2*A_PtrSize, "UInt")
rThread:=""
rThread:=InjectAhkDll(pid, AutoHotkeyDll,, 1)
h := DllCall("OpenProcess", "uint", PROCESS_ALL_ACCESS := 0x1F0FFF, "int", 0, "uint", PID, "ptr")
DllCall("ntdll.dll\NtResumeProcess", "ptr", h)
DllCall("CloseHandle", "ptr", h)
FileRead,HookScript, %HookFile%
rThread.Exec(HookScript)
return

f11::
if !multiCapture
   rThread.Exec("singleCapture := 1")
return

f12::
multiCapture := !multiCapture
if multiCapture
   rThread.Exec("multiCapture := 1")
else
   rThread.Exec("multiCapture := """"")
return


InjectAhkDll(PID,dll:="AutoHotkey64.dll",script:=0, deleteThread := false)
{
   static PROCESS_ALL_ACCESS:=0x1F0FFF,MEM_COMMIT := 0x1000,MEM_RELEASE:=0x8000,PAGE_EXECUTE_READWRITE:=64
   ,hKernel32:=DllCall("LoadLibrary","Str","kernel32.dll","PTR"),LoadLibraryA:=DllCall("GetProcAddress","PTR",hKernel32,"AStr","LoadLibraryA","PTR")
   ,FreeLibrary:=DllCall("GetProcAddress","PTR",hKernel32,"AStr","FreeLibrary","PTR")
   ,TH32CS_SNAPMODULE:=0x00000008,INVALID_HANDLE_VALUE:=-1
   ,MAX_PATH:=260,MAX_MODULE_NAME32:=255,ModuleName:="",init:=VarSetCapacity(ModuleName,MAX_PATH*(A_IsUnicode?2:1))
   base:= deleteThread ? {__Call:"InjectAhkDll",__Delete:"InjectAhkDll"} : {__Call:"InjectAhkDll"}

   if IsObject(PID)
   {
      if (dll!="Exec" && script)
         return "Only Exec method can be used here!"

      hProc := DllCall("OpenProcess", "UInt", PROCESS_ALL_ACCESS, "Int",0, "UInt", PID.PID,"PTR")
      if !hProc
         return "Could not open process for PID: " PID.PID

      if (!script) ; Free Library in remote process (object is being deleted)
      {
         ; Terminate the thread in ahkdll
         hThread := DllCall("CreateRemoteThread", "PTR", hProc, "PTR", 0, "PTR", 0, "PTR", PID.ahkTerminate, "PTR", 0, "UInt", 0, "PTR", 0,"PTR")
         DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
         ,DllCall("CloseHandle", "PTR", hThread)

         ; Free library in remote process
         hThread := DllCall("CreateRemoteThread", "PTR", hProc, "UInt", 0, "UInt", 0, "PTR", FreeLibrary, "PTR", PID.hModule, "UInt", 0, "UInt", 0,"PTR")
         DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
         ,DllCall("CloseHandle", "PTR", hThread),DllCall("CloseHandle", "PTR", hProc)
         return
      }

      nScriptLength := VarSetCapacity(nScript, (StrLen(script)+1)*(A_IsUnicode?2:1), 0)
      ,StrPut(script,&nScript)

      ; Reserve memory in remote process where our script will be saved
      if !pBufferRemote := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nScriptLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
         return "Could not reseve memory for process"
      ,DllCall("CloseHandle", "PTR", hProc)

      ; Write script to remote process memory
      DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferRemote, "Ptr", &nScript, "PTR", nScriptLength, "Ptr", 0)

      ; Start execution of code
      hThread := DllCall("CreateRemoteThread", "PTR", hProc, "PTR", 0, "PTR", 0, "PTR", PID.ahkExec, "PTR", pBufferRemote, "UInt", 0, "PTR", 0,"PTR")
      if !hThread
      {
         DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nScriptLength,MEM_RELEASE)
         ,DllCall("CloseHandle", "PTR", hProc)
         return "Could not execute script in remote process"
      }

      ; Wait for thread to finish
      DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)

      ; Get Exit code returned by ahkExec (1 = script could be executed / 0 = script could not be executed)
      DllCall("GetExitCodeThread", "PTR", hThread, "UIntP", lpExitCode)
      if !lpExitCode
         return "Could not execute script in remote process"

      DllCall("CloseHandle", "PTR", hThread)
      ,DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nScriptLength,MEM_RELEASE)
      ,DllCall("CloseHandle", "PTR", hProc)
      return
   }
   else if !hDll:=DllCall("LoadLibrary","Str",dll,"PTR")
      return "Could not find " dll " library", DllCall("CloseHandle", "PTR", hProc)
   else
   {
      hProc := DllCall("OpenProcess","UInt", PROCESS_ALL_ACCESS, "Int",0,"UInt", DllCall("GetCurrentProcessId"),"PTR")
      DllCall("GetModuleFileName","PTR",hDll,"PTR",&ModuleName,"UInt",MAX_PATH)
      DllCall("CloseHandle","PTR",hProc)
   }
   ; Open Process to PID
   hProc := DllCall("OpenProcess", "UInt", PROCESS_ALL_ACCESS, "Int",0, "UInt", PID,"PTR")
   if !hProc
      return "Could not open process for PID: " PID
   
   Loop, Files, %dll%, F
      dll := A_LoopFileLongPath
   ; Reserve some memory and write dll path (ANSI)
   nDirLength := VarSetCapacity(nDir, StrLen(dll)+1, 0)
   ,StrPut(dll,&nDir,"CP0")

   ; Reserve memory in remote process
   if !pBufferRemote := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nDirLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
      return "Could not reseve memory for process", DllCall("CloseHandle", "PTR", hProc)

   ; Write dll path to remote process memory
   DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferRemote, "Ptr", &nDir, "PTR", nDirLength, "Ptr", 0)

   ; Start new thread loading our dll

   hThread:=DllCall("CreateRemoteThread","PTR",hProc,"PTR",0,"PTR",0,"PTR",LoadLibraryA,"PTR",pBufferRemote,"UInt",0,"PTR",0,"PTR")
   if !hThread
   {
      DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,"Uint",MEM_RELEASE)
      ,DllCall("CloseHandle", "PTR", hProc)
      return "Could not load " dll " in remote process"
   }
   ; Wait for thread to finish
   DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)

   ; Get Exit code returned by thread (HMODULE for our dll)
   DllCall("GetExitCodeThread", "PTR", hThread, "UInt*", hModule)

   ; Close Thread
   DllCall("CloseHandle", "PTR", hThread)

   if (A_PtrSize=8)
   { ; use different method to retrieve base address because GetExitCodeThread returns DWORD only
      hModule:=0,VarSetCapacity(me32, (A_PtrSize=8?48:32)+(A_IsUnicode?1032:516), 0) ;W:1080:1064, A:564:548
      ;  Take a snapshot of all modules in the specified process.
      hModuleSnap := DllCall("CreateToolhelp32Snapshot","UInt", TH32CS_SNAPMODULE,"UInt", PID, "PTR" )
      if ( hModuleSnap != INVALID_HANDLE_VALUE )
      {
         ; reset hModule and set the size of the structure before using it.
         NumPut((A_PtrSize=8?48:32)+(A_IsUnicode?1032:516), &me32, 0, "UInt") ;dwSize  ;W:1080:1064, A:564:548
         ;  Retrieve information about the first module,
         ;  and exit if unsuccessful
         if ( !DllCall("Module32First" (A_IsUnicode?"W":""),"PTR", hModuleSnap,"PTR", &me32 ) )
         {
            ; Free memory used for passing dll path to remote thread
            DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
            ,DllCall("CloseHandle","PTR", hModuleSnap ) ; Must clean up the snapshot object!
            return false
         }
         ;  Now walk the module list of the process,and display information about each module
         while(A_Index=1 || DllCall("Module32Next" (A_IsUnicode?"W":""),"PTR",hModuleSnap,"PTR", &me32 ) )
            if (StrGet(&me32+(A_PtrSize=8?48:32)+(A_IsUnicode?512:256))=dll) ;szExePath ;W:560:544, A:304:288
            {
               hModule := NumGet(me32, A_PtrSize=8?40:28, "Ptr") ;hModule
               break
            }
         DllCall("CloseHandle","PTR",hModuleSnap) ; clean up
      }
   }

   hDll:=DllCall("LoadLibrary","Str",dll,"PTR")

   ; Calculate pointer to ahkdll and ahkExec functions
   ahktextdll:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahktextdll","PTR")-hDll
   ahkExec:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahkExec","PTR")-hDll
   ahkTerminate:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahkTerminate","PTR")-hDll

   if script
   {
      nScriptLength := VarSetCapacity(nScript, (StrLen(script)+1)*(A_IsUnicode?2:1), 0)
      ,StrPut(script,&nScript)
      ; Reserve memory in remote process where our script will be saved
      if !pBufferScript := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nScriptLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
         return "Could not reseve memory for process"
      ,DllCall("CloseHandle", "PTR", hProc)

      ; Write script to remote process memory
      DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferScript, "Ptr", &nScript, "PTR", nScriptLength, "Ptr", 0)
   }
   else
      pBufferScript:=0

   ; Run ahkdll function in remote thread
   hThread := DllCall("CreateRemoteThread","PTR",hProc,"PTR",0,"PTR",0,"PTR",ahktextdll,"PTR",pBufferScript,"PTR",0,"UInt",0,"PTR")
   if !hThread
   { ; could not start ahkdll in remote process
      ; Free memory used for passing dll path to remote thread
      DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
      DllCall("CloseHandle", "PTR", hProc)
      return "Could not start ahkdll in remote process"
   }
   DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
   DllCall("GetExitCodeThread", "PTR", hThread, "UIntP", lpExitCode)

   ; Release memory and handles
   DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
   DllCall("CloseHandle", "PTR", hThread)
   DllCall("CloseHandle", "PTR", hProc)

   if !lpExitCode ; thread could not be created.
      return "Could not create a thread in remote process"

   return {PID:PID,hModule:hModule,ahkExec:ahkExec,ahkTerminate:ahkTerminate,base:base}
}
minhook.ahk (change TargetWinTitle, OutputDir, Extension, and fps with Yours).

Code: Select all

TargetWinTitle := "ahk_class gfx_test"
global OutputDir := "D:\temp"
global Extension := "png"   ; can be: png, bmp, jpg, tiff, gif
global fps := 1
MinhookDll := "MinHook.dll"
Global IDXGISwapChain_Present_Original, IDXGISwapChain_ResizeBuffers_Original, ResolutionChanged, widthChanged, heightChanged, formatChanged, singleCapture, multiCapture



array := {"MinHook.dll": MinhookDll}
For key, value in array
{
   if !FileExist(value)
   {
      msgbox %value% does not exist
      ExitApp
   }
   oFile := FileOpen(value, "r")
   oFile.Seek(0x3c)
   oFile.Seek(oFile.ReadInt()+4)
   machineType := oFile.ReadUShort()
   oFile.Close()
   if (machineType = 0x14c) and (A_PtrSize = 8)
   {
      msgbox %key% 32 bit, but AutoHotkey.exe 64 bit
      ExitApp
   }
   if ((machineType = 0x8664) or (machineType = 0x200)) and (A_PtrSize = 4)
   {
      msgbox %key% 64 bit, but AutoHotkey.exe 32 bit
      ExitApp
   }
}

WinWait, % TargetWinTitle
hwnd := WinExist(TargetWinTitle)
fps := 1000/fps
SetWorkingDir %A_ScriptDir%
LoadDll()

VarSetCapacity(SwapChainDesc, 48+A_PtrSize*3, 0)
NumPut(60, SwapChainDesc, 8, "uint")   ; DXGI_MODE_DESC DXGI_RATIONAL Numerator
NumPut(1, SwapChainDesc, 12, "uint")   ; DXGI_MODE_DESC DXGI_RATIONAL Denominator
NumPut(DXGI_FORMAT_R8G8B8A8_UNORM := 28, SwapChainDesc, 16, "uint")   ; DXGI_MODE_DESC Format
NumPut(1, SwapChainDesc, 28, "uint")   ; DXGI_SAMPLE_DESC count
NumPut(DXGI_USAGE_RENDER_TARGET_OUTPUT := 32, SwapChainDesc, 36, "uint")   ; BufferUsage
NumPut(1, SwapChainDesc, 40, "uint")   ; BufferCount
NumPut(hwnd, SwapChainDesc, 40+A_PtrSize, "ptr")   ; OutputWindow
NumPut(1, SwapChainDesc, 40+2*A_PtrSize, "int")   ; Windowed
NumPut(DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH := 2, SwapChainDesc, 48+2*A_PtrSize, "uint")   ; Flags

VarSetCapacity(D3D_FEATURE_LEVEL, 4, 0)
NumPut(D3D_FEATURE_LEVEL_11_0 := 0xb000, D3D_FEATURE_LEVEL, 0, "uint")
D3D11CreateDeviceAndSwapChain(0, D3D_DRIVER_TYPE_HARDWARE := 1, 0, 0, &D3D_FEATURE_LEVEL, 1, D3D11_SDK_VERSION := 7, &SwapChainDesc, IDXGI_SwapChain, ID3D11Device, 0, ID3D11DeviceContext)
IDXGISwapChain_Present := IDXGISwapChain_Present_Get(IDXGI_SwapChain)
IDXGISwapChain_ResizeBuffers := IDXGISwapChain_ResizeBuffers_Get(IDXGI_SwapChain)
Release(IDXGI_SwapChain)
Release(ID3D11DeviceContext)
Release(ID3D11Device)
IDXGI_SwapChain := ID3D11DeviceContext := ID3D11Device := ""

MinHook_Init(MinhookDll)
MH_CreateHook(IDXGISwapChain_Present, RegisterCallback("IDXGISwapChain_Present_Hook", "F"), IDXGISwapChain_Present_Original)
MH_CreateHook(IDXGISwapChain_ResizeBuffers, RegisterCallback("IDXGISwapChain_ResizeBuffers_Hook", "F"), IDXGISwapChain_ResizeBuffers_Original)
MH_EnableHook()
return


IDXGISwapChain_Present_Hook(SwapChain, SyncInterval, Flags)
{
   Critical
   static ImmediateContext, staging_texture, temp_texture, source, MipLevels, ArraySize, ResolutionOk, width, height, format, formatGuid, Guid, fmt, NewFormat, wic, Convert, ContainerFormat, timeElapsed, multiCaptureInit, multiCaptureNext
   if multiCapture
   {
      if (multiCaptureInit = "")
      {
         timeElapsed := A_TickCount
         multiCaptureInit := multiCaptureNext := 1
      }
      else
      {
         if (A_TickCount - timeElapsed >= fps)
         {
            multiCaptureNext := 1
            timeElapsed+=fps
         }
      }
   }
   if singleCapture or multiCaptureNext
   {
      if (ResolutionChanged = 1)
         ResolutionOk := ResolutionChanged := "", width := widthChanged, height := heightChanged, format := formatChanged
      if (ResolutionOK = "")
      {
         if (ContainerFormat = "")
         {
            if (Extension = "png")
               ContainerFormat := "GUID_ContainerFormatPng"
            else if (Extension = "bmp")
               ContainerFormat := "GUID_ContainerFormatBmp"
            else if (Extension = "jpg")
               ContainerFormat := "GUID_ContainerFormatJpeg"
            else if (Extension = "tiff")
               ContainerFormat := "GUID_ContainerFormatTiff"
            else if (Extension = "gif")
               ContainerFormat := "GUID_ContainerFormatGif"
            else
            {
               msgbox extension %Extension% cannot use
               ExitApp
            }
         }
         if ImmediateContext
         {
            Release(ImmediateContext)
            ImmediateContext := ""
         }
         if staging_texture
         {
            Release(staging_texture)
            staging_texture := ""
         }
         if temp_texture
         {
            Release(temp_texture)
            temp_texture := ""
         }
         IDXGISwapChain_GetDevice(SwapChain, ID3D11Device)
         ID3D11Device_GetImmediateContext(ID3D11Device, ImmediateContext)
         if (width = "")
         {
            VarSetCapacity(SwapChainDesc, 48+A_PtrSize*3, 0)
            IDXGISwapChain_GetDesc(SwapChain, &SwapChainDesc)
            width := NumGet(SwapChainDesc, 0, "uint")
            height := NumGet(SwapChainDesc, 4, "uint")
         }
      }
      IDXGISwapChain_GetBuffer(SwapChain, BackBuffer)
      if (ResolutionOK = "")
      {
         ID3D11Buffer_GetType(BackBuffer, ResourceDimension)
         if (ResourceDimension != 3)   ; D3D11_RESOURCE_DIMENSION_TEXTURE2D
         {
            msgbox does not support 1D or volume textures
            ExitApp
         }
         VarSetCapacity(D3D11_TEXTURE2D_DESC, 44, 0)
         ID3D11Texture2D_GetDesc(BackBuffer, &D3D11_TEXTURE2D_DESC)
         if (format = "")
            format := NumGet(D3D11_TEXTURE2D_DESC, 16, "uint")   ; Format
         if (format = 1) or (format = 2)
            formatGuid := "GUID_WICPixelFormat128bppRGBAFloat"
         else if (format = 3) or (format = 4)
            formatGuid := "GUID_WICPixelFormat128bppRGBAFixedPoint"
         else if (format = 5) or (format = 6)
            formatGuid := "GUID_WICPixelFormat96bppRGBFloat"
         else if (format = 7) or (format = 8)
            formatGuid := "GUID_WICPixelFormat96bppRGBFixedPoint"
         else if (format >= 9) and (format <= 14)
            formatGuid := "GUID_WICPixelFormat64bppRGBA"
         else if (format >= 23) and (format <= 25)
            formatGuid := "GUID_WICPixelFormat32bppRGBA1010102"
         else if (format >= 27) and (format <= 32)
            formatGuid := "GUID_WICPixelFormat32bppRGBA"
         else if (format >= 44) and (format <= 46)
            formatGuid := "GUID_WICPixelFormat32bppGrayFloat"
         else if ((format >= 53) and (format <= 56)) or (format = 58)
            formatGuid := "GUID_WICPixelFormat16bppGrayHalf"
         else if (format = 57) or (format = 59)
            formatGuid := "GUID_WICPixelFormat16bppGrayFixedPoint"
         else if (format >= 60) and (format <= 64)
            formatGuid := "GUID_WICPixelFormat8bppGray" 
         else if (format = 65)
            formatGuid := "GUID_WICPixelFormat8bppAlpha"
         else if (format = 66)
            formatGuid := "GUID_WICPixelFormat1bppIndexed"
         else if (format = 85)
            formatGuid := "GUID_WICPixelFormat16bppBGR565"
         else if (format = 86)
            formatGuid := "GUID_WICPixelFormat16bppBGRA5551"
         else if (format = 87) or (format = 88)
            formatGuid := "GUID_WICPixelFormat32bppBGRA"
         else if (format = 89)
            formatGuid := "GUID_WICPixelFormat32bppBGR101010"
         else if (format >= 90) and (format <= 93)
            formatGuid := "GUID_WICPixelFormat32bppBGRA"
         else
         {
            msgbox format %format% does not supported
            ExitApp
         }
         MipLevels := NumGet(D3D11_TEXTURE2D_DESC, 8, "uint")
         ArraySize := NumGet(D3D11_TEXTURE2D_DESC, 12, "uint")
         if (MipLevels > 1) or (ArraySize > 1)
            msgbox WARNING: does not support 2D arrays, cubemaps, or mipmaps; only the first surface is written
         if (NumGet(D3D11_TEXTURE2D_DESC, 20, "uint") > 1)   ; DXGI_SAMPLE_DESC count Multisample
         {
            source := "MSAA"
            ; msgbox multisampling
         }
         else if (NumGet(D3D11_TEXTURE2D_DESC, 28, "uint") = 3) and (NumGet(D3D11_TEXTURE2D_DESC, 36, "uint") & 0x20000)   ; (Usage = D3D11_USAGE_STAGING) and (CPUAccessFlags & D3D11_CPU_ACCESS_READ)
         {            
            source := "stage"
            ; msgbox stage
         }
         else
            source := "non-MSAA"
         if (source = "MSAA") or (source = "non-MSAA")
         {
            if (source = "MSAA")
            {
               NumPut(1, D3D11_TEXTURE2D_DESC, 20, "uint")   ; DXGI_SAMPLE_DESC count
               NumPut(0, D3D11_TEXTURE2D_DESC, 24, "uint")   ; DXGI_SAMPLE_DESC Quality
               ID3D11Device_CreateTexture2D(ID3D11Device, &D3D11_TEXTURE2D_DESC, 0, temp_texture)
               if (format = 1)
                  fmt := 2
               else if (format = 5)
                  fmt := 6
               else if (format = 9)
                  fmt := 11
               else if (format = 15)
                  fmt := 16
               else if (format = 23)
                  fmt := 24
               else if (format = 27)
                  fmt := 28
               else if (format = 33)
                  fmt := 35
               else if (format = 39)
                  fmt := 41
               else if (format = 48)
                  fmt := 49
               else if (format = 53)
                  fmt := 56
               else if (format = 60)
                  fmt := 61
               else if (format = 70)
                  fmt := 71
               else if (format = 73)
                  fmt := 74
               else if (format = 76)
                  fmt := 77
               else if (format = 79)
                  fmt := 80
               else if (format = 82)
                  fmt := 83
               else if (format = 90)
                  fmt := 87
               else if (format = 92)
                  fmt := 88
               else if (format = 97)
                  fmt := 98
               else
                  fmt := format
               ID3D11Device_CheckFormatSupport(ID3D11Device, fmt, support)
               if !(support & 0x40000)   ; D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE 
               {
                  msgbox ID3D11Device_CheckFormatSupport not support D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE
                  ExitApp
               }
            }
            NumPut(D3D11_USAGE_STAGING := 3, D3D11_TEXTURE2D_DESC, 28, "uint")   ; Usage
            NumPut(0, D3D11_TEXTURE2D_DESC, 32, "uint")   ; BindFlags
            NumPut(D3D11_CPU_ACCESS_READ := 0x20000, D3D11_TEXTURE2D_DESC, 36, "uint")   ; CPUAccessFlags
            NumPut((NumGet(D3D11_TEXTURE2D_DESC, 40, "uint")&=0x4), D3D11_TEXTURE2D_DESC, 40, "uint")   ; MiscFlags add D3D11_RESOURCE_MISC_TEXTURECUBE
            ID3D11Device_CreateTexture2D(ID3D11Device, &D3D11_TEXTURE2D_DESC, 0, staging_texture)
         }
      }
      if (source = "stage")
         staging_texture := BackBuffer
      else if (source = "non-MSAA")
         ID3D11DeviceContext_CopyResource(ImmediateContext, staging_texture, BackBuffer)
      else
      {
         item := 0
         loop % ArraySize
         {
            level := 0
            loop % MipLevels
            {
               index := D3D11CalcSubresource(level, item, MipLevels)
               ID3D11DeviceContext_ResolveSubresource(ImmediateContext, temp_texture, index, BackBuffer, index, fmt)
               level++
            }
            item++
         }
         ID3D11DeviceContext_CopyResource(ImmediateContext, staging_texture, temp_texture)
      }
      VarSetCapacity(D3D11_MAPPED_SUBRESOURCE, 8+A_PtrSize, 0)
      ID3D11DeviceContext_Map(ImmediateContext, staging_texture, 0, D3D11_MAP_READ := 1, 0, &D3D11_MAPPED_SUBRESOURCE)
      pBits := NumGet(D3D11_MAPPED_SUBRESOURCE, 0, "ptr")
      pitch := NumGet(D3D11_MAPPED_SUBRESOURCE, A_PtrSize, "uint")
      if !wic
         wic := IWICCreate()
      IWICImagingFactory_CreateStream(wic, stream)
      IWICStream_InitializeFromFilename(stream, OutputDir "\" A_YYYY "_" A_MM "_" A_DD "_" A_Hour "_" A_Min "_" A_Sec "_" A_MSec "." Extension, GENERIC_WRITE := 0x40000000)
      IWICImagingFactory_CreateEncoder(wic, ContainerFormat, 0, encoder)
      IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache := 0x2)
      IWICBitmapEncoder_CreateNewFrame(encoder, frame)
      IWICBitmapFrameEncode_Initialize(frame)
      IWICBitmapFrameEncode_SetSize(frame, width, height)
      if (ResolutionOK = "")
      {
         if IWICBitmapFrameEncode_SetPixelFormat(frame, formatGuid, NewFormat, guid)
            Convert := ""
         else
            Convert := 1
      }
      if (Convert = "")
      {
         if (ResolutionOK = "")
            ResolutionOK := 1  
         else
            IWICBitmapFrameEncode_SetPixelFormat(frame, &NewFormat)
         IWICBitmapFrameEncode_WritePixels(frame, height, pitch, pitch * height, pBits)
      }
      else
      {
         IWICImagingFactory_CreateFormatConverter(wic, FormatConverter)
         if (ResolutionOK = "")
         {
            IWICFormatConverter_CanConvert(FormatConverter, formatGuid, &NewFormat)
            ResolutionOK := 1
         }
         IWICImagingFactory_CreateBitmapFromMemory(wic, width, height, formatGuid, pitch, pitch * height, pBits, Bitmap)
         IWICFormatConverter_Initialize(FormatConverter, Bitmap, "GUID_WICPixelFormat24bppBGR", WICBitmapDitherTypeNone := 0, 0, 0, WICBitmapPaletteTypeMedianCut := 0x1)
         IWICBitmapFrameEncode_SetPixelFormat(frame, &NewFormat)
         VarSetCapacity(Rect, 16, 0)
         NumPut(width, Rect, 8, "int")
         NumPut(height, Rect, 12, "int")
         IWICBitmapFrameEncode_WriteSource(frame, FormatConverter, &Rect)
         Release(FormatConverter)
         Release(Bitmap)
         FormatConverter := Bitmap := ""
      }
      IWICBitmapFrameEncode_Commit(frame)
      IWICBitmapEncoder_Commit(encoder)
      ID3D11DeviceContext_Unmap(ImmediateContext, staging_texture, 0)
      Release(BackBuffer)
      Release(stream)
      Release(frame)
      Release(encoder)
      BackBuffer := stream := frame := encoder := ""
      if singleCapture
         singleCapture := ""
      else
         multiCaptureNext := ""
   }
   DllCall(IDXGISwapChain_Present_Original, "ptr", SwapChain, "uint", SyncInterval, "uint", Flags)
   return 
}

IDXGISwapChain_ResizeBuffers_Hook(SwapChain, BufferCount, SwapChainWidth, SwapChainHeight, NewFormatBuf, SwapChainFlags)
{
   widthChanged := SwapChainWidth, heightChanged := SwapChainHeight, formatChanged := NewFormatBuf
   ResolutionChanged := 1
   DllCall(IDXGISwapChain_ResizeBuffers_Original, "ptr", SwapChain, "uint", BufferCount, "uint", SwapChainWidth, "uint", SwapChainHeight, "uint", NewFormatBuf, "uint", SwapChainFlags)
   return 
}



LoadDll()
{
   if !DllCall("GetModuleHandle","str","DXGI", "ptr")
   {
      MsgBox, 16, Error, DXGI failed.
      ExitApp
   }
   if !DllCall("GetModuleHandle","str","D3D11", "ptr")
   {
      MsgBox, 16, Error, D3D11 failed.
      ExitApp
   }
   return
}


ID3D11Buffer_GetType(this, ByRef pResourceDimension)
{
   DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr*", pResourceDimension)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_ResolveSubresource(this, pDstResource, DstSubresource, pSrcResource, SrcSubresource, Format)
{
   DllCall(NumGet(NumGet(this+0)+57*A_PtrSize), "ptr", this, "ptr", pDstResource, "uint", DstSubresource, "ptr", pSrcResource, "uint", SrcSubresource, "uint", Format)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

D3D11CalcSubresource(MipSlice, ArraySlice, MipLevels)
{
   hr := DllCall("D3D11\D3D11CalcSubresource", "uint", MipSlice, "uint", ArraySlice, "uint", MipLevels, "uint")
   if ErrorLevel
      _Error(A_ThisFunc " ErrorLevel: " ErrorLevel)
   return hr
}

ID3D11Device_CheckFormatSupport(this, Format, ByRef pFormatSupport)  
{
   hr := DllCall(NumGet(NumGet(this+0)+29*A_PtrSize), "ptr", this, "uint", Format, "uint*", pFormatSupport)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

D3D11CreateDeviceAndSwapChain(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, SwapChainDesc, ByRef ppSwapChain, ByRef ppDevice, pFeatureLevel, ByRef ppImmediateContext)
{
   hr := DllCall("D3D11\D3D11CreateDeviceAndSwapChain", "ptr", pAdapter, "int", DriverType, "ptr", Software, "uint", Flags, "ptr", pFeatureLevels, "uint", FeatureLevels, "uint", SDKVersion, "ptr", SwapChainDesc, "ptr*", ppSwapChain, "ptr*", ppDevice, "ptr", pFeatureLevel, "ptr*", ppImmediateContext)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGISwapChain_GetDevice(this, ByRef ppDevice)
{
   GUID(riid, "{db6f6ddb-ac77-4e88-8253-819df9bbf140}")
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", &riid, "ptr*", ppDevice)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11Device_GetImmediateContext(this, ByRef ppImmediateContext)
{
   DllCall(NumGet(NumGet(this+0)+40*A_PtrSize), "ptr", this, "ptr*", ppImmediateContext)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGISwapChain_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), "ptr", this, "ptr", pDesc)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGISwapChain_GetBuffer(this, ByRef ppSurface)
{
   GUID(riid, "{6f15aaf2-d208-4e89-9ab4-489535d34f9c}")
   hr := DllCall(NumGet(NumGet(this+0)+9*A_PtrSize), "ptr", this, "uint", 0, "ptr", &riid, "ptr*", ppSurface)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11Texture2D_GetDesc(this, pDesc)
{
   DllCall(NumGet(NumGet(this+0)+10*A_PtrSize), "ptr", this, "ptr", pDesc)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11Device_CreateTexture2D(this, pDesc, pInitialData, ByRef ppTexture2D)
{
   hr := DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "ptr", pDesc, "ptr", pInitialData, "ptr*", ppTexture2D)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_CopyResource(this, pDstResource, pSrcResource)
{
   DllCall(NumGet(NumGet(this+0)+47*A_PtrSize), "ptr", this, "ptr", pDstResource, "ptr", pSrcResource)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_Map(this, pResource, Subresource, MapType, MapFlags, pMappedResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this, "ptr", pResource, "uint", Subresource, "uint", MapType, "uint", MapFlags, "ptr", pMappedResource)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

ID3D11DeviceContext_Unmap(this, pResource, Subresource)
{
   DllCall(NumGet(NumGet(this+0)+15*A_PtrSize), "ptr", this, "ptr", pResource, "uint", Subresource)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IDXGISwapChain_Present_Get(this)
{
   return NumGet(NumGet(this+0)+8*A_PtrSize)
}

IDXGISwapChain_ResizeBuffers_Get(this)
{
   return NumGet(NumGet(this+0)+13*A_PtrSize)
}

Release(this)
{
   DllCall(NumGet(NumGet(this+0)+2*A_PtrSize), "ptr", this)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

GUID(ByRef GUID, sGUID)
{
    VarSetCapacity(GUID, 16, 0)
    return DllCall("ole32\CLSIDFromString", "WStr", sGUID, "Ptr", &GUID) >= 0 ? &GUID : ""
}

_Error(val)
{
   msgbox % val
   ExitApp
}



MinHook_Init(MinhookDll)
{
   Static h
   If Not h
   {
      h:=DllCall("LoadLibrary","Str",MinhookDll, "Ptr")
      MH_Initialize()
   }
}

; Creates a Hook for the specified target function, in disabled state.
; Parameters:
;   pTarget    [in]  A pointer to the target function, which will be
;                    overridden by the detour function.
;   pDetour    [in]  A pointer to the detour function, which will override
;                    the target function.
;   ppOriginal [out] A pointer to the trampoline function, which will be
;                    used to call the original target function.
;                    This parameter can be NULL.
MH_CreateHook(pTarget, pDetour, ByRef ppOriginal := 0) {
	return DllCall("MinHook\MH_CreateHook"
	               , "ptr", pTarget
	               , "ptr", pDetour
	               , "uptr*", ppOriginal )
}

; Initialize the MinHook library. You must call this function EXACTLY ONCE
; at the beginning of your program.
MH_Initialize() {
	return DllCall("MinHook\MH_Initialize")
}

; Uninitialize the MinHook library. You must call this function EXACTLY
; ONCE at the end of your program.
MH_Uninitialize() {
	return DllCall("MinHook\MH_Uninitialize")
}

; Removes an already created hook.
; Parameters:
;   pTarget [in] A pointer to the target function.
MH_RemoveHook(pTarget) {
	return DllCall("MinHook\MH_RemoveHook", "ptr", pTarget)
}

/*
	#define MH_ALL_HOOKS NULL
*/

; Enables an already created hook.
; Parameters:
;   pTarget [in] A pointer to the target function.
;                If this parameter is MH_ALL_HOOKS, all created hooks are
;                enabled in one go.
MH_EnableHook(pTarget := 0) {
	return DllCall("MinHook\MH_EnableHook", "ptr", pTarget)
}

; Disables an already created hook.
; Parameters:
;   pTarget [in] A pointer to the target function.
;                If this parameter is MH_ALL_HOOKS, all created hooks are
;                disabled in one go.
MH_DisableHook(pTarget := 0) {
	return DllCall("MinHook\MH_DisableHook", "ptr", pTarget)
}



IWICCreate()
{
   return ComObjCreate("{cacaf262-9370-4615-a13b-9f5539da4c0a}", "{ec5ec8a9-c395-4314-9c77-54d7a935ff70}")
}

IWICImagingFactory_CreateStream(this, ByRef ppIWICStream)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this, "ptr*", ppIWICStream)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
}

IWICImagingFactory_CreateFormatConverter(this, ByRef ppIFormatConverter)
{
   hr := DllCall(NumGet(NumGet(this+0)+10*A_PtrSize), "ptr", this, "ptr*", ppIFormatConverter)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
}

IWICStream_InitializeFromFilename(this, wzFileName, dwDesiredAccess)
{
   hr := DllCall(NumGet(NumGet(this+0)+15*A_PtrSize), "ptr", this, "str", wzFileName, "uint", dwDesiredAccess)
   if hr
      _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
}

IWICImagingFactory_CreateEncoder(this, guidContainerFormat, pguidVendor, ByRef ppIEncoder)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "ptr", WIC_GUID(GUID1, guidContainerFormat), "ptr", WIC_GUID(GUID2, pguidVendor), "ptr*", ppIEncoder)
   if hr
      _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
}

IWICBitmapEncoder_Initialize(this, pIStream, cacheOption)
{
   hr := DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "ptr", pIStream, "int", cacheOption)
   if hr
      _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
}

IWICBitmapEncoder_CreateNewFrame(this, ByRef ppIFrameEncode, ppIEncoderOptions := 0)
{
   hr := DllCall(NumGet(NumGet(this+0)+10*A_PtrSize), "ptr", this, "ptr*", ppIFrameEncode, "ptr*", ppIEncoderOptions)
   if hr
      _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
}

IWICBitmapEncoder_Commit(this)
{
   hr := DllCall(NumGet(NumGet(this+0)+11*A_PtrSize), "ptr", this)
   if hr
      _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
}

IWICBitmapFrameEncode_Initialize(this, pIEncoderOptions := 0)
{
   hr := DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "ptr", pIEncoderOptions)
   if hr
      _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
}

IWICBitmapFrameEncode_SetSize(this, uiWidth, uiHeight)
{
   hr := DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint", uiWidth, "uint", uiHeight)
   if hr
      _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
}

IWICBitmapFrameEncode_WritePixels(this, lineCount, cbStride, cbBufferSize, pbPixels)
{
   hr := DllCall(NumGet(NumGet(this+0)+10*A_PtrSize), "ptr", this, "uint", lineCount, "uint", cbStride, "uint", cbBufferSize, "ptr", pbPixels)
   if hr
      _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
}

IWICBitmapFrameEncode_Commit(this)
{
   hr := DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), "ptr", this)
   if hr
      _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
}

IWICBitmapFrameEncode_WriteSource(this, pIBitmapSource, prc)
{
   hr := DllCall(NumGet(NumGet(this+0)+11*A_PtrSize), "ptr", this, "ptr", pIBitmapSource, "ptr", prc)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
}

IWICImagingFactory_CreateBitmapFromMemory(this, uiWidth, uiHeight, pixelFormat, cbStride, cbBufferSize, pbBuffer, ByRef ppIBitmap)
{
   hr := DllCall(NumGet(NumGet(this+0)+20*A_PtrSize), "ptr", this, "uint", uiWidth, "uint", uiHeight, "ptr", pixelFormat, "uint", cbStride, "uint", cbBufferSize, "ptr", pbBuffer, "ptr*", ppIBitmap)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
}

IWICFormatConverter_Initialize(this, pISource, dstFormat, dither, pIPalette, alphaThresholdPercent, paletteTranslate)
{
   dstFormat := WIC_GUID(GUID, dstFormat)
   hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "ptr", pISource, "ptr", dstFormat, "uint", dither, "ptr", pIPalette, "double", alphaThresholdPercent, "uint", alphaThresholdPercent)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
}

IWICFormatConverter_CanConvert(this, srcPixelFormat, dstPixelFormat)
{
   hr := DllCall(NumGet(NumGet(this+0)+9*A_PtrSize), "ptr", this, "ptr", srcPixelFormat, "ptr", dstPixelFormat, "ptr*", pfCanConvert)
   if hr or ErrorLevel or !pfCanConvert
      _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel "`npfCanConvert=0")
}

IWICBitmapFrameEncode_SetPixelFormat(this, ByRef FormatGuid, ByRef NewFormat:="dontCheck", ByRef GUID:="")
{
   if (NewFormat = "dontCheck")
   {
      hr := DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "ptr", FormatGuid)
      if hr or ErrorLevel
         _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
   }
   else
   {
      FormatGuid := WIC_GUID(GUID, FormatGuid)
      VarSetCapacity(NewFormat, 16, 0)
      DllCall("msvcrt\memcpy", "ptr", &NewFormat, "ptr", FormatGuid, "uint", 16, "cdecl")
      hr := DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "ptr", &NewFormat)
      if hr or ErrorLevel
         _Error(A_ThisFunc " error: " WIC_hr(hr) "`nErrorLevel: " ErrorLevel)
      if (DllCall("msvcrt\memcmp", "ptr", FormatGuid, "ptr", &NewFormat, Ptr, 16) = 0)
         return true
   }
}

WIC_GUID(ByRef GUID,name){
	static init:=1,_:={}
	if init {
	init:=0
	; Decoders
	 _.CLSID_WICBmpDecoder:=[0x6b462062, 0x7cbf, 0x400d, 0x9f, 0xdb, 0x81, 0x3d, 0xd1, 0xf, 0x27, 0x78]
	,_.CLSID_WICPngDecoder:=[0x389ea17b, 0x5078, 0x4cde, 0xb6, 0xef, 0x25, 0xc1, 0x51, 0x75, 0xc7, 0x51]
	,_.CLSID_WICIcoDecoder:=[0xc61bfcdf, 0x2e0f, 0x4aad, 0xa8, 0xd7, 0xe0, 0x6b, 0xaf, 0xeb, 0xcd, 0xfe]
	,_.CLSID_WICJpegDecoder:=[0x9456a480, 0xe88b, 0x43ea, 0x9e, 0x73, 0xb, 0x2d, 0x9b, 0x71, 0xb1, 0xca]
	,_.CLSID_WICGifDecoder:=[0x381dda3c, 0x9ce9, 0x4834, 0xa2, 0x3e, 0x1f, 0x98, 0xf8, 0xfc, 0x52, 0xbe]
	,_.CLSID_WICTiffDecoder:=[0xb54e85d9, 0xfe23, 0x499f, 0x8b, 0x88, 0x6a, 0xce, 0xa7, 0x13, 0x75, 0x2b]
	,_.CLSID_WICWmpDecoder:=[0xa26cec36, 0x234c, 0x4950, 0xae, 0x16, 0xe3, 0x4a, 0xac, 0xe7, 0x1d, 0x0d]
	; Encoders
	 _.CLSID_WICBmpEncoder:=[0x69be8bb4, 0xd66d, 0x47c8, 0x86, 0x5a, 0xed, 0x15, 0x89, 0x43, 0x37, 0x82]
	,_.CLSID_WICPngEncoder:=[0x27949969, 0x876a, 0x41d7, 0x94, 0x47, 0x56, 0x8f, 0x6a, 0x35, 0xa4, 0xdc]
	,_.CLSID_WICJpegEncoder:=[0x1a34f5c1, 0x4a5a, 0x46dc, 0xb6, 0x44, 0x1f, 0x45, 0x67, 0xe7, 0xa6, 0x76]
	,_.CLSID_WICGifEncoder:=[0x114f5598, 0xb22, 0x40a0, 0x86, 0xa1, 0xc8, 0x3e, 0xa4, 0x95, 0xad, 0xbd]
	,_.CLSID_WICTiffEncoder:=[0x0131be10, 0x2001, 0x4c5f, 0xa9, 0xb0, 0xcc, 0x88, 0xfa, 0xb6, 0x4c, 0xe8]
	,_.CLSID_WICWmpEncoder:=[0xac4ce3cb, 0xe1c1, 0x44cd, 0x82, 0x15, 0x5a, 0x16, 0x65, 0x50, 0x9e, 0xc2]
	; Container Formats
	 _.GUID_ContainerFormatBmp:=[0xaf1d87e, 0xfcfe, 0x4188, 0xbd, 0xeb, 0xa7, 0x90, 0x64, 0x71, 0xcb, 0xe3]
	,_.GUID_ContainerFormatPng:=[0x1b7cfaf4, 0x713f, 0x473c, 0xbb, 0xcd, 0x61, 0x37, 0x42, 0x5f, 0xae, 0xaf]
	,_.GUID_ContainerFormatIco:=[0xa3a860c4, 0x338f, 0x4c17, 0x91, 0x9a, 0xfb, 0xa4, 0xb5, 0x62, 0x8f, 0x21]
	,_.GUID_ContainerFormatJpeg:=[0x19e4a5aa, 0x5662, 0x4fc5, 0xa0, 0xc0, 0x17, 0x58, 0x2, 0x8e, 0x10, 0x57]
	,_.GUID_ContainerFormatTiff:=[0x163bcc30, 0xe2e9, 0x4f0b, 0x96, 0x1d, 0xa3, 0xe9, 0xfd, 0xb7, 0x88, 0xa3]
	,_.GUID_ContainerFormatGif:=[0x1f8a5601, 0x7d4d, 0x4cbd, 0x9c, 0x82, 0x1b, 0xc8, 0xd4, 0xee, 0xb9, 0xa5]
	,_.GUID_ContainerFormatWmp:=[0x57a37caa, 0x367a, 0x4540, 0x91, 0x6b, 0xf1, 0x83, 0xc5, 0x09, 0x3a, 0x4b]
	; Component Identifiers
	 _.CLSID_WICImagingCategories:=[0xfae3d380, 0xfea4, 0x4623, 0x8c, 0x75, 0xc6, 0xb6, 0x11, 0x10, 0xb6, 0x81]
	,_.CATID_WICBitmapDecoders:=[0x7ed96837, 0x96f0, 0x4812, 0xb2, 0x11, 0xf1, 0x3c, 0x24, 0x11, 0x7e, 0xd3]
	,_.CATID_WICBitmapEncoders:=[0xac757296, 0x3522, 0x4e11, 0x98, 0x62, 0xc1, 0x7b, 0xe5, 0xa1, 0x76, 0x7e]
	,_.CATID_WICPixelFormats:=[0x2b46e70f, 0xcda7, 0x473e, 0x89, 0xf6, 0xdc, 0x96, 0x30, 0xa2, 0x39, 0x0b]
	,_.CATID_WICFormatConverters:=[0x7835eae8, 0xbf14, 0x49d1, 0x93, 0xce, 0x53, 0x3a, 0x40, 0x7b, 0x22, 0x48]
	,_.CATID_WICMetadataReader:=[0x05af94d8, 0x7174, 0x4cd2, 0xbe, 0x4a, 0x41, 0x24, 0xb8, 0x0e, 0xe4, 0xb8]
	,_.CATID_WICMetadataWriter:=[0xabe3b9a4, 0x257d, 0x4b97, 0xbd, 0x1a, 0x29, 0x4a, 0xf4, 0x96, 0x22, 0x2e]
	; Format Converters
	 _.CLSID_WICDefaultFormatConverter:=[0x1a3f11dc, 0xb514, 0x4b17, 0x8c, 0x5f, 0x21, 0x54, 0x51, 0x38, 0x52, 0xf1]
	,_.CLSID_WICFormatConverterHighColor:=[0xac75d454, 0x9f37, 0x48f8, 0xb9, 0x72, 0x4e, 0x19, 0xbc, 0x85, 0x60, 0x11]
	,_.CLSID_WICFormatConverterNChannel:=[0xc17cabb2, 0xd4a3, 0x47d7, 0xa5, 0x57, 0x33, 0x9b, 0x2e, 0xfb, 0xd4, 0xf1]
	,_.CLSID_WICFormatConverterWMPhoto:=[0x9cb5172b, 0xd600, 0x46ba, 0xab, 0x77, 0x77, 0xbb, 0x7e, 0x3a, 0x00, 0xd9]
	; Metadata Handlers
	 _.GUID_MetadataFormatUnknown:=[0xA45E592F, 0x9078, 0x4A7C, 0xAD, 0xB5, 0x4E, 0xDC, 0x4F, 0xD6, 0x1B, 0x1F]
	,_.GUID_MetadataFormatIfd:=[0x537396C6, 0x2D8A, 0x4BB6, 0x9B, 0xF8, 0x2F, 0x0A, 0x8E, 0x2A, 0x3A, 0xDF]
	,_.GUID_MetadataFormatSubIfd:=[0x58A2E128, 0x2DB9, 0x4E57, 0xBB, 0x14, 0x51, 0x77, 0x89, 0x1E, 0xD3, 0x31]
	,_.GUID_MetadataFormatExif:=[0x1C3C4F9D, 0xB84A, 0x467D, 0x94, 0x93, 0x36, 0xCF, 0xBD, 0x59, 0xEA, 0x57]
	,_.GUID_MetadataFormatGps:=[0x7134AB8A, 0x9351, 0x44AD, 0xAF, 0x62, 0x44, 0x8D, 0xB6, 0xB5, 0x02, 0xEC]
	,_.GUID_MetadataFormatInterop:=[0xED686F8E, 0x681F, 0x4C8B, 0xBD, 0x41, 0xA8, 0xAD, 0xDB, 0xF6, 0xB3, 0xFC]
	,_.GUID_MetadataFormatApp0:=[0x79007028, 0x268D, 0x45d6, 0xA3, 0xC2, 0x35, 0x4E, 0x6A, 0x50, 0x4B, 0xC9]
	,_.GUID_MetadataFormatApp1:=[0x8FD3DFC3, 0xF951, 0x492B, 0x81, 0x7F, 0x69, 0xC2, 0xE6, 0xD9, 0xA5, 0xB0]
	,_.GUID_MetadataFormatApp13:=[0x326556A2, 0xF502, 0x4354, 0x9C, 0xC0, 0x8E, 0x3F, 0x48, 0xEA, 0xF6, 0xB5]
	,_.GUID_MetadataFormatIPTC:=[0x4FAB0914, 0xE129, 0x4087, 0xA1, 0xD1, 0xBC, 0x81, 0x2D, 0x45, 0xA7, 0xB5]
	,_.GUID_MetadataFormatIRB:=[0x16100D66, 0x8570, 0x4BB9, 0xB9, 0x2D, 0xFD, 0xA4, 0xB2, 0x3E, 0xCE, 0x67]
	,_.GUID_MetadataFormat8BIMIPTC:=[0x0010568c, 0x0852, 0x4e6a, 0xb1, 0x91, 0x5c, 0x33, 0xac, 0x5b, 0x04, 0x30]
	,_.GUID_MetadataFormat8BIMResolutionInfo:=[0x739F305D, 0x81DB, 0x43CB, 0xAC, 0x5E, 0x55, 0x01, 0x3E, 0xF9, 0xF0, 0x03]
	 _.GUID_MetadataFormat8BIMIPTCDigest:=[0x1CA32285, 0x9CCD, 0x4786, 0x8B, 0xD8, 0x79, 0x53, 0x9D, 0xB6, 0xA0, 0x06]
	,_.GUID_MetadataFormatXMP:=[0xBB5ACC38, 0xF216, 0x4CEC, 0xA6, 0xC5, 0x5F, 0x6E, 0x73, 0x97, 0x63, 0xA9]
	,_.GUID_MetadataFormatThumbnail:=[0x243dcee9, 0x8703, 0x40ee, 0x8e, 0xf0, 0x22, 0xa6, 0x0, 0xb8, 0x5, 0x8c]
	,_.GUID_MetadataFormatChunktEXt:=[0x568d8936, 0xc0a9, 0x4923, 0x90, 0x5d, 0xdf, 0x2b, 0x38, 0x23, 0x8f, 0xbc]
	,_.GUID_MetadataFormatXMPStruct:=[0x22383CF1, 0xED17, 0x4E2E, 0xAF, 0x17, 0xD8, 0x5B, 0x8F, 0x6B, 0x30, 0xD0]
	,_.GUID_MetadataFormatXMPBag:=[0x833CCA5F, 0xDCB7, 0x4516, 0x80, 0x6F, 0x65, 0x96, 0xAB, 0x26, 0xDC, 0xE4]
	,_.GUID_MetadataFormatXMPSeq:=[0x63E8DF02, 0xEB6C,0x456C, 0xA2, 0x24, 0xB2, 0x5E, 0x79, 0x4F, 0xD6, 0x48]
	,_.GUID_MetadataFormatXMPAlt:=[0x7B08A675, 0x91AA, 0x481B, 0xA7, 0x98, 0x4D, 0xA9, 0x49, 0x08, 0x61, 0x3B]
	,_.GUID_MetadataFormatLSD:=[0xE256031E, 0x6299, 0x4929, 0xB9, 0x8D, 0x5A, 0xC8, 0x84, 0xAF, 0xBA, 0x92]
	,_.GUID_MetadataFormatIMD:=[0xBD2BB086, 0x4D52, 0x48DD, 0x96, 0x77, 0xDB, 0x48, 0x3E, 0x85, 0xAE, 0x8F]
	,_.GUID_MetadataFormatGCE:=[0x2A25CAD8, 0xDEEB, 0x4C69, 0xA7, 0x88, 0xE, 0xC2, 0x26, 0x6D, 0xCA, 0xFD]
	,_.GUID_MetadataFormatAPE:=[0x2E043DC2, 0xC967, 0x4E05, 0x87, 0x5E, 0x61, 0x8B, 0xF6, 0x7E, 0x85, 0xC3]
	 _.GUID_MetadataFormatJpegChrominance:=[0xF73D0DCF, 0xCEC6, 0x4F85, 0x9B, 0x0E, 0x1C, 0x39, 0x56, 0xB1, 0xBE, 0xF7]
	,_.GUID_MetadataFormatJpegLuminance:=[0x86908007, 0xEDFC, 0x4860, 0x8D, 0x4B, 0x4E, 0xE6, 0xE8, 0x3E, 0x60, 0x58]
	,_.GUID_MetadataFormatJpegComment:=[0x220E5F33, 0xAFD3, 0x474E, 0x9D, 0x31, 0x7D, 0x4F, 0xE7, 0x30, 0xF5, 0x57]
	,_.GUID_MetadataFormatGifComment:=[0xC4B6E0E0, 0xCFB4, 0x4AD3, 0xAB, 0x33, 0x9A, 0xAD, 0x23, 0x55, 0xA3, 0x4A]
	,_.GUID_MetadataFormatChunkgAMA:=[0xF00935A5, 0x1D5D, 0x4CD1, 0x81, 0xB2, 0x93, 0x24, 0xD7, 0xEC, 0xA7, 0x81]
	,_.GUID_MetadataFormatChunkbKGD:=[0xE14D3571, 0x6B47, 0x4DEA, 0xB6, 0xA, 0x87, 0xCE, 0xA, 0x78, 0xDF, 0xB7]
	,_.GUID_MetadataFormatChunkiTXt:=[0xC2BEC729, 0xB68, 0x4B77, 0xAA, 0xE, 0x62, 0x95, 0xA6, 0xAC, 0x18, 0x14]
	,_.GUID_MetadataFormatChunkcHRM:=[0x9DB3655B, 0x2842, 0x44B3, 0x80, 0x67, 0x12, 0xE9, 0xB3, 0x75, 0x55, 0x6A]
	,_.GUID_MetadataFormatChunkhIST:=[0xC59A82DA, 0xDB74, 0x48A4, 0xBD, 0x6A, 0xB6, 0x9C, 0x49, 0x31, 0xEF, 0x95]
	,_.GUID_MetadataFormatChunkiCCP:=[0xEB4349AB, 0xB685, 0x450F, 0x91, 0xB5, 0xE8, 0x2, 0xE8, 0x92, 0x53, 0x6C]
	,_.GUID_MetadataFormatChunksRGB:=[0xC115FD36, 0xCC6F, 0x4E3F, 0x83, 0x63, 0x52, 0x4B, 0x87, 0xC6, 0xB0, 0xD9]
	,_.GUID_MetadataFormatChunktIME:=[0x6B00AE2D, 0xE24B, 0x460A, 0x98, 0xB6, 0x87, 0x8B, 0xD0, 0x30, 0x72, 0xFD]
	; Vendor Identification
	 _.GUID_VendorMicrosoft:=[0x69fd0fdc, 0xa866, 0x4108, 0xb3, 0xb2, 0x98, 0x44, 0x7f, 0xa9, 0xed, 0xd4]
	,_.GUID_VendorMicrosoftBuiltIn:=[0x257a30fd, 0x6b6, 0x462b, 0xae, 0xa4, 0x63, 0xf7, 0xb, 0x86, 0xe5, 0x33]
	; WICBitmapPaletteType
	 _.GUID_WICPixelFormatDontCare:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x00]
	,_.GUID_WICPixelFormat1bppIndexed:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x01]
	,_.GUID_WICPixelFormat2bppIndexed:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x02]
	,_.GUID_WICPixelFormat4bppIndexed:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x03]
	,_.GUID_WICPixelFormat8bppIndexed:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x04]
	,_.GUID_WICPixelFormatBlackWhite:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x05]
	,_.GUID_WICPixelFormat2bppGray:=[  0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x06]
	,_.GUID_WICPixelFormat4bppGray:=[  0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x07]
	,_.GUID_WICPixelFormat8bppGray:=[  0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x08]
	,_.GUID_WICPixelFormat8bppAlpha:=[0xe6cd0116, 0xeeba, 0x4161, 0xaa, 0x85, 0x27, 0xdd, 0x9f, 0xb3, 0xa8, 0x95]
	,_.GUID_WICPixelFormat16bppBGR555:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x09]
	,_.GUID_WICPixelFormat16bppBGR565:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0a]
	,_.GUID_WICPixelFormat16bppBGRA5551:=[0x05ec7c2b, 0xf1e6, 0x4961, 0xad, 0x46, 0xe1, 0xcc, 0x81, 0x0a, 0x87, 0xd2]
	 _.GUID_WICPixelFormat16bppGray:=[  0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0b]
	,_.GUID_WICPixelFormat24bppBGR:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0c]
	,_.GUID_WICPixelFormat24bppRGB:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0d]
	,_.GUID_WICPixelFormat32bppBGR:=[  0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0e]
	,_.GUID_WICPixelFormat32bppBGRA:=[ 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0f]
	,_.GUID_WICPixelFormat32bppPBGRA:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x10]
	,_.GUID_WICPixelFormat32bppGrayFloat:=[ 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x11]
	,_.GUID_WICPixelFormat32bppRGBA:=[0xf5c7ad2d, 0x6a8d, 0x43dd, 0xa7, 0xa8, 0xa2, 0x99, 0x35, 0x26, 0x1a, 0xe9]
	,_.GUID_WICPixelFormat32bppPRGBA:=[0x3cc4a650, 0xa527, 0x4d37, 0xa9, 0x16, 0x31, 0x42, 0xc7, 0xeb, 0xed, 0xba]
	,_.GUID_WICPixelFormat48bppRGB:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x15]
	,_.GUID_WICPixelFormat48bppBGR:=[0xe605a384, 0xb468, 0x46ce, 0xbb, 0x2e, 0x36, 0xf1, 0x80, 0xe6, 0x43, 0x13]
	,_.GUID_WICPixelFormat64bppRGBA:=[ 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x16]
	,_.GUID_WICPixelFormat64bppBGRA:=[ 0x1562ff7c, 0xd352, 0x46f9, 0x97, 0x9e, 0x42, 0x97, 0x6b, 0x79, 0x22, 0x46]
	 _.GUID_WICPixelFormat64bppPRGBA:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x17]
	,_.GUID_WICPixelFormat64bppPBGRA:=[0x8c518e8e, 0xa4ec, 0x468b, 0xae, 0x70, 0xc9, 0xa3, 0x5a, 0x9c, 0x55, 0x30]
	,_.GUID_WICPixelFormat16bppGrayFixedPoint:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x13]
	,_.GUID_WICPixelFormat32bppBGR101010:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x14]
	,_.GUID_WICPixelFormat48bppRGBFixedPoint:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x12]
	,_.GUID_WICPixelFormat48bppBGRFixedPoint:=[0x49ca140e, 0xcab6, 0x493b, 0x9d, 0xdf, 0x60, 0x18, 0x7c, 0x37, 0x53, 0x2a]
	,_.GUID_WICPixelFormat96bppRGBFixedPoint:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x18]
	,_.GUID_WICPixelFormat128bppRGBAFloat:=[ 0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x19]
	,_.GUID_WICPixelFormat128bppPRGBAFloat:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x1a]
	,_.GUID_WICPixelFormat128bppRGBFloat:=[  0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x1b]
	,_.GUID_WICPixelFormat32bppCMYK:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x1c]
	,_.GUID_WICPixelFormat64bppRGBAFixedPoint:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x1d]
	,_.GUID_WICPixelFormat64bppBGRAFixedPoint:=[0x356de33c, 0x54d2, 0x4a23, 0xbb, 0x4, 0x9b, 0x7b, 0xf9, 0xb1, 0xd4, 0x2d]
	 _.GUID_WICPixelFormat64bppRGBFixedPoint:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x40]
	,_.GUID_WICPixelFormat128bppRGBAFixedPoint:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x1e]
	,_.GUID_WICPixelFormat128bppRGBFixedPoint:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x41]
	,_.GUID_WICPixelFormat64bppRGBAHalf:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x3a]
	,_.GUID_WICPixelFormat64bppRGBHalf:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x42]
	,_.GUID_WICPixelFormat48bppRGBHalf:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x3b]
	,_.GUID_WICPixelFormat32bppRGBE:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x3d]
	,_.GUID_WICPixelFormat16bppGrayHalf:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x3e]
	,_.GUID_WICPixelFormat32bppGrayFixedPoint:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x3f]
	,_.GUID_WICPixelFormat32bppRGBA1010102:=[0x25238D72, 0xFCF9, 0x4522, 0xb5, 0x14, 0x55, 0x78, 0xe5, 0xad, 0x55, 0xe0]
	,_.GUID_WICPixelFormat32bppRGBA1010102XR:=[0x00DE6B9A, 0xC101, 0x434b, 0xb5, 0x02, 0xd0, 0x16, 0x5e, 0xe1, 0x12, 0x2c]
	,_.GUID_WICPixelFormat64bppCMYK:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x1f]
	,_.GUID_WICPixelFormat24bpp3Channels:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x20]
	 _.GUID_WICPixelFormat32bpp4Channels:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x21]
	,_.GUID_WICPixelFormat40bpp5Channels:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x22]
	,_.GUID_WICPixelFormat48bpp6Channels:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x23]
	,_.GUID_WICPixelFormat56bpp7Channels:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x24]
	,_.GUID_WICPixelFormat64bpp8Channels:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x25]
	,_.GUID_WICPixelFormat48bpp3Channels:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x26]
	,_.GUID_WICPixelFormat64bpp4Channels:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x27]
	,_.GUID_WICPixelFormat80bpp5Channels:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x28]
	,_.GUID_WICPixelFormat96bpp6Channels:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x29]
	,_.GUID_WICPixelFormat112bpp7Channels:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x2a]
	,_.GUID_WICPixelFormat128bpp8Channels:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x2b]
	,_.GUID_WICPixelFormat40bppCMYKAlpha:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x2c]
	,_.GUID_WICPixelFormat80bppCMYKAlpha:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x2d]
	,_.GUID_WICPixelFormat32bpp3ChannelsAlpha:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x2e]
	 _.GUID_WICPixelFormat40bpp4ChannelsAlpha:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x2f]
	,_.GUID_WICPixelFormat48bpp5ChannelsAlpha:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x30]
	,_.GUID_WICPixelFormat56bpp6ChannelsAlpha:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x31]
	,_.GUID_WICPixelFormat64bpp7ChannelsAlpha:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x32]
	,_.GUID_WICPixelFormat72bpp8ChannelsAlpha:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x33]
	,_.GUID_WICPixelFormat64bpp3ChannelsAlpha:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x34]
	,_.GUID_WICPixelFormat80bpp4ChannelsAlpha:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x35]
	,_.GUID_WICPixelFormat96bpp5ChannelsAlpha:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x36]
	,_.GUID_WICPixelFormat112bpp6ChannelsAlpha:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x37]
	,_.GUID_WICPixelFormat128bpp7ChannelsAlpha:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x38]
	,_.GUID_WICPixelFormat144bpp8ChannelsAlpha:=[0x6fddc324, 0x4e03, 0x4bfe, 0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x39]

	}
	if _.haskey(name){
		p:=_[name]
		VarSetCapacity(GUID,16)
		,NumPut(p.1+(p.2<<32)+(p.3<<48),GUID,0,"int64")
		,NumPut(p.4+(p.5<<8)+(p.6<<16)+(p.7<<24)+(p.8<<32)+(p.9<<40)+(p.10<<48)+(p.11<<56),GUID,8,"int64")
		return &GUID
	}else return name
}

WIC_hr(a){
	static init:=1,err:={0x8000FFFF:"Catastrophic failure error.",0x80004001:"Not implemented error.",0x8007000E:"Out of memory error.",0x80070057:"One or more arguments are not valid error.",0x80004002:"Interface not supported error.",0x80004003:"Pointer not valid error.",0x80070006:"Handle not valid error.",0x80004004:"Operation aborted error.",0x80004005:"Unspecified error.",0x80070005:"General access denied error.",0x800401E5:"The object identified by this moniker could not be found."}
	if init{
		init:=0
		 err[0x80004005]:="WINCODEC_ERR_GENERIC_ERROR"
		,err[0x80070057]:="WINCODEC_ERR_INVALIDPARAMETER"
		,err[0x8007000E]:="WINCODEC_ERR_OUTOFMEMORY"
		,err[0x80004001]:="WINCODEC_ERR_NOTIMPLEMENTED"
		,err[0x80004004]:="WINCODEC_ERR_ABORTED"
		,err[0x80070005]:="WINCODEC_ERR_ACCESSDENIED"
		,err[0x88982f04]:="WINCODEC_ERR_WRONGSTATE"
		,err[0x88982f05]:="WINCODEC_ERR_VALUEOUTOFRANGE"
		,err[0x88982f07]:="WINCODEC_ERR_UNKNOWNIMAGEFORMAT"
		,err[0x88982f0B]:="WINCODEC_ERR_UNSUPPORTEDVERSION"
		,err[0x88982f0C]:="WINCODEC_ERR_NOTINITIALIZED"
		,err[0x88982f0D]:="WINCODEC_ERR_ALREADYLOCKED"
		,err[0x88982f40]:="WINCODEC_ERR_PROPERTYNOTFOUND"
		,err[0x88982f41]:="WINCODEC_ERR_PROPERTYNOTSUPPORTED"
		,err[0x88982f42]:="WINCODEC_ERR_PROPERTYSIZE"
		,err[0x88982f43]:="WINCODEC_ERR_CODECPRESENT"
		,err[0x88982f44]:="WINCODEC_ERR_CODECNOTHUMBNAIL"
		,err[0x88982f45]:="WINCODEC_ERR_PALETTEUNAVAILABLE"
		,err[0x88982f46]:="WINCODEC_ERR_CODECTOOMANYSCANLINES"
		,err[0x88982f48]:="WINCODEC_ERR_INTERNALERROR"
		,err[0x88982f49]:="WINCODEC_ERR_SOURCERECTDOESNOTMATCHDIMENSIONS"
		,err[0x88982f50]:="WINCODEC_ERR_COMPONENTNOTFOUND"
		 err[0x88982f51]:="WINCODEC_ERR_IMAGESIZEOUTOFRANGE"
		,err[0x88982f52]:="WINCODEC_ERR_TOOMUCHMETADATA"
		,err[0x88982f60]:="WINCODEC_ERR_BADIMAGE"
		,err[0x88982f61]:="WINCODEC_ERR_BADHEADER"
		,err[0x88982f62]:="WINCODEC_ERR_FRAMEMISSING"
		,err[0x88982f63]:="WINCODEC_ERR_BADMETADATAHEADER"
		,err[0x88982f70]:="WINCODEC_ERR_BADSTREAMDATA"
		,err[0x88982f71]:="WINCODEC_ERR_STREAMWRITE"
		,err[0x88982f72]:="WINCODEC_ERR_STREAMREAD"
		,err[0x88982f73]:="WINCODEC_ERR_STREAMNOTAVAILABLE"
		,err[0x88982f80]:="WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT"
		,err[0x88982f81]:="WINCODEC_ERR_UNSUPPORTEDOPERATION"
		,err[0x88982f8A]:="WINCODEC_ERR_INVALIDREGISTRATION"
		,err[0x88982f8B]:="WINCODEC_ERR_COMPONENTINITIALIZEFAILURE"
		,err[0x88982f8C]:="WINCODEC_ERR_INSUFFICIENTBUFFER"
		,err[0x88982f8D]:="WINCODEC_ERR_DUPLICATEMETADATAPRESENT"
		,err[0x88982f8E]:="WINCODEC_ERR_PROPERTYUNEXPECTEDTYPE"
		,err[0x88982f8F]:="WINCODEC_ERR_UNEXPECTEDSIZE"
		,err[0x88982f90]:="WINCODEC_ERR_INVALIDQUERYREQUEST"
		,err[0x88982f91]:="WINCODEC_ERR_UNEXPECTEDMETADATATYPE"
		,err[0x88982f92]:="WINCODEC_ERR_REQUESTONLYVALIDATMETADATAROOT"
		,err[0x88982f93]:="WINCODEC_ERR_INVALIDQUERYCHARACTER"
	}	
	if a && (a&=0xFFFFFFFF)
        { 
	   if err.haskey(a)
              return err[a]
        }
	return a
}
Attachments
hook.zip
(1.49 MiB) Downloaded 229 times
wpb
Posts: 139
Joined: 14 Dec 2015, 01:53

Re: MinHook - API Hooking Library

01 May 2020, 09:52

I tried to hook the DrawTextW function, but I get zero calls to the hook function.
Can anyone tell me what I'm doing wrong?
Thanks!

Code: Select all

SetWorkingDir %A_ScriptDir%
#NoEnv
#Include <MinHook>

allCalls := ""
nCalls := 0
hook1 := New MinHook("user32.dll", "DrawTextW", "DrawTextW_Hook")
if !hook1
	MsgBox, Failed!

hook1.Enable()

StartTime := A_TickCount
loop
{
	if ((A_TickCount - StartTime) > 1000)
		break
}

hook1.Disable()
MsgBox, % nCalls " calls:`n`n" allCalls

hook1 := "" ; Remove hook

; int DrawTextW(
;   HDC     hdc,
;   LPCWSTR lpchText,
;   int     cchText,
;   LPRECT  lprc,
;   UINT    format
; );

DrawTextW_Hook(HDC, lpchText, cchText, lprc, format) {
	global hook1
	global allCalls
	global nCalls
	nCalls++
	allCalls .= StrGet(lpchText,"utf-16",cchText)
	return DllCall(hook1.original, "ptr", HDC, "ptr", lpchText, "int", cchText, "ptr", lprc, "uint", format)
}
wpb
Posts: 139
Joined: 14 Dec 2015, 01:53

Re: MinHook - API Hooking Library

02 May 2020, 14:46

Ah, i think I realise why, but perhaps someone can confirm.

Does MinHook only hook APIs in the context of the calling program? I was hoping to hook calls to DrawText from another process, but I don't think MinHook does that...
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: MinHook - API Hooking Library

02 May 2020, 15:54

Example 3 - Hook another process using HotkeyIt's InjectAhkDll and AutoHotkey.dll

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: chinagreenelvis, Google [Bot], ntepa and 84 guests