commit 6c9de40fbcd0dbc62bffce68a82d170d62bb0df0 Author: mr.exodia Date: Thu Nov 14 21:55:18 2013 +0100 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..50bd37f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,49 @@ +#ignore directories +*/obj/ +bin/*/* +ipch/* +*/Win32/ +*/x64/ + +#global filetypes to ignore +*.depend +*.layout +*.cscope_file_list +*.bmarks +*.chw +*.cbTemp +*.ini +*.opensdf +*.sdf +*.suo + +#whitelisted bin files +!bin/*/TitanEngine.dll +!bin/*/test.dll +!bin/*/test.exe +!bin/*/dbghelp.dll +!bin/*/sqlite.dll +!bin/*/BeaEngine.dll +!bin/*/Scylla.dll + +#files to ignore +todo_bridge.txt + +#debugger files to ignore +x64_dbg_dbg/ODbgScript.chm +x64_dbg_dbg/ODbgScript.chw +x64_dbg_dbg/CppCheckResults.xml +x64_dbg_dbg/.cccc/ +x64_dbg_dbg/suggestions.txt + +# For GUI +*.pro.user +x64_dbg_gui/DebuggerX64-build-Debug +x64_dbg_gui/DebuggerX64-build-Release +x64_dbg_gui/bin +x64_dbg_gui/Project/GeneratedFiles/ +x64_dbg_gui/Project/release/ +x64_dbg_gui/Project/Win32/ +x64_dbg_gui/Project/x64/ +x64_dbg_gui/Project/Src/Bridge/libx32_bridge.a +x64_dbg_gui/Project/Src/Bridge/libx64_bridge.a \ No newline at end of file diff --git a/bin/x32/BeaEngine.dll b/bin/x32/BeaEngine.dll new file mode 100644 index 00000000..4b0f640a Binary files /dev/null and b/bin/x32/BeaEngine.dll differ diff --git a/bin/x32/Scylla.dll b/bin/x32/Scylla.dll new file mode 100644 index 00000000..b0cce4c3 Binary files /dev/null and b/bin/x32/Scylla.dll differ diff --git a/bin/x32/TitanEngine.dll b/bin/x32/TitanEngine.dll new file mode 100644 index 00000000..888bc339 Binary files /dev/null and b/bin/x32/TitanEngine.dll differ diff --git a/bin/x32/dbghelp.dll b/bin/x32/dbghelp.dll new file mode 100644 index 00000000..e671d388 Binary files /dev/null and b/bin/x32/dbghelp.dll differ diff --git a/bin/x32/sqlite.dll b/bin/x32/sqlite.dll new file mode 100644 index 00000000..bf4df296 Binary files /dev/null and b/bin/x32/sqlite.dll differ diff --git a/bin/x32/test.dll b/bin/x32/test.dll new file mode 100644 index 00000000..57c6a278 Binary files /dev/null and b/bin/x32/test.dll differ diff --git a/bin/x32/test.exe b/bin/x32/test.exe new file mode 100644 index 00000000..b6cd8bb3 Binary files /dev/null and b/bin/x32/test.exe differ diff --git a/bug.ico b/bug.ico new file mode 100644 index 00000000..889bc279 Binary files /dev/null and b/bug.ico differ diff --git a/help/Calculations.htm b/help/Calculations.htm new file mode 100644 index 00000000..5e5e4973 --- /dev/null +++ b/help/Calculations.htm @@ -0,0 +1,50 @@ + + + +Calculations + + + + + + + +

Calculations
The debugger allows usage of basic math +operations, just type an expression in the +command window and the result will be displayed in the console. Apart from +calculations, it allows quick variable changes using a C-like syntax.

+

Operators
You can use the +following operators in your expression. They are processed in the following order:

+

1:brackets: '(' and ')' Brackets are +resolved first, there is no need for a terminating bracket, unless you want to +use one.

+

2:not: '~' The not operator can be used before a +number of a variable, like in C.

+

3:addition/substraction +: '+' and '-'

+

4:muliplication/devision: '*' += regular multiplication (signed/unsigned), '#' = get the higher part of the +multiplication, '/' = regular devision (signed/unsigned, devide by zero=error) +and '%' = get the modulo (remainder) of the devision.

+

5:shift: '<' = shift left (shl for unsigned, +sal for signed), '>' = shift right (shr for unsigned, sar for signed).

+

6:and: '&' Just the regular AND operation like +in C.

+

7:xor: '^' Just the regular XOR operation like in +C.

+

8:or: '|' Just the regular OR operation like in +C.

+

Quick-Assigning
Changing memory, a +variable, register or flag can be easily done using a C-like +syntax:

+

a?=b: '?' can be any mathematical operation. 'a' +can be any register, flag, variable or memory location. 'b' can be anything that is recognized as a mathmatical +input.

+

a++/a--: 'a' can be any register, flag, variable or memory +location.

\ No newline at end of file diff --git a/help/Commands.htm b/help/Commands.htm new file mode 100644 index 00000000..ba890aab --- /dev/null +++ b/help/Commands.htm @@ -0,0 +1,35 @@ + + + +Commands + + + + + + + +

+command[,alias1,alias2]
Command description +here.

+

arguments
  arg1: Argument description.

+

[arg2]: Optional argument.

+

[arg3]: Another optional argument (can only be given when the +previous argument is also +given).

+

result
Description of the command result.

+

REMARK: Commands cannot contain any of the following characters: "," +(comma), " " (space) and "\" (backslash). They need to be +prefixed.

\ No newline at end of file diff --git a/help/DeleteBPX_bpc_bc.htm b/help/DeleteBPX_bpc_bc.htm new file mode 100644 index 00000000..6e1a9908 --- /dev/null +++ b/help/DeleteBPX_bpc_bc.htm @@ -0,0 +1,23 @@ + + + +DeleteBPX/bpc/bc + + + + + + + +

DeleteBPX[,bpc,bc]
Delete a +breakpoint set using the SetBPX command.

+

arguments
[arg1]: Name or address of the breakpoint to delete. If this argument is not specified, all breakpoints will be +enabled.

+

result
This command does not set any result variables.

+

 

\ No newline at end of file diff --git a/help/DisableBPX_bpd_bd.htm b/help/DisableBPX_bpd_bd.htm new file mode 100644 index 00000000..8d51c76a --- /dev/null +++ b/help/DisableBPX_bpd_bd.htm @@ -0,0 +1,26 @@ + + + +DisableBPX/bpd/bd + + + + + + +DisableBPX[,bpd,bd]
Disable a breakpoint set using the SetBPX +command. +

arguments
[arg1]: Name or address of the breakpoint to disable. If +this argument is not specified, all breakpoints will be enabled.

+

+ +result +
+
This command does not set any result +variables.

\ No newline at end of file diff --git a/help/EnableBPX_bpe_be.htm b/help/EnableBPX_bpe_be.htm new file mode 100644 index 00000000..1a19d52a --- /dev/null +++ b/help/EnableBPX_bpe_be.htm @@ -0,0 +1,25 @@ + + + +EnableBPX/bpe/be + + + + + + + +

EnableBPX[,bpe,be]
Enable +a breakpoint set using the SetBPX +command.

+

arguments
[arg1]: Name or address of the breakpoint to enable. If this +argument is not specified, all breakpoints +will be enabled.

+

result
This command does not set any result +variables.

\ No newline at end of file diff --git a/help/Fill_memset.htm b/help/Fill_memset.htm new file mode 100644 index 00000000..9c524bbe --- /dev/null +++ b/help/Fill_memset.htm @@ -0,0 +1,25 @@ + + + +Fill/memset + + + + + + + +

Fill[,memset]
Set memory of the +debuggee to a specified byte.

+

arguments
  arg1: Memory address to start setting bytes.

+

  arg2: Value (byte) to set memory with.

+

[arg3]: Size to set. When not specified the rest of the +page is used.

+

result
This command does not set any result +variables.

diff --git a/help/HideDebugger_dbh_hide.htm b/help/HideDebugger_dbh_hide.htm new file mode 100644 index 00000000..5da209ad --- /dev/null +++ b/help/HideDebugger_dbh_hide.htm @@ -0,0 +1,31 @@ + + + +HideDebugger/dbh/hide + + + + + + + +

HideDebugger[,dbh,hide]
Hide the debugger from (very) simple detection +methods.

+

arguments
This command has no arguments.

+

+ + +result +
+ +
+
+ +This command does not set any result +variables.

diff --git a/help/Hotkeys.htm b/help/Hotkeys.htm new file mode 100644 index 00000000..ee87421b --- /dev/null +++ b/help/Hotkeys.htm @@ -0,0 +1,24 @@ + + + +Hotkeys + + + + + + + +

Hotkeys
This section is a listing of +all hotkeys.

+

RIGHT-ALT: Use right-alt to toggle between the last +selected window the process has access to and the console window. This is useful +when you quickly need to enter a command and then switch back to the previous +window. The window selected will be set to +the foreground.

diff --git a/help/InitDebug_initdbg_init.htm b/help/InitDebug_initdbg_init.htm new file mode 100644 index 00000000..ce734c83 --- /dev/null +++ b/help/InitDebug_initdbg_init.htm @@ -0,0 +1,41 @@ + + + +InitDebug/initdbg/init + + + + + + + +

InitDebug[,init,initdbg]
Initializes the debugger. This command will load +the executable (do some basic checks), set breakpoints on TLS callbacks + (if present), set a breakpoint at the process entry point and +break at the system breakpoint before giving back control to the +user.

+

arguments
  arg1 : Path to the executable file to debug. If no full path is given, the GetCurrentDirectory API will be +called to retrieve a full path. Use quotation marks to include spaces in your path. + + +

+

[arg2]: Commandline to create the process with. + + +

+

[arg3]: Current folder (passed to the CreateProcess API). + + +

+

result
This command will +give control back to the user after the system breakpoint is reached. It will set +$pid and $hp/$hProcessvariables. + + +

\ No newline at end of file diff --git a/help/Input.htm b/help/Input.htm new file mode 100644 index 00000000..be55fd3e --- /dev/null +++ b/help/Input.htm @@ -0,0 +1,62 @@ + + + +Input + + + + + + + +

Input
This program accepts various options of input:

+

commands: +Commands have the following format: "command[space]arg1,[optional space]arg2,argN".

+

variables: +Variables optionally start with a $ and can only store one DWORD (QWORD on +x64).

+

debug registers: All debug registers (all sizes) can be used as +variables.

+

memory locations: You can read from a memory location by using one of the +following expressions:
@addr
+ @n:addr (where n is the amount of bytes to read, +this can be anything smaller then 4 on x32 and smaller then +8 on x64, when specified otherwise, there will be an error). addr is directly interpreted +as a value, when you want to read [addr+1] you should use +brackets: @(addr+1), @addr+1 will read: [addr]+1.

+

+ + + + + flags: Debug flags (interpreted as integer) can be used +as input. Flags are prefixed with a '!' following the flag name or the bit number their on. +Valid flags are: !cf, !pf, !af, !zf, !sf, !tf, !if, !df, !of, !rf, !vm, !ac, !vif, !vip and !id.

+

numbers: All +numbers are interpreted as hex by default. If you want to be sure, you can use +the "x" prefix. Decimal numbers can be used by prefixing the number with a "." +(.123=7B).

+

basic calculations : + + See "Calculations" for more +information.

+

+ +Input + +for arguments can always be done in any of the above forms, except if stated +otherwise.

\ No newline at end of file diff --git a/help/Introduction.htm b/help/Introduction.htm new file mode 100644 index 00000000..2965842c --- /dev/null +++ b/help/Introduction.htm @@ -0,0 +1,20 @@ + + + +Introduction + + + + + + + +

Introduction
[introductional talk +with motivation here].

+ \ No newline at end of file diff --git a/help/SetBPXOptions_bptype.htm b/help/SetBPXOptions_bptype.htm new file mode 100644 index 00000000..926f6873 --- /dev/null +++ b/help/SetBPXOptions_bptype.htm @@ -0,0 +1,23 @@ + + + +SetBPXOptions/bptype + + + + + + + +

SetBPXOptions[,bptype]
Set the default type for the "SetBPX" command.

+

arguments
  arg1: Default type. This can be "short" (CC), +"long" (CD03) or "ud2" (0F0B). Type default type affects +both NORMAL and SINGLESHOT breakpoints.

+

result
This command does not set any result +variables.

\ No newline at end of file diff --git a/help/SetBPX_bp_bpx.htm b/help/SetBPX_bp_bpx.htm new file mode 100644 index 00000000..68b1897d --- /dev/null +++ b/help/SetBPX_bp_bpx.htm @@ -0,0 +1,46 @@ + + + +SetBPX/bp/bpx + + + + + + + +

SetBPX[,bp,bpx]
Set an INT3 (SHORT/LONG) or UD2 breakpoint +and optionally assign a name to it.

+

arguments
  arg1: Address to put a breakpoint on. This can be an API name [not + implemented].

+

+ [arg2]: Name of the breakpoint, use quotation marks to +include spaces. This name can be used + by the EnableBPX, DisableBPX and DeleteBPX functions as alias, +but is mainly intended to provide a single line of information about the +currently-hit breakpoint. When arg2 equals to a + valid type (arg3) the type is used and arg2 +is + ignored.

+

+ [arg3]: Breakpoint type. Can be one of the following +options + in random order: "ss" (single shot breakpoint), "long" (CD03), +"ud2" (0F0B) and "short" (CC). You can combine the "ss" option +with one of the type options in one string. Example: "SetBPX 00401000,"entrypoint",ssud2" will set a +single shot UD2 breakpoint at 00401000 with the name "entrypoint". + When specifying no type or just the type "ss" +the default type will be used. Per default this equals to the +"short" type. You can change the default type using the "SetBPXOptions" + command.

+

result
+ + + This command does not any result + variables.

\ No newline at end of file diff --git a/help/SetHardwareBreakpoint_bph_bphws.htm b/help/SetHardwareBreakpoint_bph_bphws.htm new file mode 100644 index 00000000..79562cbb --- /dev/null +++ b/help/SetHardwareBreakpoint_bph_bphws.htm @@ -0,0 +1,34 @@ + + + +SetHardwareBreakpoint/bph/bphws + + + + + + + +

SetHardwareBreakpoint[,bph,bphws]
Set a +hardware breakpoint (using debug registers).

+

arguments
  +arg1: Address of the hardware breakpoint. 

+

[arg2]: Hardware breakpoint type. Can be either 'r' +(readwrite), 'w' (write) or 'x' (execute). When not specified, 'x' is +assumed. 

+

+ [arg3]: Hardware breakpoint +size. Can be +either '1', '2', '4' or '8' (x64 only). Per default, '1' is assumed. The address +you're putting the hardware breakpoint on must be aligned to the specified +size.

+

result
This command does not set any result +variables.

\ No newline at end of file diff --git a/help/SetMemoryBPX_membp_bpm.htm b/help/SetMemoryBPX_membp_bpm.htm new file mode 100644 index 00000000..230fbc1c --- /dev/null +++ b/help/SetMemoryBPX_membp_bpm.htm @@ -0,0 +1,51 @@ + + + +SetMemoryBPX/membp/bpm + + + + + + + +

SetMemoryBPX[,membp,bpm]
Set a memory +breakpoint (GUARD_PAGE) on the whole memory region the provided address is +in.

+

+ +arguments +
+ +
+ +   arg1: Address of or +inside a memory region that will be watched. +

+

+ + [arg2]: +1/0 restore the memory breakpoint once it's hit? When this value is not equal to one, it's assumed to be arg3. This +means "bpm eax,r" would be the same command as: "bpm +eax,0,r". +

+

+ +[arg3]: Breakpoint type, it +can be 'r' (execute+read), 'w' (write) or 'x' (execute). Per default, +it's a combination of execute, read and write. +

+

result +
This command does not set any result variables. + +

+

 

\ No newline at end of file diff --git a/help/SingleStep.htm b/help/SingleStep.htm new file mode 100644 index 00000000..afb5cab0 --- /dev/null +++ b/help/SingleStep.htm @@ -0,0 +1,25 @@ + + + +SingleStep/sstep/sst + + + + + + + +

SingleStep[,sstep,sst]
Step a +specified number of instructions using the Trap-Flag.

+

arguments
[arg1]: The number of instructions to executre (this can be +any valid expression). When not specified, a StepInto is performed.

+

result
This command does not set any result +variables.

\ No newline at end of file diff --git a/help/Special_Thanks.htm b/help/Special_Thanks.htm new file mode 100644 index 00000000..2f42bb31 --- /dev/null +++ b/help/Special_Thanks.htm @@ -0,0 +1,24 @@ + + + +Special Thanks + + + + + + + +

Special Thanks
This page is reserved +to companies/people who get credit for their used work or support.

+

VisualPharm for their great icon!
ReversingLabs for TitanEngine!
BeatriX for +BeaEngine!

\ No newline at end of file diff --git a/help/StepInto.htm b/help/StepInto.htm new file mode 100644 index 00000000..f8532004 --- /dev/null +++ b/help/StepInto.htm @@ -0,0 +1,24 @@ + + + +StepInto/sti + + + + + + + +

StepInto[,sti]
Single Step (using +Trap-Flag).

+

arguments
This command has no arguments.

+

result
This command does not set any result +variables.

diff --git a/help/StepOver.htm b/help/StepOver.htm new file mode 100644 index 00000000..a5bbeb6f --- /dev/null +++ b/help/StepOver.htm @@ -0,0 +1,25 @@ + + + +StepOver/step/sto/st + + + + + + + +

StepOver[,step,sto,st]
Step over +calls, when the instruction at CIP isn't a call, a StepInto is performed.

+

arguments
This command has no arguments. +

+

result
This command does not set any result +variables.

\ No newline at end of file diff --git a/help/ToggleBPX_bpt_bt.htm b/help/ToggleBPX_bpt_bt.htm new file mode 100644 index 00000000..4ea65b9e --- /dev/null +++ b/help/ToggleBPX_bpt_bt.htm @@ -0,0 +1,26 @@ + + + +ToggleBPX/bpt/bt + + + + + + + +

ToggleBPX[,bpt,bt]
Toggle +(enable/disable) a breakpoint.

+

arguments
  arg1: +Name or address of the +breakpoint to toggle.

+

result
The $result variable will be set to the +state of the breakpoint before it was toggled. 1: breakpoint was enabled before, +0: breakpoint +was disabled before.

\ No newline at end of file diff --git a/help/Variables.htm b/help/Variables.htm new file mode 100644 index 00000000..eea2c0fd --- /dev/null +++ b/help/Variables.htm @@ -0,0 +1,38 @@ + + + +Variables + + + + + + + +

Variables
This program supports variables. There are three types of +variables:

+

USER: +Variables created by the user using the "var" command. These variables have no +access restrictions.

+

SYSTEM: +Variables created by the system, that can be read and written, but cannot be +deleted.

+

READONLY: +Variables created by the system, that can be read, but not written or +deleted.

+

Reserved +Variables
There are a few reserved +variables:

+

$res/$result: General result variable.
$resN/$resultN: +Optional other result variables (N= + 1-4).
$pid: Project ID of the debugged +executable.
$hp/$hProcess: Debugged executable +handle.
$lastalloc: Last result of the +'alloc' command.

\ No newline at end of file diff --git a/help/alloc.htm b/help/alloc.htm new file mode 100644 index 00000000..aa15c424 --- /dev/null +++ b/help/alloc.htm @@ -0,0 +1,25 @@ + + + +alloc + + + + + + + +

alloc
Allocate memory in the debuggee (using +VirtualAllocEx). The memory is allocated +with PAGE_EXECUTE_READWRITE protection.

+

arguments
[arg1]: Size of the memory to +allocate. When not specified, a default size of 0x1000 is used.

+

result
This command sets $result to the allocated memory address. It also sets the $lastalloc +variable to the allocated memory address when VirtualAllocEx +succeeded.

\ No newline at end of file diff --git a/help/bplist.htm b/help/bplist.htm new file mode 100644 index 00000000..c7e15acb --- /dev/null +++ b/help/bplist.htm @@ -0,0 +1,35 @@ + + + +bplist + + + + + + + +

bplist
Get a list of breakpoints. +This list includes their state (enabled/disabled), their type, their address and +(optionally) their names.

+

arguments
This command has no arguments.

+

result
+ This command does not set any result variables. A list entry has the +following format:

+

STATE:TYPE:ADDRESS[:NAME]

+

STATE can be 0 or 1. 0 means disabled, 1 means +enabled. Only singleshoot and 'normal' breakpoints can be disabled.

+

TYPE can be one of the following values: BP, +SS, HW and GP. BP stands for a normal breakpoint (set using the SetBPX command), +SS stands for SINGLESHOT, HW stands for HARDWARE and GP stand for Guard Page, +the way of setting memory breakpoints.

+

ADDRESS is the breakpoint address, given in 32 and 64 +bits for the x32 and x64 debugger respectively.

+

NAME is the name assigned +to the breakpoint.

\ No newline at end of file diff --git a/help/chd.htm b/help/chd.htm new file mode 100644 index 00000000..f2c3e20c --- /dev/null +++ b/help/chd.htm @@ -0,0 +1,23 @@ + + + +chd + + + + + + + +

chd
Change current directory +(SetCurrentDirectory).

+

arguments
  arg1: Path of a directory to change +to.

+

result
This command does not set any result +variables.

\ No newline at end of file diff --git a/help/cls.htm b/help/cls.htm new file mode 100644 index 00000000..5cf1356e --- /dev/null +++ b/help/cls.htm @@ -0,0 +1,21 @@ + + + +cls + + + + + + + +

cls
Clear the console screen.

+

arguments
This command has no arguments.

+

result
This command does not set any result +variables.

\ No newline at end of file diff --git a/help/disasm_dis_d.htm b/help/disasm_dis_d.htm new file mode 100644 index 00000000..f06cbafd --- /dev/null +++ b/help/disasm_dis_d.htm @@ -0,0 +1,32 @@ + + + +disasm/dis/d + + + + + + + +

disasm[,dis,d]
Disassemble 500 +instructions and put the result in the disassembly window.

+

+ +arguments +
+ +
+ + + +[arg1]: The address to disassemble at. When not specified, +there will be assembled at CIP. +

result
This command does not set any result +variables.

diff --git a/help/free.htm b/help/free.htm new file mode 100644 index 00000000..3dd6b288 --- /dev/null +++ b/help/free.htm @@ -0,0 +1,31 @@ + + + +free + + + + + + + +

free
+ Free memory in the debuggee (using VirtualFreeEx).

+

+ arguments
[arg1]: Address of the memory to free. When not +specified, the value at $lastalloc is used.

+

+ +result + +
+This command sets $result +to 1 if VirtualFreeEx succeeded, otherwise it's set to +0. $lastalloc is set to zero when the address specified is equal +to $lastalloc.

diff --git a/help/mov_set.htm b/help/mov_set.htm new file mode 100644 index 00000000..3855a848 --- /dev/null +++ b/help/mov_set.htm @@ -0,0 +1,29 @@ + + + +mov/set + + + + + + + +

mov[,set]
Set a variable.

+

arguments
  arg1: Variable name (optionally prefixed with a $) to +set. When the variable does not exist, it will be +created. +

+

+  +arg2: Value to store in the variable.

+

result
This command does not set any result +variables.

\ No newline at end of file diff --git a/help/rtr.htm b/help/rtr.htm new file mode 100644 index 00000000..bcc49dad --- /dev/null +++ b/help/rtr.htm @@ -0,0 +1,36 @@ + + + +rtr + + + + + + + +

rtr
Return from function by calling +StepOver until the current instruction is a RET.

+

+ + +arguments + + +
+
+ +This command has no arguments.

+

+ + +result
+
This command does not set any result +variables.

diff --git a/help/run_go_r_g.htm b/help/run_go_r_g.htm new file mode 100644 index 00000000..f4cedf85 --- /dev/null +++ b/help/run_go_r_g.htm @@ -0,0 +1,24 @@ + + + +run/go/r/g + + + + + + + +

run[,go,r,g]
Free the lock and allow +the program to run.

+

arguments
This command has no arguments.

+

result +
+This command does not set any result +variables.

diff --git a/help/strlen_charcount_ccount.htm b/help/strlen_charcount_ccount.htm new file mode 100644 index 00000000..40aff1ab --- /dev/null +++ b/help/strlen_charcount_ccount.htm @@ -0,0 +1,27 @@ + + + +strlen/charcount/ccount + + + + + + + +

strlen[,charcount,ccount]
Get the +length of a string. This was the first command ever, left in for historical reasons.

+

arguments
  arg1: String you want to get the length of.

+

result
This +command does not set any result variables.

\ No newline at end of file diff --git a/help/template/btn_next_g.gif b/help/template/btn_next_g.gif new file mode 100644 index 00000000..19017f07 Binary files /dev/null and b/help/template/btn_next_g.gif differ diff --git a/help/template/btn_next_n.gif b/help/template/btn_next_n.gif new file mode 100644 index 00000000..9617d42f Binary files /dev/null and b/help/template/btn_next_n.gif differ diff --git a/help/template/btn_prev_g.gif b/help/template/btn_prev_g.gif new file mode 100644 index 00000000..fc72235f Binary files /dev/null and b/help/template/btn_prev_g.gif differ diff --git a/help/template/btn_prev_n.gif b/help/template/btn_prev_n.gif new file mode 100644 index 00000000..98691853 Binary files /dev/null and b/help/template/btn_prev_n.gif differ diff --git a/help/template/fixedtop.htm b/help/template/fixedtop.htm new file mode 100644 index 00000000..3a909fd9 --- /dev/null +++ b/help/template/fixedtop.htm @@ -0,0 +1,59 @@ + + + +($title$) + + + + + + + +
+ + + + + +
+
+New Help > + ($navigation$)
+
($title$) +
+
+PreviousNext +
+
+
+

($content$)

+
+ No + Copyright
+ + + + diff --git a/help/template/winchm_template_style.css b/help/template/winchm_template_style.css new file mode 100644 index 00000000..ad3f440c --- /dev/null +++ b/help/template/winchm_template_style.css @@ -0,0 +1,69 @@ +div { margin: 0; padding: 0; outline: 0; } + +html,body { + padding: 0px; + margin: 0px; + overflow: hidden; + height: 100%; +} + +#winchm_template_top { + padding: 0px; + margin: 0px; + border-bottom: 1px solid #B7B7B7; +} + +#winchm_template_navigation{ + PADDING-RIGHT: 2px; + PADDING-LEFT: 2px; + FONT-SIZE: 11px; + PADDING-BOTTOM: 2px; + MARGIN: 0px; + PADDING-TOP: 2px; + FONT-FAMILY: Courier New; +} + +#winchm_template_title{ + PADDING-RIGHT: 2px; + PADDING-LEFT: 2px; + FONT-WEIGHT: bold; + FONT-SIZE: 14px; + PADDING-BOTTOM: 2px; + MARGIN: 0px; + PADDING-TOP: 2px; + FONT-FAMILY: Courier New; +} + + +@media screen +{ +#winchm_template_content{ + margin: 0px; + padding: 15px; + position: absolute; + top : 51px; + right: 0px; + bottom: 0px; + left: 0px; + overflow: auto; +} +} + +@media print +{ +#winchm_template_content{ + position: static; + margin: 0px; + padding: 5px; + + width: auto; + height: auto; + overflow: auto; +} +#winchm_template_prev{ +visibility:hidden; +} +#winchm_template_next{ +visibility:hidden; +} +} \ No newline at end of file diff --git a/help/template_courier.htm b/help/template_courier.htm new file mode 100644 index 00000000..e6d9e9ee --- /dev/null +++ b/help/template_courier.htm @@ -0,0 +1,19 @@ + + + +New Item2 + + + + + + + +

 

+ \ No newline at end of file diff --git a/help/var_varnew.htm b/help/var_varnew.htm new file mode 100644 index 00000000..9262924d --- /dev/null +++ b/help/var_varnew.htm @@ -0,0 +1,27 @@ + + + +var/varnew + + + + + + + +

var[,varnew]
Declare a new variable.

+

arguments
  arg1: Variable name (will be prefixed with '$' if not +done). +

+

+ [arg2]: Initial variable value (see console input for details).

+

result
This command does not set any result +variables.

\ No newline at end of file diff --git a/help/vardel.htm b/help/vardel.htm new file mode 100644 index 00000000..8a208d65 --- /dev/null +++ b/help/vardel.htm @@ -0,0 +1,23 @@ + + + +vardel + + + + + + + +

vardel
Delete a user-defined variable.

+

arguments
  arg1: Name of the variable to delete ($ will be +prepended when not present).

+

result
This command does not set any result +variables.

\ No newline at end of file diff --git a/help/varlist.htm b/help/varlist.htm new file mode 100644 index 00000000..8db8685b --- /dev/null +++ b/help/varlist.htm @@ -0,0 +1,23 @@ + + + +varlist + + + + + + + +

varlist
Get a list of all variables and their +values.

+

arguments
[arg1]: Filter (USER, SYSTEM, READONLY).

+

result
This command does not set any result +variables.

\ No newline at end of file diff --git a/help/x64_dbg.wcp b/help/x64_dbg.wcp new file mode 100644 index 00000000..84e06e42 --- /dev/null +++ b/help/x64_dbg.wcp @@ -0,0 +1,460 @@ +[GENERAL] +Ver=2 +Title=x64_dbg +RootDir= +DefaultTopic= +CompiledFile=\x64_dbg.chm +CustomTemplate=\template_courier.htm +DefaultTemplate=0 +Language=0x0413 +Encoding=UTF-8 +DeleteProject=0 +ViewCompiledFile=0 +HasChild=0 +NoChild=10 +HtmlHelpTemplate=template\fixedtop.htm +HtmlHelpTitle=x64_dbg +HtmlHelpTitleSame=1 +HtmlHelpOutputEncoding=Windows-1252 +WebHelpDefault= +WebHelpOutputFolder=\output\WebHelp\ +WebHelpTemplate=template\fixedtop.htm +WebHelpTitle=x64_dbg +WebHelpDefaultSame=1 +WebHelpTemplateSame=1 +WebHelpTilteSame=1 +WebHelpLanguage=1 +StartFromRoot=1 +AutoCollapse=0 +DrawLines=1 +SingleHtmlFilename=all.htm +SingleHtmlOutputFolder=\output\SingleHTML\ +SingleHtmlTitle=x64_dbg +SingleHtmlHasToc=0 +SingleHtmlSame=1 +HeadProperties=1 +PageProperties=1 +RealColorIcon=0 +ShowIndex=1 +NavWidth=270 +WebFontColor=#DBEFF9 +WebBackColor= +WebBackground=1 +HHPFolder= + +[CHMSetting] +Top=50 +Left=50 +Height=650 +Width=900 +PaneWidth=270 +DefaultTab=0 +ShowMSDNMenu=0 +ShowPanesToolbar=1 +ShowPane=1 +HideToolbar=0 +HideToolbarText=0 +StayOnTop=0 +Maximize=0 +Hide=1 +Locate=1 +Back=1 +bForward=1 +Stop=1 +Refresh=1 +Home=1 +Print=1 +Option=1 +Jump1=0 +Jump2=0 +AutoShowHide=0 +AutoSync=1 +Content=1 +Index=1 +Search=1 +Favorite=1 +UseFolder=0 +AutoTrack=0 +SelectRow=0 +PlusMinus=1 +ShowSelection=1 +ShowRoot=1 +DrawLines=1 +AutoExpand=0 +RightToLeft=0 +LeftScroll=0 +Border=0 +DialogFrame=0 +RaisedEdge=0 +SunkenEdge=0 +SavePosition=0 +ContentsFont=Courier New,8,0 +IndexFont=Courier New,8,0 +Title=x64_dbg +Language=0x0413 +Font= +DefaultTopic=Introduction.htm + +[TOPICS] +TitleList=36 +TitleList.Title.0=Introduction +TitleList.Level.0=0 +TitleList.Url.0=Introduction.htm +TitleList.Icon.0=0 +TitleList.Status.0=0 +TitleList.Keywords.0= +TitleList.ContextNumber.0=1000 +TitleList.ApplyTemp.0=0 +TitleList.Expanded.0=1 +TitleList.Kind.0=0 +TitleList.Title.1=Input +TitleList.Level.1=1 +TitleList.Url.1=Input.htm +TitleList.Icon.1=0 +TitleList.Status.1=0 +TitleList.Keywords.1= +TitleList.ContextNumber.1=1001 +TitleList.ApplyTemp.1=0 +TitleList.Expanded.1=0 +TitleList.Kind.1=0 +TitleList.Title.2=Variables +TitleList.Level.2=1 +TitleList.Url.2=Variables.htm +TitleList.Icon.2=0 +TitleList.Status.2=0 +TitleList.Keywords.2= +TitleList.ContextNumber.2=1002 +TitleList.ApplyTemp.2=0 +TitleList.Expanded.2=0 +TitleList.Kind.2=0 +TitleList.Title.3=Calculations +TitleList.Level.3=1 +TitleList.Url.3=Calculations.htm +TitleList.Icon.3=0 +TitleList.Status.3=0 +TitleList.Keywords.3= +TitleList.ContextNumber.3=1020 +TitleList.ApplyTemp.3=0 +TitleList.Expanded.3=0 +TitleList.Kind.3=0 +TitleList.Title.4=Hotkeys +TitleList.Level.4=1 +TitleList.Url.4=Hotkeys.htm +TitleList.Icon.4=0 +TitleList.Status.4=0 +TitleList.Keywords.4= +TitleList.ContextNumber.4=1034 +TitleList.ApplyTemp.4=0 +TitleList.Expanded.4=0 +TitleList.Kind.4=0 +TitleList.Title.5=Commands +TitleList.Level.5=0 +TitleList.Url.5=Commands.htm +TitleList.Icon.5=0 +TitleList.Status.5=0 +TitleList.Keywords.5= +TitleList.ContextNumber.5=1003 +TitleList.ApplyTemp.5=0 +TitleList.Expanded.5=0 +TitleList.Kind.5=0 +TitleList.Title.6=x/exit +TitleList.Level.6=1 +TitleList.Url.6=x_exit.htm +TitleList.Icon.6=0 +TitleList.Status.6=0 +TitleList.Keywords.6= +TitleList.ContextNumber.6=1004 +TitleList.ApplyTemp.6=0 +TitleList.Expanded.6=0 +TitleList.Kind.6=0 +TitleList.Title.7=strlen/charcount/ccount +TitleList.Level.7=1 +TitleList.Url.7=strlen_charcount_ccount.htm +TitleList.Icon.7=0 +TitleList.Status.7=0 +TitleList.Keywords.7= +TitleList.ContextNumber.7=1005 +TitleList.ApplyTemp.7=0 +TitleList.Expanded.7=0 +TitleList.Kind.7=0 +TitleList.Title.8=var/varnew +TitleList.Level.8=1 +TitleList.Url.8=var_varnew.htm +TitleList.Icon.8=0 +TitleList.Status.8=0 +TitleList.Keywords.8= +TitleList.ContextNumber.8=1006 +TitleList.ApplyTemp.8=0 +TitleList.Expanded.8=0 +TitleList.Kind.8=0 +TitleList.Title.9=vardel +TitleList.Level.9=1 +TitleList.Url.9=vardel.htm +TitleList.Icon.9=0 +TitleList.Status.9=0 +TitleList.Keywords.9= +TitleList.ContextNumber.9=1007 +TitleList.ApplyTemp.9=0 +TitleList.Expanded.9=0 +TitleList.Kind.9=0 +TitleList.Title.10=mov/set +TitleList.Level.10=1 +TitleList.Url.10=mov_set.htm +TitleList.Icon.10=0 +TitleList.Status.10=0 +TitleList.Keywords.10= +TitleList.ContextNumber.10=1008 +TitleList.ApplyTemp.10=0 +TitleList.Expanded.10=0 +TitleList.Kind.10=0 +TitleList.Title.11=cls +TitleList.Level.11=1 +TitleList.Url.11=cls.htm +TitleList.Icon.11=0 +TitleList.Status.11=0 +TitleList.Keywords.11= +TitleList.ContextNumber.11=1009 +TitleList.ApplyTemp.11=0 +TitleList.Expanded.11=0 +TitleList.Kind.11=0 +TitleList.Title.12=varlist +TitleList.Level.12=1 +TitleList.Url.12=varlist.htm +TitleList.Icon.12=0 +TitleList.Status.12=0 +TitleList.Keywords.12= +TitleList.ContextNumber.12=1010 +TitleList.ApplyTemp.12=0 +TitleList.Expanded.12=0 +TitleList.Kind.12=0 +TitleList.Title.13=InitDebug/initdbg/init +TitleList.Level.13=1 +TitleList.Url.13=InitDebug_initdbg_init.htm +TitleList.Icon.13=0 +TitleList.Status.13=0 +TitleList.Keywords.13= +TitleList.ContextNumber.13=1011 +TitleList.ApplyTemp.13=0 +TitleList.Expanded.13=0 +TitleList.Kind.13=0 +TitleList.Title.14=run/go/r/g +TitleList.Level.14=1 +TitleList.Url.14=run_go_r_g.htm +TitleList.Icon.14=0 +TitleList.Status.14=0 +TitleList.Keywords.14= +TitleList.ContextNumber.14=1013 +TitleList.ApplyTemp.14=0 +TitleList.Expanded.14=0 +TitleList.Kind.14=0 +TitleList.Title.15=SetBPXOptions/bptype +TitleList.Level.15=1 +TitleList.Url.15=SetBPXOptions_bptype.htm +TitleList.Icon.15=0 +TitleList.Status.15=0 +TitleList.Keywords.15= +TitleList.ContextNumber.15=1018 +TitleList.ApplyTemp.15=0 +TitleList.Expanded.15=0 +TitleList.Kind.15=0 +TitleList.Title.16=SetBPX/bp/bpx +TitleList.Level.16=1 +TitleList.Url.16=SetBPX_bp_bpx.htm +TitleList.Icon.16=0 +TitleList.Status.16=0 +TitleList.Keywords.16= +TitleList.ContextNumber.16=1012 +TitleList.ApplyTemp.16=0 +TitleList.Expanded.16=0 +TitleList.Kind.16=0 +TitleList.Title.17=EnableBPX/bpe/be +TitleList.Level.17=1 +TitleList.Url.17=EnableBPX_bpe_be.htm +TitleList.Icon.17=0 +TitleList.Status.17=0 +TitleList.Keywords.17= +TitleList.ContextNumber.17=1014 +TitleList.ApplyTemp.17=0 +TitleList.Expanded.17=0 +TitleList.Kind.17=0 +TitleList.Title.18=DisableBPX/bpd/bd +TitleList.Level.18=1 +TitleList.Url.18=DisableBPX_bpd_bd.htm +TitleList.Icon.18=0 +TitleList.Status.18=0 +TitleList.Keywords.18= +TitleList.ContextNumber.18=1016 +TitleList.ApplyTemp.18=0 +TitleList.Expanded.18=0 +TitleList.Kind.18=0 +TitleList.Title.19=ToggleBPX/bpt/bt +TitleList.Level.19=1 +TitleList.Url.19=ToggleBPX_bpt_bt.htm +TitleList.Icon.19=0 +TitleList.Status.19=0 +TitleList.Keywords.19= +TitleList.ContextNumber.19=1019 +TitleList.ApplyTemp.19=0 +TitleList.Expanded.19=0 +TitleList.Kind.19=0 +TitleList.Title.20=DeleteBPX/bpc/bc +TitleList.Level.20=1 +TitleList.Url.20=DeleteBPX_bpc_bc.htm +TitleList.Icon.20=0 +TitleList.Status.20=0 +TitleList.Keywords.20= +TitleList.ContextNumber.20=1017 +TitleList.ApplyTemp.20=0 +TitleList.Expanded.20=0 +TitleList.Kind.20=0 +TitleList.Title.21=bplist +TitleList.Level.21=1 +TitleList.Url.21=bplist.htm +TitleList.Icon.21=0 +TitleList.Status.21=0 +TitleList.Keywords.21= +TitleList.ContextNumber.21=1015 +TitleList.ApplyTemp.21=0 +TitleList.Expanded.21=0 +TitleList.Kind.21=0 +TitleList.Title.22=StepInto/sti +TitleList.Level.22=1 +TitleList.Url.22=StepInto.htm +TitleList.Icon.22=0 +TitleList.Status.22=0 +TitleList.Keywords.22= +TitleList.ContextNumber.22=1021 +TitleList.ApplyTemp.22=0 +TitleList.Expanded.22=0 +TitleList.Kind.22=0 +TitleList.Title.23=StepOver/step/sto/st +TitleList.Level.23=1 +TitleList.Url.23=StepOver.htm +TitleList.Icon.23=0 +TitleList.Status.23=0 +TitleList.Keywords.23= +TitleList.ContextNumber.23=1022 +TitleList.ApplyTemp.23=0 +TitleList.Expanded.23=0 +TitleList.Kind.23=0 +TitleList.Title.24=SingleStep/sstep/sst +TitleList.Level.24=1 +TitleList.Url.24=SingleStep.htm +TitleList.Icon.24=0 +TitleList.Status.24=0 +TitleList.Keywords.24= +TitleList.ContextNumber.24=1023 +TitleList.ApplyTemp.24=0 +TitleList.Expanded.24=0 +TitleList.Kind.24=0 +TitleList.Title.25=HideDebugger/dbh/hide +TitleList.Level.25=1 +TitleList.Url.25=HideDebugger_dbh_hide.htm +TitleList.Icon.25=0 +TitleList.Status.25=0 +TitleList.Keywords.25= +TitleList.ContextNumber.25=1025 +TitleList.ApplyTemp.25=0 +TitleList.Expanded.25=0 +TitleList.Kind.25=0 +TitleList.Title.26=disasm/dis/d +TitleList.Level.26=1 +TitleList.Url.26=disasm_dis_d.htm +TitleList.Icon.26=0 +TitleList.Status.26=0 +TitleList.Keywords.26= +TitleList.ContextNumber.26=1026 +TitleList.ApplyTemp.26=0 +TitleList.Expanded.26=0 +TitleList.Kind.26=0 +TitleList.Title.27=SetMemoryBPX/membp/bpm +TitleList.Level.27=1 +TitleList.Url.27=SetMemoryBPX_membp_bpm.htm +TitleList.Icon.27=0 +TitleList.Status.27=0 +TitleList.Keywords.27= +TitleList.ContextNumber.27=1027 +TitleList.ApplyTemp.27=0 +TitleList.Expanded.27=0 +TitleList.Kind.27=0 +TitleList.Title.28=chd +TitleList.Level.28=1 +TitleList.Url.28=chd.htm +TitleList.Icon.28=0 +TitleList.Status.28=0 +TitleList.Keywords.28= +TitleList.ContextNumber.28=1029 +TitleList.ApplyTemp.28=0 +TitleList.Expanded.28=0 +TitleList.Kind.28=0 +TitleList.Title.29=rtr +TitleList.Level.29=1 +TitleList.Url.29=rtr.htm +TitleList.Icon.29=0 +TitleList.Status.29=0 +TitleList.Keywords.29= +TitleList.ContextNumber.29=1028 +TitleList.ApplyTemp.29=0 +TitleList.Expanded.29=0 +TitleList.Kind.29=0 +TitleList.Title.30=SetHardwareBreakpoint/bph/bphws +TitleList.Level.30=1 +TitleList.Url.30=SetHardwareBreakpoint_bph_bphws.htm +TitleList.Icon.30=0 +TitleList.Status.30=0 +TitleList.Keywords.30= +TitleList.ContextNumber.30=1030 +TitleList.ApplyTemp.30=0 +TitleList.Expanded.30=0 +TitleList.Kind.30=0 +TitleList.Title.31=alloc +TitleList.Level.31=1 +TitleList.Url.31=alloc.htm +TitleList.Icon.31=0 +TitleList.Status.31=0 +TitleList.Keywords.31= +TitleList.ContextNumber.31=1032 +TitleList.ApplyTemp.31=0 +TitleList.Expanded.31=0 +TitleList.Kind.31=0 +TitleList.Title.32=free +TitleList.Level.32=1 +TitleList.Url.32=free.htm +TitleList.Icon.32=0 +TitleList.Status.32=0 +TitleList.Keywords.32= +TitleList.ContextNumber.32=1031 +TitleList.ApplyTemp.32=0 +TitleList.Expanded.32=0 +TitleList.Kind.32=0 +TitleList.Title.33=Fill/memset +TitleList.Level.33=1 +TitleList.Url.33=Fill_memset.htm +TitleList.Icon.33=0 +TitleList.Status.33=0 +TitleList.Keywords.33= +TitleList.ContextNumber.33=1033 +TitleList.ApplyTemp.33=0 +TitleList.Expanded.33=0 +TitleList.Kind.33=0 +TitleList.Title.34=Special Thanks +TitleList.Level.34=0 +TitleList.Url.34=Special_Thanks.htm +TitleList.Icon.34=0 +TitleList.Status.34=0 +TitleList.Keywords.34= +TitleList.ContextNumber.34=1024 +TitleList.ApplyTemp.34=0 +TitleList.Expanded.34=0 +TitleList.Kind.34=0 +TitleList.Title.35=Fixed Top Style +TitleList.Level.35=0 +TitleList.Url.35=template\fixedtop.htm +TitleList.Icon.35=0 +TitleList.Status.35=0 +TitleList.Keywords.35= +TitleList.ContextNumber.35= +TitleList.ApplyTemp.35=0 +TitleList.Expanded.35=0 +TitleList.Kind.35=2 + diff --git a/help/x_exit.htm b/help/x_exit.htm new file mode 100644 index 00000000..9461bf99 --- /dev/null +++ b/help/x_exit.htm @@ -0,0 +1,23 @@ + + + +x/exit + + + + + + + +

x[,exit]
Exit the program.

+

arguments
This command has no arguments.

+

result
This +command does not set any result variables.

\ No newline at end of file diff --git a/readme.txt b/readme.txt new file mode 100644 index 00000000..e2067d43 --- /dev/null +++ b/readme.txt @@ -0,0 +1,34 @@ +This is a x32/x64 debugger that is currently in active development. + +The debugger has (currently) three parts: +- DBG +- GUI +- Bridge + +DBG is the debugging part of the debugger. It handles debugging (using +TitanEngine) and will provide data for the GUI. + +GUI is the graphical part of the debugger. It is built on top of QT and it +provides the user interaction, the dump window (not yet implemented), the +disassembly, the register window (not yet implemented), the memory map +view (not yet implemented) etc. + +Bridge is the communication library for the DBG and GUI part (and maybe in +the future more parts). The bridge can be used to work on new features, +without having to update the code of the other parts. + +Right now the debugger supports the following features: +- variables (with regard to the upcoming script feature) +- basic calculations (var*@401000+.45^4A) +- hide debugger (very basic) +- software breakpoints (INT3, LONG INT3, UD2) +- memory breakpoints (read, write, execute) +- hardware breakpoints (access, write, execute) +- stepping (into, over, n instructions) +- rtr (return from function) +- memory allocation/deallocation in the debuggee +- quickly accessing API addresses (GetProcAddress->76E13620) +- highlighting (not yet customizable, but really helpful) + +The debugger core is based on TitanEngine (an updated version) and the +disassembly is powered by BeaEngine. The icon is taken from VisualPharm. \ No newline at end of file diff --git a/todo_dbg.txt b/todo_dbg.txt new file mode 100644 index 00000000..97c3dcfa --- /dev/null +++ b/todo_dbg.txt @@ -0,0 +1,62 @@ +- attach/detach debugger +- asm command +- advanced readprocessmemory (over multiple pages) +- memcpy +- pe data access +- fpu support +- mmx support +- find asm +- find memory +- mov [mem],#data#,size +- getremotestring +- function parameter +- isjumpgonnaexecute +- help file updates +- plugins +- scripting +- thread support +- tls callbacks +- inject dll +- dump memory +- dump process +- set pe data in memory +- va to offset +- offset to va +- getapiname +- float calculations +- command help +- inject asm code +- and or xor commands +- delete mem breakpoints +- delete hw breakpoints +- udd file format +- analysis +- symbol loader +- getlasterror +- display open handles +- log clear command +- build howto +- step to user code +- tracing(?) +- child processes (TitanEngine) +- display source +- patching +- handle view +- window view +- debug strings +- process privileges +- loaded modules +- strings +- references +- callstack +- stack +- heap +- functions +- TEB/TBI +- PEB/PBI +- debug pause +- cpu filename+thread id +- GetAddrInfo/SetAddrInfo +- shift+f7f8f9 +- restart (last process) +- log breakpoints \ No newline at end of file diff --git a/x64_dbg.sln b/x64_dbg.sln new file mode 100644 index 00000000..fe287546 --- /dev/null +++ b/x64_dbg.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "x64_dbg_bridge", "x64_dbg_bridge\x64_dbg_bridge.vcxproj", "{944D9923-CB1A-6F6C-BCBC-9E00A71954C1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "x64_dbg_exe", "x64_dbg_exe\x64_dbg_exe.vcxproj", "{3A22175E-6B72-FDCC-1603-C4A2163C7900}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "x64_dbg_dbg", "x64_dbg_dbg\x64_dbg_dbg.vcxproj", "{E6548308-401E-3A8A-5819-905DB90522A6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {944D9923-CB1A-6F6C-BCBC-9E00A71954C1}.Release|Win32.ActiveCfg = Release|Win32 + {944D9923-CB1A-6F6C-BCBC-9E00A71954C1}.Release|Win32.Build.0 = Release|Win32 + {944D9923-CB1A-6F6C-BCBC-9E00A71954C1}.Release|x64.ActiveCfg = Release|x64 + {944D9923-CB1A-6F6C-BCBC-9E00A71954C1}.Release|x64.Build.0 = Release|x64 + {3A22175E-6B72-FDCC-1603-C4A2163C7900}.Release|Win32.ActiveCfg = Release|Win32 + {3A22175E-6B72-FDCC-1603-C4A2163C7900}.Release|Win32.Build.0 = Release|Win32 + {3A22175E-6B72-FDCC-1603-C4A2163C7900}.Release|x64.ActiveCfg = Release|x64 + {3A22175E-6B72-FDCC-1603-C4A2163C7900}.Release|x64.Build.0 = Release|x64 + {E6548308-401E-3A8A-5819-905DB90522A6}.Release|Win32.ActiveCfg = Release|Win32 + {E6548308-401E-3A8A-5819-905DB90522A6}.Release|Win32.Build.0 = Release|Win32 + {E6548308-401E-3A8A-5819-905DB90522A6}.Release|x64.ActiveCfg = Release|x64 + {E6548308-401E-3A8A-5819-905DB90522A6}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/x64_dbg.workspace b/x64_dbg.workspace new file mode 100644 index 00000000..e48a355d --- /dev/null +++ b/x64_dbg.workspace @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/x64_dbg_bridge/_global.cpp b/x64_dbg_bridge/_global.cpp new file mode 100644 index 00000000..45beffbd --- /dev/null +++ b/x64_dbg_bridge/_global.cpp @@ -0,0 +1,29 @@ +#include "_global.h" + +//hInst GUI/DBG +HINSTANCE hInstGui; +HINSTANCE hInstDbg; + +//GUI functions +GUIGUIINIT _gui_guiinit; +GUIDISASSEMBLEAT _gui_disassembleat; +GUISETDEBUGSTATE _gui_setdebugstate; +GUIADDLOGMESSAGE _gui_addlogmessage; +GUILOGCLEAR _gui_logclear; +GUIUPDATEREGISTERVIEW _gui_updateregisterview; + +//DBG functions +DBGDBGINIT _dbg_dbginit; +DBGMEMFINDBASEADDR _dbg_memfindbaseaddr; +DBGMEMREAD _dbg_memread; +DBGDBGCMDEXEC _dbg_dbgcmdexec; +DBGMEMMAP _dbg_memmap; +DBGDBGEXITSIGNAL _dbg_dbgexitsignal; +DBGVALFROMSTRING _dbg_valfromstring; +DBGISDEBUGGING _dbg_isdebugging; +DBGISJUMPGOINGTOEXECUTE _dbg_isjumpgoingtoexecute; +DBGADDRINFOGET _dbg_addrinfoget; +DBGADDRINFOSET _dbg_addrinfoset; +DBGBPGETTYPEAT _dbg_bpgettypeat; +DBGGETREGDUMP _dbg_getregdump; +DBGVALTOSTRING _dbg_valtostring; diff --git a/x64_dbg_bridge/_global.h b/x64_dbg_bridge/_global.h new file mode 100644 index 00000000..a3025a27 --- /dev/null +++ b/x64_dbg_bridge/_global.h @@ -0,0 +1,78 @@ +#ifndef _GLOBAL_H +#define _GLOBAL_H + +#include +#include "bridgemain.h" + +#ifndef DLL_EXPORT +#define DLL_EXPORT __declspec(dllexport) +#endif //DLL_IMPORT +#ifndef DLL_EXPORT +#define DLL_IMPORT __declspec(dllimport) +#endif //DLL_IMPORT + +#ifdef _WIN64 //defined by default +#define fhex "%.16llX" +#define fext "ll" +#define uint unsigned long long +#define sint long long +#else +#define fhex "%.8X" +#define fext "" +#define uint unsigned long +#define sint long +#endif // _WIN64 + +//hInst GUI/DBG +extern HINSTANCE hInstGui; +extern HINSTANCE hInstDbg; + +//GUI typedefs +typedef int (*GUIGUIINIT)(int, char**); +typedef void (*GUIDISASSEMBLEAT)(duint va, duint cip); +typedef void (*GUISETDEBUGSTATE)(DBGSTATE state); +typedef void (*GUIADDLOGMESSAGE)(const char* msg); +typedef void (*GUILOGCLEAR)(); +typedef void (*GUIUPDATEREGISTERVIEW)(); + +//GUI functions +extern GUIGUIINIT _gui_guiinit; +extern GUIDISASSEMBLEAT _gui_disassembleat; +extern GUISETDEBUGSTATE _gui_setdebugstate; +extern GUIADDLOGMESSAGE _gui_addlogmessage; +extern GUILOGCLEAR _gui_logclear; +extern GUIUPDATEREGISTERVIEW _gui_updateregisterview; + +//DBG typedefs +typedef const char* (*DBGDBGINIT)(); +typedef duint (*DBGMEMFINDBASEADDR)(duint addr, duint* size); +typedef bool (*DBGMEMREAD)(duint addr, unsigned char* dest, duint size, duint* read); +typedef bool (*DBGDBGCMDEXEC)(const char* cmd); +typedef bool (*DBGMEMMAP)(MEMMAP* memmap); +typedef void (*DBGDBGEXITSIGNAL)(); +typedef bool (*DBGVALFROMSTRING)(const char* string, duint* value); +typedef bool (*DBGISDEBUGGING)(); +typedef bool (*DBGISJUMPGOINGTOEXECUTE)(duint addr); +typedef bool (*DBGADDRINFOGET)(duint addr, SEGMENTREG segment, ADDRINFO* addrinfo); +typedef bool (*DBGADDRINFOSET)(duint addr, ADDRINFO* addrinfo); +typedef BPXTYPE (*DBGBPGETTYPEAT)(duint addr); +typedef bool (*DBGGETREGDUMP)(REGDUMP* regdump); +typedef bool (*DBGVALTOSTRING)(const char* string, duint* value); + +//DBG functions +extern DBGDBGINIT _dbg_dbginit; +extern DBGMEMFINDBASEADDR _dbg_memfindbaseaddr; +extern DBGMEMREAD _dbg_memread; +extern DBGDBGCMDEXEC _dbg_dbgcmdexec; +extern DBGMEMMAP _dbg_memmap; +extern DBGDBGEXITSIGNAL _dbg_dbgexitsignal; +extern DBGVALFROMSTRING _dbg_valfromstring; +extern DBGISDEBUGGING _dbg_isdebugging; +extern DBGISJUMPGOINGTOEXECUTE _dbg_isjumpgoingtoexecute; +extern DBGADDRINFOGET _dbg_addrinfoget; +extern DBGADDRINFOSET _dbg_addrinfoset; +extern DBGBPGETTYPEAT _dbg_bpgettypeat; +extern DBGGETREGDUMP _dbg_getregdump; +extern DBGVALTOSTRING _dbg_valtostring; + +#endif // _GLOBAL_H diff --git a/x64_dbg_bridge/bridgemain.cpp b/x64_dbg_bridge/bridgemain.cpp new file mode 100644 index 00000000..54ad9364 --- /dev/null +++ b/x64_dbg_bridge/bridgemain.cpp @@ -0,0 +1,326 @@ +#include "_global.h" +#include "bridgemain.h" +#include + +static HINSTANCE hInst; + +#ifdef _WIN64 +#define dbg_lib "x64_dbg.dll" +#define gui_lib "x64_gui.dll" +#else +#define dbg_lib "x32_dbg.dll" +#define gui_lib "x32_gui.dll" +#endif // _WIN64 + +//Bridge +DLL_IMPEXP const char* BridgeInit() +{ + ///GUI Load + hInstGui=LoadLibraryA(gui_lib); //Sigma + if(!hInstGui) + return "Error loading GUI library ("gui_lib")!"; + //_gui_guiinit + _gui_guiinit=(GUIGUIINIT)GetProcAddress(hInstGui, "_gui_guiinit"); + if(!_gui_guiinit) + return "Export \"_gui_guiinit\" could not be found!"; + //_gui_disassembleat + _gui_disassembleat=(GUIDISASSEMBLEAT)GetProcAddress(hInstGui, "_gui_disassembleat"); + if(!_gui_disassembleat) + return "Export \"_gui_disassembleat\" could not be found!"; + //_gui_setdebugstate + _gui_setdebugstate=(GUISETDEBUGSTATE)GetProcAddress(hInstGui, "_gui_setdebugstate"); + if(!_gui_setdebugstate) + return "Export \"_gui_setdebugstate\" could not be found!"; + //_gui_addlogmessage + _gui_addlogmessage=(GUIADDLOGMESSAGE)GetProcAddress(hInstGui, "_gui_addlogmessage"); + if(!_gui_addlogmessage) + return "Export \"_gui_addlogmessage\" could not be found!"; + //_gui_logclear + _gui_logclear=(GUILOGCLEAR)GetProcAddress(hInstGui, "_gui_logclear"); + if(!_gui_logclear) + return "Export \"_gui_logclear\" could not be found!"; + //_gui_updateregisterview + _gui_updateregisterview=(GUIUPDATEREGISTERVIEW)GetProcAddress(hInstGui, "_gui_updateregisterview"); + if(!_gui_updateregisterview) + return "Export \"_gui_updateregisterview\" could not be found!"; + + ///DBG Load + hInstDbg=LoadLibraryA(dbg_lib); //Mr. eXoDia + if(!hInstDbg) + return "Error loading debugger library ("dbg_lib")!"; + //_dbg_dbginit + _dbg_dbginit=(DBGDBGINIT)GetProcAddress(hInstDbg, "_dbg_dbginit"); + if(!_dbg_dbginit) + return "Export \"_dbg_dbginit\" could not be found!"; + //_dbg_memfindbaseaddr + _dbg_memfindbaseaddr=(DBGMEMFINDBASEADDR)GetProcAddress(hInstDbg, "_dbg_memfindbaseaddr"); + if(!_dbg_memfindbaseaddr) + return "Export \"_dbg_memfindbaseaddr\" could not be found!"; + //_dbg_memfindbaseaddr + _dbg_memread=(DBGMEMREAD)GetProcAddress(hInstDbg, "_dbg_memread"); + if(!_dbg_memread) + return "Export \"_dbg_memread\" could not be found!"; + //_dbg_dbgcmdexec + _dbg_dbgcmdexec=(DBGDBGCMDEXEC)GetProcAddress(hInstDbg, "_dbg_dbgcmdexec"); + if(!_dbg_dbgcmdexec) + return "Export \"_dbg_dbgcmdexec\" could not be found!"; + //_dbg_memmap + _dbg_memmap=(DBGMEMMAP)GetProcAddress(hInstDbg, "_dbg_memmap"); + if(!_dbg_memmap) + return "Export \"_dbg_memmap\" could not be found!"; + //_dbg_dbgexitsignal + _dbg_dbgexitsignal=(DBGDBGEXITSIGNAL)GetProcAddress(hInstDbg, "_dbg_dbgexitsignal"); + if(!_dbg_dbgexitsignal) + return "Export \"_dbg_dbgexitsignal\" could not be found!"; + //_dbg_valfromstring + _dbg_valfromstring=(DBGVALFROMSTRING)GetProcAddress(hInstDbg, "_dbg_valfromstring"); + if(!_dbg_valfromstring) + return "Export \"_dbg_valfromstring\" could not be found!"; + //_dbg_isdebugging + _dbg_isdebugging=(DBGISDEBUGGING)GetProcAddress(hInstDbg, "_dbg_isdebugging"); + if(!_dbg_isdebugging) + return "Export \"_dbg_isdebugging\" could not be found!"; + //_dbg_isjumpgoingtoexecute + _dbg_isjumpgoingtoexecute=(DBGISJUMPGOINGTOEXECUTE)GetProcAddress(hInstDbg, "_dbg_isjumpgoingtoexecute"); + if(!_dbg_isjumpgoingtoexecute) + return "Export \"_dbg_isjumpgoingtoexecute\" could not be found!"; + //_dbg_addrinfoget + _dbg_addrinfoget=(DBGADDRINFOGET)GetProcAddress(hInstDbg, "_dbg_addrinfoget"); + if(!_dbg_addrinfoget) + return "Export \"_dbg_addrinfoget\" could not be found!"; + //_dbg_addrinfoset + _dbg_addrinfoset=(DBGADDRINFOSET)GetProcAddress(hInstDbg, "_dbg_addrinfoset"); + if(!_dbg_addrinfoset) + return "Export \"_dbg_addrinfoset\" could not be found!"; + //_dbg_bpgettypeat + _dbg_bpgettypeat=(DBGBPGETTYPEAT)GetProcAddress(hInstDbg, "_dbg_bpgettypeat"); + if(!_dbg_bpgettypeat) + return "Export \"_dbg_bpgettypeat\" could not be found!"; + //_dbg_getregdump + _dbg_getregdump=(DBGGETREGDUMP)GetProcAddress(hInstDbg, "_dbg_getregdump"); + if(!_dbg_getregdump) + return "Export \"_dbg_getregdump\" could not be found!"; + //_dbg_valtostring + _dbg_valtostring=(DBGVALTOSTRING)GetProcAddress(hInstDbg, "_dbg_valtostring"); + if(!_dbg_valtostring) + return "Export \"_dbg_valtostring\" could not be found!"; + return 0; +} + +DLL_IMPEXP const char* BridgeStart() +{ + if(!_dbg_dbginit || !_gui_guiinit) + return "\"_dbg_dbginit\" || \"_gui_guiinit\" was not loaded yet, call BridgeInit!"; + const char* errormsg=_dbg_dbginit(); + if(errormsg) + return errormsg; + _gui_guiinit(0, 0); //remove arguments + _dbg_dbgexitsignal(); //send exit signal to debugger + return 0; +} + +DLL_IMPEXP void* BridgeAlloc(size_t size) +{ + unsigned char* a= new unsigned char[size]; + if(!a) + { + MessageBoxA(0, "Could not allocate memory", "Error", MB_ICONERROR); + ExitProcess(1); + } + memset(a, 0, size); + return a; +} + +DLL_IMPEXP void BridgeFree(void* ptr) +{ + delete[] (unsigned char*)ptr; +} + +//Debugger +DLL_IMPEXP void DbgMemRead(duint va, unsigned char* dest, duint size) +{ + if(!_dbg_memread(va, dest, size, 0)) + memset(dest, 0x90, size); +} + +DLL_IMPEXP duint DbgMemGetPageSize(duint base) +{ + duint size=0; + _dbg_memfindbaseaddr(base, &size); + return size; +} + +DLL_IMPEXP duint DbgMemFindBaseAddr(duint addr, duint* size) +{ + return _dbg_memfindbaseaddr(addr, size); +} + +DLL_IMPEXP bool DbgCmdExec(const char* cmd) +{ + return _dbg_dbgcmdexec(cmd); +} + +DLL_IMPEXP bool DbgMemMap(MEMMAP* memmap) +{ + return _dbg_memmap(memmap); +} + +DLL_IMPEXP bool DbgIsValidExpression(const char* expression) +{ + duint value=0; + return _dbg_valfromstring(expression, &value); +} + +DLL_IMPEXP bool DbgIsDebugging() +{ + return _dbg_isdebugging(); +} + +DLL_IMPEXP bool DbgIsJumpGoingToExecute(duint addr) +{ + return _dbg_isjumpgoingtoexecute(addr); +} + +DLL_IMPEXP bool DbgGetLabelAt(duint addr, SEGMENTREG segment, char* text) //(module.)+label +{ + if(!text or !addr) + return false; + //test code (highlighting.exe|x32) + /*if(addr==0x40102b) + { + strcpy(text, "highlighting.retn"); + return true; + } + else if(addr==0x401020 || addr==0x401022) + { + strcpy(text, "highlighting.label"); + return true; + } + else if(addr==0x402000) + { + strcpy(text, "highlighting.dataLabel"); + return true; + }*/ + ADDRINFO info; + memset(&info, 0, sizeof(info)); + info.flags=label; + if(!_dbg_addrinfoget(addr, segment, &info)) + return false; + strcpy(text, info.label); + return true; +} + +DLL_IMPEXP bool DbgSetLabelAt(duint addr, const char* text) +{ + if(!text or strlen(text)>=MAX_LABEL_SIZE or !addr) + return false; + ADDRINFO info; + memset(&info, 0, sizeof(info)); + info.flags=label; + strcpy(info.label, text); + if(!_dbg_addrinfoset(addr, &info)) + return false; + return true; +} + +DLL_IMPEXP bool DbgGetCommentAt(duint addr, char* text) //comment (not live) +{ + if(!text or !addr) + return false; + //test code (highlighting.exe) + /*if(addr==0x401000) + { + strcpy(text, "test comment"); + return true; + }*/ + ADDRINFO info; + memset(&info, 0, sizeof(info)); + info.flags=comment; + if(!_dbg_addrinfoget(addr, SEG_DEFAULT, &info)) + return false; + strcpy(text, info.comment); + return true; +} + +DLL_IMPEXP bool DbgSetCommentAt(duint addr, const char* text) +{ + if(!text or strlen(text)>=MAX_COMMENT_SIZE or !addr) + return false; + ADDRINFO info; + memset(&info, 0, sizeof(info)); + info.flags=comment; + strcpy(info.comment, text); + if(!_dbg_addrinfoset(addr, &info)) + return false; + return true; +} + +DLL_IMPEXP bool DbgGetModuleAt(duint addr, char* text) +{ + if(!text or !addr) + return false; + ADDRINFO info; + memset(&info, 0, sizeof(info)); + info.flags=module; + if(!_dbg_addrinfoget(addr, SEG_DEFAULT, &info)) + return false; + strcpy(text, info.module); + return true; +} + +DLL_IMPEXP BPXTYPE DbgGetBpxTypeAt(duint addr) +{ + return _dbg_bpgettypeat(addr); +} + +DLL_IMPEXP duint DbgValFromString(const char* string) +{ + duint value=0; + _dbg_valfromstring(string, &value); + return value; +} + +DLL_IMPEXP bool DbgGetRegDump(REGDUMP* regdump) +{ + return _dbg_getregdump(regdump); +} + +DLL_IMPEXP bool DbgValToString(const char* string, duint value) +{ + duint valueCopy=value; + return _dbg_valtostring(string, &valueCopy); +} + +//GUI +DLL_IMPEXP void GuiDisasmAt(duint addr, duint cip) +{ + _gui_disassembleat(addr, cip); +} + +DLL_IMPEXP void GuiSetDebugState(DBGSTATE state) +{ + _gui_setdebugstate(state); +} + +DLL_IMPEXP void GuiAddLogMessage(const char* msg) +{ + _gui_addlogmessage(msg); +} + +DLL_IMPEXP void GuiLogClear() +{ + _gui_logclear(); +} + +DLL_IMPEXP void GuiUpdateRegisterView() +{ + _gui_updateregisterview(); +} + +//Main +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + hInst=hinstDLL; + return TRUE; +} + diff --git a/x64_dbg_bridge/bridgemain.h b/x64_dbg_bridge/bridgemain.h new file mode 100644 index 00000000..cfea0136 --- /dev/null +++ b/x64_dbg_bridge/bridgemain.h @@ -0,0 +1,173 @@ +#ifndef _BRIDGEMAIN_H_ +#define _BRIDGEMAIN_H_ + +#include + +#ifdef _WIN64 +typedef unsigned long long duint; +typedef signed long long dsint; +#else +typedef unsigned long duint; +typedef signed long dsint; +#endif //_WIN64 + +#ifndef DLL_IMPEXP +#ifdef BUILD_BRIDGE +#define DLL_IMPEXP __declspec(dllexport) +#else +#define DLL_IMPEXP __declspec(dllimport) +#endif //BUILD_BRIDGE +#endif //DLL_IMPEXP + +#ifdef __cplusplus +extern "C" +{ +#endif + +//Bridge functions +DLL_IMPEXP const char* BridgeInit(); +DLL_IMPEXP const char* BridgeStart(); +DLL_IMPEXP void* BridgeAlloc(size_t size); +DLL_IMPEXP void BridgeFree(void* ptr); + +//Debugger defines +#define MAX_LABEL_SIZE 256 +#define MAX_COMMENT_SIZE 256 + +//Debugger enums +enum DBGSTATE +{ + initialized, + paused, + running, + stopped +}; + +enum SEGMENTREG +{ + SEG_DEFAULT, + SEG_ES, + SEG_DS, + SEG_FS, + SEG_GS, + SEG_CS, + SEG_SS +}; + +enum ADDRINFOFLAGS +{ + module=1, + label=2, + comment=4 +}; + +enum BPXTYPE +{ + bpnone, + bpnormal, + bphardware, + bpmemory +}; + +//Debugger structs +struct MEMPAGE +{ + MEMORY_BASIC_INFORMATION mbi; + char mod[32]; +}; + +struct MEMMAP +{ + int count; + MEMPAGE* page; +}; + +struct ADDRINFO +{ + char module[32]; //module the address is in + char label[MAX_LABEL_SIZE]; + char comment[MAX_COMMENT_SIZE]; + int flags; //ADDRINFOFLAGS +}; + +struct FLAGS +{ + bool c; + bool p; + bool a; + bool z; + bool s; + bool t; + bool i; + bool d; + bool o; +}; + +struct REGDUMP +{ + duint cax; + duint ccx; + duint cdx; + duint cbx; + duint csp; + duint cbp; + duint csi; + duint cdi; +#ifdef _WIN64 + duint r8; + duint r9; + duint r10; + duint r11; + duint r12; + duint r13; + duint r14; + duint r15; +#endif //_WIN64 + duint cip; + unsigned int eflags; + FLAGS flags; + unsigned short gs; + unsigned short fs; + unsigned short es; + unsigned short ds; + unsigned short cs; + unsigned short ss; + duint dr0; + duint dr1; + duint dr2; + duint dr3; + duint dr6; + duint dr7; +}; + +//Debugger functions +DLL_IMPEXP void DbgMemRead(duint va, unsigned char* dest, duint size); +DLL_IMPEXP duint DbgMemGetPageSize(duint base); +DLL_IMPEXP duint DbgMemFindBaseAddr(duint addr, duint* size); +DLL_IMPEXP bool DbgCmdExec(const char* cmd); +DLL_IMPEXP bool DbgMemMap(MEMMAP* memmap); +DLL_IMPEXP bool DbgIsValidExpression(const char* expression); +DLL_IMPEXP bool DbgIsDebugging(); +DLL_IMPEXP bool DbgIsJumpGoingToExecute(duint addr); +DLL_IMPEXP bool DbgGetLabelAt(duint addr, SEGMENTREG segment, char* text); +DLL_IMPEXP bool DbgSetLabelAt(duint addr, const char* text); +DLL_IMPEXP bool DbgGetCommentAt(duint addr, char* text); +DLL_IMPEXP bool DbgSetCommentAt(duint addr, const char* text); +DLL_IMPEXP bool DbgGetModuleAt(duint addr, char* text); +DLL_IMPEXP BPXTYPE DbgGetBpxTypeAt(duint addr); +DLL_IMPEXP duint DbgValFromString(const char* string); +DLL_IMPEXP bool DbgGetRegDump(REGDUMP* regdump); +DLL_IMPEXP bool DbgValToString(const char* string, duint value); + +//GUI functions +DLL_IMPEXP void GuiDisasmAt(duint addr, duint cip); +DLL_IMPEXP void GuiSetDebugState(DBGSTATE state); +DLL_IMPEXP void GuiAddLogMessage(const char* msg); +DLL_IMPEXP void GuiLogClear(); +DLL_IMPEXP void GuiUpdateRegisterView(); + +#ifdef __cplusplus +} +#endif + +#endif // _BRIDGEMAIN_H_ diff --git a/x64_dbg_bridge/x64_dbg_bridge.cbp b/x64_dbg_bridge/x64_dbg_bridge.cbp new file mode 100644 index 00000000..1e1e1101 --- /dev/null +++ b/x64_dbg_bridge/x64_dbg_bridge.cbp @@ -0,0 +1,67 @@ + + + + + + diff --git a/x64_dbg_bridge/x64_dbg_bridge.vcxproj b/x64_dbg_bridge/x64_dbg_bridge.vcxproj new file mode 100644 index 00000000..acc272e4 --- /dev/null +++ b/x64_dbg_bridge/x64_dbg_bridge.vcxproj @@ -0,0 +1,86 @@ + + + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + Win32Proj + + + + DynamicLibrary + false + + + DynamicLibrary + false + + + + + + + + + + + + + true + $(SolutionDir)bin\x32 + $(Platform)\$(Configuration)\ + x32_bridge + + + true + $(SolutionDir)bin\x64 + x64_bridge + + + + BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + MachineX86 + true + Windows + true + true + + + + + BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + true + Windows + true + true + + + + + + \ No newline at end of file diff --git a/x64_dbg_bridge/x64_dbg_bridge.vcxproj.filters b/x64_dbg_bridge/x64_dbg_bridge.vcxproj.filters new file mode 100644 index 00000000..207b4174 --- /dev/null +++ b/x64_dbg_bridge/x64_dbg_bridge.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/x64_dbg_bridge/x64_dbg_bridge.vcxproj.user b/x64_dbg_bridge/x64_dbg_bridge.vcxproj.user new file mode 100644 index 00000000..695b5c78 --- /dev/null +++ b/x64_dbg_bridge/x64_dbg_bridge.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/x64_dbg_dbg/TitanEngine/TitanEngine.h b/x64_dbg_dbg/TitanEngine/TitanEngine.h new file mode 100644 index 00000000..43b1a753 --- /dev/null +++ b/x64_dbg_dbg/TitanEngine/TitanEngine.h @@ -0,0 +1,937 @@ +#ifndef TITANENGINE +#define TITANENGINE + +#define TITCALL + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +#pragma pack(push, 1) + +// Global.Constant.Structure.Declaration: +// Engine.External: +#define UE_ACCESS_READ 0 +#define UE_ACCESS_WRITE 1 +#define UE_ACCESS_ALL 2 + +#define UE_HIDE_BASIC 1 + +#define UE_PLUGIN_CALL_REASON_PREDEBUG 1 +#define UE_PLUGIN_CALL_REASON_EXCEPTION 2 +#define UE_PLUGIN_CALL_REASON_POSTDEBUG 3 + +#define TEE_HOOK_NRM_JUMP 1 +#define TEE_HOOK_NRM_CALL 3 +#define TEE_HOOK_IAT 5 + +#define UE_ENGINE_ALOW_MODULE_LOADING 1 +#define UE_ENGINE_AUTOFIX_FORWARDERS 2 +#define UE_ENGINE_PASS_ALL_EXCEPTIONS 3 +#define UE_ENGINE_NO_CONSOLE_WINDOW 4 +#define UE_ENGINE_BACKUP_FOR_CRITICAL_FUNCTIONS 5 +#define UE_ENGINE_CALL_PLUGIN_CALLBACK 6 +#define UE_ENGINE_RESET_CUSTOM_HANDLER 7 +#define UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK 8 + +#define UE_OPTION_REMOVEALL 1 +#define UE_OPTION_DISABLEALL 2 +#define UE_OPTION_REMOVEALLDISABLED 3 +#define UE_OPTION_REMOVEALLENABLED 4 + +#define UE_STATIC_DECRYPTOR_XOR 1 +#define UE_STATIC_DECRYPTOR_SUB 2 +#define UE_STATIC_DECRYPTOR_ADD 3 + +#define UE_STATIC_DECRYPTOR_FOREWARD 1 +#define UE_STATIC_DECRYPTOR_BACKWARD 2 + +#define UE_STATIC_KEY_SIZE_1 1 +#define UE_STATIC_KEY_SIZE_2 2 +#define UE_STATIC_KEY_SIZE_4 4 +#define UE_STATIC_KEY_SIZE_8 8 + +#define UE_STATIC_APLIB 1 +#define UE_STATIC_APLIB_DEPACK 2 +#define UE_STATIC_LZMA 3 + +#define UE_STATIC_HASH_MD5 1 +#define UE_STATIC_HASH_SHA1 2 +#define UE_STATIC_HASH_CRC32 3 + +#define UE_RESOURCE_LANGUAGE_ANY -1 + +#define UE_PE_OFFSET 0 +#define UE_IMAGEBASE 1 +#define UE_OEP 2 +#define UE_SIZEOFIMAGE 3 +#define UE_SIZEOFHEADERS 4 +#define UE_SIZEOFOPTIONALHEADER 5 +#define UE_SECTIONALIGNMENT 6 +#define UE_IMPORTTABLEADDRESS 7 +#define UE_IMPORTTABLESIZE 8 +#define UE_RESOURCETABLEADDRESS 9 +#define UE_RESOURCETABLESIZE 10 +#define UE_EXPORTTABLEADDRESS 11 +#define UE_EXPORTTABLESIZE 12 +#define UE_TLSTABLEADDRESS 13 +#define UE_TLSTABLESIZE 14 +#define UE_RELOCATIONTABLEADDRESS 15 +#define UE_RELOCATIONTABLESIZE 16 +#define UE_TIMEDATESTAMP 17 +#define UE_SECTIONNUMBER 18 +#define UE_CHECKSUM 19 +#define UE_SUBSYSTEM 20 +#define UE_CHARACTERISTICS 21 +#define UE_NUMBEROFRVAANDSIZES 22 +#define UE_SECTIONNAME 23 +#define UE_SECTIONVIRTUALOFFSET 24 +#define UE_SECTIONVIRTUALSIZE 25 +#define UE_SECTIONRAWOFFSET 26 +#define UE_SECTIONRAWSIZE 27 +#define UE_SECTIONFLAGS 28 + +#define UE_CH_BREAKPOINT 1 +#define UE_CH_SINGLESTEP 2 +#define UE_CH_ACCESSVIOLATION 3 +#define UE_CH_ILLEGALINSTRUCTION 4 +#define UE_CH_NONCONTINUABLEEXCEPTION 5 +#define UE_CH_ARRAYBOUNDSEXCEPTION 6 +#define UE_CH_FLOATDENORMALOPERAND 7 +#define UE_CH_FLOATDEVIDEBYZERO 8 +#define UE_CH_INTEGERDEVIDEBYZERO 9 +#define UE_CH_INTEGEROVERFLOW 10 +#define UE_CH_PRIVILEGEDINSTRUCTION 11 +#define UE_CH_PAGEGUARD 12 +#define UE_CH_EVERYTHINGELSE 13 +#define UE_CH_CREATETHREAD 14 +#define UE_CH_EXITTHREAD 15 +#define UE_CH_CREATEPROCESS 16 +#define UE_CH_EXITPROCESS 17 +#define UE_CH_LOADDLL 18 +#define UE_CH_UNLOADDLL 19 +#define UE_CH_OUTPUTDEBUGSTRING 20 +#define UE_CH_AFTEREXCEPTIONPROCESSING 21 +#define UE_CH_ALLEVENTS 22 +#define UE_CH_SYSTEMBREAKPOINT 23 +#define UE_CH_UNHANDLEDEXCEPTION 24 + +#define UE_OPTION_HANDLER_RETURN_HANDLECOUNT 1 +#define UE_OPTION_HANDLER_RETURN_ACCESS 2 +#define UE_OPTION_HANDLER_RETURN_FLAGS 3 +#define UE_OPTION_HANDLER_RETURN_TYPENAME 4 + +#define UE_BREAKPOINT_INT3 1 +#define UE_BREAKPOINT_LONG_INT3 2 +#define UE_BREAKPOINT_UD2 3 + +#define UE_BPXREMOVED 0 +#define UE_BPXACTIVE 1 +#define UE_BPXINACTIVE 2 + +#define UE_BREAKPOINT 0 +#define UE_SINGLESHOOT 1 +#define UE_HARDWARE 2 +#define UE_MEMORY 3 +#define UE_MEMORY_READ 4 +#define UE_MEMORY_WRITE 5 +#define UE_MEMORY_EXECUTE 6 +#define UE_BREAKPOINT_TYPE_INT3 0x10000000 +#define UE_BREAKPOINT_TYPE_LONG_INT3 0x20000000 +#define UE_BREAKPOINT_TYPE_UD2 0x30000000 + +#define UE_HARDWARE_EXECUTE 4 +#define UE_HARDWARE_WRITE 5 +#define UE_HARDWARE_READWRITE 6 + +#define UE_HARDWARE_SIZE_1 7 +#define UE_HARDWARE_SIZE_2 8 +#define UE_HARDWARE_SIZE_4 9 +#define UE_HARDWARE_SIZE_8 10 + +#define UE_ON_LIB_LOAD 1 +#define UE_ON_LIB_UNLOAD 2 +#define UE_ON_LIB_ALL 3 + +#define UE_APISTART 0 +#define UE_APIEND 1 + +#define UE_PLATFORM_x86 1 +#define UE_PLATFORM_x64 2 +#define UE_PLATFORM_ALL 3 + +#define UE_FUNCTION_STDCALL 1 +#define UE_FUNCTION_CCALL 2 +#define UE_FUNCTION_FASTCALL 3 +#define UE_FUNCTION_STDCALL_RET 4 +#define UE_FUNCTION_CCALL_RET 5 +#define UE_FUNCTION_FASTCALL_RET 6 +#define UE_FUNCTION_STDCALL_CALL 7 +#define UE_FUNCTION_CCALL_CALL 8 +#define UE_FUNCTION_FASTCALL_CALL 9 +#define UE_PARAMETER_BYTE 0 +#define UE_PARAMETER_WORD 1 +#define UE_PARAMETER_DWORD 2 +#define UE_PARAMETER_QWORD 3 +#define UE_PARAMETER_PTR_BYTE 4 +#define UE_PARAMETER_PTR_WORD 5 +#define UE_PARAMETER_PTR_DWORD 6 +#define UE_PARAMETER_PTR_QWORD 7 +#define UE_PARAMETER_STRING 8 +#define UE_PARAMETER_UNICODE 9 + +#define UE_CMP_NOCONDITION 0 +#define UE_CMP_EQUAL 1 +#define UE_CMP_NOTEQUAL 2 +#define UE_CMP_GREATER 3 +#define UE_CMP_GREATEROREQUAL 4 +#define UE_CMP_LOWER 5 +#define UE_CMP_LOWEROREQUAL 6 +#define UE_CMP_REG_EQUAL 7 +#define UE_CMP_REG_NOTEQUAL 8 +#define UE_CMP_REG_GREATER 9 +#define UE_CMP_REG_GREATEROREQUAL 10 +#define UE_CMP_REG_LOWER 11 +#define UE_CMP_REG_LOWEROREQUAL 12 +#define UE_CMP_ALWAYSFALSE 13 + +#define UE_EAX 1 +#define UE_EBX 2 +#define UE_ECX 3 +#define UE_EDX 4 +#define UE_EDI 5 +#define UE_ESI 6 +#define UE_EBP 7 +#define UE_ESP 8 +#define UE_EIP 9 +#define UE_EFLAGS 10 +#define UE_DR0 11 +#define UE_DR1 12 +#define UE_DR2 13 +#define UE_DR3 14 +#define UE_DR6 15 +#define UE_DR7 16 +#define UE_RAX 17 +#define UE_RBX 18 +#define UE_RCX 19 +#define UE_RDX 20 +#define UE_RDI 21 +#define UE_RSI 22 +#define UE_RBP 23 +#define UE_RSP 24 +#define UE_RIP 25 +#define UE_RFLAGS 26 +#define UE_R8 27 +#define UE_R9 28 +#define UE_R10 29 +#define UE_R11 30 +#define UE_R12 31 +#define UE_R13 32 +#define UE_R14 33 +#define UE_R15 34 +#define UE_CIP 35 +#define UE_CSP 36 +#ifdef _WIN64 +#define UE_CFLAGS UE_RFLAGS +#else +#define UE_CFLAGS UE_EFLAGS +#endif +#define UE_SEG_GS 37 +#define UE_SEG_FS 38 +#define UE_SEG_ES 39 +#define UE_SEG_DS 40 +#define UE_SEG_CS 41 +#define UE_SEG_SS 42 + +typedef struct +{ + DWORD PE32Offset; + DWORD ImageBase; + DWORD OriginalEntryPoint; + DWORD NtSizeOfImage; + DWORD NtSizeOfHeaders; + WORD SizeOfOptionalHeaders; + DWORD FileAlignment; + DWORD SectionAligment; + DWORD ImportTableAddress; + DWORD ImportTableSize; + DWORD ResourceTableAddress; + DWORD ResourceTableSize; + DWORD ExportTableAddress; + DWORD ExportTableSize; + DWORD TLSTableAddress; + DWORD TLSTableSize; + DWORD RelocationTableAddress; + DWORD RelocationTableSize; + DWORD TimeDateStamp; + WORD SectionNumber; + DWORD CheckSum; + WORD SubSystem; + WORD Characteristics; + DWORD NumberOfRvaAndSizes; +} PE32Struct, *PPE32Struct; + +typedef struct +{ + DWORD PE64Offset; + DWORD64 ImageBase; + DWORD OriginalEntryPoint; + DWORD NtSizeOfImage; + DWORD NtSizeOfHeaders; + WORD SizeOfOptionalHeaders; + DWORD FileAlignment; + DWORD SectionAligment; + DWORD ImportTableAddress; + DWORD ImportTableSize; + DWORD ResourceTableAddress; + DWORD ResourceTableSize; + DWORD ExportTableAddress; + DWORD ExportTableSize; + DWORD TLSTableAddress; + DWORD TLSTableSize; + DWORD RelocationTableAddress; + DWORD RelocationTableSize; + DWORD TimeDateStamp; + WORD SectionNumber; + DWORD CheckSum; + WORD SubSystem; + WORD Characteristics; + DWORD NumberOfRvaAndSizes; +} PE64Struct, *PPE64Struct; + +typedef struct +{ + bool NewDll; + int NumberOfImports; + ULONG_PTR ImageBase; + ULONG_PTR BaseImportThunk; + ULONG_PTR ImportThunk; + char* APIName; + char* DLLName; +} ImportEnumData, *PImportEnumData; + +typedef struct +{ + HANDLE hThread; + DWORD dwThreadId; + void* ThreadStartAddress; + void* ThreadLocalBase; +} THREAD_ITEM_DATA, *PTHREAD_ITEM_DATA; + +typedef struct +{ + HANDLE hFile; + void* BaseOfDll; + HANDLE hFileMapping; + void* hFileMappingView; + char szLibraryPath[MAX_PATH]; + char szLibraryName[MAX_PATH]; +} LIBRARY_ITEM_DATA, *PLIBRARY_ITEM_DATA; + +typedef struct +{ + HANDLE hFile; + void* BaseOfDll; + HANDLE hFileMapping; + void* hFileMappingView; + wchar_t szLibraryPath[MAX_PATH]; + wchar_t szLibraryName[MAX_PATH]; +} LIBRARY_ITEM_DATAW, *PLIBRARY_ITEM_DATAW; + +typedef struct +{ + HANDLE hProcess; + DWORD dwProcessId; + HANDLE hThread; + DWORD dwThreadId; + HANDLE hFile; + void* BaseOfImage; + void* ThreadStartAddress; + void* ThreadLocalBase; +} PROCESS_ITEM_DATA, *PPROCESS_ITEM_DATA; + +typedef struct +{ + ULONG ProcessId; + HANDLE hHandle; +} HandlerArray, *PHandlerArray; + +typedef struct +{ + char PluginName[64]; + DWORD PluginMajorVersion; + DWORD PluginMinorVersion; + HMODULE PluginBaseAddress; + void* TitanDebuggingCallBack; + void* TitanRegisterPlugin; + void* TitanReleasePlugin; + void* TitanResetPlugin; + bool PluginDisabled; +} PluginInformation, *PPluginInformation; + +#define TEE_MAXIMUM_HOOK_SIZE 14 +#define TEE_MAXIMUM_HOOK_RELOCS 7 +#if defined(_WIN64) +#define TEE_MAXIMUM_HOOK_INSERT_SIZE 14 +#else +#define TEE_MAXIMUM_HOOK_INSERT_SIZE 5 +#endif + +typedef struct HOOK_ENTRY +{ + bool IATHook; + BYTE HookType; + DWORD HookSize; + void* HookAddress; + void* RedirectionAddress; + BYTE HookBytes[TEE_MAXIMUM_HOOK_SIZE]; + BYTE OriginalBytes[TEE_MAXIMUM_HOOK_SIZE]; + void* IATHookModuleBase; + DWORD IATHookNameHash; + bool HookIsEnabled; + bool HookIsRemote; + void* PatchedEntry; + DWORD RelocationInfo[TEE_MAXIMUM_HOOK_RELOCS]; + int RelocationCount; +} HOOK_ENTRY, *PHOOK_ENTRY; + +#define UE_DEPTH_SURFACE 0 +#define UE_DEPTH_DEEP 1 + +#define UE_UNPACKER_CONDITION_SEARCH_FROM_EP 1 + +#define UE_UNPACKER_CONDITION_LOADLIBRARY 1 +#define UE_UNPACKER_CONDITION_GETPROCADDRESS 2 +#define UE_UNPACKER_CONDITION_ENTRYPOINTBREAK 3 +#define UE_UNPACKER_CONDITION_RELOCSNAPSHOT1 4 +#define UE_UNPACKER_CONDITION_RELOCSNAPSHOT2 5 + +#define UE_FIELD_OK 0 +#define UE_FIELD_BROKEN_NON_FIXABLE 1 +#define UE_FIELD_BROKEN_NON_CRITICAL 2 +#define UE_FIELD_BROKEN_FIXABLE_FOR_STATIC_USE 3 +#define UE_FIELD_BROKEN_BUT_CAN_BE_EMULATED 4 +#define UE_FILED_FIXABLE_NON_CRITICAL 5 +#define UE_FILED_FIXABLE_CRITICAL 6 +#define UE_FIELD_NOT_PRESET 7 +#define UE_FIELD_NOT_PRESET_WARNING 8 + +#define UE_RESULT_FILE_OK 10 +#define UE_RESULT_FILE_INVALID_BUT_FIXABLE 11 +#define UE_RESULT_FILE_INVALID_AND_NON_FIXABLE 12 +#define UE_RESULT_FILE_INVALID_FORMAT 13 + +typedef struct +{ + BYTE OveralEvaluation; + bool EvaluationTerminatedByException; + bool FileIs64Bit; + bool FileIsDLL; + bool FileIsConsole; + bool MissingDependencies; + bool MissingDeclaredAPIs; + BYTE SignatureMZ; + BYTE SignaturePE; + BYTE EntryPoint; + BYTE ImageBase; + BYTE SizeOfImage; + BYTE FileAlignment; + BYTE SectionAlignment; + BYTE ExportTable; + BYTE RelocationTable; + BYTE ImportTable; + BYTE ImportTableSection; + BYTE ImportTableData; + BYTE IATTable; + BYTE TLSTable; + BYTE LoadConfigTable; + BYTE BoundImportTable; + BYTE COMHeaderTable; + BYTE ResourceTable; + BYTE ResourceData; + BYTE SectionTable; +} FILE_STATUS_INFO, *PFILE_STATUS_INFO; + +typedef struct +{ + BYTE OveralEvaluation; + bool FixingTerminatedByException; + bool FileFixPerformed; + bool StrippedRelocation; + bool DontFixRelocations; + DWORD OriginalRelocationTableAddress; + DWORD OriginalRelocationTableSize; + bool StrippedExports; + bool DontFixExports; + DWORD OriginalExportTableAddress; + DWORD OriginalExportTableSize; + bool StrippedResources; + bool DontFixResources; + DWORD OriginalResourceTableAddress; + DWORD OriginalResourceTableSize; + bool StrippedTLS; + bool DontFixTLS; + DWORD OriginalTLSTableAddress; + DWORD OriginalTLSTableSize; + bool StrippedLoadConfig; + bool DontFixLoadConfig; + DWORD OriginalLoadConfigTableAddress; + DWORD OriginalLoadConfigTableSize; + bool StrippedBoundImports; + bool DontFixBoundImports; + DWORD OriginalBoundImportTableAddress; + DWORD OriginalBoundImportTableSize; + bool StrippedIAT; + bool DontFixIAT; + DWORD OriginalImportAddressTableAddress; + DWORD OriginalImportAddressTableSize; + bool StrippedCOM; + bool DontFixCOM; + DWORD OriginalCOMTableAddress; + DWORD OriginalCOMTableSize; +} FILE_FIX_INFO, *PFILE_FIX_INFO; + +#ifdef __cplusplus +extern "C" +{ +#endif + +// Global.Function.Declaration: +// TitanEngine.Dumper.functions: +__declspec(dllexport) bool TITCALL DumpProcess(HANDLE hProcess, LPVOID ImageBase, char* szDumpFileName, ULONG_PTR EntryPoint); +__declspec(dllexport) bool TITCALL DumpProcessW(HANDLE hProcess, LPVOID ImageBase, wchar_t* szDumpFileName, ULONG_PTR EntryPoint); +__declspec(dllexport) bool TITCALL DumpProcessEx(DWORD ProcessId, LPVOID ImageBase, char* szDumpFileName, ULONG_PTR EntryPoint); +__declspec(dllexport) bool TITCALL DumpProcessExW(DWORD ProcessId, LPVOID ImageBase, wchar_t* szDumpFileName, ULONG_PTR EntryPoint); +__declspec(dllexport) bool TITCALL DumpMemory(HANDLE hProcess, LPVOID MemoryStart, ULONG_PTR MemorySize, char* szDumpFileName); +__declspec(dllexport) bool TITCALL DumpMemoryW(HANDLE hProcess, LPVOID MemoryStart, ULONG_PTR MemorySize, wchar_t* szDumpFileName); +__declspec(dllexport) bool TITCALL DumpMemoryEx(DWORD ProcessId, LPVOID MemoryStart, ULONG_PTR MemorySize, char* szDumpFileName); +__declspec(dllexport) bool TITCALL DumpMemoryExW(DWORD ProcessId, LPVOID MemoryStart, ULONG_PTR MemorySize, wchar_t* szDumpFileName); +__declspec(dllexport) bool TITCALL DumpRegions(HANDLE hProcess, char* szDumpFolder, bool DumpAboveImageBaseOnly); +__declspec(dllexport) bool TITCALL DumpRegionsW(HANDLE hProcess, wchar_t* szDumpFolder, bool DumpAboveImageBaseOnly); +__declspec(dllexport) bool TITCALL DumpRegionsEx(DWORD ProcessId, char* szDumpFolder, bool DumpAboveImageBaseOnly); +__declspec(dllexport) bool TITCALL DumpRegionsExW(DWORD ProcessId, wchar_t* szDumpFolder, bool DumpAboveImageBaseOnly); +__declspec(dllexport) bool TITCALL DumpModule(HANDLE hProcess, LPVOID ModuleBase, char* szDumpFileName); +__declspec(dllexport) bool TITCALL DumpModuleW(HANDLE hProcess, LPVOID ModuleBase, wchar_t* szDumpFileName); +__declspec(dllexport) bool TITCALL DumpModuleEx(DWORD ProcessId, LPVOID ModuleBase, char* szDumpFileName); +__declspec(dllexport) bool TITCALL DumpModuleExW(DWORD ProcessId, LPVOID ModuleBase, wchar_t* szDumpFileName); +__declspec(dllexport) bool TITCALL PastePEHeader(HANDLE hProcess, LPVOID ImageBase, char* szDebuggedFileName); +__declspec(dllexport) bool TITCALL PastePEHeaderW(HANDLE hProcess, LPVOID ImageBase, wchar_t* szDebuggedFileName); +__declspec(dllexport) bool TITCALL ExtractSection(char* szFileName, char* szDumpFileName, DWORD SectionNumber); +__declspec(dllexport) bool TITCALL ExtractSectionW(wchar_t* szFileName, wchar_t* szDumpFileName, DWORD SectionNumber); +__declspec(dllexport) bool TITCALL ResortFileSections(char* szFileName); +__declspec(dllexport) bool TITCALL ResortFileSectionsW(wchar_t* szFileName); +__declspec(dllexport) bool TITCALL FindOverlay(char* szFileName, LPDWORD OverlayStart, LPDWORD OverlaySize); +__declspec(dllexport) bool TITCALL FindOverlayW(wchar_t* szFileName, LPDWORD OverlayStart, LPDWORD OverlaySize); +__declspec(dllexport) bool TITCALL ExtractOverlay(char* szFileName, char* szExtactedFileName); +__declspec(dllexport) bool TITCALL ExtractOverlayW(wchar_t* szFileName, wchar_t* szExtactedFileName); +__declspec(dllexport) bool TITCALL AddOverlay(char* szFileName, char* szOverlayFileName); +__declspec(dllexport) bool TITCALL AddOverlayW(wchar_t* szFileName, wchar_t* szOverlayFileName); +__declspec(dllexport) bool TITCALL CopyOverlay(char* szInFileName, char* szOutFileName); +__declspec(dllexport) bool TITCALL CopyOverlayW(wchar_t* szInFileName, wchar_t* szOutFileName); +__declspec(dllexport) bool TITCALL RemoveOverlay(char* szFileName); +__declspec(dllexport) bool TITCALL RemoveOverlayW(wchar_t* szFileName); +__declspec(dllexport) bool TITCALL MakeAllSectionsRWE(char* szFileName); +__declspec(dllexport) bool TITCALL MakeAllSectionsRWEW(wchar_t* szFileName); +__declspec(dllexport) long TITCALL AddNewSectionEx(char* szFileName, char* szSectionName, DWORD SectionSize, DWORD SectionAttributes, LPVOID SectionContent, DWORD ContentSize); +__declspec(dllexport) long TITCALL AddNewSectionExW(wchar_t* szFileName, char* szSectionName, DWORD SectionSize, DWORD SectionAttributes, LPVOID SectionContent, DWORD ContentSize); +__declspec(dllexport) long TITCALL AddNewSection(char* szFileName, char* szSectionName, DWORD SectionSize); +__declspec(dllexport) long TITCALL AddNewSectionW(wchar_t* szFileName, char* szSectionName, DWORD SectionSize); +__declspec(dllexport) bool TITCALL ResizeLastSection(char* szFileName, DWORD NumberOfExpandBytes, bool AlignResizeData); +__declspec(dllexport) bool TITCALL ResizeLastSectionW(wchar_t* szFileName, DWORD NumberOfExpandBytes, bool AlignResizeData); +__declspec(dllexport) void TITCALL SetSharedOverlay(char* szFileName); +__declspec(dllexport) void TITCALL SetSharedOverlayW(wchar_t* szFileName); +__declspec(dllexport) char* TITCALL GetSharedOverlay(); +__declspec(dllexport) wchar_t* TITCALL GetSharedOverlayW(); +__declspec(dllexport) bool TITCALL DeleteLastSection(char* szFileName); +__declspec(dllexport) bool TITCALL DeleteLastSectionW(wchar_t* szFileName); +__declspec(dllexport) bool TITCALL DeleteLastSectionEx(char* szFileName, DWORD NumberOfSections); +__declspec(dllexport) bool TITCALL DeleteLastSectionExW(wchar_t* szFileName, DWORD NumberOfSections); +__declspec(dllexport) long long TITCALL GetPE32DataFromMappedFile(ULONG_PTR FileMapVA, DWORD WhichSection, DWORD WhichData); +__declspec(dllexport) long long TITCALL GetPE32Data(char* szFileName, DWORD WhichSection, DWORD WhichData); +__declspec(dllexport) long long TITCALL GetPE32DataW(wchar_t* szFileName, DWORD WhichSection, DWORD WhichData); +__declspec(dllexport) bool TITCALL GetPE32DataFromMappedFileEx(ULONG_PTR FileMapVA, LPVOID DataStorage); +__declspec(dllexport) bool TITCALL GetPE32DataEx(char* szFileName, LPVOID DataStorage); +__declspec(dllexport) bool TITCALL GetPE32DataExW(wchar_t* szFileName, LPVOID DataStorage); +__declspec(dllexport) bool TITCALL SetPE32DataForMappedFile(ULONG_PTR FileMapVA, DWORD WhichSection, DWORD WhichData, ULONG_PTR NewDataValue); +__declspec(dllexport) bool TITCALL SetPE32Data(char* szFileName, DWORD WhichSection, DWORD WhichData, ULONG_PTR NewDataValue); +__declspec(dllexport) bool TITCALL SetPE32DataW(wchar_t* szFileName, DWORD WhichSection, DWORD WhichData, ULONG_PTR NewDataValue); +__declspec(dllexport) bool TITCALL SetPE32DataForMappedFileEx(ULONG_PTR FileMapVA, LPVOID DataStorage); +__declspec(dllexport) bool TITCALL SetPE32DataEx(char* szFileName, LPVOID DataStorage); +__declspec(dllexport) bool TITCALL SetPE32DataExW(wchar_t* szFileName, LPVOID DataStorage); +__declspec(dllexport) long TITCALL GetPE32SectionNumberFromVA(ULONG_PTR FileMapVA, ULONG_PTR AddressToConvert); +__declspec(dllexport) long long TITCALL ConvertVAtoFileOffset(ULONG_PTR FileMapVA, ULONG_PTR AddressToConvert, bool ReturnType); +__declspec(dllexport) long long TITCALL ConvertVAtoFileOffsetEx(ULONG_PTR FileMapVA, DWORD FileSize, ULONG_PTR ImageBase, ULONG_PTR AddressToConvert, bool AddressIsRVA, bool ReturnType); +__declspec(dllexport) long long TITCALL ConvertFileOffsetToVA(ULONG_PTR FileMapVA, ULONG_PTR AddressToConvert, bool ReturnType); +__declspec(dllexport) long long TITCALL ConvertFileOffsetToVAEx(ULONG_PTR FileMapVA, DWORD FileSize, ULONG_PTR ImageBase, ULONG_PTR AddressToConvert, bool ReturnType); +// TitanEngine.Realigner.functions: +__declspec(dllexport) bool TITCALL FixHeaderCheckSum(char* szFileName); +__declspec(dllexport) bool TITCALL FixHeaderCheckSumW(wchar_t* szFileName); +__declspec(dllexport) long TITCALL RealignPE(ULONG_PTR FileMapVA, DWORD FileSize, DWORD RealingMode); +__declspec(dllexport) long TITCALL RealignPEEx(char* szFileName, DWORD RealingFileSize, DWORD ForcedFileAlignment); +__declspec(dllexport) long TITCALL RealignPEExW(wchar_t* szFileName, DWORD RealingFileSize, DWORD ForcedFileAlignment); +__declspec(dllexport) bool TITCALL WipeSection(char* szFileName, int WipeSectionNumber, bool RemovePhysically); +__declspec(dllexport) bool TITCALL WipeSectionW(wchar_t* szFileName, int WipeSectionNumber, bool RemovePhysically); +__declspec(dllexport) bool TITCALL IsPE32FileValidEx(char* szFileName, DWORD CheckDepth, LPVOID FileStatusInfo); +__declspec(dllexport) bool TITCALL IsPE32FileValidExW(wchar_t* szFileName, DWORD CheckDepth, LPVOID FileStatusInfo); +__declspec(dllexport) bool TITCALL FixBrokenPE32FileEx(char* szFileName, LPVOID FileStatusInfo, LPVOID FileFixInfo); +__declspec(dllexport) bool TITCALL FixBrokenPE32FileExW(wchar_t* szFileName, LPVOID FileStatusInfo, LPVOID FileFixInfo); +__declspec(dllexport) bool TITCALL IsFileDLL(char* szFileName, ULONG_PTR FileMapVA); +__declspec(dllexport) bool TITCALL IsFileDLLW(wchar_t* szFileName, ULONG_PTR FileMapVA); +// TitanEngine.Hider.functions: +__declspec(dllexport) void* TITCALL GetPEBLocation(HANDLE hProcess); +__declspec(dllexport) bool TITCALL HideDebugger(HANDLE hProcess, DWORD PatchAPILevel); +__declspec(dllexport) bool TITCALL UnHideDebugger(HANDLE hProcess, DWORD PatchAPILevel); +// TitanEngine.Relocater.functions: +__declspec(dllexport) void TITCALL RelocaterCleanup(); +__declspec(dllexport) void TITCALL RelocaterInit(DWORD MemorySize, ULONG_PTR OldImageBase, ULONG_PTR NewImageBase); +__declspec(dllexport) void TITCALL RelocaterAddNewRelocation(HANDLE hProcess, ULONG_PTR RelocateAddress, DWORD RelocateState); +__declspec(dllexport) long TITCALL RelocaterEstimatedSize(); +__declspec(dllexport) bool TITCALL RelocaterExportRelocation(ULONG_PTR StorePlace, DWORD StorePlaceRVA, ULONG_PTR FileMapVA); +__declspec(dllexport) bool TITCALL RelocaterExportRelocationEx(char* szFileName, char* szSectionName); +__declspec(dllexport) bool TITCALL RelocaterExportRelocationExW(wchar_t* szFileName, char* szSectionName); +__declspec(dllexport) bool TITCALL RelocaterGrabRelocationTable(HANDLE hProcess, ULONG_PTR MemoryStart, DWORD MemorySize); +__declspec(dllexport) bool TITCALL RelocaterGrabRelocationTableEx(HANDLE hProcess, ULONG_PTR MemoryStart, ULONG_PTR MemorySize, DWORD NtSizeOfImage); +__declspec(dllexport) bool TITCALL RelocaterMakeSnapshot(HANDLE hProcess, char* szSaveFileName, LPVOID MemoryStart, ULONG_PTR MemorySize); +__declspec(dllexport) bool TITCALL RelocaterMakeSnapshotW(HANDLE hProcess, wchar_t* szSaveFileName, LPVOID MemoryStart, ULONG_PTR MemorySize); +__declspec(dllexport) bool TITCALL RelocaterCompareTwoSnapshots(HANDLE hProcess, ULONG_PTR LoadedImageBase, ULONG_PTR NtSizeOfImage, char* szDumpFile1, char* szDumpFile2, ULONG_PTR MemStart); +__declspec(dllexport) bool TITCALL RelocaterCompareTwoSnapshotsW(HANDLE hProcess, ULONG_PTR LoadedImageBase, ULONG_PTR NtSizeOfImage, wchar_t* szDumpFile1, wchar_t* szDumpFile2, ULONG_PTR MemStart); +__declspec(dllexport) bool TITCALL RelocaterChangeFileBase(char* szFileName, ULONG_PTR NewImageBase); +__declspec(dllexport) bool TITCALL RelocaterChangeFileBaseW(wchar_t* szFileName, ULONG_PTR NewImageBase); +__declspec(dllexport) bool TITCALL RelocaterRelocateMemoryBlock(ULONG_PTR FileMapVA, ULONG_PTR MemoryLocation, void* RelocateMemory, DWORD RelocateMemorySize, ULONG_PTR CurrentLoadedBase, ULONG_PTR RelocateBase); +__declspec(dllexport) bool TITCALL RelocaterWipeRelocationTable(char* szFileName); +__declspec(dllexport) bool TITCALL RelocaterWipeRelocationTableW(wchar_t* szFileName); +// TitanEngine.Resourcer.functions: +__declspec(dllexport) long long TITCALL ResourcerLoadFileForResourceUse(char* szFileName); +__declspec(dllexport) long long TITCALL ResourcerLoadFileForResourceUseW(wchar_t* szFileName); +__declspec(dllexport) bool TITCALL ResourcerFreeLoadedFile(LPVOID LoadedFileBase); +__declspec(dllexport) bool TITCALL ResourcerExtractResourceFromFileEx(ULONG_PTR FileMapVA, char* szResourceType, char* szResourceName, char* szExtractedFileName); +__declspec(dllexport) bool TITCALL ResourcerExtractResourceFromFile(char* szFileName, char* szResourceType, char* szResourceName, char* szExtractedFileName); +__declspec(dllexport) bool TITCALL ResourcerExtractResourceFromFileW(wchar_t* szFileName, char* szResourceType, char* szResourceName, char* szExtractedFileName); +__declspec(dllexport) bool TITCALL ResourcerFindResource(char* szFileName, char* szResourceType, DWORD ResourceType, char* szResourceName, DWORD ResourceName, DWORD ResourceLanguage, PULONG_PTR pResourceData, LPDWORD pResourceSize); +__declspec(dllexport) bool TITCALL ResourcerFindResourceW(wchar_t* szFileName, wchar_t* szResourceType, DWORD ResourceType, wchar_t* szResourceName, DWORD ResourceName, DWORD ResourceLanguage, PULONG_PTR pResourceData, LPDWORD pResourceSize); +__declspec(dllexport) bool TITCALL ResourcerFindResourceEx(ULONG_PTR FileMapVA, DWORD FileSize, wchar_t* szResourceType, DWORD ResourceType, wchar_t* szResourceName, DWORD ResourceName, DWORD ResourceLanguage, PULONG_PTR pResourceData, LPDWORD pResourceSize); +__declspec(dllexport) void TITCALL ResourcerEnumerateResource(char* szFileName, void* CallBack); +__declspec(dllexport) void TITCALL ResourcerEnumerateResourceW(wchar_t* szFileName, void* CallBack); +__declspec(dllexport) void TITCALL ResourcerEnumerateResourceEx(ULONG_PTR FileMapVA, DWORD FileSize, void* CallBack); +// TitanEngine.Threader.functions: +__declspec(dllexport) bool TITCALL ThreaderImportRunningThreadData(DWORD ProcessId); +__declspec(dllexport) void* TITCALL ThreaderGetThreadInfo(HANDLE hThread, DWORD ThreadId); +__declspec(dllexport) void TITCALL ThreaderEnumThreadInfo(void* EnumCallBack); +__declspec(dllexport) bool TITCALL ThreaderPauseThread(HANDLE hThread); +__declspec(dllexport) bool TITCALL ThreaderResumeThread(HANDLE hThread); +__declspec(dllexport) bool TITCALL ThreaderTerminateThread(HANDLE hThread, DWORD ThreadExitCode); +__declspec(dllexport) bool TITCALL ThreaderPauseAllThreads(bool LeaveMainRunning); +__declspec(dllexport) bool TITCALL ThreaderResumeAllThreads(bool LeaveMainPaused); +__declspec(dllexport) bool TITCALL ThreaderPauseProcess(); +__declspec(dllexport) bool TITCALL ThreaderResumeProcess(); +__declspec(dllexport) long long TITCALL ThreaderCreateRemoteThread(ULONG_PTR ThreadStartAddress, bool AutoCloseTheHandle, LPVOID ThreadPassParameter, LPDWORD ThreadId); +__declspec(dllexport) bool TITCALL ThreaderInjectAndExecuteCode(LPVOID InjectCode, DWORD StartDelta, DWORD InjectSize); +__declspec(dllexport) long long TITCALL ThreaderCreateRemoteThreadEx(HANDLE hProcess, ULONG_PTR ThreadStartAddress, bool AutoCloseTheHandle, LPVOID ThreadPassParameter, LPDWORD ThreadId); +__declspec(dllexport) bool TITCALL ThreaderInjectAndExecuteCodeEx(HANDLE hProcess, LPVOID InjectCode, DWORD StartDelta, DWORD InjectSize); +__declspec(dllexport) void TITCALL ThreaderSetCallBackForNextExitThreadEvent(LPVOID exitThreadCallBack); +__declspec(dllexport) bool TITCALL ThreaderIsThreadStillRunning(HANDLE hThread); +__declspec(dllexport) bool TITCALL ThreaderIsThreadActive(HANDLE hThread); +__declspec(dllexport) bool TITCALL ThreaderIsAnyThreadActive(); +__declspec(dllexport) bool TITCALL ThreaderExecuteOnlyInjectedThreads(); +__declspec(dllexport) long long TITCALL ThreaderGetOpenHandleForThread(DWORD ThreadId); +__declspec(dllexport) void* TITCALL ThreaderGetThreadData(); +__declspec(dllexport) bool TITCALL ThreaderIsExceptionInMainThread(); +// TitanEngine.Debugger.functions: +__declspec(dllexport) void* TITCALL StaticDisassembleEx(ULONG_PTR DisassmStart, LPVOID DisassmAddress); +__declspec(dllexport) void* TITCALL StaticDisassemble(LPVOID DisassmAddress); +__declspec(dllexport) void* TITCALL DisassembleEx(HANDLE hProcess, LPVOID DisassmAddress, bool ReturnInstructionType); +__declspec(dllexport) void* TITCALL Disassemble(LPVOID DisassmAddress); +__declspec(dllexport) long TITCALL StaticLengthDisassemble(LPVOID DisassmAddress); +__declspec(dllexport) long TITCALL LengthDisassembleEx(HANDLE hProcess, LPVOID DisassmAddress); +__declspec(dllexport) long TITCALL LengthDisassemble(LPVOID DisassmAddress); +__declspec(dllexport) void* TITCALL InitDebug(char* szFileName, char* szCommandLine, char* szCurrentFolder); +__declspec(dllexport) void* TITCALL InitDebugW(wchar_t* szFileName, wchar_t* szCommandLine, wchar_t* szCurrentFolder); +__declspec(dllexport) void* TITCALL InitDebugEx(char* szFileName, char* szCommandLine, char* szCurrentFolder, LPVOID EntryCallBack); +__declspec(dllexport) void* TITCALL InitDebugExW(wchar_t* szFileName, wchar_t* szCommandLine, wchar_t* szCurrentFolder, LPVOID EntryCallBack); +__declspec(dllexport) void* TITCALL InitDLLDebug(char* szFileName, bool ReserveModuleBase, char* szCommandLine, char* szCurrentFolder, LPVOID EntryCallBack); +__declspec(dllexport) void* TITCALL InitDLLDebugW(wchar_t* szFileName, bool ReserveModuleBase, wchar_t* szCommandLine, wchar_t* szCurrentFolder, LPVOID EntryCallBack); +__declspec(dllexport) bool TITCALL StopDebug(); +__declspec(dllexport) void TITCALL SetBPXOptions(long DefaultBreakPointType); +__declspec(dllexport) bool TITCALL IsBPXEnabled(ULONG_PTR bpxAddress); +__declspec(dllexport) bool TITCALL EnableBPX(ULONG_PTR bpxAddress); +__declspec(dllexport) bool TITCALL DisableBPX(ULONG_PTR bpxAddress); +__declspec(dllexport) bool TITCALL SetBPX(ULONG_PTR bpxAddress, DWORD bpxType, LPVOID bpxCallBack); +__declspec(dllexport) bool TITCALL SetBPXEx(ULONG_PTR bpxAddress, DWORD bpxType, DWORD NumberOfExecution, DWORD CmpRegister, DWORD CmpCondition, ULONG_PTR CmpValue, LPVOID bpxCallBack, LPVOID bpxCompareCallBack, LPVOID bpxRemoveCallBack); +__declspec(dllexport) bool TITCALL DeleteBPX(ULONG_PTR bpxAddress); +__declspec(dllexport) bool TITCALL SafeDeleteBPX(ULONG_PTR bpxAddress); +__declspec(dllexport) bool TITCALL SetAPIBreakPoint(char* szDLLName, char* szAPIName, DWORD bpxType, DWORD bpxPlace, LPVOID bpxCallBack); +__declspec(dllexport) bool TITCALL DeleteAPIBreakPoint(char* szDLLName, char* szAPIName, DWORD bpxPlace); +__declspec(dllexport) bool TITCALL SafeDeleteAPIBreakPoint(char* szDLLName, char* szAPIName, DWORD bpxPlace); +__declspec(dllexport) bool TITCALL SetMemoryBPX(ULONG_PTR MemoryStart, DWORD SizeOfMemory, LPVOID bpxCallBack); +__declspec(dllexport) bool TITCALL SetMemoryBPXEx(ULONG_PTR MemoryStart, DWORD SizeOfMemory, DWORD BreakPointType, bool RestoreOnHit, LPVOID bpxCallBack); +__declspec(dllexport) bool TITCALL RemoveMemoryBPX(ULONG_PTR MemoryStart, DWORD SizeOfMemory); +__declspec(dllexport) bool TITCALL GetContextFPUDataEx(HANDLE hActiveThread, void* FPUSaveArea); +__declspec(dllexport) long long TITCALL GetContextDataEx(HANDLE hActiveThread, DWORD IndexOfRegister); +__declspec(dllexport) long long TITCALL GetContextData(DWORD IndexOfRegister); +__declspec(dllexport) bool TITCALL SetContextFPUDataEx(HANDLE hActiveThread, void* FPUSaveArea); +__declspec(dllexport) bool TITCALL SetContextDataEx(HANDLE hActiveThread, DWORD IndexOfRegister, ULONG_PTR NewRegisterValue); +__declspec(dllexport) bool TITCALL SetContextData(DWORD IndexOfRegister, ULONG_PTR NewRegisterValue); +__declspec(dllexport) void TITCALL ClearExceptionNumber(); +__declspec(dllexport) long TITCALL CurrentExceptionNumber(); +__declspec(dllexport) bool TITCALL MatchPatternEx(HANDLE hProcess, void* MemoryToCheck, int SizeOfMemoryToCheck, void* PatternToMatch, int SizeOfPatternToMatch, PBYTE WildCard); +__declspec(dllexport) bool TITCALL MatchPattern(void* MemoryToCheck, int SizeOfMemoryToCheck, void* PatternToMatch, int SizeOfPatternToMatch, PBYTE WildCard); +__declspec(dllexport) long long TITCALL FindEx(HANDLE hProcess, LPVOID MemoryStart, DWORD MemorySize, LPVOID SearchPattern, DWORD PatternSize, LPBYTE WildCard); +extern "C" __declspec(dllexport) long long TITCALL Find(LPVOID MemoryStart, DWORD MemorySize, LPVOID SearchPattern, DWORD PatternSize, LPBYTE WildCard); +__declspec(dllexport) bool TITCALL FillEx(HANDLE hProcess, LPVOID MemoryStart, DWORD MemorySize, PBYTE FillByte); +__declspec(dllexport) bool TITCALL Fill(LPVOID MemoryStart, DWORD MemorySize, PBYTE FillByte); +__declspec(dllexport) bool TITCALL PatchEx(HANDLE hProcess, LPVOID MemoryStart, DWORD MemorySize, LPVOID ReplacePattern, DWORD ReplaceSize, bool AppendNOP, bool PrependNOP); +__declspec(dllexport) bool TITCALL Patch(LPVOID MemoryStart, DWORD MemorySize, LPVOID ReplacePattern, DWORD ReplaceSize, bool AppendNOP, bool PrependNOP); +__declspec(dllexport) bool TITCALL ReplaceEx(HANDLE hProcess, LPVOID MemoryStart, DWORD MemorySize, LPVOID SearchPattern, DWORD PatternSize, DWORD NumberOfRepetitions, LPVOID ReplacePattern, DWORD ReplaceSize, PBYTE WildCard); +__declspec(dllexport) bool TITCALL Replace(LPVOID MemoryStart, DWORD MemorySize, LPVOID SearchPattern, DWORD PatternSize, DWORD NumberOfRepetitions, LPVOID ReplacePattern, DWORD ReplaceSize, PBYTE WildCard); +__declspec(dllexport) void* TITCALL GetDebugData(); +__declspec(dllexport) void* TITCALL GetTerminationData(); +__declspec(dllexport) long TITCALL GetExitCode(); +__declspec(dllexport) long long TITCALL GetDebuggedDLLBaseAddress(); +__declspec(dllexport) unsigned long long TITCALL GetDebuggedFileBaseAddress(); +__declspec(dllexport) bool TITCALL GetRemoteString(HANDLE hProcess, LPVOID StringAddress, LPVOID StringStorage, int MaximumStringSize); +__declspec(dllexport) long long TITCALL GetFunctionParameter(HANDLE hProcess, DWORD FunctionType, DWORD ParameterNumber, DWORD ParameterType); +__declspec(dllexport) long long TITCALL GetJumpDestinationEx(HANDLE hProcess, ULONG_PTR InstructionAddress, bool JustJumps); +__declspec(dllexport) long long TITCALL GetJumpDestination(HANDLE hProcess, ULONG_PTR InstructionAddress); +__declspec(dllexport) bool TITCALL IsJumpGoingToExecuteEx(HANDLE hProcess, HANDLE hThread, ULONG_PTR InstructionAddress, ULONG_PTR RegFlags); +__declspec(dllexport) bool TITCALL IsJumpGoingToExecute(); +__declspec(dllexport) void TITCALL SetCustomHandler(DWORD ExceptionId, LPVOID CallBack); +__declspec(dllexport) void TITCALL ForceClose(); +__declspec(dllexport) void TITCALL StepInto(LPVOID traceCallBack); +__declspec(dllexport) void TITCALL StepOver(LPVOID traceCallBack); +__declspec(dllexport) void TITCALL SingleStep(DWORD StepCount, LPVOID StepCallBack); +__declspec(dllexport) bool TITCALL GetUnusedHardwareBreakPointRegister(LPDWORD RegisterIndex); +__declspec(dllexport) bool TITCALL SetHardwareBreakPointEx(HANDLE hActiveThread, ULONG_PTR bpxAddress, DWORD IndexOfRegister, DWORD bpxType, DWORD bpxSize, LPVOID bpxCallBack, LPDWORD IndexOfSelectedRegister); +__declspec(dllexport) bool TITCALL SetHardwareBreakPoint(ULONG_PTR bpxAddress, DWORD IndexOfRegister, DWORD bpxType, DWORD bpxSize, LPVOID bpxCallBack); +__declspec(dllexport) bool TITCALL DeleteHardwareBreakPoint(DWORD IndexOfRegister); +__declspec(dllexport) bool TITCALL RemoveAllBreakPoints(DWORD RemoveOption); +__declspec(dllexport) void* TITCALL GetProcessInformation(); +__declspec(dllexport) void* TITCALL GetStartupInformation(); +__declspec(dllexport) void TITCALL DebugLoop(); +__declspec(dllexport) void TITCALL SetDebugLoopTimeOut(DWORD TimeOut); +__declspec(dllexport) void TITCALL SetNextDbgContinueStatus(DWORD SetDbgCode); +__declspec(dllexport) bool TITCALL AttachDebugger(DWORD ProcessId, bool KillOnExit, LPVOID DebugInfo, LPVOID CallBack); +__declspec(dllexport) bool TITCALL DetachDebugger(DWORD ProcessId); +__declspec(dllexport) bool TITCALL DetachDebuggerEx(DWORD ProcessId); +__declspec(dllexport) void TITCALL DebugLoopEx(DWORD TimeOut); +__declspec(dllexport) void TITCALL AutoDebugEx(char* szFileName, bool ReserveModuleBase, char* szCommandLine, char* szCurrentFolder, DWORD TimeOut, LPVOID EntryCallBack); +__declspec(dllexport) void TITCALL AutoDebugExW(wchar_t* szFileName, bool ReserveModuleBase, wchar_t* szCommandLine, wchar_t* szCurrentFolder, DWORD TimeOut, LPVOID EntryCallBack); +__declspec(dllexport) bool TITCALL IsFileBeingDebugged(); +__declspec(dllexport) void TITCALL SetErrorModel(bool DisplayErrorMessages); +// TitanEngine.FindOEP.functions: +__declspec(dllexport) void TITCALL FindOEPInit(); +__declspec(dllexport) bool TITCALL FindOEPGenerically(char* szFileName, LPVOID TraceInitCallBack, LPVOID CallBack); +__declspec(dllexport) bool TITCALL FindOEPGenericallyW(wchar_t* szFileName, LPVOID TraceInitCallBack, LPVOID CallBack); +// TitanEngine.Importer.functions: +__declspec(dllexport) void TITCALL ImporterCleanup(); +__declspec(dllexport) void TITCALL ImporterSetImageBase(ULONG_PTR ImageBase); +__declspec(dllexport) void TITCALL ImporterSetUnknownDelta(ULONG_PTR DeltaAddress); +__declspec(dllexport) long long TITCALL ImporterGetCurrentDelta(); +__declspec(dllexport) void TITCALL ImporterInit(DWORD MemorySize, ULONG_PTR ImageBase); +__declspec(dllexport) void TITCALL ImporterAddNewDll(char* szDLLName, ULONG_PTR FirstThunk); +__declspec(dllexport) void TITCALL ImporterAddNewAPI(char* szAPIName, ULONG_PTR ThunkValue); +__declspec(dllexport) void TITCALL ImporterAddNewOrdinalAPI(ULONG_PTR OrdinalNumber, ULONG_PTR ThunkValue); +__declspec(dllexport) long TITCALL ImporterGetAddedDllCount(); +__declspec(dllexport) long TITCALL ImporterGetAddedAPICount(); +__declspec(dllexport) void* TITCALL ImporterGetLastAddedDLLName(); +__declspec(dllexport) void TITCALL ImporterMoveIAT(); +__declspec(dllexport) bool TITCALL ImporterExportIAT(ULONG_PTR StorePlace, ULONG_PTR FileMapVA); +__declspec(dllexport) long TITCALL ImporterEstimatedSize(); +__declspec(dllexport) bool TITCALL ImporterExportIATEx(char* szExportFileName, char* szSectionName); +__declspec(dllexport) bool TITCALL ImporterExportIATExW(wchar_t* szExportFileName, char* szSectionName); +__declspec(dllexport) long long TITCALL ImporterFindAPIWriteLocation(char* szAPIName); +__declspec(dllexport) long long TITCALL ImporterFindOrdinalAPIWriteLocation(ULONG_PTR OrdinalNumber); +__declspec(dllexport) long long TITCALL ImporterFindAPIByWriteLocation(ULONG_PTR APIWriteLocation); +__declspec(dllexport) long long TITCALL ImporterFindDLLByWriteLocation(ULONG_PTR APIWriteLocation); +__declspec(dllexport) void* TITCALL ImporterGetDLLName(ULONG_PTR APIAddress); +__declspec(dllexport) void* TITCALL ImporterGetAPIName(ULONG_PTR APIAddress); +__declspec(dllexport) long long TITCALL ImporterGetAPIOrdinalNumber(ULONG_PTR APIAddress); +__declspec(dllexport) void* TITCALL ImporterGetAPINameEx(ULONG_PTR APIAddress, ULONG_PTR DLLBasesList); +__declspec(dllexport) long long TITCALL ImporterGetRemoteAPIAddress(HANDLE hProcess, ULONG_PTR APIAddress); +__declspec(dllexport) long long TITCALL ImporterGetRemoteAPIAddressEx(char* szDLLName, char* szAPIName); +__declspec(dllexport) long long TITCALL ImporterGetLocalAPIAddress(HANDLE hProcess, ULONG_PTR APIAddress); +__declspec(dllexport) void* TITCALL ImporterGetDLLNameFromDebugee(HANDLE hProcess, ULONG_PTR APIAddress); +__declspec(dllexport) void* TITCALL ImporterGetAPINameFromDebugee(HANDLE hProcess, ULONG_PTR APIAddress); +__declspec(dllexport) long long TITCALL ImporterGetAPIOrdinalNumberFromDebugee(HANDLE hProcess, ULONG_PTR APIAddress); +__declspec(dllexport) long TITCALL ImporterGetDLLIndexEx(ULONG_PTR APIAddress, ULONG_PTR DLLBasesList); +__declspec(dllexport) long TITCALL ImporterGetDLLIndex(HANDLE hProcess, ULONG_PTR APIAddress, ULONG_PTR DLLBasesList); +__declspec(dllexport) long long TITCALL ImporterGetRemoteDLLBase(HANDLE hProcess, HMODULE LocalModuleBase); +__declspec(dllexport) long long TITCALL ImporterGetRemoteDLLBaseEx(HANDLE hProcess, char* szModuleName); +__declspec(dllexport) bool TITCALL ImporterRelocateWriteLocation(ULONG_PTR AddValue); +__declspec(dllexport) bool TITCALL ImporterIsForwardedAPI(HANDLE hProcess, ULONG_PTR APIAddress); +__declspec(dllexport) void* TITCALL ImporterGetForwardedAPIName(HANDLE hProcess, ULONG_PTR APIAddress); +__declspec(dllexport) void* TITCALL ImporterGetForwardedDLLName(HANDLE hProcess, ULONG_PTR APIAddress); +__declspec(dllexport) long TITCALL ImporterGetForwardedDLLIndex(HANDLE hProcess, ULONG_PTR APIAddress, ULONG_PTR DLLBasesList); +__declspec(dllexport) long long TITCALL ImporterGetForwardedAPIOrdinalNumber(HANDLE hProcess, ULONG_PTR APIAddress); +__declspec(dllexport) long long TITCALL ImporterGetNearestAPIAddress(HANDLE hProcess, ULONG_PTR APIAddress); +__declspec(dllexport) void* TITCALL ImporterGetNearestAPIName(HANDLE hProcess, ULONG_PTR APIAddress); +__declspec(dllexport) bool TITCALL ImporterCopyOriginalIAT(char* szOriginalFile, char* szDumpFile); +__declspec(dllexport) bool TITCALL ImporterCopyOriginalIATW(wchar_t* szOriginalFile, wchar_t* szDumpFile); +__declspec(dllexport) bool TITCALL ImporterLoadImportTable(char* szFileName); +__declspec(dllexport) bool TITCALL ImporterLoadImportTableW(wchar_t* szFileName); +__declspec(dllexport) bool TITCALL ImporterMoveOriginalIAT(char* szOriginalFile, char* szDumpFile, char* szSectionName); +__declspec(dllexport) bool TITCALL ImporterMoveOriginalIATW(wchar_t* szOriginalFile, wchar_t* szDumpFile, char* szSectionName); +__declspec(dllexport) void TITCALL ImporterAutoSearchIAT(HANDLE hProcess, char* szFileName, ULONG_PTR ImageBase, ULONG_PTR SearchStart, DWORD SearchSize, LPVOID pIATStart, LPVOID pIATSize); +__declspec(dllexport) void TITCALL ImporterAutoSearchIATW(HANDLE hProcess, wchar_t* szFileName, ULONG_PTR ImageBase, ULONG_PTR SearchStart, DWORD SearchSize, LPVOID pIATStart, LPVOID pIATSize); +__declspec(dllexport) void TITCALL ImporterAutoSearchIATEx(HANDLE hProcess, ULONG_PTR ImageBase, ULONG_PTR SearchStart, DWORD SearchSize, LPVOID pIATStart, LPVOID pIATSize); +__declspec(dllexport) void TITCALL ImporterEnumAddedData(LPVOID EnumCallBack); +__declspec(dllexport) long TITCALL ImporterAutoFixIATEx(HANDLE hProcess, char* szDumpedFile, char* szSectionName, bool DumpRunningProcess, bool RealignFile, ULONG_PTR EntryPointAddress, ULONG_PTR ImageBase, ULONG_PTR SearchStart, DWORD SearchSize, DWORD SearchStep, bool TryAutoFix, bool FixEliminations, LPVOID UnknownPointerFixCallback); +__declspec(dllexport) long TITCALL ImporterAutoFixIATExW(HANDLE hProcess, wchar_t* szDumpedFile, char* szSectionName, bool DumpRunningProcess, bool RealignFile, ULONG_PTR EntryPointAddress, ULONG_PTR ImageBase, ULONG_PTR SearchStart, DWORD SearchSize, DWORD SearchStep, bool TryAutoFix, bool FixEliminations, LPVOID UnknownPointerFixCallback); +__declspec(dllexport) long TITCALL ImporterAutoFixIAT(HANDLE hProcess, char* szDumpedFile, ULONG_PTR ImageBase, ULONG_PTR SearchStart, DWORD SearchSize, DWORD SearchStep); +__declspec(dllexport) long TITCALL ImporterAutoFixIATW(HANDLE hProcess, wchar_t* szDumpedFile, ULONG_PTR ImageBase, ULONG_PTR SearchStart, DWORD SearchSize, DWORD SearchStep); +// Global.Engine.Hook.functions: +__declspec(dllexport) bool TITCALL HooksSafeTransitionEx(LPVOID HookAddressArray, int NumberOfHooks, bool TransitionStart); +__declspec(dllexport) bool TITCALL HooksSafeTransition(LPVOID HookAddress, bool TransitionStart); +__declspec(dllexport) bool TITCALL HooksIsAddressRedirected(LPVOID HookAddress); +__declspec(dllexport) void* TITCALL HooksGetTrampolineAddress(LPVOID HookAddress); +__declspec(dllexport) void* TITCALL HooksGetHookEntryDetails(LPVOID HookAddress); +__declspec(dllexport) bool TITCALL HooksInsertNewRedirection(LPVOID HookAddress, LPVOID RedirectTo, int HookType); +__declspec(dllexport) bool TITCALL HooksInsertNewIATRedirectionEx(ULONG_PTR FileMapVA, ULONG_PTR LoadedModuleBase, char* szHookFunction, LPVOID RedirectTo); +__declspec(dllexport) bool TITCALL HooksInsertNewIATRedirection(char* szModuleName, char* szHookFunction, LPVOID RedirectTo); +__declspec(dllexport) bool TITCALL HooksRemoveRedirection(LPVOID HookAddress, bool RemoveAll); +__declspec(dllexport) bool TITCALL HooksRemoveRedirectionsForModule(HMODULE ModuleBase); +__declspec(dllexport) bool TITCALL HooksRemoveIATRedirection(char* szModuleName, char* szHookFunction, bool RemoveAll); +__declspec(dllexport) bool TITCALL HooksDisableRedirection(LPVOID HookAddress, bool DisableAll); +__declspec(dllexport) bool TITCALL HooksDisableRedirectionsForModule(HMODULE ModuleBase); +__declspec(dllexport) bool TITCALL HooksDisableIATRedirection(char* szModuleName, char* szHookFunction, bool DisableAll); +__declspec(dllexport) bool TITCALL HooksEnableRedirection(LPVOID HookAddress, bool EnableAll); +__declspec(dllexport) bool TITCALL HooksEnableRedirectionsForModule(HMODULE ModuleBase); +__declspec(dllexport) bool TITCALL HooksEnableIATRedirection(char* szModuleName, char* szHookFunction, bool EnableAll); +__declspec(dllexport) void TITCALL HooksScanModuleMemory(HMODULE ModuleBase, LPVOID CallBack); +__declspec(dllexport) void TITCALL HooksScanEntireProcessMemory(LPVOID CallBack); +__declspec(dllexport) void TITCALL HooksScanEntireProcessMemoryEx(); +// TitanEngine.Tracer.functions: +__declspec(dllexport) void TITCALL TracerInit(); +__declspec(dllexport) long long TITCALL TracerLevel1(HANDLE hProcess, ULONG_PTR AddressToTrace); +__declspec(dllexport) long long TITCALL HashTracerLevel1(HANDLE hProcess, ULONG_PTR AddressToTrace, DWORD InputNumberOfInstructions); +__declspec(dllexport) long TITCALL TracerDetectRedirection(HANDLE hProcess, ULONG_PTR AddressToTrace); +__declspec(dllexport) long long TITCALL TracerFixKnownRedirection(HANDLE hProcess, ULONG_PTR AddressToTrace, DWORD RedirectionId); +__declspec(dllexport) long long TITCALL TracerFixRedirectionViaModule(HMODULE hModuleHandle, HANDLE hProcess, ULONG_PTR AddressToTrace, DWORD IdParameter); +__declspec(dllexport) long TITCALL TracerFixRedirectionViaImpRecPlugin(HANDLE hProcess, char* szPluginName, ULONG_PTR AddressToTrace); +// TitanEngine.Exporter.functions: +__declspec(dllexport) void TITCALL ExporterCleanup(); +__declspec(dllexport) void TITCALL ExporterSetImageBase(ULONG_PTR ImageBase); +__declspec(dllexport) void TITCALL ExporterInit(DWORD MemorySize, ULONG_PTR ImageBase, DWORD ExportOrdinalBase, char* szExportModuleName); +__declspec(dllexport) bool TITCALL ExporterAddNewExport(char* szExportName, DWORD ExportRelativeAddress); +__declspec(dllexport) bool TITCALL ExporterAddNewOrdinalExport(DWORD OrdinalNumber, DWORD ExportRelativeAddress); +__declspec(dllexport) long TITCALL ExporterGetAddedExportCount(); +__declspec(dllexport) long TITCALL ExporterEstimatedSize(); +__declspec(dllexport) bool TITCALL ExporterBuildExportTable(ULONG_PTR StorePlace, ULONG_PTR FileMapVA); +__declspec(dllexport) bool TITCALL ExporterBuildExportTableEx(char* szExportFileName, char* szSectionName); +__declspec(dllexport) bool TITCALL ExporterBuildExportTableExW(wchar_t* szExportFileName, char* szSectionName); +__declspec(dllexport) bool TITCALL ExporterLoadExportTable(char* szFileName); +__declspec(dllexport) bool TITCALL ExporterLoadExportTableW(wchar_t* szFileName); +// TitanEngine.Librarian.functions: +__declspec(dllexport) bool TITCALL LibrarianSetBreakPoint(char* szLibraryName, DWORD bpxType, bool SingleShoot, LPVOID bpxCallBack); +__declspec(dllexport) bool TITCALL LibrarianRemoveBreakPoint(char* szLibraryName, DWORD bpxType); +__declspec(dllexport) void* TITCALL LibrarianGetLibraryInfo(char* szLibraryName); +__declspec(dllexport) void* TITCALL LibrarianGetLibraryInfoW(wchar_t* szLibraryName); +__declspec(dllexport) void* TITCALL LibrarianGetLibraryInfoEx(void* BaseOfDll); +__declspec(dllexport) void* TITCALL LibrarianGetLibraryInfoExW(void* BaseOfDll); +__declspec(dllexport) void TITCALL LibrarianEnumLibraryInfo(void* EnumCallBack); +__declspec(dllexport) void TITCALL LibrarianEnumLibraryInfoW(void* EnumCallBack); +// TitanEngine.Process.functions: +__declspec(dllexport) long TITCALL GetActiveProcessId(char* szImageName); +__declspec(dllexport) long TITCALL GetActiveProcessIdW(wchar_t* szImageName); +__declspec(dllexport) void TITCALL EnumProcessesWithLibrary(char* szLibraryName, void* EnumFunction); +// TitanEngine.TLSFixer.functions: +__declspec(dllexport) bool TITCALL TLSBreakOnCallBack(LPVOID ArrayOfCallBacks, DWORD NumberOfCallBacks, LPVOID bpxCallBack); +__declspec(dllexport) bool TITCALL TLSGrabCallBackData(char* szFileName, LPVOID ArrayOfCallBacks, LPDWORD NumberOfCallBacks); +__declspec(dllexport) bool TITCALL TLSGrabCallBackDataW(wchar_t* szFileName, LPVOID ArrayOfCallBacks, LPDWORD NumberOfCallBacks); +__declspec(dllexport) bool TITCALL TLSBreakOnCallBackEx(char* szFileName, LPVOID bpxCallBack); +__declspec(dllexport) bool TITCALL TLSBreakOnCallBackExW(wchar_t* szFileName, LPVOID bpxCallBack); +__declspec(dllexport) bool TITCALL TLSRemoveCallback(char* szFileName); +__declspec(dllexport) bool TITCALL TLSRemoveCallbackW(wchar_t* szFileName); +__declspec(dllexport) bool TITCALL TLSRemoveTable(char* szFileName); +__declspec(dllexport) bool TITCALL TLSRemoveTableW(wchar_t* szFileName); +__declspec(dllexport) bool TITCALL TLSBackupData(char* szFileName); +__declspec(dllexport) bool TITCALL TLSBackupDataW(wchar_t* szFileName); +__declspec(dllexport) bool TITCALL TLSRestoreData(); +__declspec(dllexport) bool TITCALL TLSBuildNewTable(ULONG_PTR FileMapVA, ULONG_PTR StorePlace, ULONG_PTR StorePlaceRVA, LPVOID ArrayOfCallBacks, DWORD NumberOfCallBacks); +__declspec(dllexport) bool TITCALL TLSBuildNewTableEx(char* szFileName, char* szSectionName, LPVOID ArrayOfCallBacks, DWORD NumberOfCallBacks); +__declspec(dllexport) bool TITCALL TLSBuildNewTableExW(wchar_t* szFileName, char* szSectionName, LPVOID ArrayOfCallBacks, DWORD NumberOfCallBacks); +// TitanEngine.TranslateName.functions: +__declspec(dllexport) void* TITCALL TranslateNativeName(char* szNativeName); +__declspec(dllexport) void* TITCALL TranslateNativeNameW(wchar_t* szNativeName); +// TitanEngine.Handler.functions: +__declspec(dllexport) long TITCALL HandlerGetActiveHandleCount(DWORD ProcessId); +__declspec(dllexport) bool TITCALL HandlerIsHandleOpen(DWORD ProcessId, HANDLE hHandle); +__declspec(dllexport) void* TITCALL HandlerGetHandleName(HANDLE hProcess, DWORD ProcessId, HANDLE hHandle, bool TranslateName); +__declspec(dllexport) void* TITCALL HandlerGetHandleNameW(HANDLE hProcess, DWORD ProcessId, HANDLE hHandle, bool TranslateName); +__declspec(dllexport) long TITCALL HandlerEnumerateOpenHandles(DWORD ProcessId, LPVOID HandleBuffer, DWORD MaxHandleCount); +__declspec(dllexport) long long TITCALL HandlerGetHandleDetails(HANDLE hProcess, DWORD ProcessId, HANDLE hHandle, DWORD InformationReturn); +__declspec(dllexport) bool TITCALL HandlerCloseRemoteHandle(HANDLE hProcess, HANDLE hHandle); +__declspec(dllexport) long TITCALL HandlerEnumerateLockHandles(char* szFileOrFolderName, bool NameIsFolder, bool NameIsTranslated, LPVOID HandleDataBuffer, DWORD MaxHandleCount); +__declspec(dllexport) long TITCALL HandlerEnumerateLockHandlesW(wchar_t* szFileOrFolderName, bool NameIsFolder, bool NameIsTranslated, LPVOID HandleDataBuffer, DWORD MaxHandleCount); +__declspec(dllexport) bool TITCALL HandlerCloseAllLockHandles(char* szFileOrFolderName, bool NameIsFolder, bool NameIsTranslated); +__declspec(dllexport) bool TITCALL HandlerCloseAllLockHandlesW(wchar_t* szFileOrFolderName, bool NameIsFolder, bool NameIsTranslated); +__declspec(dllexport) bool TITCALL HandlerIsFileLocked(char* szFileOrFolderName, bool NameIsFolder, bool NameIsTranslated); +__declspec(dllexport) bool TITCALL HandlerIsFileLockedW(wchar_t* szFileOrFolderName, bool NameIsFolder, bool NameIsTranslated); +// TitanEngine.Handler[Mutex].functions: +__declspec(dllexport) long TITCALL HandlerEnumerateOpenMutexes(HANDLE hProcess, DWORD ProcessId, LPVOID HandleBuffer, DWORD MaxHandleCount); +__declspec(dllexport) long long TITCALL HandlerGetOpenMutexHandle(HANDLE hProcess, DWORD ProcessId, char* szMutexString); +__declspec(dllexport) long long TITCALL HandlerGetOpenMutexHandleW(HANDLE hProcess, DWORD ProcessId, wchar_t* szMutexString); +__declspec(dllexport) long TITCALL HandlerGetProcessIdWhichCreatedMutex(char* szMutexString); +__declspec(dllexport) long TITCALL HandlerGetProcessIdWhichCreatedMutexW(wchar_t* szMutexString); +// TitanEngine.Injector.functions: +__declspec(dllexport) bool TITCALL RemoteLoadLibrary(HANDLE hProcess, char* szLibraryFile, bool WaitForThreadExit); +__declspec(dllexport) bool TITCALL RemoteLoadLibraryW(HANDLE hProcess, wchar_t* szLibraryFile, bool WaitForThreadExit); +__declspec(dllexport) bool TITCALL RemoteFreeLibrary(HANDLE hProcess, HMODULE hModule, char* szLibraryFile, bool WaitForThreadExit); +__declspec(dllexport) bool TITCALL RemoteFreeLibraryW(HANDLE hProcess, HMODULE hModule, wchar_t* szLibraryFile, bool WaitForThreadExit); +__declspec(dllexport) bool TITCALL RemoteExitProcess(HANDLE hProcess, DWORD ExitCode); +// TitanEngine.StaticUnpacker.functions: +__declspec(dllexport) bool TITCALL StaticFileLoad(char* szFileName, DWORD DesiredAccess, bool SimulateLoad, LPHANDLE FileHandle, LPDWORD LoadedSize, LPHANDLE FileMap, PULONG_PTR FileMapVA); +__declspec(dllexport) bool TITCALL StaticFileLoadW(wchar_t* szFileName, DWORD DesiredAccess, bool SimulateLoad, LPHANDLE FileHandle, LPDWORD LoadedSize, LPHANDLE FileMap, PULONG_PTR FileMapVA); +__declspec(dllexport) bool TITCALL StaticFileUnload(char* szFileName, bool CommitChanges, HANDLE FileHandle, DWORD LoadedSize, HANDLE FileMap, ULONG_PTR FileMapVA); +__declspec(dllexport) bool TITCALL StaticFileUnloadW(wchar_t* szFileName, bool CommitChanges, HANDLE FileHandle, DWORD LoadedSize, HANDLE FileMap, ULONG_PTR FileMapVA); +__declspec(dllexport) bool TITCALL StaticFileOpen(char* szFileName, DWORD DesiredAccess, LPHANDLE FileHandle, LPDWORD FileSizeLow, LPDWORD FileSizeHigh); +__declspec(dllexport) bool TITCALL StaticFileOpenW(wchar_t* szFileName, DWORD DesiredAccess, LPHANDLE FileHandle, LPDWORD FileSizeLow, LPDWORD FileSizeHigh); +__declspec(dllexport) bool TITCALL StaticFileGetContent(HANDLE FileHandle, DWORD FilePositionLow, LPDWORD FilePositionHigh, void* Buffer, DWORD Size); +__declspec(dllexport) void TITCALL StaticFileClose(HANDLE FileHandle); +__declspec(dllexport) void TITCALL StaticMemoryDecrypt(LPVOID MemoryStart, DWORD MemorySize, DWORD DecryptionType, DWORD DecryptionKeySize, ULONG_PTR DecryptionKey); +__declspec(dllexport) void TITCALL StaticMemoryDecryptEx(LPVOID MemoryStart, DWORD MemorySize, DWORD DecryptionKeySize, void* DecryptionCallBack); +__declspec(dllexport) void TITCALL StaticMemoryDecryptSpecial(LPVOID MemoryStart, DWORD MemorySize, DWORD DecryptionKeySize, DWORD SpecDecryptionType, void* DecryptionCallBack); +__declspec(dllexport) void TITCALL StaticSectionDecrypt(ULONG_PTR FileMapVA, DWORD SectionNumber, bool SimulateLoad, DWORD DecryptionType, DWORD DecryptionKeySize, ULONG_PTR DecryptionKey); +__declspec(dllexport) bool TITCALL StaticMemoryDecompress(void* Source, DWORD SourceSize, void* Destination, DWORD DestinationSize, int Algorithm); +__declspec(dllexport) bool TITCALL StaticRawMemoryCopy(HANDLE hFile, ULONG_PTR FileMapVA, ULONG_PTR VitualAddressToCopy, DWORD Size, bool AddressIsRVA, char* szDumpFileName); +__declspec(dllexport) bool TITCALL StaticRawMemoryCopyW(HANDLE hFile, ULONG_PTR FileMapVA, ULONG_PTR VitualAddressToCopy, DWORD Size, bool AddressIsRVA, wchar_t* szDumpFileName); +__declspec(dllexport) bool TITCALL StaticRawMemoryCopyEx(HANDLE hFile, DWORD RawAddressToCopy, DWORD Size, char* szDumpFileName); +__declspec(dllexport) bool TITCALL StaticRawMemoryCopyExW(HANDLE hFile, DWORD RawAddressToCopy, DWORD Size, wchar_t* szDumpFileName); +__declspec(dllexport) bool TITCALL StaticRawMemoryCopyEx64(HANDLE hFile, DWORD64 RawAddressToCopy, DWORD64 Size, char* szDumpFileName); +__declspec(dllexport) bool TITCALL StaticRawMemoryCopyEx64W(HANDLE hFile, DWORD64 RawAddressToCopy, DWORD64 Size, wchar_t* szDumpFileName); +__declspec(dllexport) bool TITCALL StaticHashMemory(void* MemoryToHash, DWORD SizeOfMemory, void* HashDigest, bool OutputString, int Algorithm); +__declspec(dllexport) bool TITCALL StaticHashFileW(wchar_t* szFileName, char* HashDigest, bool OutputString, int Algorithm); +__declspec(dllexport) bool TITCALL StaticHashFile(char* szFileName, char* HashDigest, bool OutputString, int Algorithm); +// TitanEngine.Engine.functions: +__declspec(dllexport) void TITCALL EngineUnpackerInitialize(char* szFileName, char* szUnpackedFileName, bool DoLogData, bool DoRealignFile, bool DoMoveOverlay, void* EntryCallBack); +__declspec(dllexport) void TITCALL EngineUnpackerInitializeW(wchar_t* szFileName, wchar_t* szUnpackedFileName, bool DoLogData, bool DoRealignFile, bool DoMoveOverlay, void* EntryCallBack); +__declspec(dllexport) bool TITCALL EngineUnpackerSetBreakCondition(void* SearchStart, DWORD SearchSize, void* SearchPattern, DWORD PatternSize, DWORD PatternDelta, ULONG_PTR BreakType, bool SingleBreak, DWORD Parameter1, DWORD Parameter2); +__declspec(dllexport) void TITCALL EngineUnpackerSetEntryPointAddress(ULONG_PTR UnpackedEntryPointAddress); +__declspec(dllexport) void TITCALL EngineUnpackerFinalizeUnpacking(); +// TitanEngine.Engine.functions: +__declspec(dllexport) void TITCALL SetEngineVariable(DWORD VariableId, bool VariableSet); +__declspec(dllexport) bool TITCALL EngineCreateMissingDependencies(char* szFileName, char* szOutputFolder, bool LogCreatedFiles); +__declspec(dllexport) bool TITCALL EngineCreateMissingDependenciesW(wchar_t* szFileName, wchar_t* szOutputFolder, bool LogCreatedFiles); +__declspec(dllexport) bool TITCALL EngineFakeMissingDependencies(HANDLE hProcess); +__declspec(dllexport) bool TITCALL EngineDeleteCreatedDependencies(); +__declspec(dllexport) bool TITCALL EngineCreateUnpackerWindow(char* WindowUnpackerTitle, char* WindowUnpackerLongTitle, char* WindowUnpackerName, char* WindowUnpackerAuthor, void* StartUnpackingCallBack); +__declspec(dllexport) void TITCALL EngineAddUnpackerWindowLogMessage(char* szLogMessage); +// Global.Engine.Extension.Functions: +__declspec(dllexport) bool TITCALL ExtensionManagerIsPluginLoaded(char* szPluginName); +__declspec(dllexport) bool TITCALL ExtensionManagerIsPluginEnabled(char* szPluginName); +__declspec(dllexport) bool TITCALL ExtensionManagerDisableAllPlugins(); +__declspec(dllexport) bool TITCALL ExtensionManagerDisablePlugin(char* szPluginName); +__declspec(dllexport) bool TITCALL ExtensionManagerEnableAllPlugins(); +__declspec(dllexport) bool TITCALL ExtensionManagerEnablePlugin(char* szPluginName); +__declspec(dllexport) bool TITCALL ExtensionManagerUnloadAllPlugins(); +__declspec(dllexport) bool TITCALL ExtensionManagerUnloadPlugin(char* szPluginName); +__declspec(dllexport) void* TITCALL ExtensionManagerGetPluginInfo(char* szPluginName); + +#ifdef __cplusplus +} +#endif + +#pragma pack(pop) + +#endif /*TITANENGINE*/ diff --git a/x64_dbg_dbg/TitanEngine/TitanEngine.txt b/x64_dbg_dbg/TitanEngine/TitanEngine.txt new file mode 100644 index 00000000..f5d99192 --- /dev/null +++ b/x64_dbg_dbg/TitanEngine/TitanEngine.txt @@ -0,0 +1,20727 @@ +TitanEngine + +SDK References + +Contents +Introduction to TitanEngine 12 + Introduction to static unpackers . 13 + Introduction to dynamic unpackers 14 + Introduction to generic unpackers 15 + Dynamic unpacker layout . 16 +TitanEngine SDK References . 18 +Unicode support . 19 +Python support . 19 +LUA support 19 +Debugger module . 20 +Debugger module constants . 21 + StaticDisassembleEx function . 24 + StaticDisassemble function . 25 + *DisassembleEx function 26 + *Disassemble function 27 + StaticLengthDisassemble function 28 + *LengthDisassembleEx function . 29 + *LengthDisassemble function . 30 + *InitDebug function 31 + *InitDebugEx function . 32 + *InitDLLDebug function 33 + *AutoDebugEx function 34 + SetErrorModel function 35 + *IsFileBeingDebugged function 36 + *AttachDebugger function 37 + *DetachDebugger function . 38 + *DetachDebuggerEx function . 39 + *GetProcessInformation function . 40 + *GetStartupInformation function . 41 + *GetDebuggedDLLBaseAddress function . 42 + *GetDebuggedFileBaseAddress function 43 + *GetExitCode function 44 + *DebugLoop function 45 + *DebugLoopEx function 46 + SetDebugLoopTimeOut function 47 + SetNextDbgContinueStatus function 48 + *StopDebug function 49 + *ForceClose function 50 + *SetBPXOptions function 51 + *SetBPX function . 52 + *SetBPXEx function . 53 + *EnableBPX function . 55 + *DisableBPX function 56 + *IsBPXEnabled function 57 + *DeleteBPX function . 58 + *SafeDeleteBPX function 59 + *SetAPIBreakPoint function 60 + *DeleteAPIBreakPoint function 61 + *SafeDeleteAPIBreakPoint function . 62 + *SetMemoryBPX function . 63 + *SetMemoryBPXEx function . 64 + *RemoveMemoryBPX function . 65 + *SetHardwareBreakPoint function . 66 + *SetHardwareBreakPointEx function 67 + *DeleteHardwareBreakPoint function 68 + *GetUnusedHardwareBreakPointRegister function . 69 + *RemoveAllBreakPoints function . 70 + *CurrentExceptionNumber function 71 + *ClearExceptionNumber function . 72 + *GetDebugData function 73 + *GetTerminationData function . 74 + *GetContextDataEx function 75 + *GetContextData function 76 + *SetContextDataEx function . 77 + *SetContextData function . 78 + *GetContextFPUDataEx function 79 + *SetContextFPUDataEx function. 80 + *StepInto function 81 + *StepOver function . 82 + *SingleStep function . 83 + *FindEx function . 84 + *Find function . 85 + *MatchPatternEx function 86 + *MatchPattern function 87 + *FillEx function 88 + *Fill function 89 + *PatchEx function . 90 + *Patch function . 91 + *ReplaceEx function 92 + *Replace function . 94 + *GetRemoteString function 96 + *GetFunctionParameter function . 97 + *GetJumpDestinationEx function . 99 + *GetJumpDestination function . 100 + *IsJumpGoingToExecuteEx function . 101 + *IsJumpGoingToExecute function . 102 + *SetCustomHandler function 103 + SetCustomHandler CallBack details 104 + *HideDebugger function . 106 + *UnHideDebugger function 107 + *GetPEBLocation function 108 + **SetEngineVariable function . 109 +Threader module 110 +Threader module structures . 111 + **ThreaderGetThreadInfo function 112 + **ThreaderGetThreadData function 113 + **ThreaderEnumThreadInfo function 114 + **ThreaderPauseThread function 115 + **ThreaderResumeThread function . 116 + **ThreaderTerminateThread function . 117 + **ThreaderPauseAllThreads function . 118 + **ThreaderResumeAllThreads function . 119 + **ThreaderPauseProcess function . 120 + **ThreaderResumeProcess function 121 + **ThreaderIsThreadStillRunning function 122 + **ThreaderIsThreadActive function . 123 + **ThreaderIsAnyThreadActive function . 124 + **ThreaderIsExceptionInMainThread function 125 + **ThreaderGetOpenHandleForThread function 126 + **ThreaderSetCallBackForNextExitThreadEvent function . 127 + **ThreaderCreateRemoteThreadEx function . 128 + **ThreaderCreateRemoteThread function 129 + **ThreaderInjectAndExecuteCodeEx function . 130 + **ThreaderInjectAndExecuteCode function . 131 + **ThreaderExecuteOnlyInjectedThreads function . 132 + **ThreaderImportRunningThreadData function 133 +TLS module 134 + TLSBreakOnCallBack function . 135 + TLSBreakOnCallBackEx function 136 + TLSGrabCallBackData function 137 + TLSRemoveCallback function 138 + TLSRemoveTable function . 139 + TLSBackupData function . 140 + TLSRestoreData function. 141 + TLSBuildNewTable function 142 + TLSBuildNewTableEx function. 143 +Librarian module . 144 +Librarian module constants 145 +Librarian module structures 145 + *LibrarianSetBreakPoint function . 146 + *LibrarianRemoveBreakPoint function . 147 + *LibrarianGetLibraryInfo function 148 + *LibrarianGetLibraryInfoEx function . 149 + **LibrarianEnumLibraryInfo function . 150 +Hooks module . 151 +Hooks module constants. 152 +Hooks module structures 152 + HooksSafeTransition function . 153 + HooksSafeTransitionEx function . 154 + HooksDisableRedirection function 155 + HooksDisableRedirectionsForModule function 156 + HooksDisableIATRedirection function 157 + HooksEnableRedirection function 158 + HooksEnableRedirectionsForModule function . 159 + HooksEnableIATRedirection function . 160 + HooksRemoveRedirection function 161 + HooksRemoveRedirectionsForModule function . 162 + HooksRemoveIATRedirection function . 163 + HooksInsertNewRedirection function . 164 + HooksInsertNewIATRedirectionEx function 165 + HooksInsertNewIATRedirection function . 166 + HooksGetTrampolineAddress function . 167 + HooksGetHookEntryDetails function 168 + HooksScanModuleMemory function 169 + HooksScanEntireProcessMemory function . 170 + HooksScanEntireProcessMemoryEx function . 171 +OEP Finder module . 172 + FindOEPInit function . 173 + FindOEPGenerically function 174 +Process module . 175 + *GetActiveProcessId function . 176 + *EnumProcessesWithLibrary function 177 + *RemoteLoadLibrary function 178 + *RemoteFreeLibrary function . 179 + *RemoteExitProcess function . 180 + *TranslateNativeName function . 181 +Dumper module 182 +Dumper module constants . 183 +Dumper module structures . 184 + *DumpProcess function 186 + *DumpProcessEx function 187 + *DumpMemory function 188 + *DumpMemoryEx function . 189 + *DumpRegions function 190 + *DumpRegionsEx function 191 + *DumpModule function 192 + *DumpModuleEx function 193 + *PastePEHeader function . 194 + ExtractSection function . 195 + ResortFileSections function 196 + FindOverlay function . 197 + ExtractOverlay function 198 + AddOverlay function . 199 + CopyOverlay function 200 + RemoveOverlay function 201 + MakeAllSectionsRWE function 202 + AddNewSectionEx function . 203 + AddNewSection function 204 + ResizeLastSection function . 205 + SetSharedOverlay function . 206 + GetSharedOverlay function. 207 + DeleteLastSection function . 208 + DeleteLastSectionEx function . 209 + *GetPE32DataFromMappedFile function . 210 + *GetPE32DataFromMappedFileEx function . 211 + *GetPE32Data function . 212 + *GetPE32DataEx function . 213 + *SetPE32DataForMappedFile function . 214 + *SetPE32DataForMappedFileEx function . 215 + *SetPE32Data function . 216 + *SetPE32DataEx function 217 + *GetPE32SectionNumberFromVA function 218 + *ConvertVAtoFileOffset function 219 + *ConvertVAtoFileOffsetEx function 220 + *ConvertFileOffsetToVA function . 221 + *ConvertFileOffsetToVAEx function . 222 +Importer module . 223 +Importer module structures . 224 + ImporterInit function 225 + ImporterSetImageBase function . 226 + ImporterAddNewDll function . 227 + ImporterAddNewAPI function 228 + ImporterAddNewOrdinalAPI function 229 + ImporterGetLastAddedDLLName function . 230 + ImporterGetAddedDllCount function . 231 + ImporterGetAddedAPICount function 232 + ImporterEnumAddedData function 233 + ImporterEstimatedSize function . 234 + ImporterCleanup function 235 + ImporterExportIATEx function 236 + ImporterExportIAT function 237 + ImporterGetDLLName function 238 + ImporterGetAPIName function . 239 + ImporterGetAPINameEx function . 240 + ImporterGetAPIOrdinalNumber function . 241 + *ImporterGetRemoteAPIAddress function . 242 + *ImporterGetRemoteAPIAddressEx function . 243 + ImporterGetLocalAPIAddress function . 244 + *ImporterGetDLLNameFromDebugee function . 245 + *ImporterGetAPINameFromDebugee function 246 + *ImporterGetAPIOrdinalNumberFromDebugee function 247 + ImporterGetDLLIndexEx function . 248 + ImporterGetDLLIndex function . 249 + *ImporterGetRemoteDLLBase function 250 + *ImporterGetRemoteDLLBaseEx function 251 + ImporterIsForwardedAPI function 252 + ImporterGetForwardedAPIName function . 253 + ImporterGetForwardedAPIOrdinalNumber function . 254 + ImporterGetForwardedDLLName function . 255 + ImporterGetForwardedDLLIndex function . 256 + ImporterFindAPIWriteLocation function 257 + ImporterFindOrdinalAPIWriteLocation function 258 + ImporterFindAPIByWriteLocation function 259 + ImporterFindDLLByWriteLocation function 260 + ImporterGetNearestAPIAddress function . 261 + ImporterGetNearestAPIName function 262 + ImporterMoveIAT function . 263 + ImporterRelocateWriteLocation function . 264 + ImporterSetUnknownDelta function 265 + ImporterGetCurrentDelta function . 266 + ImporterLoadImportTable function 267 + ImporterCopyOriginalIAT function 268 + ImporterMoveOriginalIAT function 269 + ImporterAutoSearchIAT function 270 + ImporterAutoSearchIATEx function 271 + ImporterAutoFixIATEx function 272 + ImporterAutoFixIAT function 274 +Tracer module . 275 + **TracerInit function 276 + **TracerLevel1 function . 277 + **HashTracerLevel1 function . 278 + **TracerDetectRedirection function 279 + **TracerFixKnownRedirection function . 280 + **TracerFixRedirectionViaImpRecPlugin function 281 +Realigner module 282 +Realigner module structures and constants . 283 + RealignPE function 285 + RealignPEEx function . 286 + FixHeaderCheckSum function . 287 + WipeSection function 288 + *IsFileDLL function 289 + *IsPE32FileValidEx function 290 + FixBrokenPE32FileEx function . 291 +Relocater module 292 + RelocaterInit function . 293 + RelocaterCleanup function . 294 + RelocaterAddNewRelocation function 295 + RelocaterEstimatedSize function 296 + RelocaterExportRelocationEx function . 297 + RelocaterExportRelocation function . 298 + RelocaterGrabRelocationTableEx function . 299 + RelocaterGrabRelocationTable function . 300 + RelocaterMakeSnapshot function 301 + RelocaterCompareTwoSnapshots function 302 + RelocaterWipeRelocationTable function 303 + RelocaterRelocateMemoryBlock function 304 +Exporter module . 305 + ExporterInit function . 306 + ExporterSetImageBase function . 307 + ExporterCleanup function . 308 + ExporterAddNewExport function 309 + ExporterAddNewOrdinalExport function 310 + ExporterGetAddedExportCount function . 311 + ExporterEstimatedSize function 312 + ExporterBuildExportTableEx function . 313 + ExporterBuildExportTable function. 314 + *ExporterLoadExportTable function . 315 +Resourcer module . 316 + ResourcerLoadFileForResourceUse function 317 + ResourcerFreeLoadedFile function . 318 + ResourcerExtractResourceFromFileEx function 319 + ResourcerExtractResourceFromFile function . 320 + ResourcerFindResource function 321 + ResourcerFindResourceEx function 323 + ResourcerEnumerateResource function . 325 + ResourcerEnumerateResourceEx function . 326 +Static module 327 +Static module constants 328 + StaticFileOpen function . 329 + StaticFileGetContent function. 330 + StaticFileClose function . 331 + StaticFileLoad function 332 + StaticFileUnload function 333 + StaticMemoryDecrypt function 334 + StaticMemoryDecryptEx function . 335 + StaticSectionDecrypt function 336 + StaticMemoryDecryptSpecial function . 337 + StaticMemoryDecompress function . 338 + StaticRawMemoryCopy function 339 + StaticRawMemoryCopyEx function 340 + StaticRawMemoryCopyEx64 function 341 + StaticHashMemory function . 342 + StaticHashFile function . 343 +Handler module 344 +Handler module constants 345 +Handler module structures . 345 + **HandlerGetActiveHandleCount function 346 + **HandlerIsHandleOpen function 347 + **HandlerGetHandleName function 348 + **HandlerGetHandleDetails function . 349 + **HandlerEnumerateOpenHandles function . 350 + **HandlerIsFileLocked function 351 + **HandlerCloseAllLockHandles function 352 + **HandlerEnumerateLockHandles function . 353 + **HandlerCloseRemoteHandle function 354 + **HandlerEnumerateOpenMutexes function 355 + **HandlerGetOpenMutexHandle function . 356 + **HandlerGetProcessIdWhichCreatedMutex function 357 +Extension module . 358 +Guide to writing extensions for TitanEngine 359 +Extension structure and function definitions . 359 + **ExtensionManagerIsPluginLoaded function . 360 + **ExtensionManagerIsPluginEnabled function 361 + **ExtensionManagerDisablePlugin function 362 + **ExtensionManagerDisableAllPlugins function 363 + **ExtensionManagerEnablePlugin function . 364 + **ExtensionManagerEnableAllPlugins function . 365 + **ExtensionManagerUnloadPlugin function 366 + **ExtensionManagerUnloadAllPlugins function 367 + **ExtensionManagerGetPluginInfo function 368 +Engine module 369 + EngineCreateMissingDependencies function . 370 + EngineFakeMissingDependencies function 371 + EngineDeleteCreatedDependencies function . 372 + EngineCreateUnpackerWindow function . 373 + EngineAddUnpackerWindowLogMessage function 374 +Engine unpacker simplification module 375 +Engine simplification module constants . 376 + EngineUnpackerInitialize function 377 + EngineUnpackerSetBreakCondition function . 378 + EngineUnpackerSetEntryPointAddress function 381 + EngineUnpackerFinalizeUnpacking function 382 + TitanEngine 2.0.1 - history 383 + TitanEngine 2.0.2 - history 384 + TitanEngine 2.0.3 - history 385 +License . 386 + + + + + +Introduction to TitanEngine + + + +One of the greatest challenges of modern reverse engineering is taking apart and analyzing +software protections. During the last decade a vast number of such shell modifiers have appeared. +Software Protection as an industry has come a long way from simple encryption that protects +executable and data parts to current highly sophisticated protections that are packed with tricks aiming +at slow down in the reversing process. Number of such techniques increases every year. Hence we need +to ask ourselves, can we keep up with the tools that we have? + +Protections have evolved over the last few years, but so have the reverser’s tools. Some of those +tools are still in use today since they were written to solve a specific problem, or at least a part of it. Yet +when it comes to writing unpackers this process hasn’t evolved much. We are limited to writing our own +code for every scenario in the field. + +We have designed TitanEngine in such fashion that writing unpackers would mimic analyst’s +manual unpacking process. Basic set of libraries, which will later become the framework, had the +functionality of the four most common tools used in the unpacking process: debugger, dumper, +importer and realigner. With the guided execution and a set of callbacks these separate modules +complement themselves in a manner compatible with the way any reverse engineer would use his tools +of choice to unpack the file. This creates an execution timeline which parries the protection execution +and gathers information from it while guided to the point from where the protection passes control to +the original software code. When that point is reached file gets dumped to disk and fixed so it resembles +the original to as great of a degree as possible. In this fashion problems of making static unpackers have +been solved. Yet static unpacking is still important due to the fact that it will always be the most secure, +and in some cases, fastest available method. That is why we will discuss both static and dynamic +unpackers. We will also see into methods of making generic code to support large number of formats +without knowing the format specifics. + +TitanEngine can be described as Swiss army knife for reversers. With its 400 functions, every +reverser tool created to this date has been covered through its fabric. Best yet, TitanEngine can be +automated. It is suitable for more than just file unpacking. TitanEngine can be used to make new tools +that work with PE files. Support for both x86 and x64 systems make this framework the only framework +supporting work with PE32+ files. As such, it can be used to create all known types of unpackers. Engine +is open source making it open to modifications that will only ease its integration into existing solutions +and would enable creation of new ones suiting different project needs. + + + +TitanEngine SDK contains: + +. Integrated x86/x64 debugger +. Integrated x86/x64 disassembler +. Integrated memory dumper +. Integrated import tracer & fixer +. Integrated relocation fixer +. Integrated file realigner +. Functions to work with TLS, Resources, Exports,… + + + + + + + + + +Introduction to static unpackers + +Most of basic unpackers are of the static variety. We take this observation very loosely as this +depends on the complexity of the format being unpacked. In most cases writing such unpackers is easy +because the format being unpacked is a simple one or more commonly referred to as a crypter. + +This kind of PE file protectors (because packing is a very basic form of protection) have a simple +layout that only encrypts the code and resources, and in some cases even takes the role of the import +loader. Even if we encounter the most advanced representative of this shell protection type it won’t +differ much from its most basic protection model. Which is, no modification to the PE section layout +other than adding a new section for the crypter code and encryption of the entire code and resource +sections with possible import loader role for the crypter stub. Since these modifications don’t impact the +file in such way that major file reconstruction should be done writing static unpackers also has its +general model. This is, get the needed data for decryption of the encrypter parts and reconstruction of +the import table followed by removing the crypter section. + +With the slight variations of the guidelines described above this could be considered as the basic +crypter model. These variations could be variations in the position of the crypter code, way it handles +imports and some protection shell specifics such as: protected entry point, import redirections or +eliminations, code splices, code markers, etc. + + However static unpackers can be used for a more difficult use cases which require the full file +reconstruction in order to complete the unpacking process. In such cases static unpacking can be used +and it’s recommended only if the security is of the vital importance. These cases most commonly require +the identification of the compression algorithm used and its adaptation to our own code. This code +ripping must be done very carefully and it requires the full understanding of the algorithm which +decompresses the code. There are a few standard compression algorithms in use by most PE shells so +we can use this to create our own database of corresponding decompression algorithms to ease the +unpacker writing process. No matter which path we choose we must always check whether or not the +algorithm has changed since this is one way to tamper with the unpackers. Dynamic unpackers are +resilient to such changes. + + + +Original Entry Point + +jump + +Import + +resolving + +Section + +decryption + +Internal data +decryption + +Overlay + +STUB + +Sections + +(encrypted) + +PE + +DOS + +Figure (1) Crypter file & execution layout + + + + +Introduction to dynamic unpackers + +Most common unpacker type is dynamic. This model is widely used because it is easy to +implement and resilient to minor changes in packing shell decryption and decompression algorithms. +But due to the fact that files do execute during unpacking process this method must be conducted with +great care about system security. There is a risk of files being executed outside the unpacking process or +even stuck in infinite loops. This can and must be avoided by the unpacker implementation. Most logical +choice is creation of internal sandbox for the unpacking process itself. + +Dynamic unpacking is used on specific shell modifier types. These types have a more complex +layout and file content is commonly not only encrypted but compressed too. To avoid heavy coding to +allow what is basically recompiling of the file we execute it to the original entry point which is the first +instruction of the code before the file was protected. Even though all shells can be dynamically +unpacked this kind of unpacking is only used on packers, protectors, bundlers and hybrids. + +Basic layout of such shell modifiers includes compression of the file sections and vital data and +optionally their protection by encryption. Stub is usually located in the last section and section layout +before packing is either preserved or all sections are merged into one. First case usually implies that +each section still contains its original data only compressed while the second one implies a physically +empty section which only serves as virtual memory space reserve. In this second case compressed data +is usually stored inside stub section and upon its decompression returned to original location. + +When creating dynamic unpackers it is important to always keep control over executing sample. +At no point this control must be left in a gray area in which we are uncertain what will occur. +Furthermore unpacking must be conducted inside safe environment so software sandbox must be +designed. This along with multiple checks before and during the unpacking process ensures that we +retain maximum control during this risky process. This kind of unpackers has a standard model which +will be described in Dynamic unpacker layout. That kind of unpacker is a basic unpacker type that can be +created with TitanEngine whose largest number of functions is dedicated to writing. + +Original Entry Point + +jump + +Import Resolving & +TLS callback execution + +Relocation + +to new base + +Section +decompression + +Overlay + +STUB + +Sections + +(compressed) + +PE + +DOS + +Figure (2) Packer file & execution layout + + + + +Introduction to generic unpackers + +Most complex way of creating unpackers is creating generic unpackers. Totally opposite from +the other two cases when creating generic unpackers you don’t need to worry about extracting a good +enough patter on code segment to create a good signature for your unpacker. Quite simply because +these unpackers don’t care about the shell specifics, they only care about their overall behavior which is +common for shell modifiers of the same group. This means that there can never be a general generic +unpacker but several wide range generic unpackers targeting specific behavior groups. + + Here we will focus only on generic unpacking of packed executables and present a wide generic +algorithm targeting these shell modifiers. Major challenge here is retaining as much control as possible +without slowing down the unpacking process drastically. Slowdown occurs because we use memory +breakpoints to monitor packed shell access to executable sections. If we reset the memory breakpoint +each time the packer accesses the section we will have a major speed impact and if we don’t we reset +we risk not to catch the original entry point jump event and even let file execute. There are a few ways +to do this but one is most common. + +Figure (3) Generic unpacker algorithm layout + +Code sections + +SetMemoryBPX + +SetMemoryBPX + +SetMemoryBPX + +GetPEData + +Hash +test + +Your code + +1. EIP inside sections +2. Already written to +3. Hash has changed +4. Not a simple redirection + + +Generic unpackers commonly use WaitForDebugEvent timeouts to reset the breakpoints once +one such breakpoint has been hit. Memory breakpoints can be hit for three reasons: when memory is +read from, written to or executing. Since we only place memory breakpoints on places where we expect +entry point to be we are only interested in execution case. To check whether or not that memory is +executing we just check the EIP register to see if it matches our region. If it does that memory is +executing. However we can set a breakpoint on the section which contains packer code. That is why we +will track if the section has been written to prior its execution. If it has been written to it is highly +possible that the entry point resides there and that we are at the right spot. We can track writing with +memory breakpoints but one can also check that section hash just to make sure that the data has +actually changed. Last check that should be performed before determining that we are sitting on a +possible entry point is a check for known simple redirections that packers such as ASPack use to fool +generic algorithms. Once we verify this last thing we can be fairly certain that we have found our entry +point. To finish the unpacking we must dump and process imports which can be done with TitanEngine. + + + +StopDebug(); + +Finalize unpacking + + + + +Dynamic unpacker layout + +In order to use the TitanEngine SDK you must know the order in which APIs must be called. The +order is fairly strict, and the layout of your unpacker will always be pretty much the same. Every +unpacker starts with debugging and setting a breakpoint on your target's entry point. After this you +must debug the program by running it until you get to the IAT filling code. This code uses LoadLibrary or +GetModuleHandle API to load the dependent .dll files and GetProcAddress to find the locations of the +necessary APIs. When this is done you need to break on the Original Entry Point (OEP), dump the file and +paste imports to it. + + To start debugging you must first find the OEP address. To do this you can call GetPE32Data API and +load the ImageBase and OriginalEntryPoint data. The sum of these two values is the address of the entry +point. When this is done, initialize debugging by calling the InitDebug API. This API creates the debugged +process but it does not start the actual debugging. In this suspended state call SetBpx to set the main +breakpoint at OEP. This breakpoint's callback will be called as soon as the debugged process finishes +loading. To get the debugging process to this point you must call the DebugLoop API. After it is called, +the debugger takes over the debugging process. The only way to control the debugging process from +this point is by callback procedures. Callbacks are set with all types of breakpoints. So if you set the +breakpoint at OEP call the DebugLoop API first callback which will be called is the callback for original +entry point breakpoint. Use that callback to set all the other breakpoints. + + The best way to find where to set the breakpoint is by using the Find API. It will tell you the location +at which your search pattern is found. If the packer for which you are writing an unpacker is single +layered, you can set all the breakpoints in the first or before the first callback, the one at the original +entry point. To get all the data needed to fix the IAT you need to set two or three breakpoints. First at +LoadLibrary or GetModuleHandle API call, second at GetProcAddress call (use two if the packer calls +GetProcAddress at two places for string API locating and ordinal API locating). But before you can +actually call any of the importer functions in order to collect the IAT data you must first call the +ImporterInit API to initialize the importer. + + After you do this and set the breakpoints you must code the breakpoint callbacks to get the IAT data. +In the LoadLibrary/GetModuleHandle callbacks, you call ImporterAddNewDll API. One of its parameters +is the string which holds the name of the .dll file which is loaded. This data location if located in a +register or in a specific memory address. To get this data call the GetContextData API. If the data is in a +location on which the string is located, and not an ordinal number, you must call the +ReadProcessMemory API to read the .dll name from the debugged processes. Then you can add the new +.dll to importer engine. Note that once you add the .dll by calling the ImporterAddNewDll API all calls to +ImporterAddNewAPI add APIs to last added .dll file. APIs are added by calling the ImporterAddNewAPI +the same way you add a new .dll to the importer engine. But unlike ImporterAddNewDll API, you must +specify the location on which the API pointer will be stored. This is a memory location to which the +pointer loaded with GetProcAddress API is written. After you collect all the data needed to fill in the IAT, +the unpacking is pretty much done. + + + + + Now you need to load the unpacked file's OEP (this depends on the packer code) and dump the +debugged process with DumpProcess. After this you can use the AddNewSection API to make space for +the IAT, which needs to be pasted to the dump file. To know just how much space you need, use the +ImporterEstimatedSize API. Finally the IAT is exported to a new section by calling the ImporterExportIAT +API. Optionally you can realign the file and then stop the debugging process by calling the StopDebug +API (if you don't stop the debugging target will keep running). This terminates the debugged process and +your program's execution resumes after the call to DebugLoop. + + + +StopDebug(); + +Entry point + +RealignPE + +ExportRelocation + +ImporterExportIAT + +PastePEHeader + +DumpProcess + +CompareTwoSnapshots + + + +RelocaterMakeSnaphot + + + +ImporterAddNewAPI + +ImporterAddNewDLL + +RelocaterMakeSnaphot + +Code just after + +Packer segment + +Relocation code + +Code just before + +Relocation fix + +GetProcAddress + +LoadLibrary + +Gather import data + +Import fix + +DebugLoop(); + +SetBPX + +InitDebug + +Unpacking init + +GetPEData + +SetBPX + + +maintitan.png + + + + + + +TitanEngine SDK References + + + + +Unicode support + + + +Unicode support has been added to TitanEngine with version 2.0.2. However Unicode functions +are not documented in this document because changes between function versions that use ASCII or +UNICODE strings as input/output parameters are minor. Unicode functions are defined in the SDK and +can be used normally. Such functions can be easily recognized by the appendix “W” which they have. For +specific function definitions please refer to the SDK header files. + +Python support + + + +Python support has been added to TitanEngine with version 2.0.3. To use the python SDK +include teSDK.py with your project. SDK wrapper around the engine uses the default python libraries +which ship with Python 2.6.5. + +LUA support + + + +LUA support has been added to TitanEngine with version 2.0.3. To use the LUA SDK include +SDK.lua with your project. SDK wrapper around the engine uses Alien LUA module version 0.51. To be +able to use the LUA SDK alien module that comes with LUA 5.1.4 must be updated. We suggest that you +use LuaRocks for a simple alien update procedure. + + + + + + +Debugger module + + + +Debugger module's functions are used for process debugging, disassembling, accessing context and +manipulating memory. + + + + +Debugger module constants + + + +Constants used by: SetBPXEx function, SetHardwareBreakPoint function, SetHardwareBreakPointEx +function, DeleteHardwareBreakPoint function, GetContextDataEx function, +GetContextData function, SetContextDataEx function and SetContextData function + + + +#define UE_EAX 1 + +#define UE_EBX 2 + +#define UE_ECX 3 + +#define UE_EDX 4 + +#define UE_EDI 5 + +#define UE_ESI 6 + +#define UE_EBP 7 + +#define UE_ESP 8 + +#define UE_EIP 9 + +#define UE_EFLAGS 10 + +#define UE_DR0 11 + +#define UE_DR1 12 + +#define UE_DR2 13 + +#define UE_DR3 14 + +#define UE_DR6 15 + +#define UE_DR7 16 + +#define UE_RAX 17 + +#define UE_RBX 18 + +#define UE_RCX 19 + +#define UE_RDX 20 + +#define UE_RDI 21 + +#define UE_RSI 22 + +#define UE_RBP 23 + +#define UE_RSP 24 + +#define UE_RIP 25 + +#define UE_RFLAGS 26 + +#define UE_R8 27 + +#define UE_R9 28 + +#define UE_R10 29 + +#define UE_R11 30 + +#define UE_R12 31 + +#define UE_R13 32 + +#define UE_R14 33 + +#define UE_R15 34 + +#define UE_CIP 35 // Generic, on x86 = EIP and on x64 = RIP + +#define UE_CSP 36 // Generic, on x86 = ESP and on x64 = RSP + + + + + + + + +Constants used by: SetBPXEx function + + + +#define UE_CMP_NOCONDITION 0 + +#define UE_CMP_EQUAL 1 + +#define UE_CMP_NOTEQUAL 2 + +#define UE_CMP_GREATER 3 + +#define UE_CMP_GREATEROREQUAL 4 + +#define UE_CMP_LOWER 5 + +#define UE_CMP_LOWEROREQUAL 6 + +#define UE_CMP_REG_EQUAL 7 + +#define UE_CMP_REG_NOTEQUAL 8 + +#define UE_CMP_REG_GREATER 9 + +#define UE_CMP_REG_GREATEROREQUAL 10 + +#define UE_CMP_REG_LOWER 11 + +#define UE_CMP_REG_LOWEROREQUAL 12 + +#define UE_CMP_ALWAYSFALSE 13 + + + +Constants used by: SetBPX function, SetBPXEx function, SetMemoryBPX function, SetMemoryBPXEx +function and SetHardwareBreakPoint function + + + +#define UE_BREAKPOINT 0 + +#define UE_SINGLESHOOT 1 + +#define UE_HARDWARE 2 + +#define UE_MEMORY 3 + +#define UE_MEMORY_READ 4 + +#define UE_MEMORY_WRITE 5 + +#define UE_BREAKPOINT_TYPE_INT3 0x10000000 + +#define UE_BREAKPOINT_TYPE_LONG_INT3 0x20000000 + +#define UE_BREAKPOINT_TYPE_UD2 0x30000000 + + + +#define UE_HARDWARE_EXECUTE 4 + +#define UE_HARDWARE_WRITE 5 + +#define UE_HARDWARE_READWRITE 6 + +#define UE_HARDWARE_SIZE_1 7 + +#define UE_HARDWARE_SIZE_2 8 + +#define UE_HARDWARE_SIZE_4 9 + + + +#define UE_APISTART 0 + +#define UE_APIEND 1 + + + + + + + + +Constants used by: SetCustomHandler function + + + +#define UE_CH_BREAKPOINT 1 + +#define UE_CH_SINGLESTEP 2 + +#define UE_CH_ACCESSVIOLATION 3 + +#define UE_CH_ILLEGALINSTRUCTION 4 + +#define UE_CH_NONCONTINUABLEEXCEPTION 5 + +#define UE_CH_ARRAYBOUNDSEXCEPTION 6 + +#define UE_CH_FLOATDENORMALOPERAND 7 + +#define UE_CH_FLOATDEVIDEBYZERO 8 + +#define UE_CH_INTEGERDEVIDEBYZERO 9 + +#define UE_CH_INTEGEROVERFLOW 10 + +#define UE_CH_PRIVILEGEDINSTRUCTION 11 + +#define UE_CH_PAGEGUARD 12 + +#define UE_CH_EVERYTHINGELSE 13 + +#define UE_CH_CREATETHREAD 14 + +#define UE_CH_EXITTHREAD 15 + +#define UE_CH_CREATEPROCESS 16 + +#define UE_CH_EXITPROCESS 17 + +#define UE_CH_LOADDLL 18 + +#define UE_CH_UNLOADDLL 19 + +#define UE_CH_OUTPUTDEBUGSTRING 20 + + + +Constants used by: RemoveAllBreakPoints function + + + +#define UE_OPTION_REMOVEALL 1 + +#define UE_OPTION_DISABLEALL 2 + +#define UE_OPTION_REMOVEALLDISABLED 3 + +#define UE_OPTION_REMOVEALLENABLED 4 + +Constants used by: SetEngineVariable function + + + +#define UE_ENGINE_ALOW_MODULE_LOADING 1 + +#define UE_ENGINE_AUTOFIX_FORWARDERS 2 + +#define UE_ENGINE_PASS_ALL_EXCEPTIONS 3 + +#define UE_ENGINE_NO_CONSOLE_WINDOW 4 + +#define UE_ENGINE_BACKUP_FOR_CRITICAL_FUNCTIONS 5 + +#define UE_ENGINE_RESET_CUSTOM_HANDLER 7 + +#define UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK 8 + + + +Constants used by: HideDebugger function + + + +#define UE_HIDE_BASIC 1 + + + +Constants used by: SetBPXOptions function + + + +#define UE_BREAKPOINT_INT3 1 + +#define UE_BREAKPOINT_LONG_INT3 2 + +#define UE_BREAKPOINT_UD2 3 + + + + +StaticDisassembleEx function + +The StaticDisassembleEx function is used to disassemble data from the context of the process using the +SDK. This is only used to disassemble instructions locally, meaning code inside your executable and its +memory context. + +Syntax + + + +void* __stdcall StaticDisassembleEx( + +ULONG_PTR DisassmStart, + +LPVOID DisassmAddress + +); + + + + + + + +Parameters + +DisassmStart + + [in] Used only to help with disassembling relative instructions such as jumps. This +variable should be set to the address you are disassembling. If data was copied from +a remote process, make sure you use that address. Size of this variable varies: on +x86 its 4 bytes and on x64 its 8 bytes. Therefore it can also be declared as void* + +DisassmAddress + +[in] Pointer to the address where the instruction to be disassembled is located. Only the +first instruction in that block will be disassembled. + + + +Return value + +If disassembly succeeds, StaticDisassembleEx returns a pointer to the disassembled instruction +string, otherwise, it returns NULL. + +Remarks + +diStorm64 is used for instruction disassembling. + +Example + +None. + + + + + + +StaticDisassemble function + +The StaticDisassemble function is used to disassemble data from the context of the process using the +SDK. This is only used to disassemble instructions locally, meaning code inside your executable and its +memory context. + +Syntax + + + +void* __stdcall StaticDisassemble( + +LPVOID DisassmAddress + +); + + + + + + + +Parameters + +DisassmAddress + +[in] Pointer to the address where the instruction to be disassembled is located. Only the +first instruction in that block will be disassembled. If you use StaticDisassemble to +disassemble relative instructions, such as jumps, it will assume that instructions +resides at DiassmAddress and will disassemble them as such. If you need to +disassemble instructions that have been moved, use StaticDisassembleEx. + + + +Return value + +If disassembly succeeds, StaticDisassemble returns a pointer to the disassembled instruction +string, otherwise, it returns NULL. + +Remarks + +diStorm64 is used for instruction disassembling. + +Example + +None. + + + + + + +DisassembleEx function + +The function DisassembleEx disassembles data from the context of any running process, as long as you +have access to the process. + + Syntax + + + +void* __stdcall DisassembleEx( + +HANDLE hProcess, + +LPVOID DisassmAddress, + +bool ReturnInstructionType + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be disassembled. + +DisassmAddress + +[in] Pointer to address of the remote process containing the instruction to disassemble. +Only the first instruction in that block will be disassembled. + +ReturnInstructionType + + [in] Boolean switch specifying whether to return the disassembled string or the +instruction type of that string. For example is the disassembled instruction is: MOV +EAX,EBX and this switch is set to TRUE DisassembleEx returns only the string MOV. If +this switch is set to FALSE, DisassembleEx returns the entire disassembled string. + + + +Return value + +If DisassembleEx succeeds, it returns a pointer to either the disassembled instruction string or +the string's instruction type. If it fails, it returns NULL. + +Remarks + +diStorm64 is used for instruction disassembling. + +Example + +None. + + + + + + +Disassemble function + +The function Disassemble disassembles data from the context of currently debugged process. This +function will fail if no process is being debugged or the specified address doesn’t exist inside debugged +process. + + Syntax + + + +void* __stdcall Disassemble( + +LPVOID DisassmAddress, + +); + + + + + + + +Parameters + +DisassmAddress + +[in] Pointer to address of the remote process containing the instruction to disassemble. +Only the first instruction in that block will be disassembled. + + + +Return value + +If it succeeds, Disassemble returns a pointer to disassembled instruction string, otherwise it +returns NULL. + +Remarks + +diStorm64 is used for instruction disassembling. + +Example + +None. + + + + + + +StaticLengthDisassemble function + +The function StaticLengthDisassemble gets the length, in bytes, of a disassembled instruction from the +context of a process, using the SDK. This is only used to disassemble instructions locally, meaning code +inside your executable and its memory context. + +Syntax + + + +void* __stdcall StaticLengthDisassemble( + +LPVOID DisassmAddress + +); + + + + + + + +Parameters + +DisassmAddress + +[in] Pointer to memory which holds instruction whose size in bytes will be determined. +Only the first instruction in that block will be disassembled. + + + +Return value + +StaticLengthDisassemble returns the size of disassembled instruction string or NULL if +disassemble fails. + +Remarks + +diStorm64 is used for instruction disassembling. + +Example + +None. + + + + + + +LengthDisassembleEx function + +The function LengthDisassembleEx gets the length, in bytes, of a disassembled instruction from the +context of any running process, as long as you have the access to the process. + +Syntax + + + +long __stdcall LengthDisassembleEx( + +HANDLE hProcess, + +LPVOID DisassmAddress + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be disassembled. + +DisassmAddress + +[in] Pointer to the address of the instruction whose size you want to know. Only the first +instruction in that block will be disassembled. + + + +Return value + +If it succeeds, LengthDisassembleEx returns the size of disassembled instruction string. If it fails, +it returns either NULL or minus one. + +Remarks + +diStorm64 is used for instruction disassembling. + +Example + +None. + + + + + + +LengthDisassemble function + +The function LengthDisassemble gets the length, in bytes, of the disassembled instruction from the +context of the process currently being debugged. This function fails if no process is being debugged or if +the specified address doesn’t exist inside the debugged process. + +Syntax + + + +long __stdcall LengthDisassembleEx( + +LPVOID DisassmAddress + +); + + + + + + + +Parameters + +DisassmAddress + +[in] Pointer to the address of the instruction whose size you want to know. Only the first +instruction in that block will be disassembled. + + + +Return value + +If it succeeds, LengthDisassemble returns the size of the disassembled instruction string. If it +fails, it returns either NULL or minus one. + +Remarks + +diStorm64 is used for instruction disassembling. + +Example + +None. + + + + + + +InitDebug function + +The InitDebug function is used to initialize the debugging process. This function is always used first and +it is creating a process which will be debugged. + +Syntax + + + +void* __stdcall InitDebug( + +char* szFileName, + +char* szCommandLine, + +char* szCurrentFolder + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file to debug. + +szCommandLine + +[in] Pointer to a command line parameter string that is passed to the created process. + +szCurrentFolder + +[in] Pointer to string which will be passed to CreateProcess API during the process +creation. + + + +Return value + +InitDebug returns the pointer to PROCESS_INFORMATION structure or NULL if it fails. + +Remarks + +None. + +Example + +None. + + + + + + +InitDebugEx function + +The InitDebugEx function is used to initialize the debugging process. This function is always used first. It +creates a process which will be debugged. + +Syntax + + + +void* __stdcall InitDebug( + +char* szFileName, + +char* szCommandLine, + +char* szCurrentFolder, + +LPVOID EntryCallBack + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file to debug. + +szCommandLine + +[in] Pointer to a command line parameter string that is passed to the created process. + +szCurrentFolder + +[in] Pointer to string which will be passed to CreateProcess API during the process +creation. + +EntryCallBack + +[in] Pointer to the callback function to call when the application reaches the file entry +point. This is equal to setting breakpoint at the file entry point. + + + +Return value + +If it succeeds, InitDebugEx returns a pointer to a PROCESS_INFORMATION structure, otherwise +it returns NULL. + + Remarks + +None. + +Example + +None. + + + + + + +InitDLLDebug function + +The InitDLLDebug function is used to initialize the DLL debugging process. This function is always used +first and it is creating a process which will be debugged and it is specialized only for debugging DLL files. +This function automatically loads any DLL loaders required to make DLL debugging work. + +Syntax + + + +void* __stdcall InitDLLDebug( + +char* szFileName, + +bool ReserveModuleBase, + +char* szCommandLine, + +char* szCurrentFolder, + +LPVOID EntryCallBack + +); + + + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file to debug. + +ReserveModuleBase + + [in] Boolean variable that specifies whether or not to load a debugged DLL on a non- +default image base. + +szCommandLine + +[in] Pointer to string which will be passed to the created process as a command line +parameter. + +szCurrentFolder + +[in] Pointer to string which will be passed to CreateProcess API during the process +creation. + +EntryCallBack + +[in] Pointer to a callback function to call when the application reaches the file entry +point. This is equal to setting a breakpoint at the file entry point. + + + +Return value + +If it succeeds, InitDLLDebug returns a pointer to the PROCESS_INFORMATION structure, +otherwise it returns NULL. + + + + + + +AutoDebugEx function + +AutoDebugEx initializes the debugging process for both executables and DLLs. This function is always +used first. It creates a process which will be debugged + +Syntax + + + +void __stdcall AutoDebugEx( + +char* szFileName, + +bool ReserveModuleBase, + +char* szCommandLine, + +char* szCurrentFolder, + +DWORD TimeOut, + +LPVOID EntryCallBack + +); + + + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file to debug. + +ReserveModuleBase + + [in] Boolean variable specifying whether or not to load debugged DLL on non default +image base. + +szCommandLine + +[in] Pointer to string which will be passed to created process as a command line +parameter. + +szCurrentFolder + +[in] Pointer to string which will be passed to CreateProcess API during the process +creation. + +TimeOut + + [in] Value which will be passed to Windows WaitForDebugEvent API. + +EntryCallBack + +[in] [in] Pointer to a callback function to call when the application reaches the file entry +point. This is equal to setting a breakpoint at the file entry point. + + + +Remarks + +Since debugging is performed in second thread, any calls to the SendMessage Windows API will +cause the program to freeze. Keep this in mind while using this function. + + + + + + +SetErrorModel function + +The SetErrorModel function is used to change the way that Windows loader behaves errors found while +loading PE files. If you chose not to display error messages no warnings about broken or invalid files you +try to debug will be shown to the user. + +Syntax + + + +void __stdcall SetErrorModel( + +bool DisplayErrorMessages + +); + + + + + + + +Parameters + +DisplayErrorMessages + + [in] Boolean switch which tells the TitanEngine should Windows loader errors be +displayed or not. + + + +Return value + +None. + +Remarks + +None. + + + + + + + + +IsFileBeingDebugged function + +The IsFileBeingDebugged function is used to determine if a file is currently being debugged or not. + +Syntax + + + +bool __stdcall IsFileBeingDebugged(); + + + + + + + +Parameters + +None. + +Return value + +Boolean switch indicating whether or not a file is being debugged. + +Remarks + +None. + + + + +AttachDebugger function + +The AttachDebugger function is used to initialize the debugging process by attaching to already running +process. Your program will not return from the call to AttachDebugger before the debugging is finished +and debugged application has been terminated. + +Syntax + + + +void __stdcall AttachDebugger( + +DWORD ProcessId, + +bool KillOnExit, + +LPVOID DebugInfo, + +LPVOID CallBack + +); + + + + + + + + + +Parameters + +ProcessId + + [in] Process ID of the running process which can be acquired with Windows API. + +KillOnExit + + [in] Boolean variable specifying whether or not to terminate the process to which the +debugger was attached when debugging is complete. + +DebugInfo + +[out] Pointer to the PROCESS_INFORMATION structure to fill when the process is +attached. + +CallBack + +[in] Pointer to the callback function to call when the first system breakpoint is reached. + + + +Return value + +None. + +Remarks + +None. + + + + + + +DetachDebugger function + +Please use DetachDebuggerEx instead. The DetachDebugger function detaches the debugger from a +debugged process. DetachDebugger detaches the debugger from a running process, allowing the +process to continue running. All exceptions must be processed before detaching. Since exception +processing can’t be done from any TitanEngine callback, this function should NOT be used. + +Syntax + + + +bool __stdcall DetachDebugger( + +DWORD ProcessId + +); + + + + + + + + + +Parameters + +ProcessId + + [in] Process ID of the process from which you want to detach. The ID can be acquired +from the Windows API or internal structures. + + + +Return value + +Returns TRUE when detachment is complete, and FALSE if there is an error. + +Remarks + +This function only works on Window 2003/XP and later. + +Example + +None. + + + + + + +DetachDebuggerEx function + +The DetachDebuggerEx function detaches the debugger from a debugged process, leaving the process +running. DetachDebuggerEx ensures that all exceptions are processed before detaching. + +Syntax + + + +bool __stdcall DetachDebuggerEx( + +DWORD ProcessId + +); + + + + + + + + + +Parameters + +ProcessId + + [in] Process ID of the process from which you want to detach. The ID can be acquired +from the Windows API or internal structures. + + + +Return value + +Returns TRUE when detachment is complete, and FALSE if there is an error. + +Remarks + +This function only works on Window 2003/XP and later. + +Example + +None. + + + + +GetProcessInformation function + +The GetProcessInformation function retrieves a pointer to the PROCESS_INFORMATION structure that +contains the initialization data for the debugged process. + +Syntax + + + +void* __stdcall GetProcessInformation(); + + + + + + + +Parameters + +None. + +Return value + +Returns a pointer to the PROCESS_INFORMATION structure, and therefore can be declared as +LPPROCESS_INFORMATION. + +Remarks + +This data can only be retrieved from an active process. + +Example + +None. + + + + + + +GetStartupInformation function + +The GetStartupInformation function is used to retrieve the pointer to initialization data for the +debugged process. + +Syntax + + + +void* __stdcall GetStartupInformation(); + + + + + + + +Parameters + +None. + +Return value + +Returns pointer to a STARTUPINFOA structure, and can also be declared as LPSTARTUPINFOA. + +Remarks + +This data can only be retrieved from an active process. + +Example + +None. + + + + + + +GetDebuggedDLLBaseAddress function + +GetDebuggedDLLBaseAddress retrieves the base address on which the debugged DLL file was loaded. +This function is needed for DLL debugging, because a DLL may not be loaded on its default image base, +for example, if the default base address is reserved for some other module or ASLR file. + +Syntax + + + +long long __stdcall GetDebuggedDLLBaseAddress(); + + + + + + + +Parameters + +None. + +Return value + +This function returns a pointer to the base address on which debugged DLL file was loaded. It +can also be declared as void*. + + + +Remarks + +This data can only be retrieved from an active process whose DLL is being debugged. + +Example + +None. + + + + + + +GetDebuggedFileBaseAddress function + +GetDebuggedFileBaseAddress retrieves the base address on which the debugged file is loaded. It +retrieves the base address on which the debugged file was loaded. This function is needed for file +debugging, because a file may not be loaded on its default image base, for example, if the default base +address is reserved for some other module or ASLR file. Note, this function retrieves the base address of +the main module, so if you are debugging a DLL file, it will return the base address of the DLL loader. + +Syntax + + + +long long __stdcall GetDebuggedFileBaseAddress(); + + + + + + + +Parameters + +None. + +Return value + +This function returns a pointer the base address at which debugged file resides. It can also be +declared as void*. + + + +Remarks + +Process must be active to retrieve this data. + +Example + +None. + + + + + + +GetExitCode function + +GetExitCode retrieves a process exit code. + +Syntax + + + +long __stdcall GetExitCode(); + + + + + + + +Parameters + +None. + +Return value + +This function returns the exit code provided by the debugged file upon its termination. + + + +Remarks + +The process must be terminated to retrieve this data. + +Example + +None. + + + + +DebugLoop function + +DebugLoop starts the debugging process. Always call this function or DebugLoopEx after initializing the +debugger with one of the initialization functions. Set at least one breakpoint before running the +debugged or the application whose process is being debugged will run. DebugLoop will not return until +the debugger is finished and the debugged application has been terminated. + +Syntax + + + +void __stdcall DebugLoop(); + + + + + + + +Parameters + +None. + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + +DebugLoopEx function + +The DebugLoopEx function is used to start the debugging process. This function is always used after +debugger initialization. Before running the debugged process makes sure you have at least one +breakpoint set otherwise the application will run. Your program will not return from the call to +DebugLoopEx before the debugging is finished and debugged application has been terminated. + +Syntax + + + +void __stdcall DebugLoopEx( + +DWORD TimeOut + +); + + + + + + + + + +Parameters + +TimeOut + + [in] Value which to pass to the Windows WaitForDebugEvent API. + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + +SetDebugLoopTimeOut function + +SetDebugLoopTimeOut sets a debug timeout at runtime. This value is passed to the WaitForDebugEvent +Windows API. + +Syntax + + + +void __stdcall SetDebugLoopTimeOut( + +DWORD TimeOut + +); + + + + + + + + + +Parameters + +TimeOut + + [in] Value which will be passed to Windows WaitForDebugEvent API. + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + +SetNextDbgContinueStatus function + +SetNextDbgContinueStatus sets the parameter passed to the ContinueDebugEvent Windows API. + +Syntax + + + +void __stdcall SetNextDbgContinueStatus( + +DWORD SetDbgCode + +); + + + + + + + + + +Parameters + +SetDbgCode + + [in] Specify one of two values: DBG_CONTINUE or DBG_EXCEPTION_NOT_HANDLED. + + + +Return value + +None. + +Remarks + +USE WITH CAUTION: This function can break the debugging process. It may cause the debugged +target to exit the debugging loop, and terminate the application, or it may show an error +message on Windows Vista and later. + +Example + +None. + + + + +StopDebug function + +StopDebug stops the debugging process. The Debugged process is terminated just after the call to this +function, and program control is passed to the first command following the DebugLoop function that +started the debugging process. + +Syntax + + + +void __stdcall StopDebug(); + + + + + + + + + +Parameters + +None. + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + +ForceClose function + +ForceClose stops the debugging process. The debugged process is terminated just after the call to this +function and program control is passed to the first command following the DebugLoop function that +started the debugging process. If your code has crashed with an exception, ForceClose is a safer way to +terminate debugging than StopDebug. + +Syntax + + + +void __stdcall ForceClose(); + + + + + + + + + +Parameters + +None. + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + +SetBPXOptions function + +SetBPXOptions sets the global breakpoint type. Set type is global making all breakpoints set after calling +this function to be set as the selected type. + +Syntax + + + +void __stdcall SetBPXOptions( + +long DefaultBreakPointType + +); + + + + + + + + + +Parameters + +DefaultBreakPointType + + [in] Can be one of the following: + +. UE_BREAKPOINT_INT3 (0xCC) +. UE_BREAKPOINT_LONG_INT3 (0xCD03) +. UE_BREAKPOINT_UD2 (0x0F0B) + + +Return value + +None. + +Remarks + +UE_BREAKPOINT_UD2 refers to two byte INT3 defined as 0xCD03. + +Example + +None. + + + + + + +SetBPX function + +SetBPX sets INT 3 breakpoints. Specify the type of INT3 breakpoint with the SetBPXOptions function. + +Syntax + + + +bool __stdcall SetBPX( + +ULONG_PTR bpxAddress, + +DWORD bpxType, + +LPVOID bpxCallBack + +); + + + + + + + + + +Parameters + +bpxAddress + + [in] Address on which to set the breakpoint. + +bpxType + + [in] Type of breakpoint to set, either UE_BREAKPOINT or UE_SINGLESHOOT. By adding +one of the following values you can select the breakpoint type: + +. UE_BREAKPOINT_TYPE_INT3 (0xCC) +. UE_BREAKPOINT_TYPE_LONG_INT3 (0xCD03) +. UE_BREAKPOINT_TYPE_UD2 (0x0F0B) + + +bpxCallBack + + [in] Address of a callback to call when the breakpoint is hit. + + + +CallBack definition + +typedef void(__stdcall *cbBreakPoint)(void); + + + +Return value + +Boolean switch indicating whether or not the breakpoint was set. + +Remarks + +None. + +Example + +None. + + + + +SetBPXEx function + +SetBPXEx sets INT3 breakpoints. Set the type of INT3 breakpoint with the SetBPXOptions function. + +Syntax + + + +bool __stdcall SetBPXEx( + +ULONG_PTR bpxAddress, + +DWORD bpxType, + +DWORD NumberOfExecution, + +DWORD CmpRegister, + +DWORD CmpCondition, + +ULONG_PTR CmpValue, + +LPVOID bpxCallBack, + +LPVOID bpxCompareCallBack, + +LPVOID bpxRemoveCallBack + +); + + + + + + + + + + + + + +Parameters + +bpxAddress + + [in] Address at which a breakpoint will be set. + +bpxType + + [in] Type of the breakpoint to set. Either UE_BREAKPOINT or UE_SINGLESHOOT. By +adding one of the following values you can select the breakpoint type: + +. UE_BREAKPOINT_TYPE_INT3 (0xCC) +. UE_BREAKPOINT_TYPE_LONG_INT3 (0xCD03) +. UE_BREAKPOINT_TYPE_UD2 (0x0F0B) + + +NumberOfExecutions + + [in] Set maximum number of breakpoint executions. Specify NULL for no execution +limit. + +CmpRegister + + [in] Register to check to determine whether the breakpoint execution condition is met. + +CmpCondition + + [in] Type of comparison to run with the register. See Debugger module constants for +details. + +CmpValue + + [in] Value to use in the comparison. If condition has been met, the breakpoint callback +will be executed. See Debugger module constants for details. + + + + + + +bpxCallBack + + [in] Address of a callback to call once breakpoint has been hit. + +bpxCompareCallBack + + [in] Reserved, always set to NULL. + +bpxRemoveCallBack + + [in] The callback to call when the breakpoint is removed. + + + +CallBack definition + +typedef void(__stdcall *cbBreakPoint)(void); + + + +Return value + +Boolean switch indicating whether or not the breakpoint was set. + +Remarks + +All callbacks have the same declaration. + +Example + +None. + + + + + + +EnableBPX function + +EnableBPX enables a currently-disabled INT 3 breakpoint. This function can’t be used to enable memory +or hardware breakpoints, and should only be used after DisableBPX. + +Syntax + + + +bool __stdcall EnableBPX( + +ULONG_PTR bpxAddress + +); + + + + + + + + + +Parameters + +bpxAddress + + [in] Address of an existing breakpoint which you would like to re-enable after it has +been disabled with DisableBPX. + +Return value + +Boolean switch indicating whether or not the breakpoint was enabled. + +Remarks + +None. + +Example + +None. + + + + + + +DisableBPX function + +DisableBPX disables a currently enabled or active INT 3 breakpoint. This function can’t be used to +disable memory or hardware breakpoints. + +Syntax + + + +bool __stdcall DisableBPX( + +ULONG_PTR bpxAddress + +); + + + + + + + + + +Parameters + +bpxAddress + + [in] Address of the existing INT 3 breakpoint to disable. + +Return value + +Boolean switch indicating whether or not the breakpoint was disabled. + +Remarks + +None. + +Example + +None. + + + + + + +IsBPXEnabled function + +IsBPXEnabled determines whether or not the specified INT3 breakpoint is enabled. This function can’t +be used to check the state of memory or hardware breakpoints. + +Syntax + + + +bool __stdcall DisableBPX( + +ULONG_PTR bpxAddress + +); + + + + + + + + + +Parameters + +bpxAddress + + [in] Address of the existing INT3 breakpoint whose state you want to know. + + + +Return value + +Boolean switch indicating whether or not the breakpoint is enabled. + +Remarks + +None. + +Example + +None. + + + + + + +DeleteBPX function + +The DeleteBPX function is used to remove set INT3 breakpoints. This function can’t be used to remove +memory or hardware breakpoints. + +Syntax + + + +bool __stdcall DeleteBPX( + +ULONG_PTR bpxAddress + +); + + + + + + + + + +Parameters + +bpxAddress + + [in] Address of the INT3 breakpoint to remove. + + + +Return value + +Boolean switch indicating whether or not the breakpoint was removed. + +Remarks + +If the breakpoint was set with SetBPXEx, and a remove callback was specified via SetBPXEx, the +callback will be called once this function is called. + +Example + +None. + + + + + + +SafeDeleteBPX function + +This function has been deprecated. It has been preserved only for compatibility with earlier versions of +TitanEngine SDK. SafeDeleteBPX is used to remove an existing INT3 breakpoint. This function can’t be +used to remove memory or hardware breakpoints. + +Syntax + + + +bool __stdcall SafeDeleteBPX( + +ULONG_PTR bpxAddress + +); + + + + + + + + + +Parameters + +bpxAddress + + [in] Address of the existing INT3 breakpoint to remove. + + + +Return value + +Boolean switch indicating whether or not the breakpoint has been removed. + +Remarks + +If the breakpoint was set with SetBPXEx, and a remove callback was specified via SetBPXEx, the +callback will be called once this function is called. + +Example + +None. + + + + + + +SetAPIBreakPoint function + +The SetAPIBreakPoint sets an INT 3 breakpoint at an exported function in any loaded DLL file, not just +the system ones. + +Syntax + + + +bool __stdcall SetAPIBreakPoint( + +char* szDLLName, + +char* szAPIName, + +DWORD bpxType, + +DWORD bpxPlace, + +LPVOID bpxCallBack + +); + + + + + + + + + +Parameters + +szDLLName + + [in] Pointer to string. Specify the name of the DLL containing the function on which to +set the breakpoint, for example kernel32.dll. + +szAPIName + + [in] Pointer to string. Specify the name of the API on which to set the breakpoint, for +example VirtualAlloc. + +bpxType + + [in] Type of breakpoint to set. Either UE_BREAKPOINT or UE_SINGLESHOOT. + +bpxPlace + + [in] Where to set the breakpoint. Use UE_APISTART to specify the first +instruction of the API or UE_APIEND to specify the last instruction, which is +always RET or one of its variations. + +bpxCallBack + + [in] Address of a callback to call once the breakpoint is hit. + + + +CallBack definition + +typedef void(__stdcall *cbBreakPoint)(void); + + + +Return value + +Boolean switch indicating whether or not the breakpoint was set. + +Remarks + +None. + + + + +DeleteAPIBreakPoint function + +DeleteAPIBreakPoint removes an existing INT3 breakpoint from a function inside a DLL file. + +Syntax + + + +bool __stdcall DeleteAPIBreakPoint( + +char* szDLLName, + +char* szAPIName, + +DWORD bpxPlace + +); + + + + + + + + + +Parameters + +szDLLName + +[in] Pointer to string. Specify the name of the DLL containing the function on which to +set the breakpoint, for example kernel32.dll. + +szAPIName + + [in] Pointer to string. Specify the name of the API on which the breakpoint was set, for +example VirtualAlloc. + +bpxPlace + + [in] Where on the API the breakpoint was set. Valid values: UE_APISTART if the +breakpoint was set on the first instruction in the API, or UE_APIEND if the +breakpoint was set on the last instruction in the API, which is always RET or a +variation. + +Return value + +Boolean switch indicating whether or not the breakpoint has been removed. + +Remarks + +None. + +Example + +None. + + + + + + +SafeDeleteAPIBreakPoint function + +The SafeDeleteAPIBreakPoint function removes INT3 breakpoints from functions inside DLL files. This +function has been preserved only for backward compatibility with earlier versions of TitanEngine SDK. + +Syntax + + + +bool __stdcall SafeDeleteAPIBreakPoint( + +char* szDLLName, + +char* szAPIName, + +DWORD bpxPlace + +); + + + + + + + + + +Parameters + +szDLLName + + [in] Pointer to string specifying the name of the DLL containing the function on which +the breakpoint was set, for example kernel32.dll. + +szAPIName + + [in] Pointer to string specitying the name of the API on which the breakpoint was set, +for example VirtualAlloc. + +bpxPlace + + [in] Location in the API at which the breakpoint was set. Use UE_APISTART if the +breakpoint was set at the first instruction in the API or UE_APIEND if the +breakpoint was set at the last instructionin the API, which is always RET or a +variation. + +Return value + +Boolean switch indicating whether or not the breakpoint has been removed. + +Remarks + + This function has been replaced by DeleteAPIBreakpoint. + +Example + +None. + + + + + + +SetMemoryBPX function + +SetMemoryBPX sets memory breakpoints. These breakpoints are set by PAGE_GUARD to a targeted +memory region. If your breakpoint size is smaller than one page, the whole page will be affected by the +PAGE_GUARD and therefore it is possible that the page will be hit, but your breakpoint will not be +handled. Keep this in mind when setting this kind of breakpoint, and always set your breakpoint to a +whole page. + +Syntax + + + +bool __stdcall SetMemoryBPX( + +ULONG_PTR MemoryStart, + +DWORD SizeOfMemory, + +LPVOID bpxCallBack + +); + + + + + + + + + +Parameters + +MemoryStart + + [in] Address on which breakpoint will be set. Ideally this is equal to page start. + +SizeOfMemory + + [in] Size of the memory to be affected by PAGE_GUARD. + +bpxCallBack + +[in] Address of the callback to call once breakpoint is hit. + + + +CallBack definition + +typedef void(__stdcall *cbBreakPoint)(void); + + + +Return value + +Boolean switch indicating whether or not the breakpoint was set. + +Remarks + +None. + +Example + +None. + + + + + + +SetMemoryBPXEx function + +Like SetMemoryBPX, the function SetMemoryBPXEx sets memory breakpoints, but SetMemoryBPXEx +allows you to specify which type of memory access will trigger the break, and whether or not to restore +the breakpoint once it has been hit. + +These breakpoints are set by PAGE_GUARD to targeted memory region. If your breakpoint size is +smaller than one page, the whole page will be affected by the PAGE_GUARD and therefore it is possible +that the page will be hit, but your breakpoint will not be handled. Keep this in mind when setting this +kind of breakpoint, and always set your breakpoint to a whole page. + +Syntax + + + +bool __stdcall SetMemoryBPXEx( + +ULONG_PTR MemoryStart, + +DWORD SizeOfMemory, + +DWORD BreakPointType, + +bool RestoreOnHit, + +LPVOID bpxCallBack + +); + + + + + + + + + +Parameters + +MemoryStart + + [in] Address on which to set the breakpoint. Ideally this is the start of a page. + +SizeOfMemory + + [in] Size of the memory to be affected by PAGE_GUARD. + +BreakPointType + + [in] Defines type of memory breakpoint. Depending on the usage this can be either +UE_MEMORY, UE_MEMORY_READ, or UE_MEMORY_WRITE. Where UE_MEMORY +breaks on any type of access, UE_MEMORY_READ breaks only on read access, and +UE_MEMORY_WRITE breaks only on write access. + +RestoreOnHit + + [in] Indicates whether or not to restore the breakpoint once it is executed. By default, a +memory breakpoint is triggered only once, unless you use this option to restore it. + +bpxCallBack + + [in] Address of a callback to call when the breakpoint is hit. + +CallBack definition + +typedef void(__stdcall *cbBreakPoint)(void); + + + +Return value + +Boolean switch indicating whether or not the breakpoint was set. + + + + +RemoveMemoryBPX function + +RemoveMemoryBPX removes previously-set memory breakpoints by removing PAGE_GUARD from +page protection flags. + +Syntax + + + +bool __stdcall RemoveMemoryBPX( + +ULONG_PTR MemoryStart, + +DWORD SizeOfMemory + +); + + + + + + + + + +Parameters + +MemoryStart + + [in] Address on which breakpoint was set. + +SizeOfMemory + + [in] Size of the memory that was specified when the breakpoint was set. + + + +Return value + +Boolean switch indicating whether or not the breakpoint is removed. + +Remarks + +None. + +Example + +None. + + + + + + +SetHardwareBreakPoint function + +The SetHardwareBreakPoint function is used to set hardware breakpoints. These breakpoints can only +be set on CPUs that support them. + +Syntax + + + +bool __stdcall SetHardwareBreakPoint( + +ULONG_PTR bpxAddress, + +DWORD IndexOfRegister, + +DWORD bpxType, + +DWORD bpxSize, + +LPVOID bpxCallBack + +); + + + + + + + + + +Parameters + +bpxAddress + + [in] Address on which to set the breakpoint. + +IndexOfRegister + + [in] Register that holds the bpxAddress. Specify a register in the range DR0 to DR3. If no +register is specified, the first available free register will be used. + +bpxType + + [in] Type of the breakpoint to set. UE_HARDWARE_EXECUTE, UE_HARDWARE_WRITE or +UE_HARDWARE_READWRITE. First type sets breakpoint on that memory execution +while other two set breakpoint on memory access. + +bpxSize + + [in] Size of the breakpoint to set. UE_HARDWARE_SIZE_1, UE_HARDWARE_SIZE_2 or +UE_HARDWARE_SIZE_4 indicating the size in bytes affected by the breakpoint. + +bpxCallBack + + [in] Address of a callback which to call when the breakpoint is hit. + + + +CallBack definition + +typedef void(__stdcall *cbBreakPoint)(void); + + + +Return value + +Boolean switch indicating whether or not the breakpoint was set. + +Remarks + +None. + + + + +SetHardwareBreakPointEx function + +The SetHardwareBreakPointEx function is used to set hardware breakpoints. These breakpoints can +only be set on CPUs that support them. Function has the same callback definition as non expert version. + +Syntax + +bool __stdcall SetHardwareBreakPoint( + +HANDLE hActiveThread, + +ULONG_PTR bpxAddress, + +DWORD IndexOfRegister, + +DWORD bpxType, + +DWORD bpxSize, + +LPVOID bpxCallBack, + +LPDWORD IndexOfSelectedRegister + +); + + + + + + + + + + + + + +Parameters + +hActiveThread + + [in] Handle of the open thread from which context will be set. + +bpxAddress + + [in] Address on which to set the breakpoint. + +IndexOfRegister + + [in] Register that holds the bpxAddress. Specify a register in the range DR0 to DR3. If no +register is specified, the first available free register will be used. + +bpxType + + [in] Type of the breakpoint to set. UE_HARDWARE_EXECUTE, UE_HARDWARE_WRITE or +UE_HARDWARE_READWRITE. First type sets breakpoint on that memory execution +while other two set breakpoint on memory access. + +bpxSize + + [in] Size of the breakpoint to set. UE_HARDWARE_SIZE_1, UE_HARDWARE_SIZE_2 or +UE_HARDWARE_SIZE_4 indicating the size in bytes affected by the breakpoint. + +bpxCallBack + + [in] Address of a callback which will be called once breakpoint has been hit. + +IndexOfSelectedRegister + + [out] Pointer to DWORD variable which will receive the index of the register used to set +the hardware breakpoint. + + + +Return value + +Boolean switch indicating whether or not the breakpoint was set. + + + + +DeleteHardwareBreakPoint function + +DeleteHardwareBreakPoint removes a previously-set hardware breakpoint. + +Syntax + + + +bool __stdcall DeleteHardwareBreakPoint( + +DWORD IndexOfRegister + +); + + + + + + + + + +Parameters + +IndexOfRegister + + [in] The register containing the breakpoint's address pointer (DR0 to DR3). + + + +Return value + +Boolean switch indicating whether or not the breakpoint has been removed. + +Remarks + +None. + +Example + +None. + + + + + + +GetUnusedHardwareBreakPointRegister function + +GetUnusedHardwareBreakPointRegister get the currently free DRx register. + +Syntax + + + +bool __stdcall GetUnusedHardwareBreakPointRegister( + +LPDWORD RegisterIndex + +); + + + + + + + + + +Parameters + +IndexOfRegister + + [out] Pointer to the variable which will receive the free DRx register (DR0 to DR3). + + + +Return value + +Boolean switch indicating whether or not the any of the registers is free. + +Remarks + +None. + +Example + +None. + + + + +RemoveAllBreakPoints function + +RemoveAllBreakPoints removes/disables all breakpoints of the specified type(s). + +Syntax + + + +bool __stdcall RemoveAllBreakPoints( + +DWORD RemoveOption + +); + + + + + + + + + +Parameters + +RemoveOption + + [in] One of the following: + +. UE_OPTION_REMOVEALL, removes all breakpoints. +. UE_OPTION_DISABLEALL, disables all breakpoints excluding hardware ones. +. UE_OPTION_REMOVEALLDISABLED, removes all disabled INT3 breakpoints. +. UE_OPTION_REMOVEALLENABLED, removes all active INT3 breakpoints. + + + + +Return value + +Boolean switch indicating whether or not the breakpoints were removed. + +Remarks + +None. + +Example + +None. + + + + + + +CurrentExceptionNumber function + +CurrentExceptionNumber retrieves the number of exceptions that were registered and processed prior +to this function being called. + +Syntax + + + +long __stdcall CurrentExceptionNumber(); + + + + + + + + + +Parameters + +None. + +Return value + +Function returns the number of registered exceptions. + +Remarks + +None. + +Example + +None. + + + + + + +ClearExceptionNumber function + +ClearExceptionNumber resets to zero the number of exceptions that were registered and processed +prior to this function being called. + +Syntax + + + +long __stdcall ClearExceptionNumber(); + + + + + + + + + +Parameters + +None. + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + +GetDebugData function + +GetDebugData retrieves a pointer to an internal DEBUG_EVENT structure. + +Syntax + + + +void* __stdcall GetDebugData(); + + + + + + + + + +Parameters + +None. + +Return value + +Pointer to DEBUG_EVENT structure. Can be declared as LPDEBUG_EVENT instead of void*. + +Remarks + +Process must be active for this function to work. + +Example + +None. + + + + + + +GetTerminationData function + +GetTerminationData retrieves a pointer to an internal DEBUG_EVENT structure. GetTerminationData is +similar to GetDebugData but is used only when the process has terminated its execution. + +Syntax + + + +void* __stdcall GetTerminationData(); + + + + + + + + + +Parameters + +None. + +Return value + +Pointer to a DEBUG_EVENT structure. Can be declared as LPDEBUG_EVENT instead of void*. + +Remarks + +Function can only be used for terminated processes. + +Example + +None. + + + + + + +GetContextDataEx function + +GetContextDataEx retrieves data from the context of any debugged process thread. You can use engine +thread handling functions to get the handles of all active threads. + +Syntax + + + +long long __stdcall GetContextDataEx( + +HANDLE hActiveThread, + +DWORD IndexOfRegister + +); + + + + + + + + + +Parameters + +hActiveThread + + [in] Handle of the open thread from which to read the context. + +IndexOfRegister + + [in] Indicator on which register will be read from the context of the selected thread. See +Debugger module constants for details. + + + +Return value + +This function returns the requested data. + + + +Remarks + +None. + +Example + +None. + + + + + + +GetContextData function + +GetContextData retrieves context data from the thread that generated the last exception or timeout in +the active process that the debugger is currently processing. Use GetContextDataEx if you want to get +the context for a specific thread. + +Syntax + + + +long long __stdcall GetContextData( + +DWORD IndexOfRegister + +); + + + + + + + + + +Parameters + +IndexOfRegister + + [in] Indicator on which register will be read from the context of the selected thread. See +Debugger module constants for details. + + + +Return value + +This function returns the requested data. + + + +Remarks + +None. + +Example + +None. + + + + + + +SetContextDataEx function + +SetContextDataEx sets the context data for the process thread that is being debugged. + +Syntax + + + +bool __stdcall SetContextDataEx( + +HANDLE hActiveThread, + +DWORD IndexOfRegister, + +ULONG_PTR NewRegisterValue + +); + + + + + + + + + +Parameters + +hActiveThread + + [in] Handle of the open thread whose context will be set. + +IndexOfRegister + + [in] Specifies the context register to modify. See Debugger module constants for details. + +NewRegisterValue + + [in] The new context value to place in the register. + + + +Return value + +Boolean switch indicating whether or not the value in the register was updated. + +Remarks + +CAUTION: This function modifies context of the thread, so be careful using it, since corrupting +certain registers can cause the application to crash. + +Example + +None. + + + + + + +SetContextData function + +SetContextData sets the context data for the active process thread that generated the most recent +exception or debug timeout. + +Syntax + + + +bool __stdcall SetContextData( + +DWORD IndexOfRegister, + +ULONG_PTR NewRegisterValue + +); + + + + + + + + + +Parameters + +IndexOfRegister + + [in] Specifies the context register to modify. See Debugger module constants for details. + +NewRegisterValue + + [in] The new context value to use. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +CAUTION: This function modifies context of the thread, so be careful using it, since corrupting +certain registers can cause the application to crash. + +Example + +None. + + + + + + +GetContextFPUDataEx function + +GetContextFPUDataEx retrieves FPU data from the context of any debugged process thread. You can +use engine thread handling functions to get the handles of all active threads. + +Syntax + + + +bool __stdcall GetContextFPUDataEx( + +HANDLE hActiveThread, + +void* FPUSaveArea + +); + + + + + + + +Parameters + +hActiveThread + + [in] Handle of the open thread from which to read the context. + +FPUSaveArea + +[out] Pointer to FLOATING_SAVE_AREA structure defined in WinNT.h for 32 bit systems +or to XMM_SAVE_AREA32 for 64 bit systems. + + + +Return value + +This function returns TRUE on successful data retrieval or FALSE if data isn’t available. + + + +Remarks + +None. + +Example + +None. + + + + + + +SetContextFPUDataEx function + +SetContextFPUDataEx sets FPU data in the context of any debugged process thread. You can use engine +thread handling functions to get the handles of all active threads. + +Syntax + + + +bool __stdcall SetContextFPUDataEx( + +HANDLE hActiveThread, + +void* FPUSaveArea + +); + + + + + + + +Parameters + +hActiveThread + + [in] Handle of the open thread from which to read the context. + +FPUSaveArea + + [in] Pointer to FLOATING_SAVE_AREA structure defined in WinNT.h for 32 bit systems +or to XMM_SAVE_AREA32 for 64 bit systems. + + + +Return value + +This function returns TRUE on successful data update or FALSE if update failed. + + + +Remarks + +None. + +Example + +None. + + + + +StepInto function + +StepInto traces code by single-stepping into calls. This tracing function sets a trap flag and calls your +callback once that trap flag has been activated. This allows you to execute one instruction at a time, +making it possible to trace through the execution of each instruction. + +Syntax + + + +void __stdcall StepInto( + +LPVOID StepCallBack + +); + + + + + + + + + +Parameters + +StepCallBack + + [in] Address of the callback to call when trap flag has been hit. + + + +CallBack definition + +typedef void(__stdcall *cbBreakPoint)(void); + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + +StepOver function + +The StepOver traces code by single-stepping over calls. This tracing function sets an INT3 breakpoint +after the call, which is used to call your callback. There is no guarantee that code execution will return +from that call, and thus no guarantee that your callback will ever be called. The breakpoint is run only +once, and is removed once your callback has finished. + +Syntax + + + +void __stdcall StepOver( + +LPVOID StepCallBack + +); + + + + + + + + + +Parameters + +StepCallBack + + [in] Address of the callback to call when the breakpoint has been hit. + + + +CallBack definition + +typedef void(__stdcall *cbBreakPoint)(void); + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + +SingleStep function + +The SingleStep traces code by single-stepping through a series of instructions. This tracing function sets +a trap flag and calls your callback once that trap flag has been activated. This allows you to execute one +instruction at a time, making it possible to trace through the execution of each instruction. + +Syntax + + + +void __stdcall SingleStep( + +DWORD StepCount, + +LPVOID StepCallBack + +); + + + + + + + + + +Parameters + +StepCount + + [in] Number of instructions to trace. Your callback will be called each time an +instruction executes, up to the number of instructions specified. + +StepCallBack + + [in] Address of the callback to call when each instruction executes. + + + +CallBack definition + +typedef void(__stdcall *cbBreakPoint)(void); + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + +FindEx function + +FindEx searches the process memory for binary patterns. + +Syntax + + + +long long __stdcall FindEx( + +HANDLE hProcess, + +LPVOID MemoryStart, + +DWORD MemorySize, + +LPVOID SearchPattern, + +DWORD PatternSize, + +LPBYTE WildCard + +); + + + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be searched. + +MemoryStart + + [in] Pointer to the memory location to use as the start point for the search. + +MemorySize + + [in] Size of the memory region to search for the byte pattern. + +SearchPattern + + [in] Pointer to the sequence of bytes to find. + +PatternSize + + [in] Size of the search pattern, in bytes. + +WildCard + + [in] Pointer to a wild card byte which will be ignored during search. This wild card is +equal to search asterisk “?” and those bytes inside the search pattern will always be +considered as found. Usually this byte is NULL. + +Return value + +Function returns pointer to the first byte of the found pattern inside the remote process. It can +also be declared as void*, or NULL if byte pattern is not found. + +Remarks + +None. + + + + + + +Find function + +Find searches the process memory for binary patterns. This function always searches the memory of the +currently debugger process. + +Syntax + + + +long long __stdcall Find( + +LPVOID MemoryStart, + +DWORD MemorySize, + +LPVOID SearchPattern, + +DWORD PatternSize, + +LPBYTE WildCard + +); + + + + + + + + + + + +Parameters + +MemoryStart + + [in] Pointer to memory in remote process which is used as a start point for the search. + +MemorySize + + [in] Size of the memory which will be searched for byte pattern. + +SearchPattern + + [in] Pointer to sequence of bytes which represent the search pattern. + +PatternSize + + [in] Size of the search pattern in bytes. + +WildCard + + [in] Pointer to a wild card byte which will be ignored during search. This wild card is +equal to search asterisk “?” and those bytes inside the search pattern will always be +considered as found. Usually this byte is NULL. + +Return value + +Function returns pointer to first byte of the found pattern inside the remote process. Therefore +it can also be declared as void*, or NULL if byte pattern is not found. + +Remarks + +None. + + + + + + +MatchPatternEx function + +MatchPatternEx tries to match the selected pattern to specified memory address. + +Syntax + + + +bool __stdcall MatchPatternEx( + +HANDLE hProcess, + +void* MemoryToCheck, + +int SizeOfMemoryToCheck, + +void* PatternToMatch, + +int SizeOfPatternToMatch, + +PBYTE WildCard + +); + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be searched. + +MemoryToCheck + + [in] Pointer to the memory location to use as the start point for the pattern match. + +SizeOfMemoryToCheck + + [in] Size of the memory region to check the pattern match. + +PattternToMatch + + [in] Pointer to the sequence of bytes to match. + +SizeOfPatternToMatch + + [in] Size of the match pattern, in bytes. + +WildCard + + [in] Pointer to a wild card byte which will be ignored during search. This wild card is +equal to search asterisk “?” and those bytes inside the search pattern will always be +considered as found. Usually this byte is NULL. + +Return value + +Function returns TRUE if the provided pattern matches the memory content or FALSE if it +doesn’t. + +Remarks + +None. + + + + + + +MatchPattern function + +MatchPattern tries to match the selected pattern to specified memory address. + +Syntax + + + +bool __stdcall MatchPattern( + +void* MemoryToCheck, + +int SizeOfMemoryToCheck, + +void* PatternToMatch, + +int SizeOfPatternToMatch, + +PBYTE WildCard + +); + + + + + + + + + +Parameters + +MemoryToCheck + + [in] Pointer to the memory location to use as the start point for the pattern match. + +SizeOfMemoryToCheck + + [in] Size of the memory region to check the pattern match. + +PattternToMatch + + [in] Pointer to the sequence of bytes to match. + +SizeOfPatternToMatch + + [in] Size of the match pattern, in bytes. + +WildCard + + [in] Pointer to a wild card byte which will be ignored during search. This wild card is +equal to search asterisk “?” and those bytes inside the search pattern will always be +considered as found. Usually this byte is NULL. + +Return value + +Function returns TRUE if the provided pattern matches the memory content or FALSE if it +doesn’t. + +Remarks + +None. + + + + + + + + +FillEx function + +FillEx fills the specified process memory location with the specified byte. If the location size is larger +than a byte, the byte is repeated until the location is full. Most commonly this is done to NOP parts of +the code, or to zero out a memory region. + +Syntax + + + +bool __stdcall FillEx( + +HANDLE hProcess, + +LPVOID MemoryStart, + +DWORD MemorySize, + +PBYTE FillByte + +); + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be patched. + +MemoryStart + + [in] Pointer to memory in remote process which is used as a start point for the filling. + +MemorySize + + [in] Size of the memory which will be filled with selected byte. + +FillByte + + [in] Pointer to byte which will be used for memory filling. + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + +Fill function + +Fill fills the currently debugged process memory location with the specified byte. If the location size is +larger than a byte, the byte is repeated until the location is full. Most commonly this is done to NOP +parts of the code, or to zero out a memory region. + +Syntax + + + +bool __stdcall Fill( + +LPVOID MemoryStart, + +DWORD MemorySize, + +PBYTE FillByte + +); + + + + + + + + + +Parameters + +MemoryStart + + [in] Pointer to memory in remote process which is used as a start point for the filling. + +MemorySize + + [in] Size of the memory which will be filled with selected byte. + +FillByte + + [in] Pointer to byte which will be used for memory filling. + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + +PatchEx function + +PatchEx fills a process memory location with the specified multi-byte pattern. If the region being filled is +larger than the pattern, the remaining bytes may optionally be NOPed or left unmodified. + +Syntax + + + +bool __stdcall PatchEx( + +HANDLE hProcess, + +LPVOID MemoryStart, + +DWORD MemorySize, + +LPVOID ReplacePattern, + +DWORD ReplaceSize, + +bool AppendNOP, + +bool PrependNOP + +); + + + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be patched. + +MemoryStart + + [in] Pointer to memory in remote process which is used as a start point for the patch. + +MemorySize + + [in] Size of the memory which will be patched with selected byte pattern. + +ReplacePattern + + [in] Pointer to sequence of bytes which will be written to targeted memory. + +ReplaceSize + + [in] Size of the replace pattern. + +AppendNOP + + [in] If the patch size is lesser then targeted memory size patching NOPs can be +appended to patch bytes to make that memory execution safe. + +PrependNOP + + [in] If the patch size is lesser then targeted memory size patching NOPs can be prepend +to patch bytes to make that memory execution safe. + +Return value + +Boolean switch indicating whether or not the function was successful. + + + + + + +Patch function + +Patch fills a memory location with the specified multi-byte pattern. If the region being filled is larger +than the pattern, the remaining bytes may optionally be NOPed or left unmodified. This function always +patches the process currently being debugged. + +Syntax + + + +bool __stdcall Patch( + +LPVOID MemoryStart, + +DWORD MemorySize, + +LPVOID ReplacePattern, + +DWORD ReplaceSize, + +bool AppendNOP, + +bool PrependNOP + +); + + + + + + + + + + + +Parameters + +MemoryStart + + [in] Pointer to memory in remote process which is used as a start point for the patch. + +MemorySize + + [in] Size of the memory which will be patched with selected byte pattern. + +ReplacePattern + + [in] Pointer to sequence of bytes which will be written to targeted memory. + +ReplaceSize + + [in] Size of the replace pattern. + +AppendNOP + + [in] If the patch size is lesser then targeted memory size patching NOPs can be +appended to patch bytes to make that memory execution safe. + +PrependNOP + + [in] If the patch size is lesser then targeted memory size patching NOPs can be prepend +to patch bytes to make that memory execution safe. + +Return value + +Boolean switch indicating whether or not the function was successful. + + + + + + +ReplaceEx function + +ReplaceEx does a search and replace on a specific byte pattern in a process memory location. When the +byte pattern is found, it is replaced with the byte pattern you specify. Number of matches which will be +replaced can be specified. Any remaining bytes may optionally be NOPed or left unmodified. + + + +Syntax + + + +bool __stdcall ReplaceEx( + +HANDLE hProcess, + +LPVOID MemoryStart, + +DWORD MemorySize, + +LPVOID SearchPattern, + +DWORD PatternSize, + +DWORD NumberOfRepetitions, + +LPVOID ReplacePattern, + +DWORD ReplaceSize, + +PBYTE WildCard + +); + + + + + + + + + + + + + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be patched. + +MemoryStart + + [in] Pointer to memory in remote process which is used as a start point for the search. + +MemorySize + + [in] Size of the memory which will be searched for the byte pattern. + +SearchPattern + + [in] Pointer to sequence of bytes which represent the search pattern. + +NumberOfRepetitions + + [in] Maximum number of patterns which will be replaced. + +PatternSize + + [in] Size of the search pattern in bytes. + +ReplacePattern + + [in] Pointer to sequence of bytes which will be written to targeted memory. + +ReplaceSize + + [in] Size of the replace pattern. + +WildCard + + [in] Pointer to a wild card byte which will be ignored during search and replace. This +wild card is equal to search asterisk “?” and those bytes inside the search pattern +will always be considered as found. Usually this byte is NULL. + + + + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +Both search and replace patterns can have wild card bytes to ignore during search and replace. + +Example + +None. + + + + + + +Replace function + +Replace does a search and replace on a specific byte pattern in a memory location. When the byte +pattern is found, it is replaced with the byte pattern you specify. This function always replaces the byte +pattern in the process currently being debugged. + +Syntax + + + +bool __stdcall Replace( + +LPVOID MemoryStart, + +DWORD MemorySize, + +LPVOID SearchPattern, + +DWORD PatternSize, + +DWORD NumberOfRepetitions, + +LPVOID ReplacePattern, + +DWORD ReplaceSize, + +PBYTE WildCard + +); + + + + + + + + + + + + + +Parameters + +MemoryStart + + [in] Pointer to memory in remote process which is used as a start point for the search. + +MemorySize + + [in] Size of the memory which will be searched for the byte pattern. + +SearchPattern + + [in] Pointer to sequence of bytes which represent the search pattern. + +NumberOfRepetitions + + [in] Maximum number of patterns which will be replaced. + +PatternSize + + [in] Size of the search pattern in bytes. + +ReplacePattern + + [in] Pointer to sequence of bytes which will be written to targeted memory. + +ReplaceSize + + [in] Size of the replace pattern. + +WildCard + + [in] Pointer to a wild card byte which will be ignored during search and replace. This +wild card is equal to search asterisk “?” and those bytes inside the search pattern +will always be considered as found. Usually this byte is NULL. + + + + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +Both search and replace patterns can have wild card bytes which will be ignored during search +and replace. + +Example + +None. + + + + + + +GetRemoteString function + +GetRemoteString retrieves a string from a remote process. This function can read both ASCII and +UNICODE strings. + +Syntax + + + +bool __stdcall GetRemoteString( + +HANDLE hProcess, + +LPVOID StringAddress, + +LPVOID StringStorage, + +int MaximumStringSize + +); + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process from which the string will be read. + +StringAddress + + [in] Pointer to string in remote process which will be copied to selected memory. + +StringStorage + + [out] Pointer to memory location inside your code which will receive the remote string +content. + +MaximumStringSize + + [in] Size of the local memory buffer reserved for reading the remote string. + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +Always copies the maximum available bytes but keeping in mind the bounds imposed by the +maximum size of the string. + +Example + +None. + + + + + + +GetFunctionParameter function + +GetFunctionParameter retrieves the value of an input parameter from a standard function types. +GetFunctionParameter can only work if the function's execution has been paused at either the first +instruction of the call or the last instruction inside the call. + +Syntax + + + +long long __stdcall GetFunctionParameter( + +HANDLE hProcess, + +DWORD FunctionType, + +DWORD ParameterNumber, + +DWORD ParameterType + +); + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process from which the function parameter will be read. Debugged +process handle should always be used. + +FunctionType + + [in] Can be one of the following: + +. UE_FUNCTION_STDCALL, EIP/RIP at first instruction inside the call. +. UE_FUNCTION_CCALL, EIP/RIP at first instruction inside the call. +. UE_FUNCTION_FASTCALL, EIP/RIP at first instruction inside the call. +. UE_FUNCTION_STDCALL_RET, EIP/RIP at last instruction of the call (RET). +. UE_FUNCTION_CCALL_RET, EIP/RIP at last instruction of the call (RET). +. UE_FUNCTION_FASTCALL_RET, EIP/RIP at last instruction of the call (RET). +. UE_FUNCTION_STDCALL_CALL, reserved for future use. +. UE_FUNCTION_FASTCALL_CALL, reserved for future use. + + +ParameterNumber + + [in] Number if the input parameter whose value will be returned. + +ParameterType + + [in] Can be one of the following: UE_PARAMETER_BYTE, UE_PARAMETER_WORD, +UE_PARAMETER_DWORD, UE_PARAMETER_QWORD, UE_PARAMETER_PTR_BYTE, +UE_PARAMETER_PTR_WORD, UE_PARAMETER_PTR_DWORD, UE_PARAMETER_PTR_QWORD, +UE_PARAMETER_STRING or UE_PARAMETER_UNICODE. + + + + + + + + +Return value + +Returns either the requested value or a pointer to string, depending on the parameter type. If +the parameter type is PTR then this function will return the data to which the pointer points. So +if you use PARAMETER_PTR_DWORD it will return the DWORD to which that parameter points. + +Remarks + +Maximum length of the read string is 512 characters. + +The Stack is acquired for the currently paused thread inside the debugged process. + + + +Example: + +/*7630B86F*/ MOV EDI,EDI ;<- EIP at VirtualAlloc + +/*7630B871*/ PUSH EBP + +/*7630B872*/ MOV EBP,ESP + +/*7630B874*/ PUSH DWORD PTR SS:[EBP+14] + +/*7630B877*/ PUSH DWORD PTR SS:[EBP+10] + +/*7630B87A*/ PUSH DWORD PTR SS:[EBP+C] + +/*7630B87D*/ PUSH DWORD PTR SS:[EBP+8] + +/*7630B880*/ PUSH -1 + +/*7630B882*/ CALL kernel32.VirtualAllocEx + +/*7630B887*/ POP EBP + +/*7630B888*/ RET 10 + + + +Stack: + +0012FA6C 004015A0 /CALL to VirtualAlloc from 0040159B + +0012FA70 00000000 |Address = NULL + +0012FA74 00100000 |Size = 100000 (1048576.) + +0012FA78 00002000 |AllocationType = MEM_RESERVE + +0012FA7C 00000001 \Protect = PAGE_NOACCESS + + + + + + + + + + + + + + + + + + + +Calling GetFunctionParameter to return the second input parameter of the VirtualAlloc function we will +need to call it like this: + +GetFunctionParameter(hProcess, UE_FUNCTION_STDCALL , 2, UE_PARAMETER_DWORD); + +Which returns 0x00100000. If the EIP was at the RET instruction this function would be called like this: + +GetFunctionParameter(hProcess, UE_FUNCTION_STDCALL_RET , 2, UE_PARAMETER_DWORD); + +Which would return the same value. + + + + + + +GetJumpDestinationEx function + +GetJumpDestinationEx determines where the specified jump or call instruction will land. + +Syntax + + + +long long __stdcall GetJumpDestinationEx( + +HANDLE hProcess, + +ULONG_PTR InstructionAddress, + +bool JustJumps + +); + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process in which the jump or call resides. + +InstructionAddress + + [in] Address of the jump or call whose destination you want to find. + +JustJumps + + [in] Boolean switch that indicates whether or to get destinations for calls or only jumps. + +Return value + +Returns the address targeted by jump/call or NULL if the instruction at the specified address +isn’t a jump or call. + +Remarks + +None. + +Example + +None. + + + + + + +GetJumpDestination function + +GetJumpDestination determines where the specified jump or call instruction will land. + + Syntax + + + +long long __stdcall GetJumpDestination( + +HANDLE hProcess, + +ULONG_PTR InstructionAddress + +); + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process in which the jump or call resides. + +InstructionAddress + + [in] Address on which the jump or call is located. + + + +Return value + +Returns the address targeted by jump/call or NULL if the instruction on selected address isn’t +jump or call. + +Remarks + +Function calls GetJumpDestinationEx with JustJumps parameter set to FALSE. + +Example + +None. + + + + + + +IsJumpGoingToExecuteEx function + +IsJumpGoingToExecuteEx determines whether or not the targeted jump is going to execute. +IsJumpGoingToExecuteEx allows you to specify which process and which thread to check. + +Syntax + + + +bool __stdcall IsJumpGoingToExecuteEx( + +HANDLE hProcess, + +HANDLE hThread, + +ULONG_PTR InstructionAddress, + +ULONG_PTR RegFlags + +); + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process in which the jump resides. + +hThread + + [in] Handle of the thread from which EFLAGS/RFLAGS will be read. + +InstructionAddress + + [in] Address on which the jump is located. Optional parameter, if it is not specified +instruction at EIP/RIP will be targeted. + +RegFlags + + [in] Used to override current EFLAGS/RFLAGS. Used only if EIP/RIP isn’t at targeted +instruction. Optional parameter, if not specified EFLAGS/RFLAGS will be read from +the specified thread. + + + +Return value + +Returns TRUE if jump would execute if execution continues or FALSE if not. + +Remarks + +None. + +Example + +None. + + + + + + +IsJumpGoingToExecute function + +IsJumpGoingToExecute check if the targeted jump is going to execute or not for the currently active +thread in the process currently being debugged. + +Syntax + + + +bool __stdcall IsJumpGoingToExecute(); + + + + + + + + + +Parameters + +None. + +Return value + +Returns TRUE if jump would execute if execution continues or FALSE if not. + +Remarks + +Function assumes currently debugged process and currently active thread executing jump at +current EIP/RIP. + +Example + +None. + + + + + + +SetCustomHandler function + +SetCustomHandler allows you to specify a custom exception handler for the specified exception. You +can handle the most commonly generated errors via the built-in definitions, or you can handle all +exceptions and filter only the ones of interest to you. + +Syntax + + + +void __stdcall SetCustomHandler( + +DWORD ExceptionId, + +LPVOID CallBack + +); + + + + + + + + + +Parameters + +ExceptionId + + [in] Exception identifier, exact code and alias can be found at Debugger module +constants. + +CallBack + +[in] Pointer to callback function which will be called when application encounters that +specific exception. + +CallBack definition + +typedef void(__stdcall *cbCustomHandler)(void* ExceptionData); + + + +Return value + +None. + +Remarks + +See below for ExceptionData callback details. + +Example + +None. + + + + + + +SetCustomHandler CallBack details + + + +UE_CH_BREAKPOINT + +ExceptionData points to: &DBGEvent.u.Exception.ExceptionRecord + +UE_CH_SINGLESTEP + +ExceptionData points to: &DBGEvent.u.Exception.ExceptionRecord + +UE_CH_ACCESSVIOLATION + +ExceptionData points to: &DBGEvent.u.Exception.ExceptionRecord + +UE_CH_ILLEGALINSTRUCTION + +ExceptionData points to: &DBGEvent.u.Exception.ExceptionRecord + +UE_CH_NONCONTINUABLEEXCEPTION + +ExceptionData points to: &DBGEvent.u.Exception.ExceptionRecord + +UE_CH_ARRAYBOUNDSEXCEPTION + +ExceptionData points to: &DBGEvent.u.Exception.ExceptionRecord + +UE_CH_FLOATDENORMALOPERAND + +ExceptionData points to: &DBGEvent.u.Exception.ExceptionRecord + +UE_CH_FLOATDEVIDEBYZERO + +ExceptionData points to: &DBGEvent.u.Exception.ExceptionRecord + +UE_CH_INTEGERDEVIDEBYZERO + +ExceptionData points to: &DBGEvent.u.Exception.ExceptionRecord + +UE_CH_INTEGEROVERFLOW + +ExceptionData points to: &DBGEvent.u.Exception.ExceptionRecord + +UE_CH_PRIVILEGEDINSTRUCTION + +ExceptionData points to: &DBGEvent.u.Exception.ExceptionRecord + + + + + + +UE_CH_PAGEGUARD + +ExceptionData points to: &DBGEvent.u.Exception.ExceptionRecord + +UE_CH_EVERYTHINGELSE + +ExceptionData points to: &DBGEvent.u.Exception.ExceptionRecord + +UE_CH_CREATETHREAD + +ExceptionData points to: &DBGEvent.u.CreateThread + +UE_CH_EXITTHREAD + +ExceptionData points to: &DBGEvent.u.ExitThread + +UE_CH_CREATEPROCESS + +ExceptionData points to: &DBGEvent.u.CreateProcessInfo + +UE_CH_EXITPROCESS + +ExceptionData points to: &DBGEvent.u.ExitProcess + +UE_CH_LOADDLL + +ExceptionData points to: &DBGEvent.u.LoadDll + +UE_CH_UNLOADDLL + +ExceptionData points to: &DBGEvent.u.UnloadDll + +UE_CH_OUTPUTDEBUGSTRING + +ExceptionData points to: &DBGEvent.u.DebugString + + + + + + +HideDebugger function + +HideDebugger hides the debugger from a variety of detection tricks, reducing the chances that it will be +detected. + +Syntax + + + +bool __stdcall HideDebugger( + +HANDLE hProcess, + +DWORD PatchAPILevel + +); + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the debugged process. + +PatchAPILevel + + [in] Patches following APIs when set to UE_HIDE_BASIC: + +. CheckRemoteDebuggerPresent +. GetTickCount + + + + +Return value + +Returns TRUE if the debugger is now hidden or FALSE if there were errors. + +Remarks + +None. + +Example + +None. + + + + + + +UnHideDebugger function + +UnHideDebugger reverts hiding the debugger from a variety of detection tricks. + +Syntax + + + +bool __stdcall UnHideDebugger( + +HANDLE hProcess, + +DWORD PatchAPILevel + +); + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the debugged process. + +PatchAPILevel + + [in] Patches following APIs when set to UE_HIDE_BASIC: + +. CheckRemoteDebuggerPresent +. GetTickCount + + + + +Return value + +Returns TRUE if the debugger is now visible or FALSE if there were errors. + +Remarks + +None. + +Example + +None. + + + + + + +GetPEBLocation function + +GetPEBLocation gets the PEB location inside the remote process. + +Syntax + + + +void* __stdcall GetPEBLocation( + +HANDLE hProcess + +); + + + + + + + + + +Parameters + +hProcess + + [in] Handle for process whose PEB location you are interested in. + + + +Return value + +Returns a pointer to PEB inside remote process. + +Remarks + +None. + +Example + +None. + + + + + + +SetEngineVariable function + +The SetEngineVariable sets various global settings for the TitanEngine SDK. + +Syntax + + + +void __stdcall SetEngineVariable( + +DWORD VariableId, + +bool VariableSet + +); + + + + + + + + + +Parameters + +VariableId + + [in] Can be one of the following: + +. UE_ENGINE_ALOW_MODULE_LOADING +. UE_ENGINE_AUTOFIX_FORWARDERS +. UE_ENGINE_PASS_ALL_EXCEPTIONS +. UE_ENGINE_NO_CONSOLE_WINDOW +. UE_ENGINE_BACKUP_FOR_CRITICAL_FUNCTIONS +. UE_ENGINE_RESET_CUSTOM_HANDLER +. UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK + + +VariableSet + + [in] Boolean value which will be set to the selected option. + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + +Threader module + + + +Functions in the threader module are designed for working with threads. Threader module functions +cover thread identification; thread manipulation and remote thread injection. + + + + +Threader module structures + + + +Structures used by the: ThreaderGetThreadInfo function and ThreaderEnumThreadInfo function + + + +typedef struct{ + + HANDLE hThread; + + DWORD dwThreadId; + + void* ThreadStartAddress; + + void* ThreadLocalBase; + +}THREAD_ITEM_DATA, *PTHREAD_ITEM_DATA; + + + + + ThreaderGetThreadInfo function + +ThreaderGetThreadInfo retrieves information about the threads inside the debugged process. Data is +collected each time a new thread is created, or any of the existing ones terminates. You may specify +either the thread handle or thread ID, but do not need to specify both. + +Syntax + + + +void* __stdcall ThreaderGetThreadInfo( + +HANDLE hThread, + +DWORD ThreadId + +); + + + + + + + +Parameters + +hThread + + [in] Handle of the thread whose info will be returned. + +ThreadIs + +[in] ID of thread whose info will be returned. + + + +Return value + +This function returns pointer to a THREAD_ITEM_DATA structure or NULL if the thread is no +longer active or not found. + +Remarks + +Only one of the two input parameters is needed. + +Example + +None. + + + + + + + ThreaderGetThreadData function + +ThreaderGetThreadData retrieves a pointer to an array of THREAD_ITEM_DATA entries containing +information about the existing threads. The hThread item in the last structure in the array is set to NULL. +The number of items in the array is the number of existing threads inside the debugged process. The size +of this array isn’t stored anywhere and must be determined on the fly. + +Syntax + + + +void* __stdcall ThreaderGetThreadData(); + + + + + + + +Parameters + +None. + +Return value + +This function returns pointer to THREAD_ITEM_DATA structure array. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderEnumThreadInfo function + +ThreaderEnumThreadInfo enumerates data about existing threads inside the debugged process. Data is +collected each time a new thread is created, or any of the existing ones terminates. + +Syntax + + + +void __stdcall ThreaderEnumThreadInfo( + +void* EnumCallBack + +); + + + + + + + +Parameters + +EnumCallBack + + [in] Pointer to the callback function that will process the thread item data for each +thread. + + + +CallBack definition + +typedef void(__stdcall *fEnumCallBack)(LPVOID fThreadDetail); + +// fThreadDetail is a pointer to THREAD_ITEM_DATA structure + + + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderPauseThread function + +ThreaderPauseThread changes the state of any active thread from active to suspend. + +Syntax + + + +bool __stdcall ThreaderPauseThread( + +HANDLE hThread + +); + + + + + + + +Parameters + +hThread + + [in] Handle of the thread to pause. + + + +Return value + +This function returns TRUE if thread is paused or FALSE if its execution can’t be paused at this +time. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderResumeThread function + +ThreaderResumeThread resumes execution of any currently paused thread inside the debugged +process. + +Syntax + + + +bool __stdcall ThreaderResumeThread( + +HANDLE hThread + +); + + + + + + + +Parameters + +hThread + + [in] Handle of the thread whose execution will be resumed. + + + +Return value + +This function returns TRUE if thread resumes or FALSE if its execution can’t resume at this time. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderTerminateThread function + +ThreaderTerminateThread tries to terminate an existing thread inside the debugged process. + +Syntax + + + +bool __stdcall ThreaderTerminateThread( + +HANDLE hThread, + +DWORD ThreadExitCode + +); + + + + + + + +Parameters + +hThread + + [in] Handle of the thread to terminate. + +ThreadExitCode + + [in] Exit code to pass to the TerminateThread Windows API that terminates the thread. + + + +Return value + +This function returns TRUE if the thread is terminated or FALSE if thread cannot be terminated. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderPauseAllThreads function + +ThreaderPauseAllThreads pauses all running threads inside the debugged process, optionally leaving +the main thread running. + +Syntax + + + +bool __stdcall ThreaderPauseAllThreads( + +bool LeaveMainRunning + +); + + + + + + + +Parameters + +LeaveMainRunning + + [in] Boolean switch indicating whether or not to leave the main thread running. + + + +Return value + +This function returns TRUE if the specified threads are paused or FALSE if not. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderResumeAllThreads function + +ThreaderResumeAllThreads resumes execution of all paused threads in the debugged process; +optionally leaving the main thread paused. + +Syntax + + + +bool __stdcall ThreaderResumeAllThreads( + +bool LeaveMainPaused + +); + + + + + + + +Parameters + +LeaveMainPaused + + [in] Boolean switch indicating whether or not to leave the main thread paused. + + + +Return value + +This function returns TRUE if all the existing threads are resumed or FALSE if not. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderPauseProcess function + +ThreaderPauseProcess pauses all active threads inside the debugged process, suspending that process. + +Syntax + + + +bool __stdcall ThreaderPauseProcess(); + + + + + + + +Parameters + +None. + +Return value + +This function returns TRUE if all threads are paused successfully or FALSE otherwise. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderResumeProcess function + +The ThreaderResumeProcess function is used to resume all paused threads inside the debugged +process. + +Syntax + + + +bool __stdcall ThreaderResumeProcess(); + + + + + + + +Parameters + +None. + +Return value + +This function returns TRUE if all threads get resumed or FALSE if there are no threads inside the +debugged process. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderIsThreadStillRunning function + +ThreaderIsThreadStillRunning checks whether the selected thread still exists, regardless of its state, in +the debugged process. + +Syntax + + + +bool __stdcall ThreaderIsThreadStillRunning( + +HANDLE hThread + +); + + + + + + + +Parameters + +hThread + + [in] Handle of the thread whose existence will be checked. + + + +Return value + +This function returns TRUE if the thread exists and FALSE if it has terminated. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderIsThreadActive function + +ThreaderIsThreadActive checks whether the selected thread is active and running inside the debugged +process. + +Syntax + + + +bool __stdcall ThreaderIsThreadActive( + +HANDLE hThread + +); + + + + + + + +Parameters + +hThread + + [in] Handle of the thread whose execution state will be queried. + + + +Return value + +This function returns TRUE if the thread is running and FALSE if it has terminated or it is +suspended. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderIsAnyThreadActive function + +ThreaderIsAnyThreadActive checks whether any thread in the debugged process is active and running. + +Syntax + + + +bool __stdcall ThreaderIsAnyThreadActive(); + + + + + + + +Parameters + +None. + +Return value + +This function returns TRUE if any of the threads is running and FALSE if all threads are +suspended. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderIsExceptionInMainThread function + +ThreaderIsExceptionInMainThread determines whether the last exception occurred inside the main +debugged process thread. + +Syntax + + + +bool __stdcall ThreaderIsExceptionInMainThread(); + + + + + + + +Parameters + +None. + +Return value + +This function returns TRUE if the last exception occurred inside the main thread, FALSE if it +occurred in another running thread. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderGetOpenHandleForThread function + +ThreaderGetOpenHandleForThread is used resolve the existing open handle for thread with the +specified ID. + +Syntax + + + +long long __stdcall ThreaderGetOpenHandleForThread( + +DWORD ThreadId + +); + + + + + + + +Parameters + +ThreadId + + [in] ID of the active thread, returned from thread data enumeration or Windows API. + + + +Return value + +This function returns the handle of the specified thread or NULL if the thread doesn’t exist +anymore. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderSetCallBackForNextExitThreadEvent function + +ThreaderSetCallBackForNextExitThreadEvent specifies a custom callback to call the next time an active +thread terminates. + +Syntax + + + +void __stdcall ThreaderSetCallBackForNextExitThreadEvent( + +LPVOID exitThreadCallBack + +); + + + + + + + +Parameters + +exitThreadCallBack + + [in] Pointer to callback function to call when the next active thread terminates. + + + +CallBack definition + +typedef void(__stdcall *fCustomHandler)(void* SpecialDBG); + +// Here SpecialDBG is defined as a pointer to &DBGEvent.u.ExitThread + + + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderCreateRemoteThreadEx function + +ThreaderCreateRemoteThreadEx creates a new thread inside the targeted process. + +Syntax + + + +long long __stdcall ThreaderCreateRemoteThreadEx( + +HANDLE hProcess, + +ULONG_PTR ThreadStartAddress, + +bool AutoCloseTheHandle, + +LPVOID ThreadPassParameter, + +LPDWORD ThreadId + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process in which to create the thread. + +ThreadStartAddress + + [in] Start address at which to create the thread in the remote process. + +AutoCloseTheHandle + + [in] Boolean switch indicating whether or not to close the handle to this new remote +thread automatically. + +ThreadPassParameter + + [in] Parameter which to pass to newly created thread. + +ThreadId + + [in] Pointer to DWORD to hold the ID for the newly created thread. + + + +Return value + +This function returns handle for the new thread or NULL if the thread wasn’t created or +AutoCloseTheHandle was set to TRUE. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderCreateRemoteThread function + +ThreaderCreateRemoteThread creates a new thread inside the process currently being debugged. + +Syntax + + + +long long __stdcall ThreaderCreateRemoteThreadEx( + +ULONG_PTR ThreadStartAddress, + +bool AutoCloseTheHandle, + +LPVOID ThreadPassParameter, + +LPDWORD ThreadId + +); + + + + + + + +Parameters + +ThreadStartAddress + + [in] Start address for the new thread located in the remote process. + +AutoCloseTheHandle + +[in] Boolean switch indicating whether or not to close the handle to to this new remote +thread automatically. + +ThreadPassParameter + +[in] Parameter which to pass to newly created thread. + +ThreadId + +[in] Pointer to DWORD to hold the ID for the newly created thread. + + + +Return value + +This function returns handle for the new thread or NULL if the thread wasn’t created or +AutoCloseTheHandle was set to TRUE. + +Remarks + +None. + +Example + +None. + + + + + + + + + ThreaderInjectAndExecuteCodeEx function + +ThreaderInjectAndExecuteCodeEx creates a new thread inside the targeted process and auto-executes +the injected code. + +Syntax + + + +bool __stdcall ThreaderInjectAndExecuteCodeEx( + +HANDLE hProcess, + +LPVOID InjectCode, + +DWORD StartDelta, + +DWORD InjectSize + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process in which the new thread will be created. + +InjectedCode + + [in] Pointer to the data to inject in the remote process. + +StartDelta + + [in] Used when you need to to execute the code from any other point other then the +first byte of the InjectedCode memory, the start address of the new thread will be +increased by this value. + +InjectedSize + + [in] Size of the memory the new thread will occupy in the remote process. + + + +Return value + +This function returns TRUE if the thread has been created and FALSE if there were problems. + +Remarks + +Before creating new thread data is allocated in targeted process and written there. + +Example + +None. + + + + + + + ThreaderInjectAndExecuteCode function + +ThreaderInjectAndExecuteCode creates a new thread inside the currently debugged process and auto- +executes the injected code. + +Syntax + + + +bool __stdcall ThreaderInjectAndExecuteCode( + +LPVOID InjectCode, + +DWORD StartDelta, + +DWORD InjectSize + +); + + + + + + + +Parameters + +InjectedCode + + [in] Pointer to the data to inject into the remote process. + +StartDelta + + [in] Start address of the new thread will be increased by this value. Use this option if +you need to execute the code from any other point other then the first byte of the +InjectedCode memory. + +InjectedSize + + [in] Size of the memory which will be injected inside the remote process. + + + +Return value + +This function returns TRUE if the thread has been created and FALSE if there were problems. + +Remarks + +Before creating new thread data is allocated in targeted process and written there. + +Example + +None. + + + + + + + ThreaderExecuteOnlyInjectedThreads function + +The ThreaderExecuteOnlyInjectedThreads pause all active non injected threads inside the debugged +process making that process suspended. All threads that get injected after using this function will be +executed normally. Once all injected threads finish their execution process execution must be resumed +with ThreaderResumeProcess. + +Syntax + + + +bool __stdcall ThreaderExecuteOnlyInjectedThreads(); + + + + + + + +Parameters + +None. + +Return value + +This function returns TRUE if all non injected threads get paused or FALSE if there are some +threads still running. + +Remarks + +None. + +Example + +None. + + + + + + + ThreaderImportRunningThreadData function + +ThreaderImportRunningThreadData collects data about running threads for the specified process. This +function can be used to get data about remote process threads and manipulate them. However this +function overwrites internal data and should only be used if no program is being currently debugged. + +Syntax + + + +bool __stdcall ThreaderImportRunningThreadData( + +DWORD ProcessId + +); + + + + + + + +Parameters + +ProcessId + + [in] Process ID of the running process which can be acquired with Windows API. + + + +Return value + +This function returns TRUE if the threads have been imported and FALSE if there were problems. + +Remarks + +This action removes ALL data about the threads and should only be used if no program is +debugged. + +Example + +None. + + + + + + +TLS module + + + +TLS module has functions designed for working with thread local storage both on disk and in memory. + + + + + TLSBreakOnCallBack function + +The TLSBreakOnCallBack sets a breakpoint on all TLS callbacks inside the PE header. + +Syntax + + + +bool __stdcall TLSBreakOnCallBack( + +LPVOID ArrayOfCallBacks, + +DWORD NumberOfCallBacks, + +LPVOID bpxCallBack + +); + + + + + + + +Parameters + +ArrayOfCallBacks + + [in] Pointer to array of callbacks on which the breakpoints will be set. + +NumberOfCallBacks + +[in] Number of callbacks in the provided array. + +bpxCallBack + + [in] Address of the callback to call when each TLS breakpoint has been hit. + + + +Return value + +This function returns TRUE if the breakpoint has been set and FALSE if breakpoint cannot be set. + +Remarks + +None. + +Example + +None. + + + + + + + TLSBreakOnCallBackEx function + +The TLSBreakOnCallBackEx sets a breakpoint on all TLS callbacks inside the PE header. + +Syntax + + + +bool __stdcall TLSBreakOnCallBackEx( + +char* szFileName, + +LPVOID bpxCallBack + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file to debug. + +bpxCallBack + + [in] Address of the callback to call when each TLS breakpoint has been hit. + + + +Return value + +This function returns TRUE if the breakpoint has been set and FALSE if breakpoint cannot be set. + +Remarks + +None. + +Example + +None. + + + + + + + TLSGrabCallBackData function + +The TLSGrabCallBackData function is used to retrieve the TLS callbacks from the PE header. + +Syntax + + + +bool __stdcall TLSGrabCallBackData( + +char* szFileName, + +LPVOID ArrayOfCallBacks, + +LPDWORD NumberOfCallBacks + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is the full path to the file whose TLS +callback data will be read and copied to the specified array. + +ArrayOfCallBacks + + [out] Pointer to array which will receive the callback addresses. + +NumberOfCallBacks + +[out] Number of callbacks in the TLS callback array. + + + +Return value + +This function returns TRUE if the breakpoint has been set and FALSE if breakpoint cannot be set. + +Remarks + +None. + +Example + +None. + + + + + + + TLSRemoveCallback function + +The TLSRemoveCallback remove TLS callbacks from the PE header of the selected file. + +Syntax + + + +bool __stdcall TLSRemoveCallback( + +char* szFileName + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file whose TLS callback table will be removed. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + TLSRemoveTable function + +The TLSRemoveTable removes TLS table from the PE header of the selected file. + +Syntax + + + +bool __stdcall TLSRemoveTable( + +char* szFileName + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file whose TLS table will be removed. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + TLSBackupData function + +The TLSBackupData make an internal backup of the TLS table so that it can be restored at runtime if it +gets corrupted. + +Syntax + + + +bool __stdcall TLSBackupData( + +char* szFileName + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file whose TLS table will be backed up. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + TLSRestoreData function + +The TLSRestoreData restore data from internal backup of the TLS table directly to running process +memory. In case of TLS table corruption this function can be used to restore the previously backed up +data. + +Syntax + + + +bool __stdcall TLSRestoreData(); + + + + + + + +Parameters + +None. + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + TLSBuildNewTable function + +The TLSBuildNewTable build and store completely new TLS table inside the selected PE file. This option +can be used to create a new TLS table in case of dealing with protections that use TLS elimination +protection technique. + +Syntax + + + +bool __stdcall TLSBuildNewTable( + +ULONG_PTR FileMapVA, + +ULONG_PTR StorePlace, + +ULONG_PTR StorePlaceRVA, + +LPVOID ArrayOfCallBacks, + +DWORD NumberOfCallBacks + +); + + + + + + + +Parameters + +FileMapVA + + [in] Pointer to the mapped file content which must be mapped in read/write mode. This +pointer is set by using either StaticFileLoad function or Windows API for file +mapping. + +StorePlace + + [in] Physical address inside PE file on which the new TLS table will be written. Usually +this is a new section but can also be the part of the file which is unused but still in +read/write mode. + +StorePlaceRVA + + [in] Relative virtual address inside PE file on which the new TLS table will be written. +This input is just conversion from physical to relative virtual offset. + +ArrayOfCallBacks + + [in] Pointer to array of custom TLS callback. + +NumberOfCallBacks + +[in] Number of callbacks in the provided array. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Example + +None. + + + + + TLSBuildNewTableEx function + +The TLSBuildNewTableEx build and store completely new TLS table inside the selected PE file. This +option can be used to create a new TLS table in case of dealing with protections that use TLS elimination +protection technique. + +Syntax + + + +bool __stdcall TLSBuildNewTableEx( + +char* szFileName, + +char* szSectionName, + +LPVOID ArrayOfCallBacks, + +DWORD NumberOfCallBacks + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to string specifying the full path to the file in which to write the new TLS +table. + +szSectionName + +[in] The new TLS table will be written to a new PE section in the file specified by +szFileName. This variable specifies the name to use for the new section. The section +name may be up to 8 characters long. + +ArrayOfCallBacks + + [in] Pointer to array of custom TLS callback functions. + +NumberOfCallBacks + +[in] Number of callbacks in the specified array. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + +Librarian module + + + +The Librarian module contains functions designed to manipulate loaded libraries, setting breakpoints for +specific library loading events, and retrieving information about loaded libraries. + + + + +Librarian module constants + + + +Constants used by: LibrarianSetBreakPoint function and LibrarianRemoveBreakPoint function + + + +#define UE_ON_LIB_LOAD 1 + +#define UE_ON_LIB_UNLOAD 2 + +#define UE_ON_LIB_ALL 3 + + + +Librarian module structures + + + +Structure used by: LibrarianGetLibraryInfo function, LibrarianGetLibraryInfoEx function and +LibrarianEnumLibraryInfo function + + + +typedef struct{ + +HANDLE hFile; + + void* BaseOfDll; + + HANDLE hFileMapping; + + void* hFileMappingView; + + char szLibraryPath[MAX_PATH]; + + char szLibraryName[MAX_PATH]; + +}LIBRARY_ITEM_DATA, *PLIBRARY_ITEM_DATA; + + + + + + + LibrarianSetBreakPoint function + +LibrarianSetBreakPoint sets a breakpoint on a specific type of library event, such as library loading or +unloading. + +Syntax + + + +bool __stdcall LibrarianSetBreakPoint( + +char* szLibraryName, + +DWORD bpxType, + +bool SingleShoot, + +LPVOID bpxCallBack + +); + + + + + + + +Parameters + +szLibraryName + + [in] Name of the library to watch for specified events. For example kernel32.dll + +bpxType + +[in] Specifies the type of event on which the breakpoint will be triggered. Can be one of +the following: UE_ON_LIB_LOAD, UE_ON_LIB_UNLOAD or UE_ON_LIB_ALL. + +SingleShoot + + [in] Specifies whether the breakpoint will be executed only once, or each time the +specified event occurs. + +bpxCallBack + + [in] Address of the callback to call when the breakpoint is triggered. + + + +CallBack definition + +typedef void(__stdcall *fCustomBreakPoint)(void* SpecialDBG); + +// SpecialDBG is a pointer to &DBGEvent.u.LoadDll + + + + + +Return value + +This function returns TRUE if the breakpoint is set and FALSE if breakpoint cannot be set. + +Remarks + +Maximum number of breakpoints is defined with MAX_LIBRARY_BPX. + + + + + + + LibrarianRemoveBreakPoint function + +The LibrarianRemoveBreakPoint function is used to remove a breakpoint set on specific library events +such as library loading or unloading. + +Syntax + + + +bool __stdcall LibrarianRemoveBreakPoint( + +char* szLibraryName, + +DWORD bpxType + +); + + + + + + + +Parameters + +szLibraryName + + [in] Name of the library which was used as a breakpoint trigger. For example +kernel32.dll + +bpxType + +[in] Specifies the event on which the breakpoint was set. Can be one of the following: +UE_ON_LIB_LOAD, UE_ON_LIB_UNLOAD or UE_ON_LIB_ALL. + + + +Return value + +This function returns TRUE if the breakpoint has been removed and FALSE if breakpoint cannot +be removed which should never happen. + +Remarks + +Maximum number of breakpoints is defined with MAX_LIBRARY_BPX. + +Example + +None. + + + + + + + LibrarianGetLibraryInfo function + +LibrarianGetLibraryInfo retrieves library item data for the modules loaded by the debugged process. + +Syntax + + + +void* __stdcall LibrarianGetLibraryInfo( + +char* szLibraryName + +); + + + + + + + +Parameters + +szLibraryName + + [in] Name of the library loaded inside the debugged process. For example kernel32.dll + + + +Return value + +This function returns a pointer to a LIBRARY_ITEM_DATA structure or NULL if selected DLL +cannot be found. + +Example + +None. + + + + + + + LibrarianGetLibraryInfoEx function + +LibrarianGetLibraryInfoEx retrieves additional library item data for the modules loaded by the debugged +process. + +Syntax + + + +void* __stdcall LibrarianGetLibraryInfoEx( + +void* BaseOfDll + +); + + + + + + + +Parameters + +BaseOfDll + + [in] Base address at which the selected module is loaded in remote process. + + + +Return value + +This function returns the pointer to LIBRARY_ITEM_DATA structure or NULL if selected DLL +cannot be found. + +Example + +None. + + + + + + + LibrarianEnumLibraryInfo function + +LibrarianEnumLibraryInfo enumerates data for all DLL files loaded by the debugged process. This list +contains data about only currently loaded modules. Unloaded modules are automatically removed from +the list. + +Syntax + + + +void __stdcall LibrarianEnumLibraryInfo( + +void* EnumCallBack + +); + + + + + + + +Parameters + +EnumCallBack + + [in] Address of the callback function to use for processing loaded library data. + + + +CallBack definition + +typedef void(__stdcall *fEnumCallBack)(LPVOID fLibraryDetail); + +// Here fLibraryDetail is a pointer to LIBRARY_ITEM_DATA structure + + + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + + +Hooks module + + + +The Hooks module has functions designed for in process function hooking. For hooking to be possible +entire engine or just TitaniumHooks must be loaded in the context of the process in which the hooks are +being applied. + + + + +Hooks module constants + + + +Constants used by: HooksInsertNewRedirection function + + + +#define TEE_HOOK_NRM_JUMP 1 + +#define TEE_HOOK_NRM_CALL 3 + + + +#define TEE_HOOK_IAT 5 + +#define TEE_MAXIMUM_HOOK_RELOCS 7 + +Hooks module structures + + + +Structure used by: HooksGetHookEntryDetails function + + + +typedef struct HOOK_ENTRY{ + + bool IATHook; + + BYTE HookType; + + DWORD HookSize; + + void* HookAddress; + + void* RedirectionAddress; + + BYTE HookBytes[TEE_MAXIMUM_HOOK_SIZE]; + + BYTE OriginalBytes[TEE_MAXIMUM_HOOK_SIZE]; + + void* IATHookModuleBase; + + DWORD IATHookNameHash; + + bool HookIsEnabled; + + bool HookIsRemote; + + void* PatchedEntry; + + DWORD RelocationInfo[TEE_MAXIMUM_HOOK_RELOCS]; + + int RelocationCount; + +}HOOK_ENTRY, *PHOOK_ENTRY; + + + + + + + + + HooksSafeTransition function + +HooksSafeTransition puts the running process in suspended state leaving only the thread that inserts +new hooks running. Once all the hooks are inserted paused process can be resumed by calling the same +function again. WARNING: Using this function to resume paused threads will cause all threads to be +resumed not only the ones paused by the previous use of the same function. + +Syntax + + + +bool __stdcall HooksSafeTransition( + +LPVOID HookAddress, + +bool TransitionStart + +); + + + + + + + +Parameters + +HookAddress + + [in] Single address which will be hooked inside this safe transition block. If there is more +than one hook to insert use the expert version of HookSafeTransition function. + +TransitionStart + + [in] Since the same function can be used to both pause and resume the process +execution this boolean switch indicates which of the two needs to be performed. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + HooksSafeTransitionEx function + +HooksSafeTransitionEx puts the running process in suspended state leaving only the thread that inserts +new hooks running. Once all the hooks are inserted paused process can be resumed by calling the same +function again. WARNING: Using this function to resume paused threads will cause all threads to be +resumed not only the ones paused by the previous use of the same function. + +Syntax + + + +bool __stdcall HooksSafeTransitionEx( + +LPVOID HookAddressArray, + +int NumberOfHooks, + +bool TransitionStart + +); + + + + + + + +Parameters + +HookAddressArray + + [in] Array of addresses which will be hooked inside this safe transition block. + +NumberOfHooks + + [in] Number of items in the provided array. + +TransitionStart + + [in] Since the same function can be used to both pause and resume the process +execution this boolean switch indicates which of the two needs to be performed. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + HooksDisableRedirection function + +HooksDisableRedirection disables the selected hook. Original bytes are restored in the process and +therefore using this function in multithreaded environment is recommended only after transitioning to +safe patching mode. + +Syntax + + + +bool __stdcall HooksDisableRedirection( + +LPVOID HookAddress, + +bool DisableAll + +); + + + + + + + +Parameters + +HookAddress + + [in] Hooked address whose hook will be disabled. + +DisableAll + + [in] Boolean switch indicating whether or not to disable all installed hooks. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + HooksDisableRedirectionsForModule function + +HooksDisableRedirectionsForModule disables all installed hooks inside the selected module. Original +bytes are restored in the process and therefore using this function in multithreaded environment is +recommended only after transitioning to safe patching mode. + +Syntax + + + +bool __stdcall HooksDisableRedirectionsForModule( + +HMODULE ModuleBase + +); + + + + + + + +Parameters + +ModuleBase + + [in] Base address of the loaded library whose hooks need disabling. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +Here module refers to loaded library which is hooked. + +Example + +None. + + + + + + + HooksDisableIATRedirection function + +HooksDisableIATRedirection disables all installed hooks inside the selected module’s import address +table. Original bytes are restored in the process and therefore using this function in multithreaded +environment is recommended only after transitioning to safe patching mode. + +Syntax + + + +bool __stdcall HooksDisableIATRedirection( + +char* szModuleName, + +char* szHookFunction, + +bool DisableAll + +); + + + + + + + +Parameters + +szModuleName + + [in] Name of the loaded module, for example: kernel32.dll + +szHookFunction + + [in] Name of the hooked function, for example: VirtualProtect + +DisableAll + + [in] Boolean switch indicating whether or not to disable all installed import address +hooks for the selected module. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + HooksEnableRedirection function + +HooksEnableRedirection enables the selected hook. Original bytes are restored in the process and +therefore using this function in multithreaded environment is recommended only after transitioning to +safe patching mode. + +Syntax + + + +bool __stdcall HooksEnableRedirection( + +LPVOID HookAddress, + +bool EnableAll + +); + + + + + + + +Parameters + +HookAddress + + [in] Hooked address whose hook will be disabled. + +EnableAll + + [in] Boolean switch indicating whether or not to enable all disabled hooks. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + HooksEnableRedirectionsForModule function + +HooksEnableRedirectionsForModule enables all disabled hooks inside the selected module. Original +bytes are restored in the process and therefore using this function in multithreaded environment is +recommended only after transitioning to safe patching mode. + +Syntax + + + +bool __stdcall HooksEnableRedirectionsForModule( + +HMODULE ModuleBase + +); + + + + + + + +Parameters + +ModuleBase + + [in] Base address of the loaded library whose hooks need enabling. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +Here module refers to loaded library which is hooked. + +Example + +None. + + + + + + + HooksEnableIATRedirection function + +HooksEnableIATRedirection enables all disabled hooks inside the selected module’s import address +table. Original bytes are restored in the process and therefore using this function in multithreaded +environment is recommended only after transitioning to safe patching mode. + +Syntax + + + +bool __stdcall HooksEnableIATRedirection( + +char* szModuleName, + +char* szHookFunction, + +bool EnableAll + +); + + + + + + + +Parameters + +szModuleName + + [in] Name of the loaded module, for example: kernel32.dll + +szHookFunction + + [in] Name of the hooked function, for example: VirtualProtect + +EnableAll + + [in] Boolean switch indicating whether or not to enable all disabled import address +hooks for the selected module. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + HooksRemoveRedirection function + +HooksRemoveRedirection removes the selected hook. Original bytes are restored in the process and +therefore using this function in multithreaded environment is recommended only after transitioning to +safe patching mode. + +Syntax + + + +bool __stdcall HooksRemoveRedirection( + +LPVOID HookAddress, + +bool RemoveAll + +); + + + + + + + +Parameters + +HookAddress + + [in] Hooked address whose hook will be disabled. + +RemoveAll + + [in] Boolean switch indicating whether or not to remove all installed hooks. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + HooksRemoveRedirectionsForModule function + +HooksRemoveRedirectionsForModule removes all installed hooks inside the selected module. Original +bytes are restored in the process and therefore using this function in multithreaded environment is +recommended only after transitioning to safe patching mode. + +Syntax + + + +bool __stdcall HooksRemoveRedirectionsForModule( + +HMODULE ModuleBase + +); + + + + + + + +Parameters + +ModuleBase + + [in] Base address of the loaded library whose hooks will be removed. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +Here module refers to loaded library which is hooked. + +Example + +None. + + + + + + + HooksRemoveIATRedirection function + +HooksEnableIATRedirection removes all installed hooks inside the selected module’s import address +table. Original bytes are restored in the process and therefore using this function in multithreaded +environment is recommended only after transitioning to safe patching mode. + +Syntax + + + +bool __stdcall HooksRemoveIATRedirection( + +char* szModuleName, + +char* szHookFunction, + +bool RemoveAll + +); + + + + + + + +Parameters + +szModuleName + + [in] Name of the loaded module, for example: kernel32.dll + +szHookFunction + + [in] Name of the hooked function, for example: VirtualProtect + +RemoveAll + + [in] Boolean switch indicating whether or not to remove all import address hooks for +the selected module. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + HooksInsertNewRedirection function + +HooksInsertNewRedirection installs a new hook on the selected address. Memory is changed in the +process of installing hooks and therefore using this function in multithreaded environment is +recommended only after transitioning to safe patching mode. You can only have one hook on the +selected address and therefore trying to hook the same address twice will result into this function +returning false indicating that the hook wasn’t installed. + +Syntax + + + +bool __stdcall HooksInsertNewRedirection( + +LPVOID HookAddress, + +LPVOID RedirectTo, + +int HookType + +; + + + + + + + +Parameters + +HookAddress + + [in] Address which will be redirected by a hook. + +RedirectTo + + [in] Installed hook will redirect code execution to this address. + +HookType + + [in] Indicates which type of hook to use. Can be one of the following: +TEE_HOOK_NRM_JUMP or TEE_HOOK_NRM_CALL. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + HooksInsertNewIATRedirectionEx function + +HooksInsertNewIATRedirectionEx installs a new import address hook. Memory is changed in the +process of installing hooks and therefore using this function in multithreaded environment is +recommended only after transitioning to safe patching mode. You can only have one hook on the +selected address and therefore trying to hook the same address twice will result into this function +returning false indicating that the hook wasn’t installed. + +Syntax + + + +bool __stdcall HooksInsertNewIATRedirectionEx( + +ULONG_PTR FileMapVA, + +ULONG_PTR LoadedModuleBase, + +char* szHookFunction, + +LPVOID RedirectTo + +); + + + + + + + +Parameters + +FileMapVA + + [in] Pointer to the mapped file content which must be mapped in read/write mode. This +pointer is set by using either StaticFileLoad function or Windows API for file +mapping. + +LoadedModuleBase + + [in] Base address on which the module whose IAT is being patched is loaded on. + +szHookFunction + + [in] Name of the hooked function, for example: VirtualProtect + +RedirectTo + + [in] Installed hook will redirect code execution to this address. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + HooksInsertNewIATRedirection function + +HooksInsertNewIATRedirection installs a new import address hook. Memory is changed in the process +of installing hooks and therefore using this function in multithreaded environment is recommended only +after transitioning to safe patching mode. You can only have one hook on the selected address and +therefore trying to hook the same address twice will result into this function returning false indicating +that the hook wasn’t installed. + +Syntax + + + +bool __stdcall HooksInsertNewIATRedirection( + +char* szModuleName, + +char* szHookFunction, + +LPVOID RedirectTo + +); + + + + + + + +Parameters + +szModuleName + + [in] Name of the loaded module, for example: kernel32.dll + +szHookFunction + + [in] Name of the hooked function, for example: VirtualProtect + +RedirectTo + + [in] Installed hook will redirect code execution to this address. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + HooksGetTrampolineAddress function + +HooksGetTrampolineAddress retrieves the trampoline address which can be called if the hooked +function needs to execute the original function and not just replace its functionality. This function is +used for both API and IAT hooks. + +Syntax + + + +void* __stdcall HooksGetTrampolineAddress( + +LPVOID HookAddress + +); + + + + + + + +Parameters + +HookAddress + + [in] Address which was hooked for which the function will return the appropriate +trampoline. + + + +Return value + +Function returns trampoline address or NULL is there is no hook at the selected address. + +Remarks + +None. + +Example + +None. + + + + + + + HooksGetHookEntryDetails function + +HooksGetHookEntryDetails retrieves the information about installed hooks. This function is used for all +hooks. Data returned can be manipulated to affect the hook state. + +Syntax + + + +void* __stdcall HooksGetHookEntryDetails( + +LPVOID HookAddress + +); + + + + + + + +Parameters + +HookAddress + + [in] Address which was hooked for which the function will return the hook info. + + + +Return value + +Function returns the hook info or NULL is there is no hook at the selected address. + +Remarks + +None. + +Example + +None. + + + + + + + HooksScanModuleMemory function + +HooksScanModuleMemory function scans the selected module memory for installed hooks which are +registered to internal hooking system. All found hooks are registered regardless of which component of +the program installed them. Therefore this can be used to uninstall existing hooks not inserted by the +Hooks module. + +Syntax + + + +void __stdcall HooksScanModuleMemory( + +HMODULE ModuleBase, + +LPVOID CallBack + +); + + + + + + + +Parameters + +ModuleBase + + [in] Base address of the loaded library whose memory will be scanned for hooks. + +CallBack + +[in] Pointer to the callback function to call for each found hook. + + + +CallBack definition + +typedef bool(__stdcall *fEnumCallBack)(PHOOK_ENTRY HookDetails, \ + +void* ptrOriginalInstructions, PLIBRARY_ITEM_DATA ModuleInformation, \ + +DWORD SizeOfImage); + + + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + HooksScanEntireProcessMemory function + +HooksScanEntireProcessMemory function scans the entire process memory for installed hooks which +are registered to internal hooking system. All found hooks are registered regardless of which component +of the program installed them. Therefore this can be used to uninstall existing hooks not inserted by the +Hooks module. + +Syntax + + + +void __stdcall HooksScanEntireProcessMemory( + +LPVOID CallBack + +); + + + + + + + +Parameters + +CallBack + +[in] Pointer to the callback function to call for each found hook. + + + +CallBack definition + +typedef bool(__stdcall *fEnumCallBack)(PHOOK_ENTRY HookDetails, \ + +void* ptrOriginalInstructions, PLIBRARY_ITEM_DATA ModuleInformation, \ + +DWORD SizeOfImage); + + + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + HooksScanEntireProcessMemoryEx function + +HooksScanEntireProcessMemoryEx function scans the entire process memory for installed hooks which +are registered to internal hooking system. All found hooks are registered regardless of which component +of the program installed them. Therefore this can be used to uninstall existing hooks not inserted by the +Hooks module. + +Syntax + + + +void __stdcall HooksScanEntireProcessMemoryEx(); + + + + + + + +Parameters + +None. + +Return value + +None. + +Remarks + +Found hooks are registered without any notification. + +Example + +None. + + + + +OEP Finder module + + + +The OEP Finder module has functions designed for generic entry point finding. + + + + + FindOEPInit function + +FindOEPInit initializes the OEP tracing process. It is not necessary to call it directly, since it will be +automatically called by the engine itself. + +Syntax + + + +void __stdcall FindOEPInit(); + + + + + + + +Parameters + +None. + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + FindOEPGenerically function + +FindOEPGenerically finds the packed file's original entry point. There are some limitations to what +formats are supported. This function only supports packers which use LoadLibrary in order to load more +than just kernel32.dll. WARNING: It is possible for the file to execute when this function is called, so use +this function with caution! + +Syntax + + + +void __stdcall FindOEPGenerically( + +char* szFileName, + +LPVOID TraceInitCallBack, + +LPVOID CallBack + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file whose entry point you want to find. + +TraceInitCallBack + + [in] Callback to call once the packed file hits its packed entry point. + +CallBack + + [in] Callback to call once the packed file hits its original entry point. + + + +Return value + +None. + +Remarks + +All callbacks used here are normal breakpoint callbacks. See SetBPX function for details. + +Example + +See RL!dePacke2 source code. + + + + + + +Process module + + + +The Process module includes functions that enumerate processes and execute basic operations inside +the context of a remote process. + + + + + GetActiveProcessId function + +GetActiveProcessId finds an active process using its image name. + +Syntax + + + +long __stdcall GetActiveProcessId( + +char* szImageName + +); + + + + + + + +Parameters + +szImageName + + [in] The image name of the running process. For example explorer.exe + + + +Return value + +This function returns process ID if the process is running and found, or NULL if the image with +the specified name isn’t currently running. + +Remarks + +In case of multiple process images with the same name, this function always returns the ID of +the first one found. + +Example + +None. + + + + + + + EnumProcessesWithLibrary function + +EnumProcessesWithLibrary enumerates all processes that have loaded the specified DLL image. + +Syntax + + + +void __stdcall EnumProcessesWithLibrary( + +char* szLibraryName, + +void* EnumFunction + +); + + + + + + + +Parameters + +szLibraryName + + [in] Name of the library in which you are interested. For example kernel32.dll + +EnumFunction + + [in] Address of a callback function that will process the data. + + + +CallBack definition + +typedef void(__stdcall *fEnumFunction)(DWORD ProcessId, + + HMODULE ModuleBaseAddress); + + + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + RemoteLoadLibrary function + +RemoteLoadLibrary makes a remote process load the selected DLL file. This function injects a remote +thread in the selected process which calls LoadLibraryA in order to load the DLL file from disk. + +Syntax + + + +bool __stdcall RemoteLoadLibrary( + +HANDLE hProcess, + +char* szLibraryFile, + +bool WaitForThreadExit + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process in which the new thread that loads the DLL will be created. + +szLibraryName + + [in] Name of the library to load inside remote process. For example advapi32.dll + +WaitForThreadExit + + [in] Boolean switch indicating whether or not to wait for the remote thread to +terminate before returning from this function call. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + RemoteFreeLibrary function + +RemoteFreeLibrary make a remote process unload the selected DLL file. This function injects a remote +thread in the selected process. The thread calls FreeLibrary to unload the specified DLL file. + +Syntax + + + +bool __stdcall RemoteFreeLibrary( + +HANDLE hProcess, + +HMODULE hModule, + +char* szLibraryFile, + +bool WaitForThreadExit + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process in which to create the new thread that will unload the DLL. + +hModule + + [in] Base address at which the DLL file is loaded in remote process. + +szLibraryName + + [in] Name of the library to unload from the remote process. For example advapi32.dll + +WaitForThreadExit + + [in] Boolean switch indicating whether or not to wait for the remote thread to +terminate before returning from this function call. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +You only need to specify the name or the base address of the module, not both. + +Example + +None. + + + + + + + RemoteExitProcess function + +RemoteExitProcess injects a remote thread in the selected process to terminate the process by calling +ExitProcess. + +Syntax + + + +bool __stdcall RemoteExitProcess( + +HANDLE hProcess, + +DWORD ExitCode + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process to terminate. + +ExitCode + + [in] Exit code that will be passed to the ExitProcess API. Can be NULL. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + TranslateNativeName function + +TranslateNativeName resolves the full path to a file using its native name. TranslateNativeName is used +to resolve paths that contain physical devices in their file references. + +Syntax + + + +void* __stdcall TranslateNativeName( + +char* szNativeName + +); + + + + + + + +Parameters + +szNativeName + + [in] The native name of the file whose path you want to resolve. + + + +Return value + +Function returns a pointer to the decoded file name, or NULL if the supplied string can’t be +decoded. + +Remarks + +CAUTION: A string with the translated native name is stored inside the engine which makes this +function multi thread unsafe. + +Example + +None. + + + + + + +Dumper module + + + +Dumper module has functions designed for the dumping process, region and module memory dumping. +This module also contains functions to aid in work with PE header specifics and file overlay. + + + + +Dumper module constants + + + +Constants used by: GetPE32DataFromMappedFile function, GetPE32Data function, +SetPE32DataForMappedFile function, and SetPE32Data function. + + + +#define UE_PE_OFFSET 0 + +#define UE_IMAGEBASE 1 + +#define UE_OEP 2 + +#define UE_SIZEOFIMAGE 3 + +#define UE_SIZEOFHEADERS 4 + +#define UE_SIZEOFOPTIONALHEADER 5 + +#define UE_SECTIONALIGNMENT 6 + +#define UE_IMPORTTABLEADDRESS 7 + +#define UE_IMPORTTABLESIZE 8 + +#define UE_RESOURCETABLEADDRESS 9 + +#define UE_RESOURCETABLESIZE 10 + +#define UE_EXPORTTABLEADDRESS 11 + +#define UE_EXPORTTABLESIZE 12 + +#define UE_TLSTABLEADDRESS 13 + +#define UE_TLSTABLESIZE 14 + +#define UE_RELOCATIONTABLEADDRESS 15 + +#define UE_RELOCATIONTABLESIZE 16 + +#define UE_TIMEDATESTAMP 17 + +#define UE_SECTIONNUMBER 18 + +#define UE_CHECKSUM 19 + +#define UE_SUBSYSTEM 20 + +#define UE_CHARACTERISTICS 21 + +#define UE_NUMBEROFRVAANDSIZES 22 + +#define UE_SECTIONNAME 23 + +#define UE_SECTIONVIRTUALOFFSET 24 + +#define UE_SECTIONVIRTUALSIZE 25 + +#define UE_SECTIONRAWOFFSET 26 + +#define UE_SECTIONRAWSIZE 27 + +#define UE_SECTIONFLAGS 28 + +Constants used by: GetPE32SectionNumberFromVA function + + + +#define UE_VANOTFOUND -2 + + + + + + + + +Dumper module structures + + + +Structures used by: GetPE32DataFromMappedFileEx function, GetPE32DataEx function, + +SetPE32DataForMappedFileEx function and SetPE32DataEx function. + + + +typedef struct{ + + DWORD PE32Offset; + + DWORD ImageBase; + + DWORD OriginalEntryPoint; + + DWORD NtSizeOfImage; + + DWORD NtSizeOfHeaders; + + WORD SizeOfOptionalHeaders; + + DWORD FileAlignment; + + DWORD SectionAligment; + + DWORD ImportTableAddress; + + DWORD ImportTableSize; + + DWORD ResourceTableAddress; + + DWORD ResourceTableSize; + + DWORD ExportTableAddress; + + DWORD ExportTableSize; + + DWORD TLSTableAddress; + + DWORD TLSTableSize; + + DWORD RelocationTableAddress; + + DWORD RelocationTableSize; + + DWORD TimeDateStamp; + + WORD SectionNumber; + + DWORD CheckSum; + + WORD SubSystem; + + WORD Characteristics; + + DWORD NumberOfRvaAndSizes; + +}PE32Struct, *PPE32Struct; + + + + + + + + + + + + +Structures used by: GetPE32DataFromMappedFileEx function, GetPE32DataEx function, + +SetPE32DataForMappedFileEx function and SetPE32DataEx function. + + + +typedef struct{ + + DWORD PE64Offset; + + DWORD64 ImageBase; + + DWORD OriginalEntryPoint; + + DWORD NtSizeOfImage; + + DWORD NtSizeOfHeaders; + + WORD SizeOfOptionalHeaders; + + DWORD FileAlignment; + + DWORD SectionAligment; + + DWORD ImportTableAddress; + + DWORD ImportTableSize; + + DWORD ResourceTableAddress; + + DWORD ResourceTableSize; + + DWORD ExportTableAddress; + + DWORD ExportTableSize; + + DWORD TLSTableAddress; + + DWORD TLSTableSize; + + DWORD RelocationTableAddress; + + DWORD RelocationTableSize; + + DWORD TimeDateStamp; + + WORD SectionNumber; + + DWORD CheckSum; + + WORD SubSystem; + + WORD Characteristics; + + DWORD NumberOfRvaAndSizes; + +}PE64Struct, *PPE64Struct; + + + + + + +DumpProcess function + +DumpProcess creates, for the currently running process, a memory dump in a file on disk. This image is +not a valid PE file, but a state of memory at the time the function is called. + +Syntax + + + +bool __stdcall DumpProcess( + +HANDLE hProcess, + +LPVOID ImageBase, + +char* szDumpFileName, + +ULONG_PTR EntryPoint + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be dumped to disk. + +ImageBase + +[in] Default image base of the active file image from which to dump the memory. This +value should be read from the file on disk. + +szDumpFileName + + [in] Pointer to the full path of the file in which to write the memory content. + +EntryPoint + + [in] Virtual address which will be set to the new file's entry point. The size of this +variable varies, on x86 its 4 bytes and on x64 its 8 bytes. Therefore it can also be +declared as void*. + + + +Return value + +This function returns TRUE on successful dump and FALSE if the memory dump fails. + +Remarks + +None. + +Example + +None. + + + + + + +DumpProcessEx function + +DumpProcessEx, for the specified running process, a memory dump in a file on disk. This image is not a +valid PE file, but a state of memory at the time the function is called. + +Syntax + + + +bool __stdcall DumpProcessEx( + +DWORD ProcessId, + +LPVOID ImageBase, + +char* szDumpFileName, + +ULONG_PTR EntryPoint + +); + + + + + + + +Parameters + +ProcessId + + [in] Process ID of the process, which can be acquired with the Windows API. + +ImageBase + +[in] Default image base of the active file image from which to dump the memory. This +value should be read from the file on disk. + +szDumpFileName + + [in] Pointer to the full path of the file in which to write the memory content. + +EntryPoint + + [in] Virtual address which will be set to the new file's entry point. The size of this +variable varies, on x86 its 4 bytes and on x64 its 8 bytes. Therefore it can also be +declared as void*. + + + +Return value + +This function returns TRUE on successful dump and FALSE if the memory dump fails. + +Remarks + +None. + +Example + +None. + + + + + + +DumpMemory function + +DumpMemory creates memory dump to a file on disk which for a specified part of memory from the +running process. + +Syntax + + + +bool __stdcall DumpMemory( + +HANDLE hProcess, + +LPVOID MemoryStart, + +ULONG_PTR MemorySize, + +char* szDumpFileName + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be dumped to disk. + +MemoryStart + +[in] Start of the memory range to dump. This does not need to be the start of a page. + +MemorySize + + [in] The size of memory to copy to disk. Size of this variable varies, on x86 its 4 bytes +and on x64 its 8 bytes. Therefore it can also be declared as SIZE_T. + +szDumpFileName + + [in] Pointer to the full path of the file in which to write the memory content. + + + +Return value + +This function returns TRUE on successful dump and FALSE if the memory dump fails. + +Remarks + +None. + +Example + +None. + + + + + + +DumpMemoryEx function + +DumpMemoryEx dumps to a file on disk the specified part of memory from the specified running +process. + +Syntax + + + +bool __stdcall DumpMemoryEx( + +DWORD ProcessId, + +LPVOID MemoryStart, + +ULONG_PTR MemorySize, + +char* szDumpFileName + +); + + + + + + + +Parameters + +ProcessId + + [in] Process ID of the process whose memory you want to dump, which can be acquired +with the Windows API. + +MemoryStart + +[in] Start of the memory range dump to disk. This start does not have to be the start of a +page. + +MemorySize + + [in] Specifies the size of the memory to copy to disk. The size of this variable varies, on +x86 its 4 bytes and on x64 its 8 bytes. Therefore it can also be declared as SIZE_T. + +szDumpFileName + + [in] Pointer to the full path of the file in which to write the memory content. + + + +Return value + +This function returns TRUE on successful dump and FALSE if the memory dump fails. + +Remarks + +None. + +Example + +None. + + + + + + +DumpRegions function + +DumpRegions creates a memory dump for all used memory regions in the specified running process. +The dump is written to a series of files in the specified folder on disk. Optionally this function can dump +only those regions located above the image base of the folder. + +Syntax + + + +bool __stdcall DumpRegions( + +HANDLE hProcess, + +char* szDumpFolder, + +bool DumpAboveImageBaseOnly + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be dumped to disk. + +szDumpFolder + + [in] Pointer to the full path of the folder in which to write the memory content. Each +region will be dumped into a separate file within this folder. + +DumpAboveImageBaseOnly + + [in] This variable is a switch which tells the engine which regions to dump. If its value is +FALSE it will dump all regions and if it is TRUE it will dump only regions above image +base of the targeted PE file. + + + +Return value + +This function returns TRUE on successful dump and FALSE if the memory dump fails. + +Remarks + +None. + +Example + +None. + + + + + + +DumpRegionsEx function + +DumpRegionsEx creates a memory dump for all used memory regions in the specified running process. +The dump is written to a series of files in the specified folder on disk. Optionally this function can dump +only those regions located above the image base of the folder. + +Syntax + + + +bool __stdcall DumpRegionsEx( + +DWORD ProcessId, + +char* szDumpFolder, + +bool DumpAboveImageBaseOnly + +); + + + + + + + +Parameters + +ProcessId + + [in] Process ID of the running process which can be acquired with Windows API. + +szDumpFolder + + [in] Pointer to the full path of the folder in which to write the memory content. Each +region will be dumped into a separate file within this folder. + +DumpAboveImageBaseOnly + + [in] This variable is a switch which tells the engine which regions to dump. If its value is +FALSE it will dump all regions and if it is TRUE it will dump only regions above image +base of the targeted PE file. + + + +Return value + +This function returns TRUE on successful dump and FALSE if the memory dump fails. + +Remarks + +None. + +Example + +None. + + + + + + +DumpModule function + +DumpModule dumps to a file on disk the memory of one module within the specified running process. +This image is not a valid PE file, but the state of memory at the time this function is called. + +Syntax + + + +bool __stdcall DumpModule( + +HANDLE hProcess, + +LPVOID ModuleBase, + +char* szDumpFileName + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the running process in which the module is running. + +ModuleBase + + [in] The base address of the loaded module in the specified process. + +szDumpFileName + + [in] Pointer to the full path of the file in which to write the module's memory content. + + + +Return value + +This function returns TRUE on a successful dump and FALSE if the memory dump fails. + +Remarks + +None. + +Example + +None. + + + + + + +DumpModuleEx function + +DumpModuleEx dumps to a file on disk the memory of one module within the specified running +process. This image is not a valid PE file, but the state of memory at the time this function is called. + +Syntax + + + +bool __stdcall DumpModuleEx( + +DWORD ProcessId, + +LPVOID ModuleBase, + +char* szDumpFileName + +); + + + + + + + +Parameters + +ProcessId + + [in] Process ID of the running process in which the module is loaded - can be acquired +with the Windows API. + +ModuleBase + + [in] The base address of the loaded module in the specified process. + +szDumpFileName + + [in] Pointer to the full path of the file in which to write the module's memory content. + + + +Return value + +This function returns TRUE on a successful dump and FALSE if the memory dump fails. + +Remarks + +None. + +Example + +None. + + + + + + +PastePEHeader function + +PastePEHeader loads the PE header from a file on disk and writes it to running process memory. This +can be used to fix damage to PE header during process runtime. Such damage only occurs as a result of +memory protection algorithms used by some protection solutions. + +Syntax + + + +bool __stdcall PastePEHeader( + +HANDLE hProcess, + +LPVOID ImageBase, + +char* szDebuggedFileName + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be repaired. + +ImageBase + +[in] Default image base of the targeted PE file. This value should be read from the file on +disk. + +szDebuggedFileName + + [in] Pointer to the full path of the file from which the PE header will be read. + + + +Return value + +This function returns TRUE if the PE header is fixed and FALSE otherwise. + +Remarks + +None. + +Example + +None. + + + + + + +ExtractSection function + +ExtractSection copies the physical content of the specified section in a file to a new file on disk. + +Syntax + + + +bool __stdcall ExtractSection( + +char* szFileName, + +char* szDumpFileName, + +DWORD SectionNumber + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file from which the section will be extracted. + +szDumpFileName + + [in] Pointer to the full path of the file to which the section will be written. + +SectionNumber + + [in] Number of the section to extract. Section numbers range from zero to section count +minus one. + + + +Return value + +This function returns TRUE if the extraction succeeds, and FALSE if the extraction fails. + +Remarks + +None. + +Example + +None. + + + + + + +ResortFileSections function + +ResortFileSections sorts a file's physical sections, putting them in the order of ascending physical offset. +This can be useful if there you need to add data to, or expand; the last logical section of the file, but it +isn’t physically located in the last physical section of the file. + +Syntax + + + +bool __stdcall ResortFileSections( + +char* szFileName, + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file to re-sort. + + + +Return value + +This function returns TRUE on successful resort and FALSE if the sorting fails. + +Remarks + +The file's size doesn’t change, but its hash does, because sections will be physically moved to +new positions. + +Example + +None. + + + + + + +FindOverlay function + +FindOverlay finds overlay data (extra data appended to the end of a PE file). This data can be the file +certificate or other important data that is useful for further file analysis. + +Syntax + + + +bool __stdcall FindOverlay( + +char* szFileName, + +LPDWORD OverlayStart, + +LPDWORD OverlaySize + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file from which to extract any overlay data. + +OverlayStart + + [out] Pointer to a DWORD which will hold a file pointer that points to the overlay data. +This file pointer can be used with the Windows API to access the overlay. + +OverlaySize + + [out] Pointer to a DWORD to hold the size of the overlay. + + + +Return value + +This function returns TRUE if an overlay is found, FALSE if the overlay is not found. + +Remarks + +None. + +Example + +None. + + + + + + +ExtractOverlay function + +ExtractOverlay finds overlay data (extra data appended to the end of a PE file) and copies it to new file. +This data can be the file certificate or other important data that is useful for further file analysis. + +Syntax + + + +bool __stdcall ExtractOverlay( + +char* szFileName, + +char* szExtactedFileName + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file which will be queried +for overlay presence and whose overlay will be extracted. + +szExtractedFileName + +[in] Pointer to the full path of the file to hold the overlay content extracted from the +input file. + + + +Return value + +This function returns TRUE when overlay data is found and extracted and FALSE if the overlay is +not found or overlay export fails. + +Remarks + +The output file is always overwritten. + +Example + +None. + + + + + + +AddOverlay function + +AddOverlay appends extracted overlay data to the end of PE files. This data can be the file certificate or +other important data that is useful for further file analysis. + +Syntax + + + +bool __stdcall AddOverlay( + +char* szFileName, + +char* szOverlayFileName + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file which will be queried +for overlay presence and whose overlay will be extracted. + +szOverlayFileName + +[in] Pointer to the full path of the PE file to which the overlay content will be appended +(null terminated string). + + + +Return value + +This function returns TRUE if data is successfully appended and FALSE if one of the files is not +found. + +Remarks + +This function can also be used to merge two non PE files. + +Example + +None. + + + + + + +CopyOverlay function + +CopyOverlay copies overlay data from one PE file to another. If target file already has overlay data, the +new data will be appended just after the existing data. + +Syntax + + + +bool __stdcall CopyOverlay( + +char* szInFileName, + +char* szOutFileName + +); + + + + + + + +Parameters + +szInFileName + + [in] Pointer to a null terminated string which is a full path to file which will be queried +for overlay presence and whose overlay will be copied. + +szOutFileName + + [in] Pointer to a null terminated string which is a full path to file to which new overlay +data will be appended. + + + +Return value + +This function returns TRUE if the data is successfully appended and FALSE if one of the files is +not found or not a PE file. + +Remarks + +None. + +Example + +None. + + + + + + +RemoveOverlay function + +RemoveOverlay removes overlay data from PE files. + +Syntax + + + +bool __stdcall RemoveOverlay( + +char* szFileName + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file which will be stripped of its overlay data. + + + +Return value + +This function returns TRUE if the overlay is removed and FALSE if overlay or file isn’t found. + +Remarks + +None. + +Example + +None. + + + + + + +MakeAllSectionsRWE function + +MakeAllSectionsRWE sets the characteristics of all sections in a PE file to read/write/executable. + +Syntax + + + +bool __stdcall MakeAllSectionsRWE( + +char* szFileName + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file whose PE sections will be set to +read/write/executable. + + + +Return value + +This function returns TRUE on success and FALSE if the file doesn’t exist or the PE header is +broken. + +Remarks + +None. + +Example + +None. + + + + + + +AddNewSectionEx function + +AddNewSectionEx adds a new PE section to a file. The newly created section is physical and its content +is filled with zeroes if no content is specified. This reserved space can be used to store data later. + +Syntax + + + +long __stdcall AddNewSectionEx( + +char* szFileName, + +char* szSectionName, + +DWORD SectionSize, + +DWORD SectionAttributes, + +LPVOID SectionContent, + +DWORD ContentSize + +); + + + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file to which new section +will be added. + +szSectionName + + [in] Pointer to a null terminated string which will be the new section name. This string +can be up to 8 characters long. + +SectionSize + + [in] Size of the new section, both virtual and physical. Virtual size will be rounded up to +next modus of SectionAlignment, and physical size will be rounded up to next +modus of FileAlignment. + +SectionAttributes + + [in] Section attributes as defined by PECOFF 8. If this value is NULL, attributes will be set +to default read/write/execute 0xE0000020 value. + +SectionContent + + [in] Pointer to memory whose content will be copied to the newly created section. If +null, the new section will be filled with zeroes. + +ContentSize + + [in] Size of the memory whose content which will be copied to the new section. + + + +Return value + +This function returns the relative virtual offset of the newly created section, or NULL if adding +the new section fails. + + + + +AddNewSection function + +AddNewSection adds a new physical PE section, filled with zeroes, to a file, creating space in the file +that can be used to store data later. + +Syntax + + + +long __stdcall AddNewSection( + +char* szFileName, + +char* szSectionName, + +DWORD SectionSize + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file to which new section +will be added. + +szSectionName + + [in] Pointer to a null terminated string to use as the new section name. This string can +be up to 8 characters long. + +SectionSize + + [in] Size of the new section, both virtual and physical. Virtual size will be rounded up to +next modus of SectionAlignment, and physical size will be rounded up to next +modus of FileAlignment. + + + +Return value + +This function returns relative virtual offset of the newly created section, or NULL if adding the +new section fails. + +Remarks + +None. + +Example + +None. + + + + + + +ResizeLastSection function + +ResizeLastSection increases the size of the last PE file section in a file. The section is increased both +physically and virtually. Optionally, the new section's size can be aligned to FileAlignment. + +Syntax + + + +bool __stdcall ResizeLastSection( + +char* szFileName, + +DWORD NumberOfExpandBytes, + +bool AlignResizeData + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose last PE section +will be resized. + +NumberOfExpandBytes + + [in] Last section will be increased by this variable value. + +AlignResizeData + + [in] Set to TRUE to align the last section's size to FileAlignment. + + + +Return value + +This function returns TRUE on success and FALSE if the file doesn’t exist or the PE header is +broken. + +Remarks + +The file is backed up before modification, and restored if the file cannot be resized. + +Example + +None. + + + + + + +SetSharedOverlay function + +SetSharedOverlay is used only to store string pointer provided to it. This function is from the old SDK +and is retained only for backward compatibility. + +Syntax + + + +void __stdcall SetSharedOverlay( + +char* szFileName + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of a file. This string pointer will be stored in case other +modules need to retrieve it but have no direct access to the variable. The string +itself won’t be moved or modified so it must remain at that location for all time it is +needed. + + + +Return value + +This function has no return value. + +Remarks + +None. + +Example + +None. + + + + + + +GetSharedOverlay function + +GetSharedOverlay is retrieves a store string pointer provided by SetSharedOverlay function. This +function is from the old SDK and is retained only for backward compatibility + +Syntax + + + +char* __stdcall GetSharedOverlay(); + + + + + + + +Parameters + +None. + +Return value + +This function returns the previously stored pointer. + +Remarks + +None. + +Example + +None. + + + + + + +DeleteLastSection function + +DeleteLastSection physically deletes the last PE section from the specified file. + +Syntax + + + +bool __stdcall DeleteLastSection( + +char* szFileName + +); + + + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose last PE section +will be deleted. + + + +Return value + +This function returns TRUE on success and FALSE if the file doesn’t exist or the PE header is +broken. + +Remarks + +The file is backed up before modification and restored if the file cannot be resized. + +Example + +None. + + + + + + +DeleteLastSectionEx function + +DeleteLastSectionEx physically deletes the selected number PE sections from the end of the specified +file. + +Syntax + + + +bool __stdcall DeleteLastSectionEx( + +char* szFileName, + +DWORD NumberOfSections + +); + + + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose last PE section(s) +will be deleted. + +NumberOfSections + + [in] Number of sections to remove from the end of the PE file. + + + +Return value + +This function returns TRUE on success and FALSE if the file doesn’t exist or the PE header is +broken. + +Remarks + +The file is backed up before modification and restored if the file cannot be resized. + +Example + +None. + + + + + + +GetPE32DataFromMappedFile function + +GetPE32DataFromMappedFile retrieves data from the PE header for both x86 and x64 files. + +Syntax + + + +long long __stdcall GetPE32DataFromMappedFile( + +ULONG_PTR FileMapVA, + +DWORD WhichSection, + +DWORD WhichData + +); + + + + + + + + + +Parameters + +FileMapVA + + [in] Pointer to the mapped file content. This pointer is set by using either StaticFileLoad +function or Windows API for file mapping. It is a ULONG_PTR which defines its size +on the x86 and x64 operating systems. On x86 systems this variable is 4 bytes long +and equal to DWORD, and on x64 platform this variable is 8 bytes long and equal to +DWORD64, but since this is a pointer, void* can also be used. + +WhichSection + + [in] Number of the first PE section from which to read the data. The first PE section is +section zero, so the section numbers range from zero to section count minus one. + +WhichData + + [in] Specifies which PE header info this function will return. The list of constants used by +this function is located at the beginning of this section under Dumper module +constants. + + + +Return value + +This function returns the requested PE data. The return variable should be defined as +ULONG_PTR which defines its size on x86 and x64 operating system. + +Remarks + +The file must be mapped before using this function. + + + + + + +GetPE32DataFromMappedFileEx function + +The GetPE32DataFromMappedFileEx function is used to retrieve data from the PE header for both x86 +and x64 files. + +Syntax + + + +bool __stdcall GetPE32DataFromMappedFileEx( + +ULONG_PTR FileMapVA, + +LPVOID DataStorage + +); + + + + + + + + + +Parameters + +FileMapVA + + [in] Pointer to the mapped file content. This pointer is set by using either StaticFileLoad +function or Windows API for file mapping. It is a ULONG_PTR which defines its size +on the x86 and x64 operating systems. On x86 systems this variable is 4 bytes long +and equal to DWORD, and on x64 platform this variable is 8 bytes long and equal to +DWORD64. But since this is a pointer, void* can also be used. + +DataStorage + + [in] Pointer to a structure to hold all PE header data. This structure is different for x86 +and x64 systems. Its definition is located at the beginning of this section under +Dumper module structures. + +Return value + +This function returns TRUE on success and FALSE if the file doesn’t exist or the PE header is +broken. + +Remarks + +The file must be mapped before using this function. + +Example + +None. + + + + + + +GetPE32Data function + +GetPE32Data retrieves data from the PE header for both x86 and x64 files. + +Syntax + + + +long long __stdcall GetPE32Data( + +char* szFileName, + +DWORD WhichSection, + +DWORD WhichData + +); + + + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file from which PE header +data will be read. + +WhichSection + + [in] Number of the PE section from which data will be read. The first PE section is +section zero, so the section numbers range from zero to section count minus one. + +WhichData + + [in] Specifies which PE header info this function will return. The list of constants used by +this function is located at the beginning of this section under Dumper module +constants. + +Return value + +This function returns the PE header data. The return variable should be defined as ULONG_PTR +which defines its size on x86 and x64 operating system. + +Remarks + +None. + +Example + +None. + + + + + + +GetPE32DataEx function + +The GetPE32DataEx function is used to retrieve data from the PE header for both x86 and x64 files. + +Syntax + + + +bool __stdcall GetPE32DataEx( + +char* szFileName, + +LPVOID DataStorage + +); + + + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file from which PE header +data will be read. + +DataStorage + + [in] Pointer to a structure to hold the PE header data. This structure is different for x86 +and x64. Its definition is located at the beginning of this section under Dumper +module structures. + +Return value + +This function returns TRUE on success and FALSE if the file doesn’t exist or the PE header is +broken. + +Remarks + +None. + +Example + +None. + + + + + + +SetPE32DataForMappedFile function + +The SetPE32DataFromMappedFile function is used to set data to PE header for both x86 and x64 files. + +Syntax + + + +bool __stdcall SetPE32DataForMappedFile( + +ULONG_PTR FileMapVA, + +DWORD WhichSection, + +DWORD WhichData, + +ULONG_PTR NewDataValue + +); + + + + + + + + + +Parameters + +FileMapVA + + [in] Pointer to the mapped file content. This pointer is set by using either StaticFileLoad +function or Windows API for file mapping. It is a ULONG_PTR which defines its size +on the x86 and x64 operating systems. On x86 systems this variable is 4 bytes long +and equal to DWORD, and on x64 platform this variable is 8 bytes long and equal to +DWORD64, but since this is a pointer void* can also be used. + +WhichSection + + [in] Number of the PE section from which data will be read. The first PE section is +section zero, so the section numbers range from zero to section count minus one. + +WhichData + + [in] Indicator on which PE header info this function will return. The list of constants +used by this function is located at the beginning of this section under Dumper +module constants. + +NewDataValue + + [in] Value which will be set for the selected PE header field. + + + +Return value + +This function returns TRUE on success and FALSE if the file doesn’t exist or the PE header is +broken. + +Remarks + +The file must be mapped before using this function. + + + + + + +SetPE32DataForMappedFileEx function + +SetPE32DataForMappedFileEx stores the data from a PE header into a data structure, for both x86 and +x64 files. + +Syntax + + + +bool __stdcall SetPE32DataForMappedFileEx( + +ULONG_PTR FileMapVA, + +LPVOID DataStorage + +); + + + + + + + + + +Parameters + +FileMapVA + + [in] Pointer to the mapped file content you want to store. This pointer is set by using +either StaticFileLoad function or Windows API for file mapping. It is a ULONG_PTR +which defines its size on the x86 and x64 operating systems. On x86 systems this +variable is 4 bytes long and equal to DWORD, and on x64 platform this variable is 8 +bytes long and equal to DWORD64. But since this is a pointer, void* can also be +used. + +DataStorage + + [in] Pointer to a structure that will hold the PE header data. Ideally this structure is first +filled by using GetPE32DataFromMappedFileEx. This structure is different for x86 +and x64, its definition is located at the beginning of this section under Dumper +module structures. + +Return value + +This function returns TRUE on success and FALSE if the file doesn’t exist or the PE header is +broken. + +Remarks + +The file must be mapped before using this function. + +Example + +None. + + + + + + +SetPE32Data function + +SetPE32Data sets data to the PE header for both x86 and x64 files. + +Syntax + + + +bool __stdcall SetPE32Data( + +char* szFileName, + +DWORD WhichSection, + +DWORD WhichData + +); + + + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose PE header data +will be modified. + +WhichSection + + [in] Number of the PE section from which data will be read. The first PE section is +section zero, so the section numbers range from zero to section count minus one. + +WhichData + + [in] Indicator on which PE header info this function will return. Specifies which PE +header info this function will return. The list of constants used by this function is +located at the beginning of this section Dumper module constants. + +Return value + +This function returns TRUE on success and FALSE if the file doesn’t exist or the PE header is +broken. + +Remarks + +None. + +Example + +None. + + + + + + +SetPE32DataEx function + +SetPE32DataEx sets data to the PE header for both x86 and x64 files. + +Syntax + + + +bool __stdcall SetPE32DataEx( + +char* szFileName, + +LPVOID DataStorage + +); + + + + + + + + + +Parameters + +szFileName + +[in] Pointer to a null terminated string which is a full path to file whose PE header data +will be modified. + +DataStorage + + [in] Pointer to a structure from which the PE header data is reset. Ideally this structure +is first filled by using GetPE32DataFromMappedFileEx function. This structure is +different for x86 and x64 and its definition is located at the beginning of this section +under Dumper module structures. + +Return value + +This function returns TRUE on success and FALSE if the file doesn’t exist or the PE header is +broken. + +Remarks + +None. + +Example + +None. + + + + + + +GetPE32SectionNumberFromVA function + +GetPE32SectionNumberFromVA determines in which PE section the selected virtual address resides. + +Syntax + + + +long __stdcall GetPE32SectionNumberFromVA( + +ULONG_PTR FileMapVA, + +ULONG_PTR AddressToConvert + +); + + + + + + + + + +Parameters + +FileMapVA + + [in] Pointer to the mapped file content. This pointer is set by using either StaticFileLoad +function or Windows API for file mapping. It is a ULONG_PTR which defines its size +on the x86 and x64 operating systems. On x86 systems this variable is 4 bytes long +and equal to DWORD, and on x64 platform this variable is 8 bytes long and equal to +DWORD64. But since this is a pointer void* can also be used. + +AddressToConvert + + [in] Virtual address which will be located inside mapped file sections. + + + +Return value + +This function returns number of section in which virtual address resides or UE_VANOTFOUND. +The first PE section is section zero, so the section numbers range from zero to section count +minus one. + +Remarks + +The file must be mapped before using this function. + +Example + +None. + + + + + + +ConvertVAtoFileOffset function + +ConvertVAtoFileOffset converts virtual addresses to its physical counterpart. + +Syntax + + + +long long __stdcall ConvertVAtoFileOffset( + +ULONG_PTR FileMapVA, + +ULONG_PTR AddressToConvert, + +bool ReturnType + +); + + + + + + + + + +Parameters + +FileMapVA + + [in] Pointer to the mapped file content. This pointer is set by using either StaticFileLoad +function or Windows API for file mapping. It is a ULONG_PTR which defines its size +on the x86 and x64 operating systems. + +AddressToConvert + + [in] Virtual address to convert to a physical address. + +ReturnType + + [in] Boolean variable which indicates whether or not to add the FileMapVA to the +function's return value. + + + +Return value + +This function returns the converted physical address. Return variable should be defined as +ULONG_PTR which defines its size on x86 and x64 operating system. If ReturnType is FALSE this +value will never be larger than DWORD. If this function returns NULL conversion has failed. + +Remarks + +The file must be mapped before using this function. + +Example + +None. + + + + + + +ConvertVAtoFileOffsetEx function + +ConvertVAtoFileOffsetEx converts virtual or relative virtual addresses to its physical counterpart. Using +this function is considered safer then ConvertVAtoFileOffset because it uses safety checks to ensure that +the PE file is valid and memory is there and accessible. + +Syntax + + + +long long __stdcall ConvertVAtoFileOffsetEx( + +ULONG_PTR FileMapVA, + +DWORD FileSize, + +ULONG_PTR ImageBase, + +ULONG_PTR AddressToConvert, + +bool AddressIsRVA, + +bool ReturnType + +); + + + + + + + + + + + +Parameters + +FileMapVA + + [in] Pointer to the mapped file content. This pointer is set by using either StaticFileLoad +function or Windows API for file mapping. It is a ULONG_PTR which defines its size +on the x86 and x64 operating systems. + +FileSize + + [in] Size of the mapped file. + +ImageBase + + [in] ImageBase of the mapped file, read directly from its PE header. + +AddressToConvert + + [in] Virtual address which to converted to its physical address. + +AddressIsRVA + + [in] Boolean variable which indicates whether the input address is relative or virtual. +Virtual is the default expected input. + +ReturnType + + [in] Boolean variable which indicates whether or not to add FileMapVA to function +return. + +Return value + +This function returns the converted physical address. Return variable should be defined as +ULONG_PTR which defines its size on x86 and x64 operating system. If ReturnType is FALSE this +value will never be larger than DWORD. If this function returns NULL conversion has failed. + + + + +ConvertFileOffsetToVA function + +ConvertFileOffsetToVA converts a physical address to its virtual counterpart. + +Syntax + + + +long long __stdcall ConvertFileOffsetToVA( + +ULONG_PTR FileMapVA, + +ULONG_PTR AddressToConvert, + +bool ReturnType + +); + + + + + + + + + +Parameters + +FileMapVA + + [in] Pointer to the mapped file content. This pointer is set by using either StaticFileLoad +function or Windows API for file mapping. It is a ULONG_PTR which defines its size +on the x86 and x64 operating systems. + +AddressToConvert + + [in] The physical address to convert to a virtual address. It must reside in address space +allocated with FileMapVA. + +ReturnType + + [in] Boolean variable which indicates whether or not to add ImageBase to the function's +return. + + + +Return value + +This function returns the converted virtual address. Return variable should be defined as +ULONG_PTR which defines its size on x86 and x64 operating system. If ReturnType is FALSE this +value will never be larger than DWORD. If this function returns NULL conversion has failed. + +Remarks + +The file must be mapped before using this function. + +Example + +None. + + + + + + +ConvertFileOffsetToVAEx function + +ConvertFileOffsetToVAEx converts physical addresses to its virtual counterpart. Using this function is +considered safer then ConvertFileOffsetToVA because it does safety checks to ensure that the PE file is +valid and memory is there and accessible. + +Syntax + + + +long long __stdcall ConvertFileOffsetToVAEx( + +ULONG_PTR FileMapVA, + +DWORD FileSize, + +ULONG_PTR ImageBase, + +ULONG_PTR AddressToConvert, + +bool ReturnType + +); + + + + + + + + + +Parameters + +FileMapVA + + [in] Pointer to the mapped file content. This pointer is set by using either StaticFileLoad +function or Windows API for file mapping. It is a ULONG_PTR which defines its size +on the x86 and x64 operating systems. + +FileSize + + [in] Size of the mapped file. + +ImageBase + + [in] ImageBase of the mapped file read directly from its PE header. + +AddressToConvert + +[in] Physical address which will be converted to virtual address. It must reside in address +space allocated with FileMapVA. + +ReturnType + + [in] Boolean variable which indicates whether or not to add ImageBase to function +return. + + + +Return value + +This function returns the converted virtual address. Return variable should be defined as +ULONG_PTR which defines its size on x86 and x64 operating system. If the ReturnType is FALSE +this value will never be larger than DWORD. If this function returns NULL conversion has failed. + +Remarks + +The file must be mapped before using this function. + + + + +Importer module + + + +The Importer module has functions designed for import manipulation, forward handling, and automatic +import locating and fixing. + + + + +Importer module structures + + + +Structure used by: ImporterEnumAddedData function + + + +typedef struct{ + + bool NewDll; + + int NumberOfImports; + + ULONG_PTR ImageBase; + + ULONG_PTR BaseImportThunk; + + ULONG_PTR ImportThunk; + + char* APIName; + + char* DLLName; + +}ImportEnumData, *PImportEnumData; + + + + + + + ImporterInit function + +ImporterInit initializes the importer module. It must be used before using any of the functions that do +manual import fixing. + +Syntax + + + +void __stdcall ImporterInit( + +DWORD MemorySize, + +ULONG_PTR ImageBase + +); + + + + + + + +Parameters + +MemorySize + + [in] Default memory size allocated for each of the new DLLs files you add. This size must +be large enough to hold all data needed by the engine. Usually there is no need to +reserve more than 40kb of memory. + +ImageBase + +[in] Default image base of the targeted PE file. This value should be read from the file on +disk. + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterSetImageBase function + +ImporterSetImageBase updates information passed to the engine when the importer is initialized. + +Syntax + + + +void __stdcall ImporterSetImageBase( + +ULONG_PTR ImageBase + +); + + + + + + + +Parameters + +ImageBase + +[in] Default image base of the targeted PE file. This value should be read from the file on +disk. + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterAddNewDll function + +ImporterAddNewDll adds new DLLs to the new import tree. This function creates a new DLL entry +making all subsequent ImporterAddNewAPI function calls add APIs to the current DLL. If you want to add +APIs that don’t belong to the current DLL, add a new DLL entry first. PECOFF specifications imply that +trunks are in a plus four (or eight on x64) sequence. The importer takes care of this automatically and +adds a new DLL entry equal to the last entered DLL if this sequence is broken. + +Syntax + + + +void __stdcall ImporterAddNewDll( + +char* szDLLName, + +ULONG_PTR FirstThunk + +); + + + + + + + +Parameters + +szDLLName + + [in] Pointer to string which is the name of the DLL to add to the new import tree. For +example: kernel32.dll or SomeFolder\mydll.dll in case of relative path loading. + +FirstThunk + +[in] Optional: address inside the PE file's memory that holds the pointer to an API +belonging to that DLL. This is the first pointer in the sequence. If set to NULL the +next call to ImporterAddNewAPI will set the first trunk to the data provided to it. If +the trunk is outside the PE file's memory you must use a special approach described +in examples. + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterAddNewAPI function + +ImporterAddNewAPI adds a new API to the current import tree. This function creates a new API entry +under currently selected DLL added by ImporterAddNewDLL. If the APIs don’t belong to the current DLL, +add a new DLL entry first. PECOFF specifications imply that trunks are in a plus four (or eight on x64) +sequence. The importer takes care of this automatically, and adds a new DLL entry equal to the last +entered DLL if this sequence is broken. + +Syntax + + + +void __stdcall ImporterAddNewAPI( + +char* szAPIName, + +ULONG_PTR ThunkValue + +); + + + + + + + +Parameters + +szAPIName + + [in] Pointer to string which is the name of the API to be added to the new import tree, +but belonging to current DLL. For example: VirtualProtect or VirtualAlloc, which are +added to the current DLL, which is in this case kernel32.dll + +ThunkValue + +[in] Mandatory parameter, specifying the address inside the PE file's memory that holds +the pointer to the API belonging to that DLL. In case the trunk is outside the PE file's +memory you must use a special approach described in examples. + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterAddNewOrdinalAPI function + +ImporterAddNewOrdinalAPI adds a new ordinal API to the current import tree. This function creates a +new API entry under currently selected DLL added by ImporterAddNewOrdinalAPI. If the APIs don’t +belong to the current DLL, add a new DLL entry first. PECOFF specifications imply that trunks are in a +plus four (or eight on x64) sequence. The importer takes care of this automatically, and adds a new DLL +entry equal to the last entered DLL if this sequence is broken. + +Syntax + + + +void __stdcall ImporterAddNewOrdinalAPI( + +ULONG_PTR OrdinalNumber, + +ULONG_PTR ThunkValue + +); + + + + + + + +Parameters + +OrdinalNumber + + [in] API ordinal number to be added. Can have a IMAGE_ORDINAL_FLAG mask. + +ThunkValue + +[in] Mandatory parameter, specifying the address inside the PE file's memory that holds +the pointer to the API belonging to that DLL. In case the trunk is outside the PE file's +memory you must use a special approach described in examples. + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterGetLastAddedDLLName function + +ImporterGetLastAddedDLLName retrieves the name of the last added DLL in the current importer tree. + +Syntax + + + +void* __stdcall ImporterGetLastAddedDLLName(); + + + + + + + +Parameters + +None. + +Return value + +Pointer to string holding the last added DLL name. + +Remarks + +CAUTION: A string with the DLL name is stored inside the engine which makes this function +multi thread unsafe. + +Example + +None. + + + + + + + ImporterGetAddedDllCount function + +ImporterGetAddedDllCount gets the current number of added DLLs inside the import tree. + +Syntax + + + +long __stdcall ImporterGetAddedDllCount(); + + + + + + + +Parameters + +None. + +Return value + +Returns the number of added DLLs inside the import tree. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterGetAddedAPICount function + +ImporterGetAddedAPICount gets the current number of added APIs inside the import tree. + +Syntax + + + +long __stdcall ImporterGetAddedAPICount(); + + + + + + + +Parameters + +None. + +Return value + +Returns the number of added APIs inside the import tree. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterEnumAddedData function + +ImporterEnumAddedData enumerates all added import tree data and calls the designated callback for +each one, with the details about it. + +Syntax + + + +void __stdcall ImporterEnumAddedData( + +LPVOID EnumCallBack + +); + + + + + + + +Parameters + +EnumCallBack + + [in] Address of a callback function that will process the added import data. + + + +CallBack definition + +typedef void(__stdcall *fEnumCallBack)(LPVOID ptrImportEnumData); + +typedef struct{ + + bool NewDll; // Indicator on if the dll has changed + + int NumberOfImports; + + ULONG_PTR ImageBase; + + ULONG_PTR BaseImportThunk; // Original first trunk + + ULONG_PTR ImportThunk; // Current import trunk + + char* APIName; + + char* DLLName; + +}ImportEnumData, *PImportEnumData; + + + + + + + + + + + + + +Return value + +None. + +Remarks + +Strings with the API and the DLL name is stored inside the engine which makes this function +multi thread unsafe. + + + + + + + ImporterEstimatedSize function + +ImporterEstimatedSize estimates the size of memory needed to write the import data. This value can be +used to determine the size of the new section in which the import data will be written. + +Syntax + + + +long __stdcall ImporterEstimatedSize(); + + + + + + + +Parameters + +None. + +Return value + +Returns the size needed to write the import data. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterCleanup function + +ImporterCleanup clears all added DLLs and APIs from the import tree. This resets the inputted data to its +original state. Before using the functions to add the data to import tree, you must initialize the importer +again. + +Syntax + + + +void __stdcall ImporterCleanup(); + + + + + + + +Parameters + +None. + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + ImporterExportIATEx function + +ImporterExportIATEx exports the added import data to existing PE file creating the valid import table for +the selected PE file. After this function has executed, the import data will be cleared by using the +ImporterCleanup function. + +Syntax + + + +bool __stdcall ImporterExportIATEx( + +char* szExportFileName, + +char* szSectionName + +); + + + + + + + +Parameters + +szExportFileName + + [in] Pointer to string which is a full path to the file to which new import table will be +written. This file is usually created by using DumpProcess. + +szSectionName + +[in] Name of the PE section in which the new import table content will be written. This +section will be added to the file. Length of this string is capped at 8 characters. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterExportIAT function + +ImporterExportIAT exports the added import data to the existing PE file creating the valid import table +for the selected PE file. After this function has executed, the import data will be cleared by using +ImporterCleanup function. + +Syntax + + + +bool __stdcall ImporterExportIAT( + +ULONG_PTR StorePlace, + +ULONG_PTR FileMapVA + +); + + + + + + + +Parameters + +StorePlace + + [in] Physical address inside PE file on which the new import table will be written. +Usually this is a new section, but it can also be an unused part of the file that is still +in read/write mode. + +FileMapVA + + [in] Pointer to the mapped file content, which must be mapped, in read/write mode. +This pointer is set by using either StaticFileLoad function or Windows API for file +mapping. It is a ULONG_PTR which defines its size on the x86 and x64 operating +systems. On x86 systems this variable is 4 bytes long and equal to DWORD, and on +x64 platform this variable is 8 bytes long and equal to DWORD64, but since this is a +pointer void* can also be used. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterGetDLLName function + +ImporterGetDLLName returns the name of the DLL in which address supplied to the function resides in. +This address is usually the pointer to API located inside the import table of the file whose IAT you are +fixing. + +Syntax + + + +void* __stdcall ImporterGetDLLName( + +ULONG_PTR APIAddress + +); + + + + + + + +Parameters + +APIAddress + + [in] Address on which possible API is located. This address is equal to the address +returned by the GetProcAddress Windows API for DLL and the function of interest. + + + +Return value + +Pointer to string, which is the name of the DLL which holds the API located at specified address +or NULL if no DLL is found. + +Remarks + +String with the DLL name is stored inside the engine which makes this function multi thread +unsafe. Process which is searched for the DLL is always the currently debugged process. + +Example + +ImporterGetDLLName(GetProcAddress(GetModuleHandleA(“kernel32.dll”), “VirtualAlloc”)); + +This will return a pointer to “kernel32.dll” string, without the quotes. Example can fail in ASLR +environment since API address must reside inside the debugged process, therefore if used like +this local API address inside debugger must be relocated to remote one inside the debugge. + + + + + + + ImporterGetAPIName function + +ImporterGetAPIName returns the name of the API whose address is supplied to the function. This +address is usually the pointer to API located inside the import table of the file whose IAT you are fixing. + +Syntax + + + +void* __stdcall ImporterGetAPIName( + +ULONG_PTR APIAddress + +); + + + + + + + +Parameters + +APIAddress + + [in] Address on which possible API is located. This address is equal to the address +returned by the GetProcAddress Windows API for DLL and the function of interest. + + + +Return value + +Pointer to string, which is the name of the API located at specified address or NULL if no API is +found. + +Remarks + +String with the API name is stored inside the engine which makes this function multi thread +unsafe. Process which is searched for the API is always the currently debugged process. + +Example + +ImporterGetAPIName(GetProcAddress(GetModuleHandleA(“kernel32.dll”), “VirtualAlloc”)); + +This will return a pointer to “VirtualAlloc” string, without the quotes. Example can fail in ASLR +environment since API address must reside inside the debugged process, therefore if used like +this local API address inside debugger must be relocated to remote one inside the debugge. + + + + + + + ImporterGetAPINameEx function + +ImporterGetAPINameEx returns the name of the API whose address is supplied to the function. This +address is usually the pointer to API located inside the import table of the file whose IAT you are fixing. +Expert version of this function only searches for API in the provided module list. This list is compiled of +DLL module base addresses from the debugged process. + +Syntax + + + +void* __stdcall ImporterGetAPINameEx( + +ULONG_PTR APIAddress, + +ULONG_PTR DLLBasesList + +); + + + + + + + +Parameters + +APIAddress + + [in] Address on which possible API is located. This address is equal to address returned +by GetProcAddress Windows API for DLL and function of interest. + +DLLBasesList + + [in] Pointer to array of module base addresses inside the remote process. This list is +either manually compiled or generated with EnumProcessModules Windows API. + + + +Return value + +Pointer to string which is the name of the API located at supplied address or NULL if no API is +found. + +Remarks + +String with the API name is stored inside the engine which makes this function multi thread +unsafe. Process which is searched for the API is always the currently debugged process. + +Example + +None. + + + + + + + ImporterGetAPIOrdinalNumber function + +ImporterGetAPIOrdinalNumber returns the ordinal number of the API whose address is supplied to the +function. This address is usually the pointer to API located inside the import table of the file whose IAT +you are fixing. + +Syntax + + + +long long __stdcall ImporterGetAPIOrdinalNumber( + +ULONG_PTR APIAddress + +); + + + + + + + +Parameters + +APIAddress + + [in] Address on which possible API is located. This address is equal to address returned +by GetProcAddress Windows API for DLL and function of interest. + + + +Return value + +Ordinal number of the API located at supplied address or minus one if no API is found. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterGetRemoteAPIAddress function + +ImporterGetRemoteAPIAddress realigns the local API address to remote one inside the debugged +process. This function is usefully in cases when local and remote DLL are not loaded on the same base +address or in case of ASLR. Keep in mind that your process might not have loaded all the remote DLL +files so that this function cannot be used in case that module in which the API resides isn’t loaded. + +Syntax + + + +long long __stdcall ImporterGetRemoteAPIAddress( + +HANDLE hProcess, + +ULONG_PTR APIAddress + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose modules will be searched for the supplied API. + +APIAddress + + [in] Address on which API is located. This address is equal to address returned by +GetProcAddress Windows API for DLL and function of interest. + + + +Return value + +Realigned API address matching the API address inside the debugged process. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterGetRemoteAPIAddressEx function + +ImporterGetRemoteAPIAddressEx retrieves the remote API address from any module that debugged +process has loaded. There is no need to have the remote DLL loaded locally in order to use this function. + +Syntax + + + +long long __stdcall ImporterGetRemoteAPIAddressEx( + +char* szDLLName, + +char* szAPIName + +); + + + + + + + +Parameters + +szDLLName + + [in] Name of the remote DLL file which contains the needed API. + +szAPIName + + [in] Name of the API inside the remote DLL whose address inside the remote process +will be returned. + + + +Return value + +Remote API address matching the API address inside the debugged process. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterGetLocalAPIAddress function + +ImporterGetLocalAPIAddress is used relocate the remote API address to local one. This is used when +the remote module is loaded inside the debugger and you need to know the local address of that +remote API, which is usefully in cases when local and remote DLL are not loaded on the same base +address or in case of ASLR. + +Syntax + + + +long long __stdcall ImporterGetLocalAPIAddress( + +HANDLE hProcess, + +ULONG_PTR APIAddress + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose modules will be searched for the supplied API. + +APIAddress + + [in] Address on which API is located in the remote process. This address is equal to +address returned by GetProcAddress Windows API for DLL and function of interest if +called in debugged process. + + + +Return value + +Local API address for the remotely found API or NULL if that API can’t be found in your process. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterGetDLLNameFromDebugee function + +ImporterGetDLLNameFromDebugee gets the name of the remote DLL which has the selected API. +Address of the API is the remote one so this function can be used to query if the remote address is an +API pointer. + +Syntax + + + +void* __stdcall ImporterGetDLLNameFromDebugee( + +HANDLE hProcess, + +ULONG_PTR APIAddress + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose modules will be searched for the supplied API. + +APIAddress + + [in] Address on which API is located in the remote process. This address is equal to +address returned by GetProcAddress Windows API for DLL and function of interest if +called in debugged process. + + + +Return value + +Pointer to string which is the name of the DLL that holds API located at supplied address or NULL +if no API is found. + +Remarks + +String with the DLL name is stored inside the engine which makes this function multi thread +unsafe. + +Example + +None. + + + + + + + ImporterGetAPINameFromDebugee function + +ImporterGetAPINameFromDebugee resolves the API name for the remote process API pointer. Address +of the API is the remote one so this function can be used to query if the remote address is an API +pointer. + +Syntax + + + +void* __stdcall ImporterGetAPINameFromDebugee( + +HANDLE hProcess, + +ULONG_PTR APIAddress + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose modules will be searched for the supplied API. + +APIAddress + + [in] Address on which API is located in the remote process. This address is equal to +address returned by GetProcAddress Windows API for DLL and function of interest if +called in debugged process. + + + +Return value + +Pointer to string which is the name of the API that is located at supplied address or NULL if no +API is found. + +Remarks + +String with the API name is stored inside the engine which makes this function multi thread +unsafe. + +Example + +None. + + + + + + + ImporterGetAPIOrdinalNumberFromDebugee function + +ImporterGetAPIOrdinalNumberFromDebugee resolves the API ordinal number for the remote process +API pointer. Address of the API is the remote one so this function can be used to query if the remote +address is an API pointer. + +Syntax + + + +void* __stdcall ImporterGetAPIOrdinalNumberFromDebugee( + +HANDLE hProcess, + +ULONG_PTR APIAddress + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose modules will be searched for the supplied API. + +APIAddress + + [in] Address on which API is located in the remote process. This address is equal to +address returned by GetProcAddress Windows API for DLL and function of interest if +called in debugged process. + + + +Return value + +Ordinal number of the API that is located at supplied address or minus one if no API is found. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterGetDLLIndexEx function + +ImporterGetDLLIndexEx identify in which DLL of the module list selected API is located. Process which is +searched for the API is always the currently debugged process. + +Syntax + + + +long __stdcall ImporterGetDLLIndexEx( + +ULONG_PTR APIAddress, + +ULONG_PTR DLLBasesList + +); + + + + + + + +Parameters + +APIAddress + + [in] Address on which API is located in the remote process. This address is equal to +address returned by GetProcAddress Windows API for DLL and function of interest if +called in debugged process. + +DLLBasesList + + [in] Pointer to array of module base addresses inside the remote process. This list is +either manually compiled or generated with EnumProcessModules Windows API. + + + +Return value + +Function returns the index of the DLL in the list to which selected API belongs to or NULL if API +isn’t valid or found in the provided DLL list. + +Remarks + +List contains items with indexes going from zero to list count but first (zero) item is ignored +because it is usually the base address of the debugged executable module. If API is found in the +provided list return can only be greater or equal to one. + +Example + +HMODULE mList[3] = {0x00400000, 0x7E000000, 0x7F000000}; + +ImporterGetDLLIndexEx(0x7E555105, & mList); + +Function call would return one because the API on 0x7E555105 belongs to second module. + + + + + + + ImporterGetDLLIndex function + +ImporterGetDLLIndex identify in which DLL of the module list selected API is located. + +Syntax + + + +long __stdcall ImporterGetDLLIndex( + +HANDLE hProcess, + +ULONG_PTR APIAddress, + +ULONG_PTR DLLBasesList + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose modules will be searched for the supplied API. + +APIAddress + + [in] Address on which API is located in the remote process. This address is equal to +address returned by GetProcAddress Windows API for DLL and function of interest if +called in debugged process. + +DLLBasesList + + [in] Pointer to array of module base addresses inside the remote process. This list is +either manually compiled or generated with EnumProcessModules Windows API. + + + +Return value + +Function returns the index of the DLL in the list to which selected API belongs to or NULL if API +isn’t valid or found in the provided DLL list. + +Remarks + +List contains items with indexes going from zero to list count but first (zero) item is ignored +because it is usually the base address of the debugged executable module. If API is found in the +provided list return can only be greater or equal to one. + +Example + +None. + + + + + + + ImporterGetRemoteDLLBase function + +ImporterGetRemoteDLLBase gets the remote DLL base for a locally loaded DLL file. In this case +debugger and the debugged process load the same module but due to Windows nature those two can +be loaded on two different base addresses so we use this function to resolve the module base for the +remote process. It is commonly used to get remote module bases for system DLL files in ASLR +environment. + +Syntax + + + +long long __stdcall ImporterGetRemoteDLLBase( + +HANDLE hProcess, + +HMODULE LocalModuleBase + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process which will be queried for local module presence. + +LocalModuleBase + + [in] Handle of the local DLL file which will be searched for in the remote process. + + + +Return value + +Function returns the remote DLL base for the locally loaded module or NULL if module isn’t +found. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterGetRemoteDLLBaseEx function + +ImporterGetRemoteDLLBaseEx gets the remote DLL base for a specified file. This function does not +require that the remote module is loaded locally. + +Syntax + + + +long long __stdcall ImporterGetRemoteDLLBaseEx( + +HANDLE hProcess, + +char* szModuleName + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process which will be queried for local module presence. + +szModuleName + + [in] Name of the module inside the remote process whose loaded base address will be +returned. + + + +Return value + +Function returns the remote DLL base for the specified module or NULL if module isn’t found. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterIsForwardedAPI function + +ImporterIsForwardedAPI checks if the supplied API address is forwarded from another top level +dynamic link library to lower system one. Usually forwarders can be found in kernel32.dll which are +forwarded to ntdll.dll. These APIs are automatically resolved to correct APIs by the engine itself. + +Syntax + + + +bool __stdcall ImporterIsForwardedAPI( + +HANDLE hProcess, + +ULONG_PTR APIAddress + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process which will be inspected for API forwarding. + +APIAddress + + [in] Address on which API is located in the remote process. This address is equal to +address returned by GetProcAddress Windows API for DLL and function of interest if +called in debugged process. + + + +Return value + +Function returns TRUE if API is forwarded and FALSE if it isn’t. + +Remarks + +None. + +Example + +hModule = GetModuleHandleA(“ntdll.dll”); + +ImporterIsForwardedAPI(hProcess, GetProcAddress(hModule, “RtlAllocateHeap”)); + +Function would return TRUE because this API is a forward for kernel32.HeapAlloc + + + + + + + ImporterGetForwardedAPIName function + +ImporterGetForwardedAPIName retrieves the name of the forwarded API. + +Syntax + + + +void* __stdcall ImporterGetForwardedAPIName( + +HANDLE hProcess, + +ULONG_PTR APIAddress + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process which will be inspected for API forwarding. + +APIAddress + + [in] Address on which API is located in the remote process. This address is equal to +address returned by GetProcAddress Windows API for DLL and function of interest if +called in debugged process. + + + +Return value + +Pointer to string which is the name of the API forwarded for supplied address or NULL if no API +is found. + +Remarks + +None. + +Example + +hModule = GetModuleHandleA(“ntdll.dll”); + +ImporterGetForwardedAPIName(hProcess, GetProcAddress(hModule, “RtlAllocateHeap”)); + +Function would return HeapAlloc because this API is a forward for kernel32.HeapAlloc + + + + + + + ImporterGetForwardedAPIOrdinalNumber function + +ImporterGetForwardedAPIOrdinalNumber retrieves the ordinal number of the forwarded API. + +Syntax + + + +long long __stdcall ImporterGetForwardedAPIOrdinalNumber( + +HANDLE hProcess, + +ULONG_PTR APIAddress + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process which will be inspected for API forwarding. + +APIAddress + + [in] Address on which API is located in the remote process. This address is equal to +address returned by GetProcAddress Windows API for DLL and function of interest if +called in debugged process. + + + +Return value + +Ordinal number name of the API forwarded for supplied address or minus one if no API is found. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterGetForwardedDLLName function + +ImporterGetForwardedDLLName retrieves the name of DLL which holds the forwarded API. + +Syntax + + + +void* __stdcall ImporterGetForwardedDLLName( + +HANDLE hProcess, + +ULONG_PTR APIAddress + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process which will be inspected for API forwarding. + +APIAddress + + [in] Address on which API is located in the remote process. This address is equal to +address returned by GetProcAddress Windows API for DLL and function of interest if +called in debugged process. + + + +Return value + +Pointer to string which is the name of the DLL which holds that API forwarded for supplied +address or NULL if no DLL is found. + +Remarks + +None. + +Example + +hModule = GetModuleHandleA(“ntdll.dll”); + +ImporterGetForwardedDLLName(hProcess, GetProcAddress(hModule, “RtlAllocateHeap”)); + +Return would be kernel32.dll because this API is in that DLL as a forward for kernel32.HeapAlloc + + + + + + + ImporterGetForwardedDLLIndex function + +ImporterGetForwardedDLLIndex retrieves the index of the DLL in the module list which holds the +forwarded API. + +Syntax + + + +long __stdcall ImporterGetForwardedDLLIndex( + +HANDLE hProcess, + +ULONG_PTR APIAddress, + +ULONG_PTR DLLBasesList + +); + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process which will be inspected for API forwarding. + +APIAddress + + [in] Address on which API is located in the remote process. This address is equal to +address returned by GetProcAddress Windows API for DLL and function of interest if +called in debugged process. + +DLLBasesList + + [in] Pointer to array of module base addresses inside the remote process. This list is +either manually compiled or generated with EnumProcessModules Windows API. + + + +Return value + +Function returns the index of the DLL in the list to which resolved API forwarder belongs to or +NULL if API isn’t valid or found in the provided DLL list. + +Remarks + +List contains items with indexes going from zero to list count but first (zero) item is ignored +because it is usually the base address of the debugged executable module. If API is found in the +provided list return can only be greater or equal to one. + +Example + +None. + + + + + + + ImporterFindAPIWriteLocation function + +ImporterFindAPIWriteLocation searches through the list of added APIs by ImporterAddNewAPI in order +to locate the trunk location for already added API. + +Syntax + + + +long long __stdcall ImporterFindAPIWriteLocation( + +char* szAPIName + +); + + + + + + + + + +Parameters + +szAPIName + + [in] Pointer to string which is the name of the API on which has been added to import +tree, for example VirtualAlloc. + + + +Return value + +Function returns the address on which the import trunk for selected API is written or NULL is +that API wasn’t added to import tree. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterFindOrdinalAPIWriteLocation function + +ImporterFindOrdinalAPIWriteLocation searches through the list of added APIs by ImporterAddNewAPI +in order to locate the name of the added API by using its trunk location. + +Syntax + + + +long long __stdcall ImporterFindOrdinalAPIWriteLocation( + +ULONG_PTR OrdinalNumber + +); + + + + + + + + + +Parameters + +OrdinalNumber + + [in] Ordinal number for which the write address will be located. This was the ordinal +number passed to ImporterAddNewAPI or ImporterAddNewDLL at the time of +adding that API. + + + +Return value + +Function returns the address on which the selected ordinal API is written or NULL is that ordinal +number wasn’t added to import tree. + +Remarks + +Function assumes that ordinal numbers are unique. + +Example + +None. + + + + + + + ImporterFindAPIByWriteLocation function + +ImporterFindAPIByWriteLocation searches through the list of added APIs by ImporterAddNewAPI in +order to locate the name of the added API by using its trunk location. + +Syntax + + + +long long __stdcall ImporterFindAPIByWriteLocation( + +ULONG_PTR APIWriteLocation + +); + + + + + + + + + +Parameters + +APIWriteLocation + + [in] Trunk location on which pointer to selected API will be written. This was the trunk +value passed to ImporterAddNewAPI or ImporterAddNewDLL at the time of adding +that API. + + + +Return value + +Function returns pointer to string which is the name of the API for supplied trunk address or +NULL if API isn’t found. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterFindDLLByWriteLocation function + +ImporterFindDLLByWriteLocation searches through the list of added APIs by ImporterAddNewAPI in +order to locate the name of the DLL to which the added API belongs to. + +Syntax + + + +long long __stdcall ImporterFindDLLByWriteLocation( + +ULONG_PTR APIWriteLocation + +); + + + + + + + + + +Parameters + +APIWriteLocation + + [in] Trunk location on which pointer to selected API will be written. This was the trunk +value passed to ImporterAddNewAPI or ImporterAddNewDLL at the time of adding +that API. + + + +Return value + +Function returns pointer to string which is the name of the DLL which holds the API for supplied +trunk address or NULL if API isn’t found. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterGetNearestAPIAddress function + +ImporterGetNearestAPIAddress estimates the correct API by closeness to provided API. This is useful if +by tracing you get to the address which is inside the API itself but it is unknown how many instructions +the API has before the one you are on. + +Syntax + + + +long long __stdcall ImporterGetNearestAPIAddress( + +HANDLE hProcess, + +ULONG_PTR APIAddress + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process which will be inspected for correct API estimation. + +APIAddress + + [in] Address near the possible API start in the remote process. + + + +Return value + +Function returns the address of the nearest possible API or NULL if no close API can be found. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterGetNearestAPIName function + +ImporterGetNearestAPIName gets the name of the API closest to the specified API. This is useful if, by +tracing, you get to the address of the target API from is inside the current API, but you don't know how +many instructions the target API executes prior to the start of the one you are in. + +Syntax + + + +void* __stdcall ImporterGetNearestAPIName( + +HANDLE hProcess, + +ULONG_PTR APIAddress + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process in which the target API is located. + +APIAddress + + [in] Address near the possible start of the target API the specified process. + + + +Return value + +Pointer to string which is the name of the nearest API to the specified address or NULL if no API +is found. + +Remarks + +CAUTION: The string containing the API name is stored inside the engine, which makes this +function multi thread unsafe. + +Example + +None. + + + + + + + ImporterMoveIAT function + +ImporterMoveIAT turns on a switch to make the importer export the import table in a way that ensures +strings are written after the import tree, which is important when fixing import eliminations if we don’t +know where APIs will be written. If that is the case, all APIs need to be added to the tree with relative +addresses, starting from NULL and incrementing by four (or eight for x64) or double that value if we +need to write a pointer for new DLL. This data will later be relocated to match the new section in which +it will be written. Since default strings are written to the section first, ImporterMoveIAT must be called +to move those strings behind the pointers, which will be written at the beginning of that section. This +functionality has been added to the automatic import fixing functions, so examples using this kind of +model can be seen in the TitanEngine source code. + +Syntax + + + +void __stdcall ImporterMoveIAT(); + + + + + + + +Parameters + +None. + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterRelocateWriteLocation function + +ImporterRelocateWriteLocation relocates all import data by the same value. It is used only in the +situation describes for the ImporterMoveIAT function. This value can be the offset of the newly added +section, or a code cave inside the file. + +Syntax + + + +bool __stdcall ImporterRelocateWriteLocation( + +ULONG_PTR AddValue + +); + + + + + + + +Parameters + +AddValue + + [in] Offset to add to every import tree entry added with engine functions +ImporterAddNewAPI and/or ImporterAddNewDLL. + + + +Return value + +Function returns TRUE on success or FALSE if function fails to relocate added data. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterSetUnknownDelta function + +The ImporterSetUnknownDelta function is used only in specific situation describe with function +ImporterMoveIAT to relocate all import data by the same value. This value can be the offset of the newly +added section or a code cave inside the file. + +Syntax + + + +void __stdcall ImporterSetUnknownDelta( + +ULONG_PTR DeltaAddress + +); + + + + + + + +Parameters + +DeltaAddress + + [in] Value to use as a temporary import tree entry offset, when using the engine +functions ImporterAddNewAPI and/or ImporterAddNewDLL. + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterGetCurrentDelta function + +The ImporterGetCurrentDelta function is used only in specific situation describe with function +ImporterMoveIAT to relocate all import data by the same value. + +Syntax + + + +long long __stdcall ImporterGetCurrentDelta(); + + + + + + + +Parameters + +None. + +Return value + +This function returns the current delta which will be used for writing new virtual trunk. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterLoadImportTable function + +ImporterLoadImportTable loads an import table from any PE file. The loaded table will be converted to +an internal engine import tree, making it available for further modifications before it's exported to the +same or any other PE file. + +Syntax + + + +bool __stdcall ImporterLoadImportTable( + +char* szFileName + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose import table will +be loaded by the engine. + + + +Return value + +Function returns TRUE on success or FALSE if function fails to load data. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterCopyOriginalIAT function + +ImporterCopyOriginalIAT copies IAT from one file to another. This function assumes that the IAT will be +in the same virtual location in both files, so it is only used in cases when you dynamically unpack +crypters and where the format doesn’t handle imports by itself. Instead it leaves the import table +handling to Windows loader, as if the file wasn’t packed. + +Syntax + + + +bool __stdcall ImporterCopyOriginalIAT( + +char* szOriginalFile, + +char* szDumpFile + +); + + + + + + + +Parameters + +szOriginalFile + + [in] Pointer to a null terminated string which is a full path to file from which import +table will be copied. + +szDumpFile + + [in] Pointer to a null terminated string which is a full path to file to which import table +will be copied to. + + + +Return value + +Function returns TRUE on success or FALSE if function fails to copy the import table. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterMoveOriginalIAT function + +ImporterMoveOriginalIAT moves IAT from one file to another. This function doesn’t actually modify the +original file, but loads the import table and exports it to selected dump file. + +Syntax + + + +bool __stdcall ImporterMoveOriginalIAT( + +char* szOriginalFile, + +char* szDumpFile, + +char* szSectionName + +); + + + + + + + +Parameters + +szOriginalFile + + [in] Pointer to a null terminated string which is a full path to file from which import +table will be copied. + +szDumpFile + + [in] Pointer to a null terminated string which is a full path to file to which import table +will be copied to. + +szSectionName + + [in] Pointer to a null terminated string which will be the new section name which will +hold the import table. This string can only be 8 characters long. + + + +Return value + +Function returns TRUE on success or FALSE if function fails to move the import table. + +Remarks + +None. + +Example + +None. + + + + + + + ImporterAutoSearchIAT function + +ImporterAutoSearchIAT automatically locates a possible import table location inside the packed file +memory. Returns from this function can be used to automatically fix the import table for the selected +file. + +Syntax + + + +void __stdcall ImporterAutoSearchIAT( + +HANDLE hProcess, + +char* szFileName, + +ULONG_PTR ImageBase, + +ULONG_PTR SearchStart, + +DWORD SearchSize, + +LPVOID pIATStart, + +LPVOID pIATSize + +); + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be searched for import table. + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose content will be +searched for import table. This file is a memory dump from the running process +whose handle you have provided. + +ImageBase + +[in] Default image base of the targeted PE file dump on the disk. + +SearchStart + +[in] Virtual address inside the file which is used as a start marker for the search. It is safe +to use virtual offset of the first section as a start position as only the code should be +searched. + +SearchSize + +[in] Size of the memory to be searched for import pointers. It is safe to use +NtSizeOfImage to search the whole file memory. + +pIATStart + +[out] Pointer to ULONG_PTR variable which will receive the virtual address on which the +import table has been found. + +pIATSize + +[out] Pointer to ULONG_PTR variable which will receive the size of the found import +table. + + + + + ImporterAutoSearchIATEx function + +ImporterAutoSearchIATEx automatically locates the possible import table location inside the packed file +memory. This function will automatically dump the targeted process before searching for the import +table. Returns from this function can be used to automatically fix the import table for the selected file. + +Syntax + + + +void __stdcall ImporterAutoSearchIATEx( + +HANDLE hProcess, + +ULONG_PTR ImageBase, + +ULONG_PTR SearchStart, + +DWORD SearchSize, + +LPVOID pIATStart, + +LPVOID pIATSize + +); + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be searched for import table. + +ImageBase + +[in] Default image base of the targeted PE file dump on the disk. + +SearchStart + +[in] Virtual address inside the file which is used as a start marker for the search. It is safe +to use virtual offset of the first section as a start position as only the code should be +searched. + +SearchSize + +[in] Size of the memory to be searched for import pointers. It is safe to use +NtSizeOfImage to search the whole file memory. + +pIATStart + +[out] Pointer to ULONG_PTR variable which will receive the virtual address on which the +import table has been found. + +pIATSize + +[out] Pointer to ULONG_PTR variable which will receive the size of the found import +table. + + + + + + + ImporterAutoFixIATEx function + +ImporterAutoFixIATEx automatically fixes the import table for the running process. This function can fix +all known redirections and import eliminations with the optional callback to manually fix unknown +import pointers. + +Syntax + +long __stdcall ImporterAutoFixIATEx( + +HANDLE hProcess, + +char* szDumpedFile, + +char* szSectionName, + +bool DumpRunningProcess, + +bool RealignFile, + +ULONG_PTR EntryPointAddress, + +ULONG_PTR ImageBase, + +ULONG_PTR SearchStart, + +DWORD SearchSize, + +DWORD SearchStep, + +bool TryAutoFix, + +bool FixEliminations, + +LPVOID UnknownPointerFixCallback + +); + + + + + + + + + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be searched for import table. + +szDumpedFile + +[in] Pointer to a null terminated string which is a full path to file which will contain the +memory content if DumpRunningProcess is TRUE or already contains the dump +memory content if DumpRunningProcess is FALSE. + +DumpRunningProcess + +[in] Boolean switch that indicates whether the file was dumped or not. + +RealignFile + +[in] Boolean switch that indicates whether or not the file needs realigning after fixing +imports. + +EntryPointAddress + +[in] [in] Virtual address which will be set to the new file. Size of this variable varies, on +x86 its 4 bytes and on x64 is 8 bytes. Therefore it can also be declared as void*. + + + + + + + + +ImageBase + +[in] Default image base of the targeted PE file. This value should be read from the file on +disk. + +SearchStart + +[in] Virtual address inside the file - used as a start marker for the search. This is the +return value of ImporterAutoSearchIAT function. + +SearchSize + +[in] Size of the memory to be searched for import pointers. This is the return value of +ImporterAutoSearchIAT. + +SearchStep + +[in] Search step is a value which will be used to iterate the search position. Default value +is four (or eight on x64) and it will be used is you don’t specify the search step and +use NULL. + +TryAutoFix + +[in] Boolean switch that indicates whether or not to trace possible import pointers, in +order to fix the import table. This can be always set to TRUE, but can be disabled in +case you are sure that the target doesn’t use import redirection. + +FixEliminations + +[in] Boolean switch that indicates whether or not to fix possible import eliminations, in +order to fix the import table. This can be always set to TRUE, but can be disabled in +case you are sure that the target doesn’t use import elimination. + +UnknownPointerFixCallback + +[in] Pointer to the callback to call for every possible but unknown import redirection or +elimination. Use this callback to correct import table fixing when a particular import +protection is not yet recognized by TitanEngine. + +CallBack definition + +typedef void*(__stdcall *fFixerCallback)(LPVOID fIATPointer); + +// Returns API address in remote process or NULL + + + + + +Return value + +One of the following: + +. NULL - Critical error! *just to be safe, but it should never happen +. 0x400 - Success +. 0x401 - Error, process terminated +. 0x404 - Error, memory could not be read +. 0x405 - Error, no API found +. 0x406 - Success, but realign failed + + + + + + ImporterAutoFixIAT function + +ImporterAutoFixIAT automatically fixes the import table for the running process. This function can fix all +known redirections and import eliminations, using an optional callback to manually fix unknown import +pointers. + +Syntax + +long __stdcall ImporterAutoFixIAT( + +HANDLE hProcess, + +char* szDumpedFile, + +ULONG_PTR ImageBase, + +ULONG_PTR SearchStart, + +DWORD SearchSize, + +DWORD SearchStep + +); + + + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be searched for import table. + +szDumpedFile + +[in] Pointer to a null terminated string which is a full path to file which already contains +the dump memory content. + +ImageBase + +[in] Default image base of the targeted PE file. This value should be read from the file on +disk. + +SearchStart + +[in] Virtual address inside the file. It will be used as a start marker for the search. This is +the return value of ImporterAutoSearchIAT function. + +SearchSize + +[in] Size of the memory to be searched for import pointers. This is the return value of +ImporterAutoSearchIAT function. + +SearchStep + +[in] Search step is used to iterate the search position. If you specify NULL, the default is +used: four on x86, or eight on x64. + +Return value + + See ImporterAutoFixIATEx function for return details. + + + + +Tracer module + + + +The Tracer module has functions designed for detecting and fixing import redirections. It has integrated +import tracers and can also use ImpRec modules to fix known redirections. + + + + + + + TracerInit function + +TracerInit is not used in TitanEngine and is retained only for backward compatibility issued with version +1.5. + +Syntax + + + +void __stdcall TracerInit(); + + + + + + + +Parameters + +None. + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + TracerLevel1 function + +TracerLevel1 traces the provided address via code disassembling, in order to try to find the API hiding +behind an import redirection. This function uses common code tracing to try to identify the API that is +being redirected. + +Syntax + + + +long long __stdcall TracerLevel1( + +HANDLE hProcess, + +ULONG_PTR AddressToTrace + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be traced. + +AddressToTrace + +[in] Pointer to the memory that holds the redirection code. This memory is commonly +outside the PE file memory and is allocated by the packer/protector code. + + + +Return value + +If the return value is NULL the trace has failed, and if the return value is greater than 0x1000 +then the return is an API address inside the remote process. For cases where return is greater +than NULL and lower then 0x1000, the return is the number of valid instructions detected while +tracing, which can then be used by the HashTracerLevel1 API. + +Remarks + +None. + +Example + +None. + + + + + + + HashTracerLevel1 function + +HashTracerLevel1 traces the provided address via code hashing in order to try to find the correct API +hiding behind selected import redirection. This function uses advanced code tracing in order to try to +identify the API that is being redirected. + +Syntax + + + +long long __stdcall HashTracerLevel1( + +HANDLE hProcess, + +ULONG_PTR AddressToTrace, + +DWORD InputNumberOfInstructions + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be traced. + +AddressToTrace + +[in] Pointer to the memory that holds the redirection code. This memory is commonly +outside the PE file memory and is allocated by the packer/protector code. + +InputNumberOfInstructions + +[in] Number of valid instructions detected while tracing with TraceLevel1. + + + +Return value + +If the return value is NULL or minus one, the trace has failed; if the return value is greater than +NULL then the return is an API address inside the remote process. + +Remarks + +None. + +Example + +None. + + + + + + + TracerDetectRedirection function + +TracerDetectRedirection checks whether the memory at the selected address is equal to one of the +known import redirection patterns. + +Syntax + + + +long __stdcall TracerDetectRedirection( + +HANDLE hProcess, + +ULONG_PTR AddressToTrace + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be checked for known import +redirections. + +AddressToTrace + +[in] Pointer to the memory that holds the redirection code. This memory is commonly +outside the PE file memory and is allocated by the packer/protector code. + + + +Return value + +If the return value is NULL then no known redirection was detected, and if return value is +greater than NULL then the return is an ID of the known redirection inside the internal +TitanEngine import redirection database. + +Remarks + +None. + +Example + +None. + + + + + + + TracerFixKnownRedirection function + +TracerFixKnownRedirection fixes known import redirection based on the known import redirection ID +inside the TitanEngine database. + +Syntax + + + +long long __stdcall TracerFixKnownRedirection( + +HANDLE hProcess, + +ULONG_PTR AddressToTrace, + +DWORD RedirectionId + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be checked for known import +redirections. + +AddressToTrace + +[in] Pointer to the memory that holds the redirection code. This memory is commonly +outside the PE file memory and is allocated by the packer/protector code. + +RedirectionId + +[in] ID of the detected import redirection inside the TitanEngine database. + + + +Return value + +If the return value is NULL, the trace has failed; if the return value is greater than NULL then the +return is an API address inside the remote process. + +Remarks + +None. + +Example + +None. + + + + + + + TracerFixRedirectionViaImpRecPlugin function + +TracerFixRedirectionViaImpRecPlugin fixes import redirections with ImpRec modules. To use this option +you must install all needed ImpRec plugins by placing them in the .\import\ImpRec\ folder. + +Syntax + + + +long __stdcall TracerFixRedirectionViaImpRecPlugin( + +HANDLE hProcess, + +char* szPluginName, + +ULONG_PTR AddressToTrace + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose import redirection will be fixed. + +szPluginName + +[in] Name of the ImpRec module inside the .\import\ImpRec\ folder. For example +aspr1.dll + +AddressToTrace + +[in] Pointer to the memory that holds the redirection code. This memory is commonly +outside the PE file memory and is allocated by the packer/protector code. + + + +Return value + +If the return value is NULL the trace has failed and if the return value is greater than NULL then +the return is an API address inside the remote process. + +Remarks + +This function only works on x86 systems since ImpRec and its plugins are designed that way. + +Example + +None. + + + + + + + + +Realigner module + + + +Realigner module has functions designed for PE file validation, fixing and realigning. + + + + +Realigner module structures and constants + + + +Constants used by: IsPE32FileValidEx function + + + +#define UE_DEPTH_SURFACE 0 + +#define UE_DEPTH_DEEP 1 + + + +Structures used by: IsPE32FileValidEx function + + + +typedef struct{ + + BYTE OveralEvaluation; + + bool EvaluationTerminatedByException; + + bool FileIs64Bit; + + bool FileIsDLL; + + bool FileIsConsole; + + bool MissingDependencies; + + bool MissingDeclaredAPIs; + + BYTE SignatureMZ; + + BYTE SignaturePE; + + BYTE EntryPoint; + + BYTE ImageBase; + + BYTE SizeOfImage; + + BYTE FileAlignment; + + BYTE SectionAlignment; + + BYTE ExportTable; + + BYTE RelocationTable; + + BYTE ImportTable; + + BYTE ImportTableSection; + + BYTE ImportTableData; + + BYTE IATTable; + + BYTE TLSTable; + + BYTE LoadConfigTable; + + BYTE BoundImportTable; + + BYTE COMHeaderTable; + + BYTE ResourceTable; + + BYTE ResourceData; + + BYTE SectionTable; + +}FILE_STATUS_INFO, *PFILE_STATUS_INFO; + + + +Constants used by: IsPE32FileValidEx function and FixBrokenPE32FileEx function + + + +#define UE_FIELD_OK 0 + +#define UE_FIELD_BROKEN_NON_FIXABLE 1 + +#define UE_FIELD_BROKEN_NON_CRITICAL 2 + +#define UE_FIELD_BROKEN_FIXABLE_FOR_STATIC_USE 3 + +#define UE_FIELD_BROKEN_BUT_CAN_BE_EMULATED 4 + +#define UE_FILED_FIXABLE_NON_CRITICAL 5 + + + + + + + + +#define UE_FILED_FIXABLE_CRITICAL 6 + +#define UE_FIELD_NOT_PRESET 7 + +#define UE_FIELD_NOT_PRESET_WARNING 8 + +#define UE_RESULT_FILE_OK 10 + +#define UE_RESULT_FILE_INVALID_BUT_FIXABLE 11 + +#define UE_RESULT_FILE_INVALID_AND_NON_FIXABLE 12 + +#define UE_RESULT_FILE_INVALID_FORMAT 13 + + + +Structures used by: FixBrokenPE32FileEx function + + + +typedef struct{ + + BYTE OveralEvaluation; + + bool FixingTerminatedByException; + + bool FileFixPerformed; + + bool StrippedRelocation; + + bool DontFixRelocations; + + DWORD OriginalRelocationTableAddress; + + DWORD OriginalRelocationTableSize; + + bool StrippedExports; + + bool DontFixExports; + + DWORD OriginalExportTableAddress; + + DWORD OriginalExportTableSize; + + bool StrippedResources; + + bool DontFixResources; + + DWORD OriginalResourceTableAddress; + + DWORD OriginalResourceTableSize; + + bool StrippedTLS; + + bool DontFixTLS; + + DWORD OriginalTLSTableAddress; + + DWORD OriginalTLSTableSize; + + bool StrippedLoadConfig; + + bool DontFixLoadConfig; + + DWORD OriginalLoadConfigTableAddress; + + DWORD OriginalLoadConfigTableSize; + + bool StrippedBoundImports; + + bool DontFixBoundImports; + + DWORD OriginalBoundImportTableAddress; + + DWORD OriginalBoundImportTableSize; + + bool StrippedIAT; + + bool DontFixIAT; + + DWORD OriginalImportAddressTableAddress; + + DWORD OriginalImportAddressTableSize; + + bool StrippedCOM; + + bool DontFixCOM; + + DWORD OriginalCOMTableAddress; + + DWORD OriginalCOMTableSize; + +}FILE_FIX_INFO, *PFILE_FIX_INFO; + + + + + RealignPE function + +RealignPE realigns the PE file sections so that virtual and physical data are aligned to PECOFF +specifications and extra data removed in order to minimize the file size. After file unpacking it is +recommended to use this function to make the file a valid PE image. + +Syntax + + + +long __stdcall RealignPE( + +ULONG_PTR FileMapVA, + +DWORD FileSize, + +DWORD RealingMode + +); + + + + + + + +Parameters + +FileMapVA + +[in] Pointer to the mapped file content. This pointer is set by using either StaticFileLoad +function or Windows API for file mapping. It is a ULONG_PTR which defines its size +on the x86 and x64 operating systems. On x86 systems this variable is 4 bytes long +and equal to DWORD, and on x64 platform this variable is 8 bytes long and equal to +DWORD64, but since this is a pointer void* can also be used. + +FileSize + + [in] Size of the mapped file. + +RealignMode + + [in] Reserved for future use, set to NULL always. + + + +Return value + +This function returns the new realigned file size which can be used to trim the file during the +unmapping process, or NULL if it fails. + +Remarks + +None. + +Example + +None. + + + + + + + RealignPEEx function + +RealignPEEx realigns the PE file sections so that virtual and physical data are aligned to PECOFF +specifications and extra data removed in order to minimize the file size. After file unpacking it is +recommended to use this function to make the file a valid PE image. + +Syntax + + + +long __stdcall RealignPEEx( + +char* szFileName, + +DWORD RealingFileSize, + +DWORD ForcedFileAlignment + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file which will be realigned. + +RealignedFileSize + + [in] Force the engine to make the file the specified size. This option should only be used +to increase the file size. + +ForcedFileAlignment + + [in] Specify FileAlignment manually. If no value is specified, the default of 0x200 will be +used. + + + +Return value + +This function returns the new realigned file size or NULL if it fails. + +Remarks + +None. + +Example + +None. + + + + + + + FixHeaderCheckSum function + +FixHeaderCheckSum recalculates the PE header field checksum which refers to checksum of the whole +header. After new value is calculated selected file will be updated. + +Syntax + + + +bool __stdcall FixHeaderCheckSum( + +char* szFileName + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose checksum will +be updated. + + + +Return value + +This function returns TRUE on successful checksum update and FALSE if the function fails. + +Remarks + +None. + +Example + +None. + + + + + + + WipeSection function + +WipeSection removes the section from the file but preserves that virtual space by expanding nearby +section. + +Syntax + + + +bool __stdcall WipeSection( + +char* szFileName, + +int WipeSectionNumber, + +bool RemovePhysically + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose section will be +removed. + +WipeSectionNumber + + [in] Removes the selected PE section. Section numbers go from NULL to SectionNumber +minus one. + +RemovePhysically + + [in] If set to TRUE file size will decrease because the section content will be removed +from the file and in case this switch is set to FALSE content will remain in the file and +only the PE header content will be changed. + + + +Return value + +This function returns TRUE on successful section wipe and FALSE if the function fails. + +Remarks + +None. + +Example + +None. + + + + + + + IsFileDLL function + +IsFileDLL determines if the selected file is a DLL by inspecting its PE header flags. + +Syntax + + + +bool __stdcall IsFileDLL( + +char* szFileName, + +ULONG_PTR FileMapVA + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose PE header will +be checked to see if it is a DLL file. + +FileMapVA + + [in] Pointer to the mapped file content. This pointer is set by using either StaticFileLoad +function or Windows API for file mapping. It is a ULONG_PTR which defines its size +on the x86 and x64 operating systems. On x86 systems this variable is 4 bytes long +and equal to DWORD, and on x64 platform this variable is 8 bytes long and equal to +DWORD64, but since this is a pointer void* can also be used. + + + +Return value + +This function returns TRUE if the selected file is a DLL and FALSE if it isn’t. + +Remarks + +You can specify both input parameters but only one is required. + +Example + +None. + + + + + + + IsPE32FileValidEx function + +IsPE32FileValidEx determines if the selected file is a valid PE file and provide as much additional +information about the file and detected errors. + +Syntax + + + +bool __stdcall IsPE32FileValidEx( + +char* szFileName, + +DWORD CheckDepth, + +LPVOID FileStatusInfo + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose PE header will +be validated. + +CheckDepth + + [in] Indicates how detail the checks will be. Can be either UE_DEPTH_SURFACE or +UE_DEPTH_DEEP. + +FileStatusInfo + + [out] Pointer to a FILE_STATUS_INFO structure which will be filled by this function. + + + +Return value + +This function returns TRUE if the function completes without critical errors in verification +process which can occur in broken files and FALSE if there are errors during validation. + +Remarks + +OveralEvaluation member of the structure tells the state of the file. Can be one of the following: +UE_RESULT_FILE_INVALID_FORMAT, UE_RESULT_FILE_INVALID_BUT_FIXABLE, +UE_RESULT_FILE_INVALID_AND_NON_FIXABLE or UE_RESULT_FILE_OK. + +Example + +None. + + + + + + + FixBrokenPE32FileEx function + +FixBrokenPE32FileEx tries to fix PE file errors and provide as much additional information about the file, +both detected errors and fixed errors data. + +Syntax + + + +bool __stdcall FixBrokenPE32FileEx( + +char* szFileName, + +LPVOID FileStatusInfo, + +LPVOID FileFixInfo + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose PE header will +be validated. + +FileStatusInfo + + [in] Pointer to a FILE_STATUS_INFO structure that was filled by the IsPE32FileValidEx +function, or NULL, which would make the engine call a file validation function before +fixing the file automatically. + +FileFixInfo + + [in & out] Pointer to a FILE_FIX_INFO structure to fill during file fixing. Also serves as +an input parameter which tells the engine which tables not to fix or strip. + + + +Return value + +This function returns TRUE if the function completes without critical errors in the file repair +process which can occur in broken files. It returns FALSE if there are errors during fixing. + +Remarks + +The OveralEvaluation member of the structure tells the state of the file after fixing. + +Example + +None. + + + + + + +Relocater module + + + +The relocater module has functions designed for relocation manipulation, making file memory +snapshots, and removing relocation tables. This module is used to fix a relocation table when unpacking +DLL files. + + + + + RelocaterInit function + +RelocaterInit initializes the relocater module. It must be used before using any of the relocator functions +to do manual relocation fixing. + +Syntax + + + +void __stdcall RelocaterInit( + +DWORD MemorySize, + +ULONG_PTR OldImageBase, + +ULONG_PTR NewImageBase + +); + + + + + + + +Parameters + +MemorySize + + [in] Default memory size allocated for all relocations you add. This size must be large +enough to hold all data needed by the engine. Usually there is no need to reserve +more than 100kb of memory. + +OldImageBase + +[in] Default image base of the targeted PE file. This value should be read from the file on +disk. + +NewImageBase + +[in] Base address at which the targeted DLL file, whose relocation table you are fixing, is +loaded. + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + RelocaterCleanup function + +RelocaterCleanup frees memory allocated by the engine during relocation fixing. + +Syntax + + + +void __stdcall RelocaterCleanup(); + + + + + + + +Parameters + +None. + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + RelocaterAddNewRelocation function + +RelocaterAddNewRelocation adds an address from the remote process to the list of addresses tnat +need relocating, if the file is allocated at a base address other then default one. Just like when adding +import via the importer, you must add relocations one page at a time. The engine itself will take care of +page switching but once the page is switched you can’t go back to adding data to any of the previous +pages. + +Syntax + + + +void __stdcall RelocaterAddNewRelocation( + +HANDLE hProcess, + +ULONG_PTR RelocateAddress, + +DWORD RelocateState + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process that has loaded the targeted DLL, whose relocation table you +are fixing. + +RelocateAddress + +[in] Address inside the remote process, belonging to targeted DLL, which needs +relocation if the file is being loaded at a base address other than default. + +RelocateState + +[in] Reserved for future usage, for now always set to NULL. + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + RelocaterEstimatedSize function + +RelocaterEstimatedSize estimates the space needed to write the relocation table to the file. This value +can be used to determine the size of the new section in which the relocation data will be written. + +Syntax + + + +long __stdcall RelocaterEstimatedSize(); + + + + + + + +Parameters + +None. + +Return value + +Returns the size needed to write the relocation data. + +Remarks + +None. + +Example + +None. + + + + + + + RelocaterExportRelocationEx function + +RelocaterExportRelocationEx exports the added relocation data to an existing PE file, creating a valid +relocation table for the selected PE file. After this function has executed, relocation data will be cleared +by using the RelocaterCleanup function. + +Syntax + + + +bool __stdcall RelocaterExportRelocationEx( + +char* szFileName, + +char* szSectionName + +); + + + + + + + +Parameters + +szFileName + +[in] Pointer to string which is the full path to the file in which the new relocation table +will be written. This file is usually created by the DumpProcess function. + +szSectionName + +[in] Name (up to 8 characters long) of the PE section in which the new relocation table +content will be written. This section will be added to the file. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + RelocaterExportRelocation function + +RelocaterExportRelocation exports the added relocation data to an existing PE file, creating a valid +relocation table for the selected PE file. After this function has executed relocation data will be cleared +by using RelocaterCleanup function. + +Syntax + + + +bool __stdcall RelocaterExportRelocation( + +ULONG_PTR StorePlace, + +DWORD StorePlaceRVA, + +ULONG_PTR FileMapVA + +); + + + + + + + +Parameters + +StorePlace + + [in] Physical address inside PE file at which the new relocation table will be written. +Usually this is a new section but, it can also be part of the file which is unused, but +still in read/write mode. + +StorePlaceRVA + + [in] Relative virtual address inside the PE file at which the new relocation table will be +written. This input is just a conversion from physical to relative virtual offset. + +FileMapVA + + [in] Pointer to the mapped file content, which must be mapped in read/write mode. +This pointer is set by either the StaticFileLoad function or Windows API for file +mapping. It is a ULONG_PTR which defines its size on the x86 and x64 operating +systems. On x86 systems this variable is 4 bytes long and equal to DWORD, and on +x64 platform this variable is 8 bytes long and equal to DWORD64, but since this is a +pointer void* can also be used. + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + RelocaterGrabRelocationTableEx function + +RelocaterGrabRelocationTableEx copies a PECOFF valid relocation table from the targeted process to +engine relocation data storage. This function can automatically determine the size of the relocation +table, but the size parameter must be close to or higher than the actual relocation table size so that the +targeted memory slice contains the end of the relocation table. If this function succeeds, the relocation +table is ready to be exported. + +Syntax + + + +bool __stdcall RelocaterGrabRelocationTableEx( + +HANDLE hProcess, + +ULONG_PTR MemoryStart, + +ULONG_PTR MemorySize, + +DWORD NtSizeOfImage + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process from which the relocation table will be copied. + +MemoryStart + + [in] Pointer to memory in the remote process: the start of a valid relocation table. + +MemorySize + + [in] Size of the memory inside which the relocation table resides. + +NtSizeOfImage + + [in] PE header variable read from the file on the disk. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + RelocaterGrabRelocationTable function + +RelocaterGrabRelocationTable copies a PECOFF valid relocation table from the targeted process to +engine relocation data storage. If this function succeeds the relocation table is ready to be exported. + +Syntax + + + +bool __stdcall RelocaterGrabRelocationTable( + +HANDLE hProcess, + +ULONG_PTR MemoryStart, + +ULONG_PTR MemorySize + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process from which the relocation table will be copied. + +MemoryStart + + [in] Pointer to memory in the remote process: the start of a valid relocation table. + +MemorySize + + [in] Exact size of the relocation table inside the remote process. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + RelocaterMakeSnapshot function + +RelocaterMakeSnapshot copies the selected memory segment to a file on the disk. This memory +segment should contain all data that can and will be relocated by the packer itself. Most commonly, it +covers all the executable code inside the PE files memory. By creating two snapshots, one just before +the code that relocates the file inside the packer, and one right after its execution, you create two +memory state images, which can be used to create a valid relocation table by comparing the two. + +Syntax + + + +bool __stdcall RelocaterMakeSnapshot( + +HANDLE hProcess, + +char* szSaveFileName, + +LPVOID MemoryStart, + +ULONG_PTR MemorySize + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be snapshotted. + +szFileName + + [in] Pointer to the full path of the file to create and fill with the snapshot. + +MemoryStart + + [in] Pointer to memory in the remote process: the start of the snapshot image. The +start of the snapshot must be the same for both snapshots. + +MemorySize + + [in] Size of the snapshot, which must be the same for both snapshots. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + RelocaterCompareTwoSnapshots function + +RelocaterCompareTwoSnapshots creates a valid relocation table by comparing two memory snapshots: +one taken just before the relocation code inside the packer was executed and another taken right +afterward. If this function succeeds, the relocation table is ready to be exported. + +Syntax + + + +bool __stdcall RelocaterCompareTwoSnapshots( + +HANDLE hProcess, + +ULONG_PTR LoadedImageBase, + +ULONG_PTR NtSizeOfImage, + +char* szDumpFile1, + +char* szDumpFile2, + +ULONG_PTR MemStart + +); + + + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose memory will be snapshot. + +LoadedImageBase + + [in] Base address at which the targeted file is loaded. + +NtSizeOfImage + + [in] PE header variable, read from the file on the disk for the targeted file. + +MemoryStart + + [in] Pointer to memory in remote process: used as the start for a snapshot image. + +szDumpFile1 + + [in] Pointer to the full path of the file which was created for the first memory snapshot. + +szDumpFile2 + + [in] Pointer to the full path of the file which for the second memory snapshot. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + + + + + + + RelocaterWipeRelocationTable function + +RelocaterWipeRelocationTable removes the relocation table from any PE file. However it is only +recommended that you remove the relocation table from executable files if you need to reduce their +size. + +Syntax + + + +bool __stdcall RelocaterWipeRelocationTable( + +char* szFileName + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose relocation table +will be removed. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + RelocaterRelocateMemoryBlock function + +RelocaterRelocateMemoryBlock uses mapped file relocation table to relocate selected memory +segment to new loaded base. Data about which parts of the memory need relocating is read directly +from the relocation table and therefore presence of such table is a necessity. + +Syntax + + + +bool __stdcall RelocaterRelocateMemoryBlock( + +ULONG_PTR FileMapVA, + +ULONG_PTR MemoryLocation, + +void* RelocateMemory, + +DWORD RelocateMemorySize, + +ULONG_PTR CurrentLoadedBase, + +ULONG_PTR RelocateBase + +); + + + + + + + + + +Parameters + +FileMapVA + + [in] Pointer to the mapped file content which must be mapped in read/write mode. This +pointer is set by using either StaticFileLoad function or Windows API for file +mapping. + +MemoryLocation + + [in] Virtual address of the memory segment to be relocated. + +RelocateMemory + + [in] Pointer to memory segment which will be relocated. + +RelocateMemorySize + + [in] Size of the memory segment to relocate. + +CurrentLoadedBase + + [in] Current base on which the memory segment to be relocated is loaded. + +RelocateBase + + [in] New base to which the memory segment will be relocated. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + + + + +Exporter module + + + +The exporter module has functions designed for export manipulation and building new export tables. + + + + + ExporterInit function + +The ExporterInit function initializes the importer module and it must be used before using any of the +functions used in the process of manual import fixing. + +Syntax + + + +void __stdcall ExporterInit( + +DWORD MemorySize, + +ULONG_PTR ImageBase, + +DWORD ExportOrdinalBase, + +char* szExportModuleName + +); + + + + + + + +Parameters + +MemorySize + + [in] Default memory size allocated for the entire export table data. This size must be +large enough to hold all data needed by the engine. Usually there is no need to +reserve more than 20kb of memory. + +ImageBase + +[in] Default image base of the targeted PE file. This value should be read from the file on +disk. + +ExportOrdinalBase + +[in] Sets the default ordinal base for the new export table. Default value is NULL. + +szExportModuleName + +[in] String which to use as a default library name in the export table. For example: +mylib.dll + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + ExporterSetImageBase function + +ExporterSetImageBase updates information passed to the engine when exporter is initialized. + +Syntax + + + +void __stdcall ExporterSetImageBase( + +ULONG_PTR ImageBase + +); + + + + + + + +Parameters + +ImageBase + +[in] Default image base of the targeted PE file. This value should be read from the file on +disk. + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + ExporterCleanup function + +ExporterCleanup clears all added exports. This resets the inputted data to its original state. Before using +the functions to add the export data, you must initialize the exporter again. + +Syntax + + + +void __stdcall ExporterCleanup(); + + + + + + + +Parameters + +None. + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + ExporterAddNewExport function + +ExporterAddNewExport adds new function to the export table. + +Syntax + + + +void __stdcall ExporterAddNewExport( + +char* szExportName, + +DWORD ExportRelativeAddress + +); + + + + + + + +Parameters + +szExportName + +[in] Name of the function that will be used to locate this function with APIs such as +GetProcAddress. + +ExportRelativeAddress + +[in] Relative virtual address for the exported function. Location in the PE file at which +the function you want to export is located. + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + ExporterAddNewOrdinalExport function + +ExporterAddNewOrdinalExport adds a new function to the export table. + +Syntax + + + +void __stdcall ExporterAddNewOrdinalExport( + +DWORD OrdinalNumber, + +DWORD ExportRelativeAddress + +); + + + + + + + +Parameters + +OrdinalNumber + +[in] Function will be exported as an ordinal with the specified ordinal number. + +ExportRelativeAddress + +[in] Relative virtual address for the exported function. The location in the PE file at +which the function you want to export is located. + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + ExporterGetAddedExportCount function + +ExporterGetAddedExportCount gets the current number of added functions in the export table. + +Syntax + + + +long __stdcall ExporterGetAddedExportCount(); + + + + + + + +Parameters + +None. + +Return value + +Returns the number of added items in the export table. + +Remarks + +None. + +Example + +None. + + + + + + + ExporterEstimatedSize function + +ExporterEstimatedSize estimates the size of memory needed to write the export data. This value can be +used to determine the size of the new section to which the export table will be written. + +Syntax + + + +long __stdcall ExporterEstimatedSize(); + + + + + + + +Parameters + +None. + +Return value + +Returns the size needed to write the export data. + +Remarks + +None. + +Example + +None. + + + + + + + ExporterBuildExportTableEx function + +ExporterBuildExportTableEx exports the added export data to an existing PE file, creating a valid export +table for the selected PE file. After this function executes, export data will be cleared by using +ExporterCleanup function. + +Syntax + + + +bool __stdcall ExporterBuildExportTableEx( + +char* szExportFileName, + +char* szSectionName + +); + + + + + + + +Parameters + +szExportFileName + + [in] Pointer to string which is a full path to the file in which new export table will be +written. + +szSectionName + +[in] Name (up to 8 characters long) of the PE section in which the new import table +content will be written. This section will be added to the file. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + ExporterBuildExportTable function + +ExporterBuildExportTable exports the added export data to existing PE file, creating a valid export table +for the selected PE file. After this function executes, the export data will be cleared by using +ExporterCleanup function. + +Syntax + + + +bool __stdcall ExporterBuildExportTable( + +ULONG_PTR StorePlace, + +ULONG_PTR FileMapVA + +); + + + + + + + +Parameters + +StorePlace + + [in] Physical address inside PE file to which the new export table will be written. Usually +this is a new section, but it can also be a part of the file which is unused but still in +read/write mode. + +FileMapVA + + [in] Pointer to the mapped file content which must be mapped in read/write mode. This +pointer is set by using either StaticFileLoad function or Windows API for file +mapping. It is a ULONG_PTR which defines its size on the x86 and x64 operating +systems. On x86 systems this variable is 4 bytes long and equal to DWORD, and on +x64 platform this variable is 8 bytes long and equal to DWORD64, but since this is a +pointer void* can also be used. + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + ExporterLoadExportTable function + +ExporterLoadExportTable loads an export table from any PE file. The loaded table will be converted to +an internal engine export tree, making it available for further modifications before it's exported to the +same or any other PE file. + +Syntax + + + +bool __stdcall ExporterLoadExportTable( + +char* szFileName + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose export table will +be loaded by the engine. + + + +Return value + +Function returns TRUE on success or FALSE if function fails to load data. + +Remarks + +None. + +Example + +None. + + + + + + + + +Resourcer module + + + +The resourcer module has functions designed to load and access PE files in order to work with them and +functions to extract those resources out. + + + + + ResourcerLoadFileForResourceUse function + +ResourcerLoadFileForResourceUse simulates PE file loading, in order to make all the virtual addresses +equal to physical ones in the newly loaded file. This is different than file mapping, because it simulates +only Windows PE loader behavior concerning PE file loading and storing sections in memory. No other +function of the Windows PE loader other than that is emulated. + +Syntax + + + +long long __stdcall ResourcerLoadFileForResourceUse( + +char* szFileName + +); + + + + + + + +Parameters + +szFileName + +[in] Pointer to a null terminated string which is a full path to file whose loading will be a +simulated PE loading so that all the virtual addresses match the newly loaded +physical ones. This is a done by simulating the Windows PE loader. + + + +Return value + +Return is the base address of the newly loaded file, or NULL if the file isn’t a PE file or it couldn’t +be loaded. + +Remarks + +None. + +Example + +None. + + + + + + + ResourcerFreeLoadedFile function + +ResourcerFreeLoadedFile unloads a file previously loaded by the ResourcerLoadFileForResourceUse +function. Due to the nature of the TitanEngine PE file loader simulator, using this function is equal to +using VirtualFree on the selected memory range. + +Syntax + + + +bool __stdcall ResourcerFreeLoadedFile( + +LPVOID LoadedFileBase + +); + + + + + + + +Parameters + +LoadedFileBase + +[in] Base address at which the file is loaded. This is usually a return value from the +ResourcerLoadFileForResourceUse function. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + ResourcerExtractResourceFromFileEx function + +ResourcerExtractResourceFromFileEx goes through the resource tree of the loaded file and extracts the +specified resource to disk. + +Syntax + + + +bool __stdcall ResourcerExtractResourceFromFileEx( + +ULONG_PTR FileMapVA, + +char* szResourceType, + +char* szResourceName, + +char* szExtractedFileName + +); + + + + + + + +Parameters + +FileMapVA + + [in] Pointer to the mapped file content. This pointer is set by using either StaticFileLoad +function or Windows API for file mapping. It is a ULONG_PTR which defines its size +on the x86 and x64 operating systems. On x86 systems this variable is 4 bytes long +and equal to DWORD, and on x64 platform this variable is 8 bytes long and equal to +DWORD64, but since this is a pointer void* can also be used. + +ResourceType + + [in] Pointer to string, which is a resource type identifier. If the resource type is an +integer you must convert it to string. For this conversion you can use the +MAKEINTRESOURCEA macro available in WinUser.h + +ResourceName + + [in] Pointer to string which is a resource name identifier. If the resource type is an +integer you must convert it to string. For this conversion you can use +MAKEINTRESOURCEA macro available in WinUser.h + +szExtractFileName + +[in] Pointer to the full path of the file to create and fill with the specified resource +memory content. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + + + + + + + ResourcerExtractResourceFromFile function + +ResourcerExtractResourceFromFile goes through the resource tree of the loaded file and extracts the +specified resource to disk. + +Syntax + + + +bool __stdcall ResourcerExtractResourceFromFile( + +char* szFileName, + +char* szResourceType, + +char* szResourceName, + +char* szExtractedFileName + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose resource will be +extracted. + +ResourceType + + [in] Pointer to string which is a resource type identifier. If the resource type is an +integer you must convert it to string. For this conversion you can use +MAKEINTRESOURCEA macro available in WinUser.h + +ResourceName + + [in] Pointer to string which is a resource name identifier. If the resource type is an +integer you must convert it to string. For this conversion you can use +MAKEINTRESOURCEA macro available in WinUser.h + +szExtractFileName + +[in] Pointer to a null terminated string which is a full path to file which will be created +and filled with selected resource memory content. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + ResourcerFindResource function + +ResourcerFindResource goes through the resource tree of the selected file and finds the specified +resource. + +Syntax + +bool __stdcall ResourcerFindResource( + +char* szFileName, + +char* szResourceType, + +DWORD ResourceType, + +char* szResourceName, + +DWORD ResourceName, + +DWORD ResourceLanguage, + +PULONG_PTR pResourceData, + +LPDWORD pResourceSize + +); + + + + + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file. + +szResourceType + + [in] Pointer to string which is a resource type identifier. If the resource type is an +integer use the integer input variable to locate such resource. + +ResourceType + + [in] Pointer to string which is a resource type identifier. If the resource type is an +integer use this variable to pass the value and set its string version to NULL. + +szResourceName + + [in] Pointer to string which is a resource name identifier. If the resource type is an +integer use the integer input variable to locate such resource. + +ResourceName + + [in] Pointer to string which is a resource name identifier. If the resource type is an +integer use this variable to pass the value and set its string version to NULL. + +ResourceLanguage + +[in] Integer value that indicates the language of the resource to use. + +pResourceData + +[out] Pointer to a ULONG_PTR variable which will receive the offset on which the +resource is located on. + +pResourceSize + +[in] Pointer to a DWORD variable which will receive the size of located resource. + + + + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + ResourcerFindResourceEx function + +ResourcerFindResourceEx goes through the resource tree of the selected file and finds the specified +resource. + +Syntax + +bool __stdcall ResourcerFindResourceEx( + +ULONG_PTR FileMapVA, + +DWORD FileSize, + +char* szResourceType, + +DWORD ResourceType, + +char* szResourceName, + +DWORD ResourceName, + +DWORD ResourceLanguage, + +PULONG_PTR pResourceData, + +LPDWORD pResourceSize + +); + + + + + + + + + + + + + +Parameters + +FileMapVA + + [in] Pointer to the mapped file content which must be mapped in read/write mode. This +pointer is set by using either StaticFileLoad function or Windows API for file +mapping. + +FileSize + + [in] Size of the mapped file. + +szResourceType + + [in] Pointer to string which is a resource type identifier. If the resource type is an +integer use the integer input variable to locate such resource. + +ResourceType + + [in] Pointer to string which is a resource type identifier. If the resource type is an +integer use this variable to pass the value and set its string version to NULL. + +szResourceName + + [in] Pointer to string which is a resource name identifier. If the resource type is an +integer use the integer input variable to locate such resource. + +ResourceName + + [in] Pointer to string which is a resource name identifier. If the resource type is an +integer use this variable to pass the value and set its string version to NULL. + +ResourceLanguage + +[in] Integer value that indicates the language of the resource to use. + + + + + + +pResourceData + +[out] Pointer to a ULONG_PTR variable which will receive the offset on which the +resource is located on. + +pResourceSize + +[in] Pointer to a DWORD variable which will receive the size of located resource. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + ResourcerEnumerateResource function + +ResourcerEnumerateResource goes through the resource tree of the loaded file and enumerates all +found resources. + +Syntax + + + +void __stdcall ResourcerEnumerateResource( + +char* szFileName, + +void* CallBack + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose resource will be +enumerated. + +CallBack + + [in] Address of a callback to call for each found resource. + + + +CallBack definition + +typedef bool(__stdcall *fResourceEnumerator)(wchar_t* szResourceType, \ + +DWORD ResourceType, wchar_t* szResourceName, DWORD ResourceName, \ + +DWORD ResourceLanguage, DWORD ResourceData, DWORD ResourceSize); + + + + + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + + ResourcerEnumerateResourceEx function + +ResourcerEnumerateResourceEx goes through the resource tree of the loaded file and enumerates all +found resources. + +Syntax + + + +void __stdcall ResourcerEnumerateResourceEx( + +ULONG_PTR FileMapVA, + +DWORD FileSize, + +void* CallBack + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to a null terminated string which is a full path to file whose resource will be +enumerated. + +CallBack + + [in] Address of a callback to call for each found resource. + + + +CallBack definition + +typedef bool(__stdcall *fResourceEnumerator)(wchar_t* szResourceType, \ + +DWORD ResourceType, wchar_t* szResourceName, DWORD ResourceName, \ + +DWORD ResourceLanguage, DWORD ResourceData, DWORD ResourceSize); + + + + + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + +Static module + + + +The static module has functions designed to load and access PE files in order to work with them or use +predefined decryption behaviors in order to decrypt common crypters. + + + + + + +Static module constants + + + +Constants used by: StaticFileLoad function + + + +#define UE_ACCESS_READ 0 + +#define UE_ACCESS_WRITE 1 + +#define UE_ACCESS_ALL 2 + + + +Constants used by: StaticMemoryDecrypt function, StaticMemoryDecryptEx function, +StaticSectionDecrypt function and StaticMemoryDecryptSpecial function + + + +#define UE_STATIC_DECRYPTOR_XOR 1 + +#define UE_STATIC_DECRYPTOR_SUB 2 + +#define UE_STATIC_DECRYPTOR_ADD 3 + + + +#define UE_STATIC_KEY_SIZE_1 1 + +#define UE_STATIC_KEY_SIZE_2 2 + +#define UE_STATIC_KEY_SIZE_4 4 + +#define UE_STATIC_KEY_SIZE_8 8 + +#define UE_STATIC_DECRYPTOR_FOREWARD 1 + +#define UE_STATIC_DECRYPTOR_BACKWARD 2 + +Constants used by: StaticMemoryDecompress function + + + +#define UE_STATIC_APLIB 1 + +#define UE_STATIC_APLIB_DEPACK 2 + +#define UE_STATIC_LZMA 3 + +Constants used by: StaticHashMemory function and StaticHashFile function + + + +#define UE_STATIC_HASH_MD5 1 + +#define UE_STATIC_HASH_SHA1 2 + +#define UE_STATIC_HASH_CRC32 3 + + + + + StaticFileOpen function + +StaticFileOpen opens a handle to a selected file. Using this function produces a normal Windows file +handle which can be used for other operations. + +Syntax + + + +bool __stdcall StaticFileOpen( + +char* szFileName, + +DWORD DesiredAccess, + +LPHANDLE FileHandle, + +LPDWORD FileSizeLow, + +LPDWORD FileSizeHigh + +); + + + + + + + + + +Parameters + +szFileName + +[in] Pointer to a null terminated string which is a full path to file which will be opened. + +DesiredAccess + +[in] Determines the type of file access you will have. These values are defined in +Windows as GENERIC_READ and GENERIC_WRITE. + +FileHandle + +[out] Pointer to HANDLE variable which will receive the open file handle. + +FileSizeLow + +[out] Pointer to DWORD variable which will receive the file size. + +FileSizeHigh + +[out] Pointer to DWORD variable which will receive the high file size. This parameter can +be NULL if you don’t intend to open files larger than 4 Gb. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Example + +None. + + + + + + + StaticFileGetContent function + +StaticFileGetContent retrieves data from opened file at the specified location from the start of the file. + +Syntax + + + +bool __stdcall StaticFileGetContent( + +HANDLE FileHandle, + +DWORD FilePositionLow, + +LPDWORD FilePositionHigh, + +void* Buffer, + +DWORD Size + +); + + + + + + + + + +Parameters + +FileHandle + +[in] Opened file HANDLE. File must be opened with read access. + +FilePositionLow + +[in] Low offset from which data retrieval will start. For files fewer than 4 Gb in size this is +the only positioning parameter you need. + +FilePositionHigh + +[in] High offset from which data retrieval will start. For file greater than 4 Gb in size this +parameter is needed only if the data needs to be read from addresses greater than +0xFFFFFFFF. + +Buffer + +[out] Pointer to buffer which will receive the retrieved data. Buffer must be large +enough to hold all requested data. + +Size + +[in] Size of the data to retrieve from the opened file. + + + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Example + +None. + + + + + + + StaticFileClose function + +StaticFileClose closes an open file handle. + +Syntax + + + +void __stdcall StaticFileClose( + +HANDLE FileHandle + +); + + + + + + + + + +Parameters + +FileHandle + +[in] Opened file HANDLE which will be closed by the function. + + + +Return value + +None. + +Example + +None. + + + + + StaticFileLoad function + +StaticFileLoad either maps the selected file, or simulates its loading. Depending on the type of static +unpacker being developed, you need to specify the type of file memory access. File content can be +changed with either type, without affecting the loading type you are using. + +Syntax + + + +bool __stdcall StaticFileLoad( + +char* szFileName, + +DWORD DesiredAccess, + +bool SimulateLoad, + +LPHANDLE FileHandle, + +LPDWORD LoadedSize, + +LPHANDLE FileMap, + +PULONG_PTR FileMapVA + +); + + + + + + + + + +Parameters + +szFileName + +[in] Pointer to a null terminated string which is a full path to file which will be mapped +or loaded. + +DesiredAccess + +[in] Determines the type of memory access you will have if you are mapping the file. It +can be one of the following: UE_ACCESS_READ, UE_ACCESS_WRITE and +UE_ACCESS_ALL. + +SimulateLoad + +[in] Boolean switch indicating whether or not to simulate the Windows PE loader. + +FileHandle + +[out] Pointer to HANDLE variable which will receive the open file handle. + +LoadedSize + +[out] Pointer to DWORD variable which will receive the size of the mapped file. + +FileMap + +[out] Pointer to HANDLE variable which will receive the file mapping handle. + +FileMapVA + +[out] Pointer to ULONG_PTR variable which will receive the mapped file base address. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + + + + + StaticFileUnload function + +StaticFileUnload either maps the selected file or simulates its loading. Depending on the type of static +unpacker being developed, you need to specify the type of file memory access. File content can be +changed with either type, without affecting the loading type you are using. + +Syntax + + + +bool __stdcall StaticFileUnload( + +char* szFileName, + +bool CommitChanges, + +HANDLE FileHandle, + +DWORD LoadedSize, + +HANDLE FileMap, + +ULONG_PTR FileMapVA + +); + + + + + + + + + +Parameters + +szFileName + +[in] Pointer to a null terminated string which is a full path to file which will receive the +changed file content. In case of simulated load this parameter is mandatory if you +need to save the changes to the file. + +CommitChanges + +[in] Boolean switch indicating whether or not to commit done changes to files loaded by +Windows PE loader simulation. + +FileHandle + +[in] Handle of the mapped file returned by StaticFileLoad. + +LoadedSize + +[in] Size of the mapped file returned by StaticFileLoad. You can change the file size and +by doing that either trim or increase its size. + +FileMap + +[in] File mapping handle returned by StaticFileLoad. + +FileMapVA + +[in] Base address at which the file is loaded returned by StaticFileLoad. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + + + + + + + StaticMemoryDecrypt function + +StaticMemoryDecrypt decrypts the selected memory range, using the specified decryption key and +decryption method. + +Syntax + + + +void __stdcall StaticMemoryDecrypt( + +LPVOID MemoryStart, + +DWORD MemorySize, + +DWORD DecryptionType, + +DWORD DecryptionKeySize, + +ULONG_PTR DecryptionKey + +); + + + + + + + +Parameters + +MemoryStart + + [in] Pointer to the beginning of the memory block you want to decrypt in the remote +process. + +MemorySize + + [in] Size of the memory to decrypt. + +DecryptionType + + [in] Specifies which decryption engine to use. Decryption algorithm options: +UE_STATIC_DECRYPTOR_XOR, UE_STATIC_DECRYPTOR_SUB or +UE_STATIC_DECRYPTOR_ADD. + +DecryptionKeySize + + [in] Specifies the size of the decryption key that will be used. Can only be one of the +following key sizes: UE_STATIC_KEY_SIZE_1, UE_STATIC_KEY_SIZE_2, +UE_STATIC_KEY_SIZE_4 or UE_STATIC_KEY_SIZE_8. + +DecryptionKey + + [in] Specifies the decryption key to use. + + + +Return value + +None. + +Example + +StaticMemoryDecrypt(0x00401000, 0x1000, UE_STATIC_DECRYPTOR_XOR, UE_STATIC_KEY_SIZE_1, 0x90); + + + + + StaticMemoryDecryptEx function + +StaticMemoryDecryptEx decrypts the selected memory range with a custom decryption algorithm. The +specified callback will be called for each member of the encrypted block. + +Syntax + + + +void __stdcall StaticMemoryDecryptEx( + +LPVOID MemoryStart, + +DWORD MemorySize, + +DWORD DecryptionKeySize, + +void* DecryptionCallBack + +); + + + + + + + +Parameters + +MemoryStart + + [in] Pointer to the beginning of the memory block you want to decrypt in the remote +process. + +MemorySize + + [in] Size of the memory to decrypt. + +DecryptionKeySize + + [in] Specifies the size of the decryption key that will be used. Can be custom or one of +the following key sizes: UE_STATIC_KEY_SIZE_1, UE_STATIC_KEY_SIZE_2, +UE_STATIC_KEY_SIZE_4 or UE_STATIC_KEY_SIZE_8. If you use a custom +size, make sure the MemorySize % DecryptionKeySize is NULL. If modus isn’t NULL, +the last few bytes of the memory content will not be decrypted. + +DecryptionCallBack + + [in] Callback that will decrypt the targeted memory slice. It is called for each member of +the encrypted block, with the block pointer increasing by the size of the decryption +key. + + + +CallBack definition + +typedef bool(__stdcall *fStaticCallBack)(void* sMemoryStart, int sKeySize); + + + +Return value + +None. + + + + + + + StaticSectionDecrypt function + +StaticSectionDecrypt decrypts the selected memory range with a custom decryption algorithm. The +specified callback will be called for each member of the encrypted block. + +Syntax + + + +void __stdcall StaticSectionDecrypt( + +ULONG_PTR FileMapVA, + +DWORD SectionNumber, + +bool SimulateLoad, + +DWORD DecryptionType, + +DWORD DecryptionKeySize, + +ULONG_PTR DecryptionKey + +); + + + + + + + + + +Parameters + +FileMapVA + + [in] Pointer to the mapped file content. This pointer is set by either the StaticFileLoad +function or Windows API for file mapping. + +SectionNumber + + [in] Number of the section to decrypte. Section numbers range from zero to section +count minus one. + +SimulatedLoad + + [in] Boolean switch indicating whether or not the file was loaded by simulating +Windows PE loader. If FALSE the engine assumes that the file was mapped. + +DecryptionType + + [in] Specifies which decryption engine to use. Decryption algorithm options: +UE_STATIC_DECRYPTOR_XOR, UE_STATIC_DECRYPTOR_SUB or +UE_STATIC_DECRYPTOR_ADD. + +DecryptionKeySize + + [in] Determines the size of the decryption key that will be used. Can only be one of the +following key sizes: UE_STATIC_KEY_SIZE_1, UE_STATIC_KEY_SIZE_2, +UE_STATIC_KEY_SIZE_4 or UE_STATIC_KEY_SIZE_8. + +DecryptionKey + + [in] The decryption key to use. + + + +Return value + +None. + + + + + StaticMemoryDecryptSpecial function + +StaticMemoryDecryptSpecial decrypts the selected memory range with a custom decryption algorithm. +The specified callback will be called for each member of the encrypted block. + +Syntax + +void __stdcall StaticMemoryDecryptSpecial( + +LPVOID MemoryStart, + +DWORD MemorySize, + +DWORD DecryptionKeySize, + +DWORD SpecDecryptionType, + +void* DecryptionCallBack + +); + + + + + + + + + +Parameters + +MemoryStart + + [in] Pointer to the beginning of the memory block you want to decrypt in the remote +process. + +MemorySize + + [in] Size of the memory to decrypt. + +DecryptionKeySize + + [in] Specifies the size of the decryption key that will be used. Can be custom or one of +the following key sizes: UE_STATIC_KEY_SIZE_1, UE_STATIC_KEY_SIZE_2, +UE_STATIC_KEY_SIZE_4 or UE_STATIC_KEY_SIZE_8. If you use a custom +size, make sure the MemorySize % DecryptionKeySize is NULL. If modus isn’t NULL, +the last few bytes of the memory content will not be decrypted. + +SpecDecryptionType + + [in] Type of decryption to perform, can be: UE_STATIC_DECRYPTOR_FOREWARD or +UE_STATIC_DECRYPTOR_BACKWARD. This sets decryption direction. + +DecryptionCallBack + + [in] Callback that will decrypt the targeted memory slice. It is called for each member of +the encrypted block, with the block pointer increasing by the size of the decryption +key. + +CallBack definition + +typedef bool(__stdcall *fStaticCallBack)(void* sMemoryStart, int sKeySize); + + + +Return value + +None. + + + + + StaticMemoryDecompress function + +StaticMemoryDecompress decompresses the selected memory block to designated destination. Source +memory block can be compressed with the following methods: aplib and lzma. + +Syntax + + + +void __stdcall StaticMemoryDecompress( + +void* Source, + +DWORD SourceSize, + +void* Destination, + +DWORD DestinationSize, + +int Algorithm + +); + + + + + + + +Parameters + +Source + + [in] Pointer to the beginning of the memory block you want to decompress. + +SourceSize + + [in] Size of the memory to decompress. + +Destination + + [in] Pointer to memory buffer to hold decompressed content. + +DestinationSize + + [in] Size of the destination buffer. + +Algorithm + + [in] Specifies algorithm to use for decompression, can be one of the following: +UE_STATIC_APLIB, UE_STATIC_APLIB_DEPACK or UE_STATIC_LZMA. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Example + +None. + + + + + + + StaticRawMemoryCopy function + +StaticRawMemoryCopy copies data from mapped file directly to file on the disk. This function is used as +a workaround the memory usage problem when reading data from mapped files. + +Syntax + +bool __stdcall StaticRawMemoryCopy( + +HANDLE hFile, + +ULONG_PTR FileMapVA, + +ULONG_PTR VitualAddressToCopy, + +DWORD Size, + +bool AddressIsRVA, + +char* szDumpFileName + +); + + + + + + + + + +Parameters + +hFile + + [in] Handle of the opened file. + +FileMapVA + + [in] Pointer to the mapped file content. This pointer is set by either the StaticFileLoad +function or Windows API for file mapping. + +VitualAddressToCopy + + [in] Virtual address of data inside the mapped file which will be copied to new file. + +Size + + [in] Number of bytes to copy. + +AddressIsRVA + + [in] Boolean switch indicating whether or not the VirtualAddressToCopy is a relative +address. + +szDumpFileName + + [in] Pointer to the full path of the file in which to write the memory content. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Example + +None. + + + + + + + StaticRawMemoryCopyEx function + +StaticRawMemoryCopyEx copies data from opened file directly to another file on the disk. + +Syntax + +bool __stdcall StaticRawMemoryCopyEx( + +HANDLE hFile, + +DWORD RawAddressToCopy, + +DWORD Size, + +char* szDumpFileName + +); + + + + + + + + + +Parameters + +hFile + + [in] Handle of the opened file. + +RawAddressToCopy + + [in] Offset from which the file copy will be performed. + +Size + + [in] Number of bytes to copy. + +szDumpFileName + + [in] Pointer to the full path of the file in which to write the memory content. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Example + +None. + + + + + + + StaticRawMemoryCopyEx64 function + +StaticRawMemoryCopyEx64 copies data from opened file directly to another file on the disk. This +function is used for file greater than 4 Gb in size. + +Syntax + +bool __stdcall StaticRawMemoryCopyEx64( + +HANDLE hFile, + +DWORD64 RawAddressToCopy, + +DWORD64 Size, + +char* szDumpFileName + +); + + + + + + + + + +Parameters + +hFile + + [in] Handle of the opened file. + +RawAddressToCopy + + [in] Offset from which the file copy will be performed. + +Size + + [in] Number of bytes to copy. + +szDumpFileName + + [in] Pointer to the full path of the file in which to write the memory content. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Example + +None. + + + + + + + + + StaticHashMemory function + +StaticHashMemory hashes the selected memory part with a selected hashing algorithm. + +Syntax + +bool __stdcall StaticHashMemory( + +void* MemoryToHash, + +DWORD SizeOfMemory, + +void* HashDigest, + +bool OutputString, + +int Algorithm + +); + + + + + + + + + +Parameters + +MemoryToHash + + [in] Pointer to memory to be hashed. + +SizeOfMemory + + [in] Size of the memory to be hashed. + +HashDigest + + [out] Pointer to a buffer which will receive the hash. If OutputString is set to TRUE +output will be a string otherwise it will be an array containing the hash value. + +OutputString + + [in] This input variable determines the output type. If it is set to TRUE the output will be +a string otherwise it will be an array containing the hash value. + +Algorithm + + [in] Determines which algorithm to use for hashing, can be one of the following: +UE_STATIC_HASH_MD5, UE_STATIC_HASH_SHA1 or UE_STATIC_HASH_CRC32. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Example + +None. + + + + + + + StaticHashFile function + +StaticHashFile hashes the selected file with a selected hashing algorithm. + +Syntax + +bool __stdcall StaticHashFile( + +char* szFileName, + +char* HashDigest, + +bool OutputString, + +int Algorithm + +); + + + + + + + + + +Parameters + +szFileName + + [in] Path to file which will be hashed. + +HashDigest + + [out] Pointer to a buffer which will receive the hash. If OutputString is set to TRUE +output will be a string otherwise it will be an array containing the hash value. + +OutputString + + [in] This input variable determines the output type. If it is set to TRUE the output will be +a string otherwise it will be an array containing the hash value. + +Algorithm + + [in] Determines which algorithm to use for hashing, can be one of the following: +UE_STATIC_HASH_MD5, UE_STATIC_HASH_SHA1 or UE_STATIC_HASH_CRC32. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Example + +None. + + + + +Handler module + + + +The handler module has functions designed to work with open handles and mutexes. Additionally, it can +find processes which use the designated mutex, or close all lock handles to selected files. + + + + + + +Handler module constants + + + +Constants used by: HandlerGetHandleDetails function + + + +#define UE_OPTION_HANDLER_RETURN_HANDLECOUNT 1 + +#define UE_OPTION_HANDLER_RETURN_ACCESS 2 + +#define UE_OPTION_HANDLER_RETURN_FLAGS 3 + +#define UE_OPTION_HANDLER_RETURN_TYPENAME 4 + +#define UE_OPTION_HANDLER_RETURN_TYPENAME_UNICODE 5 + +Handler module structures + + + +Structures used by: HandlerEnumerateOpenHandles function and HandlerEnumerateLockHandles +function + + + +typedef struct{ + + ULONG ProcessId; + + HANDLE hHandle; + +}HandlerArray, *PHandlerArray; + + + + + HandlerGetActiveHandleCount function + +HandlerGetActiveHandleCount gets the number of open handles inside the selected process. + +Syntax + + + +long __stdcall HandlerGetActiveHandleCount( + +DWORD ProcessId + +); + + + + + + + +Parameters + +ProcessId + + [in] Process ID of the running process, which can be acquired with the Windows API. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + HandlerIsHandleOpen function + +HandlerIsHandleOpen checks whether the remote handle is still open. + +Syntax + + + +bool __stdcall HandlerIsHandleOpen( + +DWORD ProcessId, + +HANDLE hHandle + +); + + + + + + + +Parameters + +ProcessId + + [in] Process ID of the running process, which can be acquired with the Windows API. + +hHandle + + [in] Handle inside the remote process whose state will be queried. + + + +Return value + +Boolean switch indicating whether or not the handle is still open. + +Remarks + +None. + +Example + +None. + + + + + + + HandlerGetHandleName function + +HandlerGetHandleName retrieves the name of an open handle in a remote process. + +Syntax + + + +void* __stdcall HandlerGetHandleName( + +HANDLE hProcess, + +DWORD ProcessId, + +HANDLE hHandle, + +bool TranslateName + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose handle info is needed. + +ProcessId + + [in] Process ID of the running process, which can be acquired with the Windows API. + +hHandle + + [in] Handle inside the remote process whose name you want to find. + +TranslateName + + [in] Boolean switch indicating whether or not to translate the name of the handle to +non native name. Names or paths which contain physical devices in their file +references are resolved with this function. + + + +Return value + +Function returns a pointer to the handle name, or NULL if the supplied string can’t be retrieved. + +Remarks + +CAUTION: The string with the translated native name is stored inside the engine, which makes +this function multi thread unsafe. + +Example + +None. + + + + + + + HandlerGetHandleDetails function + +HandlerGetHandleDetails retrieves additional information about an open handle in a remote process. + +Syntax + + + +long long __stdcall HandlerGetHandleDetails( + +HANDLE hProcess, + +DWORD ProcessId, + +HANDLE hHandle, + +DWORD InformationReturn + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose handle info is needed. + +ProcessId + + [in] Process ID of the running process, which can be acquired with the Windows API. + +hHandle + + [in] Handle inside the remote process whose name you want. + +InformationReturn + + [in] Defines the type of the information to return about the specified remote handle. It +can be one of the following: + +. UE_OPTION_HANDLER_RETURN_HANDLECOUNT +. UE_OPTION_HANDLER_RETURN_ACCESS +. UE_OPTION_HANDLER_RETURN_FLAGS +. UE_OPTION_HANDLER_RETURN_TYPENAME +. UE_OPTION_HANDLER_RETURN_TYPENAME_UNICODE + + + + +Return value + +Function can return a DWORD value of the selected handle property or a pointer to handle +name, depending on the InformationReturn value. + +Remarks + +CAUTION: The string with the translated native name is stored inside the engine, which makes +this function multi thread unsafe. + + + + + HandlerEnumerateOpenHandles function + +HandlerEnumerateOpenHandles gets the information about all open handles for the selected process +inside one array. + +Syntax + + + +long __stdcall HandlerEnumerateOpenHandles( + +DWORD ProcessId, + +LPVOID HandleBuffer, + +DWORD MaxHandleCount + +); + + + + + + + +Parameters + +ProcessId + + [in] Process ID of the running process, which can be acquired with the Windows API. + +HandleDataBuffer + + [out] Pointer to the array which will receive the lock handle information. The array is +defined as stated in the + +Handler module . + +MaxHandleCount + + [in] Specifies the maximum possible entries in the array. + + + +Return value + +Returns the number of open handles found. + +Remarks + +None. + +Example + +None. + + + + + + + HandlerIsFileLocked function + +HandlerIsFileLocked checks whether the selected file or folder is locked by open handles from any of +the running processes. + +Syntax + + + +bool __stdcall HandlerIsFileLocked( + +char* szFileOrFolderName, + +bool NameIsFolder, + +bool NameIsTranslated + +); + + + + + + + +Parameters + +szFileOrFolderName + +[in] Pointer to a null terminated string which is a full path to file or folder which will be +checked for locking handles. + +NameIsFolder + + [in] Boolean switch indicating whether the provided string is a folder. + +NameIsTranslated + + [in] Boolean switch indicating whether the string has already been translated. + + + +Return value + +Boolean switch indicating whether or not the file or folder is locked. + +Remarks + +None. + +Example + +None. + + + + + + + HandlerCloseAllLockHandles function + +HandlerCloseAllLockHandles checks whether the selected file or folder is locked by open handles from +any of the running processes, and if so, whether it should to try to close all of them, regardless of the +process locking the file or folder. Use this function with caution because it can cause any applications +relying on those handles to crash. + +Syntax + + + +bool __stdcall HandlerCloseAllLockHandles( + +char* szFileOrFolderName, + +bool NameIsFolder, + +bool NameIsTranslated + +); + + + + + + + +Parameters + +szFileOrFolderName + +[in] Pointer to a null terminated string which is a full path to file or folder which will be +checked for locking handles and whose lock handles will be closed. + +NameIsFolder + + [in] Boolean switch indicating whether the provided string is a folder. + +NameIsTranslated + + [in] Boolean switch indicating whether the string has already been translated. + + + +Return value + +Boolean switch indicating whether or not the file or folder is still locked. + +Remarks + +None. + +Example + +None. + + + + + + + HandlerEnumerateLockHandles function + +HandlerEnumerateLockHandles puts the information about all file or folder locking handles into one +array. + +Syntax + + + +long __stdcall HandlerEnumerateLockHandles( + +char* szFileOrFolderName, + +bool NameIsFolder, + +bool NameIsTranslated, + +LPVOID HandleDataBuffer, + +DWORD MaxHandleCount + +); + + + + + + + +Parameters + +NameIsFolder + + [in] Boolean switch indicating whether the provided string is a folder. + +NameIsTranslated + + [in] Boolean switch indicating whether the string has already been translated. + +HandleDataBuffer + + [out] Pointer to the array that will receive the lock handle information. The array is +defined as stated in the + +Handler module . + +MaxHandleCount + + [in] Defines the maximum possible entries in the array. + + + +Return value + +Returns the number of lock handles found. + +Remarks + +None. + +Example + +None. + + + + + + + HandlerCloseRemoteHandle function + +HandlerCloseRemoteHandle closes handles in a remote process. Use this function with caution because +it can cause any applications relying on those handles to crash. + +Syntax + + + +bool __stdcall HandlerCloseRemoteHandle( + +HANDLE hProcess, + +HANDLE hHandle + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose handle will be closed. + +hHandle + +[in] Handle to close inside the remote process. + + + +Return value + +Boolean switch indicating whether or not the handle has closed. + +Remarks + +None. + +Example + +None. + + + + + + + HandlerEnumerateOpenMutexes function + +HandlerEnumerateOpenMutexes puts the information about all open mutex handles for the specified +process into an array. + +Syntax + + + +long __stdcall HandlerEnumerateOpenMutexes( + +HANDLE hProcess, + +DWORD ProcessId, + +LPVOID HandleBuffer, + +DWORD MaxHandleCount + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose mutexes will be enumerated. + +ProcessId + + [in] Process ID of the running process which can be acquired with the Windows API. + +HandleDataBuffer + + [out] Pointer to the array that will receive the open mutex handle information. + +MaxHandleCount + + [in] Defines the maximum possible entries in the array. + + + +Return value + +Returns the number of open mutex handles found. + +Remarks + +Array is defined as an array of HANDLEs. + +Example + +None. + + + + + + + HandlerGetOpenMutexHandle function + +HandlerGetOpenMutexHandle gets the handle for the remotely opened mutex. + +Syntax + + + +long long __stdcall HandlerGetOpenMutexHandle( + +HANDLE hProcess, + +DWORD ProcessId, + +char* szMutexString + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose mutexes will be enumerated. + +ProcessId + + [in] Process ID of the running process which can be acquired with the Windows API. + +szMutexString + + [in] Pointer to string which is the mutex whose handle will be returned. + + + +Return value + +Returns the handle inside the remote process for the selected mutex or NULL if mutex isn’t +found. + +Remarks + +None. + +Example + +None. + + + + + + + HandlerGetProcessIdWhichCreatedMutex function + +HandlerGetProcessIdWhichCreatedMutex gets the process ID which has opened the selected mutex. + +Syntax + + + +long __stdcall HandlerGetProcessIdWhichCreatedMutex( + +char* szMutexString + +); + + + + + + + +Parameters + +szMutexString + + [in] Pointer to string which is the mutex whose presence will be queried in all of the +running processes. + + + +Return value + +Returns the ID of the process which has opened the selected mutex. + +Remarks + +None. + +Example + +None. + + + + + + +Extension module + + + +The extension module has functions designed to work with plugins created for the TitanEngine. +Functions inside this module provide interface to manipulating loaded plugins. + + + + + + +Guide to writing extensions for TitanEngine + + + +TitanEngine extensions are created as normal dynamic link libraries placed in the selected folder (either +.\plugins\x86 or .\plugins\x64) for the engine to load. Following export functions are used by the engine: + +. TitanResetPlugin – Function which is called every time the debugging starts within the +DebuLoop function. +. TitanReleasePlugin – Function which is called when the plugin gets unloaded or the engine +shuts down. +. TitanRegisterPlugin – Function which is called when the plugin gets loaded by the engine. Plugin +should register itself by using a unique name (up to 64 characters long) and optionally fill the +version information. +. TitanDebuggingCallBack – Function which is called for every debug even registered by the +engine. This function has a CallReason parameter which can be one of the following: +UE_PLUGIN_CALL_REASON_PREDEBUG, UE_PLUGIN_CALL_REASON_EXCEPTION or +UE_PLUGIN_CALL_REASON_POSTDEBUG. + + +Extension structure and function definitions + + + +typedef struct{ + + char PluginName[64]; + + DWORD PluginMajorVersion; + + DWORD PluginMinorVersion; + + HMODULE PluginBaseAddress; + + void* TitanDebuggingCallBack; + + void* TitanRegisterPlugin; + + void* TitanReleasePlugin; + + void* TitanResetPlugin; + + bool PluginDisabled; + +}PluginInformation, *PPluginInformation; + + + +__declspec(dllexport) void __stdcall TitanResetPlugin(); + +__declspec(dllexport) void __stdcall TitanReleasePlugin(); + +__declspec(dllexport) bool __stdcall TitanRegisterPlugin(char* szPluginName, +LPDWORD titanPluginMajorVersion, LPDWORD titanPluginMinorVersion); + +__declspec(dllexport) void __stdcall TitanDebuggingCallBack(LPDEBUG_EVENT +debugEvent, int CallReason); + + + + + ExtensionManagerIsPluginLoaded function + +ExtensionManagerIsPluginLoaded checks if the selected plugin is loaded. + +Syntax + + + +bool __stdcall ExtensionManagerIsPluginLoaded( + +char* szPluginName + +); + + + + + + + +Parameters + +szPluginName + + [in] Unique identifier plugin uses to register itself. + + + +Return value + +Boolean switch indicating whether or not the plugin is still loaded. + +Remarks + +None. + +Example + +None. + + + + + + + ExtensionManagerIsPluginEnabled function + +ExtensionManagerIsPluginEnabled checks if the selected plugin is enabled. + +Syntax + + + +bool __stdcall ExtensionManagerIsPluginEnabled( + +char* szPluginName + +); + + + + + + + +Parameters + +szPluginName + + [in] Unique identifier plugin uses to register itself. + + + +Return value + +Boolean switch indicating whether or not the plugin is enabled. + +Remarks + +None. + +Example + +None. + + + + + + + ExtensionManagerDisablePlugin function + +ExtensionManagerDisablePlugin temporarily disables the use of the selected plugin. + +Syntax + + + +bool __stdcall ExtensionManagerDisablePlugin( + +char* szPluginName + +); + + + + + + + +Parameters + +szPluginName + + [in] Unique identifier plugin uses to register itself. + + + +Return value + +Boolean switch indicating whether or not the plugin was disabled. + +Remarks + +None. + +Example + +None. + + + + + + + ExtensionManagerDisableAllPlugins function + +ExtensionManagerDisableAllPlugins temporarily disables the use of all loaded plugins. + +Syntax + + + +bool __stdcall ExtensionManagerDisableAllPlugins(); + + + + + + + +Parameters + +None. + +Return value + +Boolean switch indicating whether or not the plugins were disabled. + +Remarks + +None. + +Example + +None. + + + + + + + ExtensionManagerEnablePlugin function + +ExtensionManagerEnablePlugin enables the use of the selected previously disabled plugin. + +Syntax + + + +bool __stdcall ExtensionManagerEnablePlugin( + +char* szPluginName + +); + + + + + + + +Parameters + +szPluginName + + [in] Unique identifier plugin uses to register itself. + + + +Return value + +Boolean switch indicating whether or not the plugin was enabled. + +Remarks + +None. + +Example + +None. + + + + + + + ExtensionManagerEnableAllPlugins function + +ExtensionManagerEnableAllPlugins enables the use of all previously disabled plugins. + +Syntax + + + +bool __stdcall ExtensionManagerEnableAllPlugins(); + + + + + + + +Parameters + +None. + +Return value + +Boolean switch indicating whether or not the plugins were enabled. + +Remarks + +None. + +Example + +None. + + + + + + + ExtensionManagerUnloadPlugin function + +ExtensionManagerUnloadPlugin unloads the selected plugin from the current session. It will still be +loaded the next time the engine starts. Only way to actually remove the plugin completely is to delete it +from the plugins folder. + +Syntax + + + +bool __stdcall ExtensionManagerUnloadPlugin( + +char* szPluginName + +); + + + + + + + +Parameters + +szPluginName + + [in] Unique identifier plugin uses to register itself. + + + +Return value + +Boolean switch indicating whether or not the plugin was unloaded. + +Remarks + +None. + +Example + +None. + + + + + + + ExtensionManagerUnloadAllPlugins function + +ExtensionManagerUnloadAllPlugins unloads the selected plugin from the current session. All plugins +will still be loaded the next time the engine starts. Only way to actually remove any of the plugins +completely is to delete them from the plugins folder. + +Syntax + + + +bool __stdcall ExtensionManagerUnloadAllPlugins(); + + + + + + + +Parameters + +None. + +Return value + +Boolean switch indicating whether or not the plugins were unloaded. + +Remarks + +None. + +Example + +None. + + + + + + + ExtensionManagerGetPluginInfo function + +ExtensionManagerGetPluginInfo retrieves the information about the selected plugin. Data returned can +be modified in order to manipulate the plugin behavior. + +Syntax + + + +void* __stdcall ExtensionManagerGetPluginInfo( + +char* szPluginName + +); + + + + + + + +Parameters + +szPluginName + + [in] Unique identifier plugin uses to register itself. + + + +Return value + +Pointer to PluginInformation structure or NULL if the selected plugin isn’t currently loaded. + +Remarks + +None. + +Example + +None. + + + + + + +Engine module + + + +The engine module isn’t a separate module or a functional part; instead it is a top level engine +functionality which utilizes multiple engine functions to perform a certain task. + + + + + + + EngineCreateMissingDependencies function + +EngineCreateMissingDependencies goes thought the import table of the selected file and creates all +dynamic link libraries needed by the file which are not present on the system. + +Syntax + + + +bool __stdcall EngineCreateMissingDependencies( + +char* szFileName, + +char* szOutputFolder, + +bool LogCreatedFiles + +); + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file to inspect for missing dependencies. + +szOutputFolder + + [in] Pointer to the full path of the folder in which the files will be created. Most +commonly this is the folder in which the file which will be unpacked is. + +LogCreatedFile + + [in] Indicates whether or not to internally log all created files. Using this option later +enables simple deletion of created files. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + EngineFakeMissingDependencies function + +EngineFakeMissingDependencies performs low level API hooking in user mode to ensure that +dynamically loaded libraries are always virtually present. This ensures that all libraries which are loaded +by Windows API are seemingly present. This function should be called once the debugee execution hit +the packed entry point in cases when packing shell dynamically loads libraries. + +Syntax + + + +bool __stdcall EngineCreateMissingDependencies( + +HANDLE hProcess + +); + + + + + + + +Parameters + +hProcess + + [in] Handle of the process whose dynamically loaded modules will be simulated. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + EngineDeleteCreatedDependencies function + +EngineDeleteCreatedDependencies deletes logged created missing dependencies. This function +performs disk cleanup at the end of unpacking process. If files can’t be deleted at that particular time +they will be moved to system’s temporary folder for user deletion. + +Syntax + + + +bool __stdcall EngineDeleteCreatedDependencies(); + + + + + + + +Parameters + +None. + +Return value + +Boolean switch indicating whether or not the function was successful. + +Remarks + +None. + +Example + +None. + + + + + + + EngineCreateUnpackerWindow function + +EngineCreateUnpackerWindow creates a default and easily customizable graphical user interface for +your unpacker project. Program doesn’t return from this call until the window has been closed. + +Syntax + + + +bool __stdcall EngineCreateUnpackerWindow( + +char* WindowUnpackerTitle, + +char* WindowUnpackerLongTitle, + +char* WindowUnpackerName, + +char* WindowUnpackerAuthor, + +void* StartUnpackingCallBack + +); + + + + + + + +Parameters + +WindowUnpackerTitle + + [in] Custom graphical user interface window title string. + +WindowUnpackerLongTitle + + [in] Custom graphical user interface long unpacker name string. + +WindowUnpackerName + + [in] Custom graphical user interface unpacker name string. + +WindowUnpackerAuthor + + [in] Custom graphical user interface unpacker author name string. + +StartUnpackingCallBack + + [in] Callback which will be called once the user presses unpack button. + + + +CallBack definition + +typedef void(__stdcall *fStartUnpacking)( + +char* szInputFile, bool RealignFile, bool CopyOverlay); + + + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Example + +EngineCreateUnpackerWindow("UPX 1.x - 3.x", "Unpacker for UPX packed files", "RL!deUPX 1.x - 3.x", +"ReversingLabs Corporation", &InitializeUnpacking); + + + + + EngineAddUnpackerWindowLogMessage function + +EngineAddUnpackerWindowLogMessage can be used to show unpacking log messages while the +unpacker uses built-in graphical user interface. + +Syntax + + + +void __stdcall EngineAddUnpackerWindowLogMessage( + +char* szLogMessage + +); + + + + + + + +Parameters + +szLogMessage + + [in] Message which will be shown inside the unpacker log window. + + + +Return value + +None. + +Remarks + +None. + +Example + +None. + + + + + + +Engine unpacker simplification module + + + +The engine module isn’t a separate module or a functional part; instead it is a top level engine +functionality which utilizes multiple engine functions to perform a certain task. Engine unpacker +simplification functions enable easy unpacker coding for most common portable executable packers. + + + + + + +Engine simplification module constants + + + +Constants used by: EngineUnpackerSetBreakCondition function + + + +#define UE_UNPACKER_CONDITION_SEARCH_FROM_EP 1 + + + +#define UE_UNPACKER_CONDITION_LOADLIBRARY 1 + +#define UE_UNPACKER_CONDITION_GETPROCADDRESS 2 + +#define UE_UNPACKER_CONDITION_ENTRYPOINTBREAK 3 + +#define UE_UNPACKER_CONDITION_RELOCSNAPSHOT1 4 + +#define UE_UNPACKER_CONDITION_RELOCSNAPSHOT2 5 + + + + + EngineUnpackerInitialize function + +EngineUnpackerInitialize initializes simplified unpacking routines. Initialization creates an unpacking +process for any provided input portable executable be it EXE or DLL. + +Syntax + + + +void __stdcall EngineUnpackerInitialize( + +char* szFileName, + +char* szUnpackedFileName, + +bool DoLogData, + +bool DoRealignFile, + +bool DoMoveOverlay, + +void* EntryCallBack + +); + + + + + + + + + +Parameters + +szFileName + + [in] Pointer to the full path of the file to debug. + +szUnpackedFileName + + [in] Pointer to the full path of the file which will be created as the end result of the +unpacking process. + +DoLogData + + [in] Enables or disable automatic data logging. + +DoRealignFile + + [in] Enables or disables file realigning at the end of the unpacking process. + +DoMoveOverlay + + [in] Enables or disables overlay moving from original to the unpacked file at the end of +the unpacking process. + +EntryCallBack + + [in] Callback which will be called once the file reaches its packed entry point. + + + +Return value + +Boolean switch indicating whether or not the function was successful. + +Example + +None. + + + + + + + EngineUnpackerSetBreakCondition function + +EngineUnpackerSetBreakCondition function searches the debugee memory and sets breakpoints for +selected patterns. + +Syntax + + + +bool __stdcall EngineUnpackerSetBreakCondition( + +void* SearchStart, + +DWORD SearchSize, + +void* SearchPattern, + +DWORD PatternSize, + +DWORD PatternDelta, + +ULONG_PTR BreakType, + +bool SingleBreak, + +DWORD Parameter1, + +DWORD Parameter2 + +); + + + + + + + + + + + +Parameters + +SearchStart + + [in] Indicates the point in memory from which search will be performed. + +SearchSize + + [in] Size of the memory to search. + +SearchPattern + + [in] Pointer to pattern to be searched. + +PatternDelta + + [in] On successfully found pattern its offset is affected by delta value. This helps to set +the breakpoint on any byte relative to the found pattern. This variable is a signed +integer which means that delta can be negative value as well. + +BreakType + + [in] Callback address which will be called once the breakpoint has been hit. This is a +default breakpoint callback type. Additionally following values are considered valid: + +. UE_UNPACKER_CONDITION_LOADLIBRARY +. UE_UNPACKER_CONDITION_GETPROCADDRESS +. UE_UNPACKER_CONDITION_ENTRYPOINTBREAK +. UE_UNPACKER_CONDITION_RELOCSNAPSHOT1 +. UE_UNPACKER_CONDITION_RELOCSNAPSHOT2 + + + + + + + +SingleBreak + + [in] Boolean switch indicating whether or not the breakpoint will be used only once. + +Parametar1 + + [in] If you use predefined values as your BreakType Parameter1 indicates the following +data will be used by the TitanEngine when breakpoints are processed: + +. LoadLibrary +o Parameter1 is the register (UE_EAX . UE_EDI) which points to the +remote DLL name string. + + +. GetProcAddress +o Parameter1 is the register (UE_EAX . UE_EDI) which points to the +remote API name string or contains API ordinal number. Difference +between the two is automatically detected. + + +. EntryPointBreak +o Parameter1 is unused. + + +. RelocateSnapshot1 +o Relative virtual address from which the memory snapshot will start. + + +. RelocateSnapshot2 +o Relative virtual address from which the memory snapshot will start. + + + + +Parametar2 + + [in] If you use predefined values as your BreakType Parameter2 indicates the following +data will be used by the TitanEngine when breakpoints are processed: + +. LoadLibrary +o Parameter2 is the register (UE_EAX . UE_EDI) which holds the first +import trunk address. This is optional and can be set to NULL. + + +. GetProcAddress +o Parameter2 is the register (UE_EAX . UE_EDI) which holds the API write +location. + + +. EntryPointBreak +o Parameter2 is unused. + + +. RelocateSnapshot1 +o Size of the memory to snapshot. + + +. RelocateSnapshot2 +o Size of the memory to snapshot. + + + + + + + + + +Return value + +Boolean switch indicating whether or not the function was successful in finding the selected +pattern and placing the breakpoint there. + +Remarks + +For simplification to work correctly you must define LoadLibrary, GetProcAddress and entry +point breakpoints as a minimum of functionality. + +If relocation snapshot two isn’t defined second snapshot is automatically performed once the +entry point breakpoint is hit. + +If you don’t set the original entry point and use the default entry point callback EIP/RIP address +will be used to set that data. + +Example + +None. + + + + + + + EngineUnpackerSetEntryPointAddress function + +EngineUnpackerSetEntryPointAddress sets the original entry point address. This function is used if +breaking at the original entry point isn’t possible and the address of the original entry point must be +read by the program. + +Syntax + + + +void __stdcall EngineUnpackerSetEntryPointAddress( + +ULONG_PTR UnpackedEntryPointAddress + +); + + + + + + + + + +Parameters + +UnpackedEntryPointAddress + + [in] Sets the original entry point before the unpacking finalization. + + + +Return value + +None. + +Example + +None. + + + + + + + EngineUnpackerFinalizeUnpacking function + +EngineUnpackerFinalizeUnpacking finalizes the unpacking process performing the memory dumping +and image fixing procedures. This function should only be called if EngineUnpackerSetEntryPointAddress +calling was necessary. + +Syntax + + + +void __stdcall EngineUnpackerFinalizeUnpacking(); + + + + + + + + + +Parameters + +None. + + + +Return value + +None. + +Example + +None. + + + + + + + + + TitanEngine 2.0.1 - history + +. SDK +o Extended SDK headers to support Delphi +o Changes to SDK.h to support non MSVC compilers +o Changed the file/folder layout and fixed relative paths in RC file +o Removed type-o mistakes and bad function definitions + + +. Bug fixes +o Fixed some mistakes in SDK.h +o Added missing entries in TitanEngine.def +o FindEx searched only 0x1000 bytes +o Fixed a minor bug inside injectTerminator +o EngineExtractForwarderData crash on invalid input +o RelocaterGrabRelocationTableEx doesn't grab whole table +o RelocaterCompareTwoSnapshots crash when first DWORD of the snapshot is relocated +o RelocaterCompareTwoSnapshots doesn't correctly compare two snapshots for some packers +o ImporterAutoFixIATEx very rare crash handled by handler but it makes import table invalid +o ImporterAutoFixIATEx incorrect import fixing if import is only exported by ordinal +o ImporterAutoFixIATEx incorrect stepping if step is greater than one +o Fixed StaticLoadFile & StaticUnloadFile to be compatible with x64 +o Fixed a problem with imports and WinSxS folder +o Fixed a crash with Librarian on Windows XP x64 +o Fixed problem with NtdllDefWindowProc on Vista x64 +o Fixed problem with deleting temp files: DLLLoader.exe & *.module base reserve file +o Fixed problem with DumpProcess on x64 systems +o Fixed problem with DumpProcess and empty last PE sections +o Fixed problem with DumpProcess and files with non default SectionAlignment +o Fixed problem with DumpProcess and dumping PAGE_GUARD protected memory +o Fixed UPX unpacker sample not working on files packed with --lzma option +o Fixed problem with Exporter module and building new export table under x64 systems +o Fixed problem with Importer module and Windows 7 kernelbase.dll MiniWin +o Fixed problem with RealignPE/RealignPEEx and files with non default SectionAlignment + + +. Additions +o Fill & FillEx now have a default fill byte value of 0x90 if no fill byte is supplied +o SetHardwareBreakPointEx function for setting breakpoints in custom threads +o Global variable UE_ENGINE_RESET_CUSTOM_HANDLER set to TRUE resetting custom handler on debug init +o Improved speed of API & DLL data resolving +o Added function: ImporterAddNewOrdinalAPI +o Added function: ImporterGetAPIOrdinalNumber +o Added function: ImporterGetAPIOrdinalNumberFromDebugee +o Added function: ImporterGetForwardedAPIOrdinalNumber +o Added function: ImporterGetLastAddedDLLName +o Added function: ImporterGetDLLName +o Added function: GetUnusedHardwareBreakPointRegister +o Changed function: HideDebugger, less parameters and x64 compliant +o Added function: UnHideDebugger +o Added function: GetPEBLocation + + +. Samples +o Unpacking ASPack 2.12, features usage of: RelocaterGrabRelocationTableEx and GetRemoteString +o Unpacking FSG 2.0, features usage of: overlay detection +o Unpacking PeCompact 2.0 - 3.x, features usage of: ImporterAutoFixIATEx with custom callback for fixing redirection +o Unpacking DEF 1.0, features usage of: static unpacker functions +o Unpacking LameCrypt 1.0, features usage of: static unpacker functions + + + + + + + + TitanEngine 2.0.2 - history + +. SDK/PDK +o Added functions to support UNICODE +o Extended SDK headers to support MASM32 +o Changes to SDK.h to support non MSVC compilers, Set default structure align to: 1 byte +o Removed type-o mistakes and bad function definitions + + +. Bug fixes +o Fixed some mistakes in SDK.h +o Fixed a bug in SetPE32DataForMappedFile +o Fixed a bug with import processing and Windows7 x64 +o Fixed a bug in PastePEHeader which made it not work on x64 +o Fixed a bug in PastePEHeader which prevented header paste when header doesn't have write attribute +o Fixed a rare disassemble crash which happened due to distorm not having enough space +o Fixed problem with GetPE32DataFromMappedFileEx and x64 +o Fixed a rare problem with FindEx and some memory ranges +o Fixed a bug inside LibrarianGetLibraryInfoEx + + +. Additions +o Added functions +. RelocaterRelocateMemoryBlock, ThreaderImportRunningThreadData, EngineFakeMissingDependencies +. EngineDeleteCreatedDependencies, EngineCreateMissingDependencies, EngineCreateMissingDependenciesW +. ExtensionManagerIsPluginLoaded, ExtensionManagerIsPluginEnabled, ExtensionManagerDisablePlugin +. ExtensionManagerDisableAllPlugins, ExtensionManagerEnablePlugin, ExtensionManagerEnableAllPlugins +. ExtensionManagerUnloadPlugin, ExtensionManagerUnloadAllPlugins, ExtensionManagerGetPluginInfo +. HooksSafeTransition, HooksSafeTransitionEx, HooksIsAddressRedirected, HooksGetTrampolineAddress +. HooksGetHookEntryDetails, HooksInsertNewRedirection, HooksInsertNewIATRedirection +. HooksInsertNewIATRedirectionEx, HooksRemoveRedirection, HooksRemoveRedirectionsForModule +. HooksRemoveIATRedirection, HooksDisableRedirection, HooksDisableRedirectionsForModule +. HooksDisableIATRedirection, HooksEnableRedirection, HooksEnableRedirectionsForModule +. HooksEnableIATRedirection, HooksScanModuleMemory, HooksScanEntireProcessMemory +. HooksScanEntireProcessMemoryEx, StaticRawMemoryCopy, StaticMemoryDecompress, +. StaticMemoryDecryptSpecial, ResourcerFindResource, ResourcerEnumerateResource, +. StaticHashMemory, StaticHashFile, IsFileBeingDebugged + + +o Added TitaniumHooks as a module and a separate project + + +. Samples +o Samples of using Hooks module: HooksDemo and LoaderSpy +o Plugin samples +. TitanEngine: ASMExtractor, DataExtractor, lynxImpRec & Nexus +. OllyDBG: TitaniumHandles & ImportStudio +. PeID: TitaniumOverlay + + +o Tool samples +. LameCrypter + + +o Unpacker samples +. C +. MarioPack, CryptoCrackPE, ExeFog, MEW, PackMan, nPack, yC + + +. Delphi +. MEW 5, PeX + + +. MASM +. UPX + + + + + + + + + + + + + + + + + + TitanEngine 2.0.3 - history + +. SDK/PDK +o Extended SDK headers to support Python, LUA and C++ +o Removed type-o mistakes and bad function definitions +o Documented missing functions + + +. Bug fixes +o Fixed a bug inside Find/Ex +o Fixed a bug fix inside EngineSimulateNtLoaderW +o Enabled code execution inside mapped images loaded with all access +o Fixed a bug in SetPE32Data/W which prevented data update due to incorrect file access +o Fixed a bug inside ConvertVAtoFileOffset/Ex which incorrectly converted addresses in some cases +o Multiple changes inside IsPE32FileValidEx/W making it compatible with Microsoft compilers +o Multiple changes inside FixBrokenPE32FileEx/W making it compatible with Microsoft compilers +o Fixed a bug inside debugging logic that causes the debugger to handle hardware breakpoints set by the debugee +o Fixed a bug inside StepOver making it unsafe to execute with self modifying code with multi byte breakpoints turned on +o Fixed a bug inside StepInto making it execute one time more than specified by the program +o Added an option to select the type of breakpoint set with SetBPX and SetBPXEx +o Implemented UD2 breakpoints correctly inside debugging logic +o Fixed a bug inside ImporterAddNewAPI with ordinal logic +o Improved the accuracy of ImporterEstimatedSize function +o Improved ImporterFindAPIWriteLocation to take ordinals into the account +o Fixed a bug inside ImporterRelocateWriteLocation and cases of single imported DLL file +o Fixed a bug inside ImporterLoadImportTableW with certain compilers +o Improved ImporterEnumAdded data to take ordinals into the account +o Fixed a bug in HooksInsertNewIATRedirectionEx with certain compilers +o Fixed a bug inside RemoteLoadLibraryW making it fail with DEP turned on +o Fixed a bug inside RemoteFreeLibrary making it fail with DEP turned on +o Fixed a bug inside RemoteExitProcess making it fail with DEP turned on +o Fixed a bug inside StaticRawMemoryCopyW preventing it from copying all data +o Fixed a bug inside DetachDebuggerEx that crashed the debugee upon detaching + + +. Additions +o Added functionality +. Added GUI interface for unpackers +. Added unpacker simplification functions + + +o Added functions +. GetContextFPUDataEx, SetContextFPUDataEx, MatchPatternEx, MatchPattern +. SetErrorModel, ImporterFindOrdinalAPIWriteLocation, ImporterIsForwardedAPI +. StaticFileOpen, StaticFileGetContent, StaticRawMemoryCopyEx64, StaticFileClose +. EngineCreateUnpackerWindow, EngineAddUnpackerWindowLogMessage + + + + +. Samples +o Tool samples +. LameCrypt, PEValidate + + +o Unpacker samples +. C +. tELock, AHPack, AlexProtector, UPX (simplified) and FSG (simplified), DEB + + +. Python +. FSG, UPX, LameCrypt + + +. LUA +. UPX + + + + + + + + + +C:\masm32\UnpackEngine\bit9\ENGINE-Cpp\UE 1.5\SDK\Manual\lgpl.gif + + +License + + GNU LESSER GENERAL PUBLIC LICENSE +Version 3, 29 June 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + + +This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + +0. Additional Definitions. + +As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + +"The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + +An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + +A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + +The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + +The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + + + + + +1. Exception to Section 3 of the GNU GPL. + +You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + +2. Conveying Modified Versions. + +If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + +a) under this License, provided that you make a good faith effort to +ensure that, in the event an Application does not supply the +function or data, the facility still operates, and performs +whatever part of its purpose remains meaningful, or + +b) under the GNU GPL, with none of the additional permissions of +this License applicable to that copy. + +3. Object Code Incorporating Material from Library Header Files. + +The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + +a) Give prominent notice with each copy of the object code that the +Library is used in it and that the Library and its use are +covered by this License. + +b) Accompany the object code with a copy of the GNU GPL and this license +document. + +4. Combined Works. + +You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + + + + + +a) Give prominent notice with each copy of the Combined Work that +the Library is used in it and that the Library and its use are +covered by this License. + +b) Accompany the Combined Work with a copy of the GNU GPL and this license +document. + +c) For a Combined Work that displays copyright notices during +execution, include the copyright notice for the Library among +these notices, as well as a reference directing the user to the +copies of the GNU GPL and this license document. + +d) Do one of the following: + +0) Convey the Minimal Corresponding Source under the terms of this +License, and the Corresponding Application Code in a form +suitable for, and under terms that permit, the user to +recombine or relink the Application with a modified version of +the Linked Version to produce a modified Combined Work, in the +manner specified by section 6 of the GNU GPL for conveying +Corresponding Source. + +1) Use a suitable shared library mechanism for linking with the +Library. A suitable mechanism is one that (a) uses at run time +a copy of the Library already present on the user's computer +system, and (b) will operate properly with a modified version +of the Library that is interface-compatible with the Linked +Version. + +e) Provide Installation Information, but only if you would otherwise +be required to provide such information under section 6 of the +GNU GPL, and only to the extent that such information is +necessary to install and execute a modified version of the +Combined Work produced by recombining or relinking the +Application with a modified version of the Linked Version. (If +you use option 4d0, the Installation Information must accompany +the Minimal Corresponding Source and Corresponding Application +Code. If you use option 4d1, you must provide the Installation +Information in the manner specified by section 6 of the GNU GPL +for conveying Corresponding Source.) + +5. Combined Libraries. + +You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + + + +a) Accompany the combined library with a copy of the same work based +on the Library, uncombined with any other library facilities, +conveyed under the terms of this License. + +b) Give prominent notice with the combined library that part of it +is a work based on the Library, and explaining where to find the +accompanying uncombined form of the same work. + +6. Revised Versions of the GNU Lesser General Public License. + +The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + +If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + + diff --git a/x64_dbg_dbg/TitanEngine/TitanEngine_x64.a b/x64_dbg_dbg/TitanEngine/TitanEngine_x64.a new file mode 100644 index 00000000..ae802a80 Binary files /dev/null and b/x64_dbg_dbg/TitanEngine/TitanEngine_x64.a differ diff --git a/x64_dbg_dbg/TitanEngine/TitanEngine_x64.lib b/x64_dbg_dbg/TitanEngine/TitanEngine_x64.lib new file mode 100644 index 00000000..64ef6720 Binary files /dev/null and b/x64_dbg_dbg/TitanEngine/TitanEngine_x64.lib differ diff --git a/x64_dbg_dbg/TitanEngine/TitanEngine_x86.a b/x64_dbg_dbg/TitanEngine/TitanEngine_x86.a new file mode 100644 index 00000000..cf232ee8 Binary files /dev/null and b/x64_dbg_dbg/TitanEngine/TitanEngine_x86.a differ diff --git a/x64_dbg_dbg/TitanEngine/TitanEngine_x86.lib b/x64_dbg_dbg/TitanEngine/TitanEngine_x86.lib new file mode 100644 index 00000000..0a720297 Binary files /dev/null and b/x64_dbg_dbg/TitanEngine/TitanEngine_x86.lib differ diff --git a/x64_dbg_dbg/_exports.cpp b/x64_dbg_dbg/_exports.cpp new file mode 100644 index 00000000..e17a8fd8 --- /dev/null +++ b/x64_dbg_dbg/_exports.cpp @@ -0,0 +1,242 @@ +#include "_exports.h" +#include "memory.h" +#include "debugger.h" +#include "value.h" +#include "addrinfo.h" + +extern "C" DLL_EXPORT duint _dbg_memfindbaseaddr(duint addr, duint* size) +{ + return memfindbaseaddr(fdProcessInfo->hProcess, addr, size); +} + +extern "C" DLL_EXPORT bool _dbg_memread(duint addr, unsigned char* dest, duint size, duint* read) +{ + dbgdisablebpx(); + bool res=memread(fdProcessInfo->hProcess, (void*)addr, dest, size, read); + dbgenablebpx(); + return res; +} + +extern "C" DLL_EXPORT bool _dbg_memmap(MEMMAP* memmap) +{ + memset(memmap, 0, sizeof(MEMMAP)); + + MEMORY_BASIC_INFORMATION mbi; + DWORD numBytes; + uint MyAddress=0, newAddress=0; + SymInitialize(fdProcessInfo->hProcess, 0, true); + std::vector pageVector; + do + { + numBytes=VirtualQueryEx(fdProcessInfo->hProcess, (LPCVOID)MyAddress, &mbi, sizeof(mbi)); + if(mbi.State==MEM_COMMIT) + { + MEMPAGE curPage; + IMAGEHLP_MODULE64 nfo; + nfo.SizeOfStruct=sizeof(IMAGEHLP_MODULE64); + if(SymGetModuleInfo64(fdProcessInfo->hProcess, MyAddress, &nfo)) + memcpy(curPage.mod, nfo.ModuleName, sizeof(curPage.mod)); + else + memset(curPage.mod, 0, sizeof(curPage.mod)); + memcpy(&curPage.mbi, &mbi, sizeof(mbi)); + pageVector.push_back(curPage); + memmap->count++; + } + newAddress=(uint)mbi.BaseAddress+mbi.RegionSize; + if(newAddress<=MyAddress) + numBytes=0; + else + MyAddress=newAddress; + } + while(numBytes); + + //process vector + int pagecount=memmap->count; + memmap->page=(MEMPAGE*)BridgeAlloc(sizeof(MEMPAGE)*pagecount); + memset(memmap->page, 0, sizeof(MEMPAGE)*pagecount); + for(int i=0; ipage[i], &pageVector.at(i), sizeof(MEMPAGE)); + + return true; +} + +extern "C" DLL_EXPORT void _dbg_dbgexitsignal() +{ + //TODO: handle exit signal + cbStopDebug(""); + Sleep(200); + DeleteFileA("DLLLoader.exe"); +} + +extern "C" DLL_EXPORT bool _dbg_valfromstring(const char* string, duint* value) +{ + return valfromstring(string, value, 0, 0, true, 0); +} + +extern "C" DLL_EXPORT bool _dbg_isdebugging() +{ + return IsFileBeingDebugged(); +} + +extern "C" DLL_EXPORT bool _dbg_isjumpgoingtoexecute(duint addr) +{ + static unsigned int cacheFlags; + static uint cacheAddr; + static bool cacheResult; + if(cacheAddr!=addr or cacheFlags!=GetContextData(UE_EFLAGS)) + { + cacheFlags=GetContextData(UE_EFLAGS); + cacheAddr=addr; + cacheResult=IsJumpGoingToExecuteEx(fdProcessInfo->hProcess, fdProcessInfo->hThread, (ULONG_PTR)cacheAddr, cacheFlags); + } + return cacheResult; +} + +extern "C" DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, ADDRINFO* addrinfo) +{ + bool retval=false; + if(addrinfo->flags&module) //get module + { + char module[64]=""; + if(modnamefromaddr(addr, module) and strlen(module)<32) //get module name + { + strcpy(addrinfo->module, module); + retval=true; + } + } + if(addrinfo->flags&label) //TODO: get label + { + //TODO: label exports + } + if(addrinfo->flags&comment) //TODO: get comment + { + //TODO: auto-comments + } + return retval; +} + +extern "C" DLL_EXPORT bool _dbg_addrinfoset(duint addr, ADDRINFO* addrinfo) +{ + return false; +} + +extern "C" DLL_EXPORT BPXTYPE _dbg_bpgettypeat(duint addr) +{ + BREAKPOINT* found=bpfind(bplist, 0, addr, 0, BPNOTYPE); + if(!found or !found->enabled) //none found or disabled + return bpnone; + switch(found->type) + { + case BPNORMAL: + case BPSINGLESHOOT: + return bpnormal; + case BPHARDWARE: + return bphardware; + case BPMEMORY: + return bpmemory; + default: + break; + } + return bpnone; +} + +extern "C" DLL_EXPORT bool _dbg_getregdump(REGDUMP* regdump) +{ + if(!IsFileBeingDebugged()) + { + memset(regdump, 0, sizeof(REGDUMP)); + return true; + } + REGDUMP r; +#ifdef _WIN64 + r.cax=GetContextData(UE_RAX); +#else + r.cax=(duint)GetContextData(UE_EAX); +#endif // _WIN64 +#ifdef _WIN64 + r.ccx=GetContextData(UE_RCX); +#else + r.ccx=(duint)GetContextData(UE_ECX); +#endif // _WIN64 +#ifdef _WIN64 + r.cdx=GetContextData(UE_RDX); +#else + r.cdx=(duint)GetContextData(UE_EDX); +#endif // _WIN64 +#ifdef _WIN64 + r.cbx=GetContextData(UE_RBX); +#else + r.cbx=(duint)GetContextData(UE_EBX); +#endif // _WIN64 +#ifdef _WIN64 + r.cbp=GetContextData(UE_RBP); +#else + r.cbp=(duint)GetContextData(UE_EBP); +#endif // _WIN64 +#ifdef _WIN64 + r.csi=GetContextData(UE_RSI); +#else + r.csi=(duint)GetContextData(UE_ESI); +#endif // _WIN64 +#ifdef _WIN64 + r.cdi=GetContextData(UE_RDI); +#else + r.cdi=(duint)GetContextData(UE_EDI); +#endif // _WIN64 +#ifdef _WIN64 + r.r8=GetContextData(UE_R8); +#endif // _WIN64 +#ifdef _WIN64 + r.r9=GetContextData(UE_R9); +#endif // _WIN64 +#ifdef _WIN64 + r.r10=GetContextData(UE_R10); +#endif // _WIN64 +#ifdef _WIN64 + r.r11=GetContextData(UE_R11); +#endif // _WIN64 +#ifdef _WIN64 + r.r12=GetContextData(UE_R12); +#endif // _WIN64 +#ifdef _WIN64 + r.r13=GetContextData(UE_R13); +#endif // _WIN64 +#ifdef _WIN64 + r.r14=GetContextData(UE_R14); +#endif // _WIN64 +#ifdef _WIN64 + r.r15=GetContextData(UE_R15); +#endif // _WIN64 + r.csp=(duint)GetContextData(UE_CSP); + r.cip=(duint)GetContextData(UE_CIP); + r.eflags=(duint)GetContextData(UE_EFLAGS); + r.gs=(unsigned short)(GetContextData(UE_SEG_GS)&0xFFFF); + r.fs=(unsigned short)(GetContextData(UE_SEG_FS)&0xFFFF); + r.es=(unsigned short)(GetContextData(UE_SEG_ES)&0xFFFF); + r.ds=(unsigned short)(GetContextData(UE_SEG_DS)&0xFFFF); + r.cs=(unsigned short)(GetContextData(UE_SEG_CS)&0xFFFF); + r.ss=(unsigned short)(GetContextData(UE_SEG_SS)&0xFFFF); + r.dr0=(duint)GetContextData(UE_DR0); + r.dr1=(duint)GetContextData(UE_DR1); + r.dr2=(duint)GetContextData(UE_DR2); + r.dr3=(duint)GetContextData(UE_DR3); + r.dr6=(duint)GetContextData(UE_DR6); + r.dr7=(duint)GetContextData(UE_DR7); + duint cflags=r.eflags; + r.flags.c=valflagfromstring(cflags, "cf"); + r.flags.p=valflagfromstring(cflags, "pf"); + r.flags.a=valflagfromstring(cflags, "af"); + r.flags.z=valflagfromstring(cflags, "zf"); + r.flags.s=valflagfromstring(cflags, "sf"); + r.flags.t=valflagfromstring(cflags, "tf"); + r.flags.i=valflagfromstring(cflags, "if"); + r.flags.d=valflagfromstring(cflags, "df"); + r.flags.o=valflagfromstring(cflags, "of"); + memcpy(regdump, &r, sizeof(REGDUMP)); + return true; +} + +extern "C" DLL_EXPORT bool _dbg_valtostring(const char* string, duint* value) +{ + return valtostring(string, value, true); +} diff --git a/x64_dbg_dbg/_exports.h b/x64_dbg_dbg/_exports.h new file mode 100644 index 00000000..2af56efb --- /dev/null +++ b/x64_dbg_dbg/_exports.h @@ -0,0 +1,28 @@ +#ifndef _EXPORTS_H +#define _EXPORTS_H + +#include "_global.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +DLL_EXPORT duint _dbg_memfindbaseaddr(duint addr, duint* size); +DLL_EXPORT bool _dbg_memread(duint addr, unsigned char* dest, duint size, duint* read); +DLL_EXPORT bool _dbg_memmap(MEMMAP* memmap); +DLL_EXPORT void _dbg_dbgexitsignal(); +DLL_EXPORT bool _dbg_valfromstring(const char* string, duint* value); +DLL_EXPORT bool _dbg_isdebugging(); +DLL_EXPORT bool _dbg_isjumpgoingtoexecute(duint addr); +DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, ADDRINFO* addrinfo); +DLL_EXPORT bool _dbg_addrinfoset(duint addr, ADDRINFO* addrinfo); +DLL_EXPORT BPXTYPE _dbg_bpgettypeat(duint addr); +DLL_EXPORT bool _dbg_getregdump(REGDUMP* regdump); +DLL_EXPORT bool _dbg_valtostring(const char* string, duint* value); + +#ifdef __cplusplus +} +#endif + +#endif // _EXPORTS_H diff --git a/x64_dbg_dbg/_global.cpp b/x64_dbg_dbg/_global.cpp new file mode 100644 index 00000000..9174f1e5 --- /dev/null +++ b/x64_dbg_dbg/_global.cpp @@ -0,0 +1,127 @@ +#include "_global.h" + +HINSTANCE hInst; + +void* emalloc(size_t size) +{ + unsigned char* a=new unsigned char[size+0x1000]; + if(!a) + { + MessageBoxA(0, "Could not allocate memory", "Error", MB_ICONERROR); + ExitProcess(1); + } + memset(a, 0, size); + return a; +} + +void efree(void* ptr) +{ + delete[] (unsigned char*)ptr; +} + +bool arraycontains(const char* cmd_list, const char* cmd) +{ + if(!cmd_list or !cmd) + return false; + char temp[deflen]=""; + strcpy(temp, cmd_list); + int len=strlen(cmd_list); + for(int i=0; i=path_size) + return false; + sprintf(path, "%s%s", curDrive, devicepath+curDevice_len); + return true; + } + } + return false; +} + +bool PathToDevicePath(const char* path, char* devicepath, size_t devicepath_size) +{ + if(!path or path[1]!=':' or !devicepath) + return false; + char curDrive[3]=" :"; + char curDevice[MAX_PATH]=""; + *curDrive=*path; + if(!QueryDosDeviceA(curDrive, curDevice, MAX_PATH)) + return false; + if(strlen(path)-2+strlen(curDevice)>=devicepath_size) + return false; + sprintf(devicepath, "%s%s", curDevice, path+2); + return true; +} diff --git a/x64_dbg_dbg/_global.h b/x64_dbg_dbg/_global.h new file mode 100644 index 00000000..1c85acbb --- /dev/null +++ b/x64_dbg_dbg/_global.h @@ -0,0 +1,106 @@ +#ifndef _GLOBAL_H +#define _GLOBAL_H + +#define _WIN32_WINNT 0x0501 +#define WINVER 0x0501 +#define _WIN32_IE 0x0500 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "..\x64_dbg_bridge\bridgemain.h" + +#ifdef __GNUC__ +#include "dbghelp\dbghelp.h" +#else +#include +#endif //__GNUC__ + +#ifndef __GNUC__ +#define and && +#define or || +#endif + +#ifndef DLL_EXPORT +#define DLL_EXPORT __declspec(dllexport) +#endif //DLL_IMPORT +#ifndef DLL_IMPORT +#define DLL_IMPORT __declspec(dllimport) +#endif //DLL_IMPORT + +#include "dbg.h" + +//defines +#define deflen 1024 + +#ifdef _WIN64 //defined by default +#define fhex "%.16llX" +#define fext "ll" +typedef unsigned long long uint; +typedef long long sint; +#else +#define fhex "%.8X" +#define fext "" +typedef unsigned long uint; +typedef long sint; +#endif // _WIN64 + +enum BITMASK +{ + BIT1=0x1, + BIT2=0x2, + BIT3=0x4, + BIT4=0x8, + BIT5=0x10, + BIT6=0x20, + BIT7=0x40, + BIT8=0x80, + BIT9=0x100, + BIT10=0x200, + BIT11=0x400, + BIT12=0x800, + BIT13=0x1000, + BIT14=0x2000, + BIT15=0x4000, + BIT16=0x8000, + BIT17=0x10000, + BIT18=0x20000, + BIT19=0x40000, + BIT20=0x80000, + BIT21=0x100000, + BIT22=0x200000, + BIT23=0x400000, + BIT24=0x800000, + BIT25=0x1000000, + BIT26=0x2000000, + BIT27=0x4000000, + BIT28=0x8000000, + BIT29=0x10000000, + BIT30=0x20000000, + BIT31=0x40000000, + BIT32=0x80000000 +}; + +//superglobal variables +extern HINSTANCE hInst; + +//functions +void* emalloc(size_t size); +void efree(void* ptr); +bool arraycontains(const char* cmd_list, const char* cmd); +bool scmp(const char* a, const char* b); +void formathex(char* string); +void formatdec(char* string); +bool FileExists(const char* file); +bool DirExists(const char* dir); +bool DevicePathToPath(const char* devicepath, char* path, size_t path_size); +bool PathToDevicePath(const char* path, char* devicepath, size_t devicepath_size); + +#endif // _GLOBAL_H diff --git a/x64_dbg_dbg/addrinfo.cpp b/x64_dbg_dbg/addrinfo.cpp new file mode 100644 index 00000000..33652c85 --- /dev/null +++ b/x64_dbg_dbg/addrinfo.cpp @@ -0,0 +1,14 @@ +#include "addrinfo.h" +#include "debugger.h" + +bool modnamefromaddr(uint addr, char* modname) +{ + IMAGEHLP_MODULE64 modInfo; + memset(&modInfo, 0, sizeof(modInfo)); + modInfo.SizeOfStruct=sizeof(IMAGEHLP_MODULE64); + if(!SymGetModuleInfo64(fdProcessInfo->hProcess, (DWORD64)addr, &modInfo) or !modname) + return false; + _strlwr(modInfo.ModuleName); + strcpy(modname, modInfo.ModuleName); + return true; +} diff --git a/x64_dbg_dbg/addrinfo.h b/x64_dbg_dbg/addrinfo.h new file mode 100644 index 00000000..18e20453 --- /dev/null +++ b/x64_dbg_dbg/addrinfo.h @@ -0,0 +1,8 @@ +#ifndef _ADDRINFO_H +#define _ADDRINFO_H + +#include "_global.h" + +bool modnamefromaddr(uint addr, char* modname); + +#endif // _ADDRINFO_H diff --git a/x64_dbg_dbg/argument.cpp b/x64_dbg_dbg/argument.cpp new file mode 100644 index 00000000..3ae22f2a --- /dev/null +++ b/x64_dbg_dbg/argument.cpp @@ -0,0 +1,249 @@ +#include "argument.h" +#include "console.h" + +/* +formatarg: +01) remove prepended spaces +02) get command (first space) and lowercase +03) get arguments +04) remove double quotes (from arguments) +05) temp. remove double backslash +06) remove prepended/appended non-escaped commas and spaces (from arguments) + a) prepended + b) appended +07) get quote count, ignore escaped (from arguments) +08) process quotes (from arguments): + a) zero quotes + b) restore double backslash + c) escape commas and spaces +09) temp. remove double backslash +10) remove unescaped double commas (from arguments) +11) remove unescaped spaces (from arguments) +12) restore double backslash +13) combine formatted arguments and command +*/ +void argformat(char* cmd) +{ + char command_[deflen]=""; + char* command=command_; + strcpy(command, cmd); + while(*command==' ') + command++; + int len=strlen(command); + int start=0; + for(int i=0; iargcount) + { + if(!optional) + dprintf("missing argument nr %d\n", arg_num+1); + return false; + } + int len=strlen(cmd); + int start=0; + while(cmd[start]!=' ') + start++; + while(cmd[start]==' ') + start++; + char temp[deflen]=""; + strcpy(temp, cmd+start); + len=strlen(temp); + for(int i=0; inext; + bpdel(breakpoint_list, 0, cur->addr, BPNORMAL); + cur=next; + if(!cur) + bNext=false; + } + BREAKPOINT* bp; + if(!breakpoint_list) + bp=(BREAKPOINT*)emalloc(sizeof(BREAKPOINT)); + else + bp=breakpoint_list; + memset(bp, 0, sizeof(BREAKPOINT)); + return bp; +} + +BREAKPOINT* bpfind(BREAKPOINT* breakpoint_list, const char* name, uint addr, BREAKPOINT** link, BP_TYPE type) +{ + BREAKPOINT* cur=breakpoint_list; + if(!cur or !cur->addr) + return 0; + BREAKPOINT* prev=0; + while(cur) + { + BP_TYPE bptype=cur->type; + if(bptype==BPSINGLESHOOT) + bptype=BPNORMAL; + BP_TYPE realtype=type; + if(realtype==BPSINGLESHOOT) + realtype=BPNORMAL; + if(((name and arraycontains(cur->name, name)) or cur->addr==addr) and (type==BPNOTYPE or bptype==realtype)) + { + if(link) + *link=prev; + return cur; + } + prev=cur; + cur=cur->next; + } + return 0; +} + +bool bpnew(BREAKPOINT* breakpoint_list, const char* name, uint addr, short oldbytes, BP_TYPE type) +{ + if(!breakpoint_list or !addr or bpfind(breakpoint_list, name, addr, 0, type)) + return false; + BREAKPOINT* bp; + bool nonext=false; + if(!breakpoint_list->addr) + { + bp=breakpoint_list; + nonext=true; + } + else + bp=(BREAKPOINT*)emalloc(sizeof(BREAKPOINT)); + memset(bp, 0, sizeof(BREAKPOINT)); + if(name and *name) + { + bp->name=(char*)emalloc(strlen(name)+1); + strcpy(bp->name, name); + } + bp->addr=addr; + bp->type=type; + bp->oldbytes=oldbytes; + bp->enabled=true; + BREAKPOINT* cur=breakpoint_list; + if(!nonext) + { + while(cur->next) + cur=cur->next; + cur->next=bp; + } + return true; +} + +bool bpsetname(BREAKPOINT* breakpoint_list, uint addr, const char* name) +{ + //TODO: fix this BPNOTYPE, it's bullshit + if(!name or !*name or !addr or bpfind(breakpoint_list, name, 0, 0, BPNOTYPE)) + return false; + BREAKPOINT* found=bpfind(breakpoint_list, 0, addr, 0, BPNOTYPE); + if(!found) + return false; + efree(found->name); //free previous name + found->name=(char*)emalloc(strlen(name)+1); + strcpy(found->name, name); + return true; +} + +bool bpdel(BREAKPOINT* breakpoint_list, const char* name, uint addr, BP_TYPE type) +{ + BREAKPOINT* prev=0; + BREAKPOINT* found=bpfind(breakpoint_list, name, addr, &prev, type); + if(!found) + return false; + if(found->name) + efree(found->name); + if(found==breakpoint_list) + { + BREAKPOINT* next=breakpoint_list->next; + if(next) + { + memcpy(breakpoint_list, breakpoint_list->next, sizeof(BREAKPOINT)); + breakpoint_list->next=next->next; + efree(next); + } + else + memset(breakpoint_list, 0, sizeof(BREAKPOINT)); + } + else + { + prev->next=found->next; + efree(found); + } + return true; +} diff --git a/x64_dbg_dbg/breakpoint.h b/x64_dbg_dbg/breakpoint.h new file mode 100644 index 00000000..c1a8104c --- /dev/null +++ b/x64_dbg_dbg/breakpoint.h @@ -0,0 +1,35 @@ +#ifndef _BREAKPOINT_H +#define _BREAKPOINT_H + +#include "_global.h" +#include "TitanEngine\TitanEngine.h" + +//enums +enum BP_TYPE +{ + BPNORMAL=UE_BREAKPOINT, + BPSINGLESHOOT=UE_SINGLESHOOT, + BPHARDWARE=UE_HARDWARE, + BPMEMORY=UE_MEMORY, + BPNOTYPE=-1 +}; + +//structs +struct BREAKPOINT +{ + char* name; + uint addr; + bool enabled; + short oldbytes; + BP_TYPE type; + BREAKPOINT* next; +}; + +//functions +BREAKPOINT* bpinit(BREAKPOINT* breakpoint_list); +BREAKPOINT* bpfind(BREAKPOINT* breakpoint_list, const char* name, uint addr, BREAKPOINT** link, BP_TYPE type); +bool bpnew(BREAKPOINT* breakpoint_list, const char* name, uint addr, short oldbytes, BP_TYPE type); +bool bpsetname(BREAKPOINT* breakpoint_list, uint addr, const char* name); +bool bpdel(BREAKPOINT* breakpoint_list, const char* name, uint addr, BP_TYPE type); + +#endif // _BREAKPOINT_H diff --git a/x64_dbg_dbg/command.cpp b/x64_dbg_dbg/command.cpp new file mode 100644 index 00000000..c6f64087 --- /dev/null +++ b/x64_dbg_dbg/command.cpp @@ -0,0 +1,245 @@ +#include "command.h" +#include "argument.h" +#include "console.h" +#include "debugger.h" +#include "math.h" + +COMMAND* cmdfind(COMMAND* command_list, const char* name, COMMAND** link) +{ + COMMAND* cur=command_list; + if(!cur->name) + return 0; + COMMAND* prev=0; + while(cur) + { + if(arraycontains(cur->name, name)) + { + if(link) + *link=prev; + return cur; + } + prev=cur; + cur=cur->next; + } + return 0; +} + +COMMAND* cmdinit() +{ + COMMAND* cmd=(COMMAND*)emalloc(sizeof(COMMAND)); + memset(cmd, 0, sizeof(COMMAND)); + return cmd; +} + +void cmdfree(COMMAND* cmd_list) +{ + COMMAND* cur=cmd_list; + while(cur) + { + efree(cur->name); + COMMAND* next=cur->next; + efree(cur); + cur=next; + } +} + +bool cmdnew(COMMAND* command_list, const char* name, CBCOMMAND cbCommand, bool debugonly) +{ + if(!command_list or !cbCommand or !name or !*name or cmdfind(command_list, name, 0)) + return false; + COMMAND* cmd; + bool nonext=false; + if(!command_list->name) + { + cmd=command_list; + nonext=true; + } + else + cmd=(COMMAND*)emalloc(sizeof(COMMAND)); + memset(cmd, 0, sizeof(COMMAND)); + cmd->name=(char*)emalloc(strlen(name)+1); + strcpy(cmd->name, name); + cmd->cbCommand=cbCommand; + cmd->debugonly=debugonly; + COMMAND* cur=command_list; + if(!nonext) + { + while(cur->next) + cur=cur->next; + cur->next=cmd; + } + return true; +} + +COMMAND* cmdget(COMMAND* command_list, const char* cmd) +{ + char new_cmd[deflen]=""; + strcpy(new_cmd, cmd); + int len=strlen(new_cmd); + int start=0; + while(new_cmd[start]!=' ' and startcbCommand; + found->cbCommand=cbCommand; + found->debugonly=debugonly; + return old; +} + +bool cmddel(COMMAND* command_list, const char* name) +{ + COMMAND* prev=0; + COMMAND* found=cmdfind(command_list, name, &prev); + if(!found) + return false; + efree(found->name); + if(found==command_list) + { + COMMAND* next=command_list->next; + if(next) + { + memcpy(command_list, command_list->next, sizeof(COMMAND)); + command_list->next=next->next; + efree(next); + } + else + memset(command_list, 0, sizeof(COMMAND)); + } + else + { + prev->next=found->next; + efree(found); + } + return true; +} + +/* +command_list: command list +cbUnknownCommand: function to execute when an unknown command was found +cbCommandProvider: function that provides commands (fgets for example), does not return until a command was found +cbCommandFinder: non-default command finder +error_is_fatal: error return of a command callback stops the command processing +*/ +CMDRESULT cmdloop(COMMAND* command_list, CBCOMMAND cbUnknownCommand, CBCOMMANDPROVIDER cbCommandProvider, CBCOMMANDFINDER cbCommandFinder, bool error_is_fatal) +{ + if(!cbUnknownCommand or !cbCommandProvider) + return STATUS_ERROR; + char* command=(char*)emalloc(deflen); + memset(command, 0, deflen); + bool bLoop=true; + while(bLoop) + { + if(!cbCommandProvider(command, deflen)) + break; + if(strlen(command)) + { + argformat(command); //default formatting + COMMAND* cmd; + if(!cbCommandFinder) //'clean' command processing + cmd=cmdget(command_list, command); + else //'dirty' command processing + cmd=cbCommandFinder(command_list, command); + + if(!cmd or !cmd->cbCommand) //unknown command + { + CMDRESULT res=cbUnknownCommand(command); + if((error_is_fatal and res==STATUS_ERROR) or res==STATUS_EXIT) + bLoop=false; + } + else + { + if(cmd->debugonly and !IsFileBeingDebugged()) + { + dputs("this command is debug-only"); + if(error_is_fatal) + bLoop=false; + } + else + { + CMDRESULT res=cmd->cbCommand(command); + if((error_is_fatal and res==STATUS_ERROR) or res==STATUS_EXIT) + bLoop=false; + } + } + } + } + efree(command); + return STATUS_EXIT; +} + +/* +- custom command formatting rules +*/ +static void specialformat(char* string) +{ + int len=strlen(string); + char* found=strstr(string, "="); + char* str=(char*)emalloc(len*2); + memset(str, 0, len*2); + if(found) //contains = + { + char* a=(found-1); + *found=0; + found++; + if(!*found) + { + *found='='; + efree(str); + return; + } + int flen=strlen(found); //n(+)=n++ + if((found[flen-1]=='+' and found[flen-2]=='+') or (found[flen-1]=='-' and found[flen-2]=='-')) //eax++/eax-- + { + found[flen-2]=0; + char op=found[flen-1]; + sprintf(str, "%s%c1", found, op); + strcpy(found, str); + } + if(mathisoperator(*a)>2) //x*=3 -> x=x*3 + { + char op=*a; + *a=0; + sprintf(str, "mov %s,%s%c%s", string, string, op, found); + } + else + sprintf(str, "mov %s,%s", string, found); + strcpy(string, str); + } + else if((string[len-1]=='+' and string[len-2]=='+') or (string[len-1]=='-' and string[len-2]=='-')) //eax++/eax-- + { + string[len-2]=0; + char op=string[len-1]; + sprintf(str, "mov %s,%s%c1", string, string, op); + strcpy(string, str); + } + efree(str); +} + +/* +- 'default' command finder, with some custom rules +*/ +COMMAND* cmdfindmain(COMMAND* cmd_list, char* command) +{ + COMMAND* cmd=cmdfind(cmd_list, command, 0); + if(!cmd) + { + specialformat(command); + cmd=cmdget(cmd_list, command); + } + if(!cmd or !cmd->cbCommand) + mathformat(command); + return cmd; +} diff --git a/x64_dbg_dbg/command.h b/x64_dbg_dbg/command.h new file mode 100644 index 00000000..c1c24df8 --- /dev/null +++ b/x64_dbg_dbg/command.h @@ -0,0 +1,40 @@ +#ifndef _COMMAND_H +#define _COMMAND_H + +#include "_global.h" + +//typedefs + +struct COMMAND; + +enum CMDRESULT +{ + STATUS_EXIT=0, + STATUS_CONTINUE=1, + STATUS_ERROR=2 +}; + +typedef CMDRESULT (*CBCOMMAND)(const char*); +typedef bool (*CBCOMMANDPROVIDER)(char*, int); +typedef COMMAND* (*CBCOMMANDFINDER)(COMMAND*, char*); + +struct COMMAND +{ + char* name; + CBCOMMAND cbCommand; + bool debugonly; + COMMAND* next; +}; + +//functions +COMMAND* cmdinit(); +void cmdfree(COMMAND* cmd_list); +COMMAND* cmdfind(COMMAND* command_list, const char* name, COMMAND** link); +bool cmdnew(COMMAND* command_list, const char* name, CBCOMMAND cbCommand, bool debugonly); +COMMAND* cmdget(COMMAND* command_list, const char* cmd); +CBCOMMAND cmdset(COMMAND* command_list, const char* name, CBCOMMAND cbCommand, bool debugonly); +bool cmddel(COMMAND* command_list, const char* name); +CMDRESULT cmdloop(COMMAND* command_list, CBCOMMAND cbUnknownCommand, CBCOMMANDPROVIDER cbCommandProvider, CBCOMMANDFINDER cbCommandFinder, bool error_is_fatal); +COMMAND* cmdfindmain(COMMAND* cmd_list, char* command); + +#endif // _COMMAND_H diff --git a/x64_dbg_dbg/console.cpp b/x64_dbg_dbg/console.cpp new file mode 100644 index 00000000..ff35a6de --- /dev/null +++ b/x64_dbg_dbg/console.cpp @@ -0,0 +1,15 @@ +#include "console.h" + +void dputs(const char* text) +{ + dprintf("%s\n", text); +} + +void dprintf(const char* format, ...) +{ + va_list args; + va_start(args, format); + char msg[deflen]=""; + vsprintf(msg, format, args); + GuiAddLogMessage(msg); +} diff --git a/x64_dbg_dbg/console.h b/x64_dbg_dbg/console.h new file mode 100644 index 00000000..1407ed0d --- /dev/null +++ b/x64_dbg_dbg/console.h @@ -0,0 +1,10 @@ +#ifndef _CONSOLE_H +#define _CONSOLE_H + +#include "_global.h" + +//functions +void dputs(const char* text); +void dprintf(const char* format, ...); + +#endif // _CONSOLE_H diff --git a/x64_dbg_dbg/data.h b/x64_dbg_dbg/data.h new file mode 100644 index 00000000..1d1329dc --- /dev/null +++ b/x64_dbg_dbg/data.h @@ -0,0 +1,31 @@ +#ifndef _DATA_H +#define _DATA_H + +#include "_global.h" + +enum DATA_TYPE //how to display the current struct entry? +{ + thex, //%X + tint, //%d + tuint, //%u + ttext, //%c +}; + +struct STRUCT_INFO +{ + unsigned int size; //size of one entry (with type) (max 256) + DATA_TYPE display_type; //display type + unsigned int count; //number of entries with the same content (reserved[12]) + void* description; //reserved for later use (for example name of variable) +}; + +struct DATA +{ + uint page_start; //remote/local memory + uint page_size; //size of memory + uint ip; //real start of data (relative from page_start) + int struct_size; //number of entries in a struct + STRUCT_INFO* info; //actual info +}; + +#endif // _DATA_H diff --git a/x64_dbg_dbg/dbg.h b/x64_dbg_dbg/dbg.h new file mode 100644 index 00000000..eb5837cf --- /dev/null +++ b/x64_dbg_dbg/dbg.h @@ -0,0 +1,18 @@ +#ifndef __DBG_H__ +#define __DBG_H__ + +#include +#include "_global.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +void DLL_IMPORT dbg(const char* a); + +#ifdef __cplusplus +} +#endif + +#endif // __DBG_H__ diff --git a/x64_dbg_dbg/dbg/dbg.cbp b/x64_dbg_dbg/dbg/dbg.cbp new file mode 100644 index 00000000..f22b7b9e --- /dev/null +++ b/x64_dbg_dbg/dbg/dbg.cbp @@ -0,0 +1,51 @@ + + + + + + diff --git a/x64_dbg_dbg/dbg/dbg.cpp b/x64_dbg_dbg/dbg/dbg.cpp new file mode 100644 index 00000000..8504703b --- /dev/null +++ b/x64_dbg_dbg/dbg/dbg.cpp @@ -0,0 +1,8 @@ +#include "dbg.h" + +// a sample exported function +void DLL_EXPORT dbg(const char* a) +{ + char b[256]=""; + strcpy(b,a); +} diff --git a/x64_dbg_dbg/dbg/dbg.h b/x64_dbg_dbg/dbg/dbg.h new file mode 100644 index 00000000..0b317f84 --- /dev/null +++ b/x64_dbg_dbg/dbg/dbg.h @@ -0,0 +1,28 @@ +#ifndef __MAIN_H__ +#define __MAIN_H__ + +#include + +/* To use this exported function of dll, include this header + * in your project. + */ + +#ifdef BUILD_DLL +#define DLL_EXPORT __declspec(dllexport) +#else +#define DLL_EXPORT __declspec(dllimport) +#endif + + +#ifdef __cplusplus +extern "C" +{ +#endif + +void DLL_EXPORT dbg(const char* a); + +#ifdef __cplusplus +} +#endif + +#endif // __MAIN_H__ diff --git a/x64_dbg_dbg/dbghelp/dbghelp.h b/x64_dbg_dbg/dbghelp/dbghelp.h new file mode 100644 index 00000000..1bd54793 --- /dev/null +++ b/x64_dbg_dbg/dbghelp/dbghelp.h @@ -0,0 +1,4677 @@ +#ifndef _DBGHELP_ +#define _DBGHELP_ + + +// As a general principal always call the 64 bit version +// of every API, if a choice exists. The 64 bit version +// works great on 32 bit platforms, and is forward +// compatible to 64 bit platforms. + +#ifdef _WIN64 +#ifndef _IMAGEHLP64 +#define _IMAGEHLP64 +#endif +#endif + +#pragma pack(push,8) + +// For those without specstrings.h +// Since there are different versions of this header, I need to +// individually test each item and define it if it is not around. + +#ifndef __in +#define __in +#endif +#ifndef __out +#define __out +#endif +#ifndef __inout +#define __inout +#endif +#ifndef __in_opt +#define __in_opt +#endif +#ifndef __out_opt +#define __out_opt +#endif +#ifndef __inout_opt +#define __inout_opt +#endif +#ifndef __in_ecount +#define __in_ecount(x) +#endif +#ifndef __out_ecount +#define __out_ecount(x) +#endif +#ifndef __inout_ecount +#define __inout_ecount(x) +#endif +#ifndef __in_bcount +#define __in_bcount(x) +#endif +#ifndef __out_bcount +#define __out_bcount(x) +#endif +#ifndef __inout_bcount +#define __inout_bcount(x) +#endif +#ifndef __out_xcount +#define __out_xcount(x) +#endif +#ifndef __deref_opt_out +#define __deref_opt_out +#endif +#ifndef __deref_out +#define __deref_out +#endif +#ifndef __out_ecount_opt +#define __out_ecount_opt(x) +#endif +#ifndef __in_bcount_opt +#define __in_bcount_opt(x) +#endif +#ifndef __out_bcount_opt +#define __out_bcount_opt(x) +#endif +#ifndef __deref_out_opt +#define __deref_out_opt +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _IMAGEHLP_SOURCE_ +#define IMAGEAPI __stdcall +#define DBHLP_DEPRECIATED +#else +#define IMAGEAPI DECLSPEC_IMPORT __stdcall +#if (_MSC_VER >= 1300) && !defined(MIDL_PASS) +#define DBHLP_DEPRECIATED __declspec(deprecated) +#else +#define DBHLP_DEPRECIATED +#endif +#endif + +#define DBHLPAPI IMAGEAPI + +#define IMAGE_SEPARATION (64*1024) + +// Observant readers may notice that 2 new fields, +// 'fReadOnly' and 'Version' have been added to +// the LOADED_IMAGE structure after 'fDOSImage'. +// This does not change the size of the structure +// from previous headers. That is because while +// 'fDOSImage' is a byte, it is padded by the +// compiler to 4 bytes. So the 2 new fields are +// slipped into the extra space. + +typedef struct _LOADED_IMAGE +{ + PSTR ModuleName; + HANDLE hFile; + PUCHAR MappedAddress; +#ifdef _IMAGEHLP64 + PIMAGE_NT_HEADERS64 FileHeader; +#else + PIMAGE_NT_HEADERS32 FileHeader; +#endif + PIMAGE_SECTION_HEADER LastRvaSection; + ULONG NumberOfSections; + PIMAGE_SECTION_HEADER Sections; + ULONG Characteristics; + BOOLEAN fSystemImage; + BOOLEAN fDOSImage; + BOOLEAN fReadOnly; + UCHAR Version; + LIST_ENTRY Links; + ULONG SizeOfImage; +} LOADED_IMAGE, *PLOADED_IMAGE; + +#define MAX_SYM_NAME 2000 + + +// Error codes set by dbghelp functions. Call GetLastError +// to see them. +// Dbghelp also sets error codes found in winerror.h + +#define ERROR_IMAGE_NOT_STRIPPED 0x8800 // the image is not stripped. No dbg file available. +#define ERROR_NO_DBG_POINTER 0x8801 // image is stripped but there is no pointer to a dbg file +#define ERROR_NO_PDB_POINTER 0x8802 // image does not point to a pdb file + +typedef BOOL +(CALLBACK *PFIND_DEBUG_FILE_CALLBACK)( + __in HANDLE FileHandle, + __in PCSTR FileName, + __in PVOID CallerData +); + +HANDLE +IMAGEAPI +SymFindDebugInfoFile( + __in HANDLE hProcess, + __in PCSTR FileName, + __out_ecount(MAX_PATH + 1) PSTR DebugFilePath, + __in_opt PFIND_DEBUG_FILE_CALLBACK Callback, + __in_opt PVOID CallerData +); + +typedef BOOL +(CALLBACK *PFIND_DEBUG_FILE_CALLBACKW)( + __in HANDLE FileHandle, + __in PCWSTR FileName, + __in PVOID CallerData +); + +HANDLE +IMAGEAPI +SymFindDebugInfoFileW( + __in HANDLE hProcess, + __in PCWSTR FileName, + __out_ecount(MAX_PATH + 1) PWSTR DebugFilePath, + __in_opt PFIND_DEBUG_FILE_CALLBACKW Callback, + __in_opt PVOID CallerData +); + +HANDLE +IMAGEAPI +FindDebugInfoFile ( + __in PCSTR FileName, + __in PCSTR SymbolPath, + __out_ecount(MAX_PATH + 1) PSTR DebugFilePath +); + +HANDLE +IMAGEAPI +FindDebugInfoFileEx ( + __in PCSTR FileName, + __in PCSTR SymbolPath, + __out_ecount(MAX_PATH + 1) PSTR DebugFilePath, + __in_opt PFIND_DEBUG_FILE_CALLBACK Callback, + __in_opt PVOID CallerData +); + +HANDLE +IMAGEAPI +FindDebugInfoFileExW ( + __in PCWSTR FileName, + __in PCWSTR SymbolPath, + __out_ecount(MAX_PATH + 1) PWSTR DebugFilePath, + __in_opt PFIND_DEBUG_FILE_CALLBACKW Callback, + __in_opt PVOID CallerData +); + +typedef BOOL +(CALLBACK *PFINDFILEINPATHCALLBACK)( + __in PCSTR filename, + __in PVOID context +); + +BOOL +IMAGEAPI +SymFindFileInPath( + __in HANDLE hprocess, + __in_opt PCSTR SearchPath, + __in PCSTR FileName, + __in_opt PVOID id, + __in DWORD two, + __in DWORD three, + __in DWORD flags, + __out_ecount(MAX_PATH + 1) PSTR FoundFile, + __in_opt PFINDFILEINPATHCALLBACK callback, + __in_opt PVOID context +); + +typedef BOOL +(CALLBACK *PFINDFILEINPATHCALLBACKW)( + __in PCWSTR filename, + __in PVOID context +); + +BOOL +IMAGEAPI +SymFindFileInPathW( + __in HANDLE hprocess, + __in_opt PCWSTR SearchPath, + __in PCWSTR FileName, + __in_opt PVOID id, + __in DWORD two, + __in DWORD three, + __in DWORD flags, + __out_ecount(MAX_PATH + 1) PWSTR FoundFile, + __in_opt PFINDFILEINPATHCALLBACKW callback, + __in_opt PVOID context +); + +typedef BOOL +(CALLBACK *PFIND_EXE_FILE_CALLBACK)( + __in HANDLE FileHandle, + __in PCSTR FileName, + __in_opt PVOID CallerData +); + +HANDLE +IMAGEAPI +SymFindExecutableImage( + __in HANDLE hProcess, + __in PCSTR FileName, + __out_ecount(MAX_PATH + 1) PSTR ImageFilePath, + __in PFIND_EXE_FILE_CALLBACK Callback, + __in PVOID CallerData +); + +typedef BOOL +(CALLBACK *PFIND_EXE_FILE_CALLBACKW)( + __in HANDLE FileHandle, + __in PCWSTR FileName, + __in_opt PVOID CallerData +); + +HANDLE +IMAGEAPI +SymFindExecutableImageW( + __in HANDLE hProcess, + __in PCWSTR FileName, + __out_ecount(MAX_PATH + 1) PWSTR ImageFilePath, + __in PFIND_EXE_FILE_CALLBACKW Callback, + __in PVOID CallerData +); + +HANDLE +IMAGEAPI +FindExecutableImage( + __in PCSTR FileName, + __in PCSTR SymbolPath, + __out_ecount(MAX_PATH + 1) PSTR ImageFilePath +); + +HANDLE +IMAGEAPI +FindExecutableImageEx( + __in PCSTR FileName, + __in PCSTR SymbolPath, + __out_ecount(MAX_PATH + 1) PSTR ImageFilePath, + __in_opt PFIND_EXE_FILE_CALLBACK Callback, + __in_opt PVOID CallerData +); + +HANDLE +IMAGEAPI +FindExecutableImageExW( + __in PCWSTR FileName, + __in PCWSTR SymbolPath, + __out_ecount(MAX_PATH + 1) PWSTR ImageFilePath, + __in_opt PFIND_EXE_FILE_CALLBACKW Callback, + __in PVOID CallerData +); + +PIMAGE_NT_HEADERS +IMAGEAPI +ImageNtHeader ( + __in PVOID Base +); + +PVOID +IMAGEAPI +ImageDirectoryEntryToDataEx ( + __in PVOID Base, + __in BOOLEAN MappedAsImage, + __in USHORT DirectoryEntry, + __out PULONG Size, + __out_opt PIMAGE_SECTION_HEADER *FoundHeader +); + +PVOID +IMAGEAPI +ImageDirectoryEntryToData ( + __in PVOID Base, + __in BOOLEAN MappedAsImage, + __in USHORT DirectoryEntry, + __out PULONG Size +); + +PIMAGE_SECTION_HEADER +IMAGEAPI +ImageRvaToSection( + __in PIMAGE_NT_HEADERS NtHeaders, + __in PVOID Base, + __in ULONG Rva +); + +PVOID +IMAGEAPI +ImageRvaToVa( + __in PIMAGE_NT_HEADERS NtHeaders, + __in PVOID Base, + __in ULONG Rva, + __in_opt OUT PIMAGE_SECTION_HEADER *LastRvaSection +); + +#ifndef _WIN64 +// This api won't be ported to Win64 - Fix your code. + +typedef struct _IMAGE_DEBUG_INFORMATION +{ + LIST_ENTRY List; + DWORD ReservedSize; + PVOID ReservedMappedBase; + USHORT ReservedMachine; + USHORT ReservedCharacteristics; + DWORD ReservedCheckSum; + DWORD ImageBase; + DWORD SizeOfImage; + + DWORD ReservedNumberOfSections; + PIMAGE_SECTION_HEADER ReservedSections; + + DWORD ReservedExportedNamesSize; + PSTR ReservedExportedNames; + + DWORD ReservedNumberOfFunctionTableEntries; + PIMAGE_FUNCTION_ENTRY ReservedFunctionTableEntries; + DWORD ReservedLowestFunctionStartingAddress; + DWORD ReservedHighestFunctionEndingAddress; + + DWORD ReservedNumberOfFpoTableEntries; + PFPO_DATA ReservedFpoTableEntries; + + DWORD SizeOfCoffSymbols; + PIMAGE_COFF_SYMBOLS_HEADER CoffSymbols; + + DWORD ReservedSizeOfCodeViewSymbols; + PVOID ReservedCodeViewSymbols; + + PSTR ImageFilePath; + PSTR ImageFileName; + PSTR ReservedDebugFilePath; + + DWORD ReservedTimeDateStamp; + + BOOL ReservedRomImage; + PIMAGE_DEBUG_DIRECTORY ReservedDebugDirectory; + DWORD ReservedNumberOfDebugDirectories; + + DWORD ReservedOriginalFunctionTableBaseAddress; + + DWORD Reserved[ 2 ]; + +} IMAGE_DEBUG_INFORMATION, *PIMAGE_DEBUG_INFORMATION; + + +PIMAGE_DEBUG_INFORMATION +IMAGEAPI +MapDebugInformation( + __in_opt HANDLE FileHandle, + __in PCSTR FileName, + __in_opt PCSTR SymbolPath, + __in ULONG ImageBase +); + +BOOL +IMAGEAPI +UnmapDebugInformation( + __out_xcount(unknown) PIMAGE_DEBUG_INFORMATION DebugInfo +); + +#endif + +BOOL +IMAGEAPI +SearchTreeForFile( + __in PCSTR RootPath, + __in PCSTR InputPathName, + __out_ecount(MAX_PATH + 1) PSTR OutputPathBuffer +); + +BOOL +IMAGEAPI +SearchTreeForFileW( + __in PCWSTR RootPath, + __in PCWSTR InputPathName, + __out_ecount(MAX_PATH + 1) PWSTR OutputPathBuffer +); + +typedef BOOL +(CALLBACK *PENUMDIRTREE_CALLBACK)( + __in PCSTR FilePath, + __in_opt PVOID CallerData +); + +BOOL +IMAGEAPI +EnumDirTree( + __in_opt HANDLE hProcess, + __in PCSTR RootPath, + __in PCSTR InputPathName, + __out_ecount_opt(MAX_PATH + 1) PSTR OutputPathBuffer, + __in_opt PENUMDIRTREE_CALLBACK cb, + __in_opt PVOID data +); + +typedef BOOL +(CALLBACK *PENUMDIRTREE_CALLBACKW)( + __in PCWSTR FilePath, + __in_opt PVOID CallerData +); + +BOOL +IMAGEAPI +EnumDirTreeW( + __in_opt HANDLE hProcess, + __in PCWSTR RootPath, + __in PCWSTR InputPathName, + __out_ecount_opt(MAX_PATH + 1) PWSTR OutputPathBuffer, + __in_opt PENUMDIRTREE_CALLBACKW cb, + __in_opt PVOID data +); + +BOOL +IMAGEAPI +MakeSureDirectoryPathExists( + __in PCSTR DirPath +); + +// +// UnDecorateSymbolName Flags +// + +#define UNDNAME_COMPLETE (0x0000) // Enable full undecoration +#define UNDNAME_NO_LEADING_UNDERSCORES (0x0001) // Remove leading underscores from MS extended keywords +#define UNDNAME_NO_MS_KEYWORDS (0x0002) // Disable expansion of MS extended keywords +#define UNDNAME_NO_FUNCTION_RETURNS (0x0004) // Disable expansion of return type for primary declaration +#define UNDNAME_NO_ALLOCATION_MODEL (0x0008) // Disable expansion of the declaration model +#define UNDNAME_NO_ALLOCATION_LANGUAGE (0x0010) // Disable expansion of the declaration language specifier +#define UNDNAME_NO_MS_THISTYPE (0x0020) // NYI Disable expansion of MS keywords on the 'this' type for primary declaration +#define UNDNAME_NO_CV_THISTYPE (0x0040) // NYI Disable expansion of CV modifiers on the 'this' type for primary declaration +#define UNDNAME_NO_THISTYPE (0x0060) // Disable all modifiers on the 'this' type +#define UNDNAME_NO_ACCESS_SPECIFIERS (0x0080) // Disable expansion of access specifiers for members +#define UNDNAME_NO_THROW_SIGNATURES (0x0100) // Disable expansion of 'throw-signatures' for functions and pointers to functions +#define UNDNAME_NO_MEMBER_TYPE (0x0200) // Disable expansion of 'static' or 'virtual'ness of members +#define UNDNAME_NO_RETURN_UDT_MODEL (0x0400) // Disable expansion of MS model for UDT returns +#define UNDNAME_32_BIT_DECODE (0x0800) // Undecorate 32-bit decorated names +#define UNDNAME_NAME_ONLY (0x1000) // Crack only the name for primary declaration; +// return just [scope::]name. Does expand template params +#define UNDNAME_NO_ARGUMENTS (0x2000) // Don't undecorate arguments to function +#define UNDNAME_NO_SPECIAL_SYMS (0x4000) // Don't undecorate special names (v-table, vcall, vector xxx, metatype, etc) + +DWORD +IMAGEAPI +WINAPI +UnDecorateSymbolName( + __in PCSTR name, + __out_ecount(maxStringLength) PSTR outputString, + __in DWORD maxStringLength, + __in DWORD flags +); + +DWORD +IMAGEAPI +WINAPI +UnDecorateSymbolNameW( + __in PCWSTR name, + __out_ecount(maxStringLength) PWSTR outputString, + __in DWORD maxStringLength, + __in DWORD flags +); + +// +// these values are used for synthesized file types +// that can be passed in as image headers instead of +// the standard ones from ntimage.h +// + +#define DBHHEADER_DEBUGDIRS 0x1 +#define DBHHEADER_CVMISC 0x2 +#define DBHHEADER_PDBGUID 0x3 +typedef struct _MODLOAD_DATA +{ + DWORD ssize; // size of this struct + DWORD ssig; // signature identifying the passed data + PVOID data; // pointer to passed data + DWORD size; // size of passed data + DWORD flags; // options +} MODLOAD_DATA, *PMODLOAD_DATA; + +typedef struct _MODLOAD_CVMISC +{ + DWORD oCV; // ofset to the codeview record + size_t cCV; // size of the codeview record + DWORD oMisc; // offset to the misc record + size_t cMisc; // size of the misc record + DWORD dtImage; // datetime stamp of the image + DWORD cImage; // size of the image +} MODLOAD_CVMISC, *PMODLOAD_CVMISC; + +typedef struct _MODLOAD_PDBGUID_PDBAGE +{ + GUID PdbGuid; // Pdb Guid + DWORD PdbAge; // Pdb Age +} MODLOAD_PDBGUID_PDBAGE, *PMODLOAD_PDBGUID_PDBAGE; + +// +// StackWalking API +// + +typedef enum +{ + AddrMode1616, + AddrMode1632, + AddrModeReal, + AddrModeFlat +} ADDRESS_MODE; + +typedef struct _tagADDRESS64 +{ + DWORD64 Offset; + WORD Segment; + ADDRESS_MODE Mode; +} ADDRESS64, *LPADDRESS64; + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define ADDRESS ADDRESS64 +#define LPADDRESS LPADDRESS64 +#else +typedef struct _tagADDRESS +{ + DWORD Offset; + WORD Segment; + ADDRESS_MODE Mode; +} ADDRESS, *LPADDRESS; + +__inline +void +Address32To64( + __in LPADDRESS a32, + __out LPADDRESS64 a64 +) +{ + a64->Offset = (ULONG64)(LONG64)(LONG)a32->Offset; + a64->Segment = a32->Segment; + a64->Mode = a32->Mode; +} + +__inline +void +Address64To32( + __in LPADDRESS64 a64, + __out LPADDRESS a32 +) +{ + a32->Offset = (ULONG)a64->Offset; + a32->Segment = a64->Segment; + a32->Mode = a64->Mode; +} +#endif + +// +// This structure is included in the STACKFRAME structure, +// and is used to trace through usermode callbacks in a thread's +// kernel stack. The values must be copied by the kernel debugger +// from the DBGKD_GET_VERSION and WAIT_STATE_CHANGE packets. +// + +// +// New KDHELP structure for 64 bit system support. +// This structure is preferred in new code. +// +typedef struct _KDHELP64 +{ + + // + // address of kernel thread object, as provided in the + // WAIT_STATE_CHANGE packet. + // + DWORD64 Thread; + + // + // offset in thread object to pointer to the current callback frame + // in kernel stack. + // + DWORD ThCallbackStack; + + // + // offset in thread object to pointer to the current callback backing + // store frame in kernel stack. + // + DWORD ThCallbackBStore; + + // + // offsets to values in frame: + // + // address of next callback frame + DWORD NextCallback; + + // address of saved frame pointer (if applicable) + DWORD FramePointer; + + + // + // Address of the kernel function that calls out to user mode + // + DWORD64 KiCallUserMode; + + // + // Address of the user mode dispatcher function + // + DWORD64 KeUserCallbackDispatcher; + + // + // Lowest kernel mode address + // + DWORD64 SystemRangeStart; + + // + // Address of the user mode exception dispatcher function. + // Added in API version 10. + // + DWORD64 KiUserExceptionDispatcher; + + // + // Stack bounds, added in API version 11. + // + DWORD64 StackBase; + DWORD64 StackLimit; + + DWORD64 Reserved[5]; + +} KDHELP64, *PKDHELP64; + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define KDHELP KDHELP64 +#define PKDHELP PKDHELP64 +#else +typedef struct _KDHELP +{ + + // + // address of kernel thread object, as provided in the + // WAIT_STATE_CHANGE packet. + // + DWORD Thread; + + // + // offset in thread object to pointer to the current callback frame + // in kernel stack. + // + DWORD ThCallbackStack; + + // + // offsets to values in frame: + // + // address of next callback frame + DWORD NextCallback; + + // address of saved frame pointer (if applicable) + DWORD FramePointer; + + // + // Address of the kernel function that calls out to user mode + // + DWORD KiCallUserMode; + + // + // Address of the user mode dispatcher function + // + DWORD KeUserCallbackDispatcher; + + // + // Lowest kernel mode address + // + DWORD SystemRangeStart; + + // + // offset in thread object to pointer to the current callback backing + // store frame in kernel stack. + // + DWORD ThCallbackBStore; + + // + // Address of the user mode exception dispatcher function. + // Added in API version 10. + // + DWORD KiUserExceptionDispatcher; + + // + // Stack bounds, added in API version 11. + // + DWORD StackBase; + DWORD StackLimit; + + DWORD Reserved[5]; + +} KDHELP, *PKDHELP; + +__inline +void +KdHelp32To64( + __in PKDHELP p32, + __out PKDHELP64 p64 +) +{ + p64->Thread = p32->Thread; + p64->ThCallbackStack = p32->ThCallbackStack; + p64->NextCallback = p32->NextCallback; + p64->FramePointer = p32->FramePointer; + p64->KiCallUserMode = p32->KiCallUserMode; + p64->KeUserCallbackDispatcher = p32->KeUserCallbackDispatcher; + p64->SystemRangeStart = p32->SystemRangeStart; + p64->KiUserExceptionDispatcher = p32->KiUserExceptionDispatcher; + p64->StackBase = p32->StackBase; + p64->StackLimit = p32->StackLimit; +} +#endif + +typedef struct _tagSTACKFRAME64 +{ + ADDRESS64 AddrPC; // program counter + ADDRESS64 AddrReturn; // return address + ADDRESS64 AddrFrame; // frame pointer + ADDRESS64 AddrStack; // stack pointer + ADDRESS64 AddrBStore; // backing store pointer + PVOID FuncTableEntry; // pointer to pdata/fpo or NULL + DWORD64 Params[4]; // possible arguments to the function + BOOL Far; // WOW far call + BOOL Virtual; // is this a virtual frame? + DWORD64 Reserved[3]; + KDHELP64 KdHelp; +} STACKFRAME64, *LPSTACKFRAME64; + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define STACKFRAME STACKFRAME64 +#define LPSTACKFRAME LPSTACKFRAME64 +#else +typedef struct _tagSTACKFRAME +{ + ADDRESS AddrPC; // program counter + ADDRESS AddrReturn; // return address + ADDRESS AddrFrame; // frame pointer + ADDRESS AddrStack; // stack pointer + PVOID FuncTableEntry; // pointer to pdata/fpo or NULL + DWORD Params[4]; // possible arguments to the function + BOOL Far; // WOW far call + BOOL Virtual; // is this a virtual frame? + DWORD Reserved[3]; + KDHELP KdHelp; + ADDRESS AddrBStore; // backing store pointer +} STACKFRAME, *LPSTACKFRAME; +#endif + + +typedef +BOOL +(__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)( + __in HANDLE hProcess, + __in DWORD64 qwBaseAddress, + __out_bcount(nSize) PVOID lpBuffer, + __in DWORD nSize, + __out LPDWORD lpNumberOfBytesRead +); + +typedef +PVOID +(__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( + __in HANDLE ahProcess, + __in DWORD64 AddrBase +); + +typedef +DWORD64 +(__stdcall *PGET_MODULE_BASE_ROUTINE64)( + __in HANDLE hProcess, + __in DWORD64 Address +); + +typedef +DWORD64 +(__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)( + __in HANDLE hProcess, + __in HANDLE hThread, + __in LPADDRESS64 lpaddr +); + +BOOL +IMAGEAPI +StackWalk64( + __in DWORD MachineType, + __in HANDLE hProcess, + __in HANDLE hThread, + __inout LPSTACKFRAME64 StackFrame, + __inout PVOID ContextRecord, + __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, + __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, + __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, + __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) + +#define PREAD_PROCESS_MEMORY_ROUTINE PREAD_PROCESS_MEMORY_ROUTINE64 +#define PFUNCTION_TABLE_ACCESS_ROUTINE PFUNCTION_TABLE_ACCESS_ROUTINE64 +#define PGET_MODULE_BASE_ROUTINE PGET_MODULE_BASE_ROUTINE64 +#define PTRANSLATE_ADDRESS_ROUTINE PTRANSLATE_ADDRESS_ROUTINE64 + +#define StackWalk StackWalk64 + +#else + +typedef +BOOL +(__stdcall *PREAD_PROCESS_MEMORY_ROUTINE)( + __in HANDLE hProcess, + __in DWORD lpBaseAddress, + __out_bcount(nSize) PVOID lpBuffer, + __in DWORD nSize, + __out PDWORD lpNumberOfBytesRead +); + +typedef +PVOID +(__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE)( + __in HANDLE hProcess, + __in DWORD AddrBase +); + +typedef +DWORD +(__stdcall *PGET_MODULE_BASE_ROUTINE)( + __in HANDLE hProcess, + __in DWORD Address +); + +typedef +DWORD +(__stdcall *PTRANSLATE_ADDRESS_ROUTINE)( + __in HANDLE hProcess, + __in HANDLE hThread, + __out LPADDRESS lpaddr +); + +BOOL +IMAGEAPI +StackWalk( + DWORD MachineType, + __in HANDLE hProcess, + __in HANDLE hThread, + __inout LPSTACKFRAME StackFrame, + __inout PVOID ContextRecord, + __in_opt PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine, + __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine, + __in_opt PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine, + __in_opt PTRANSLATE_ADDRESS_ROUTINE TranslateAddress +); + +#endif + + +#define API_VERSION_NUMBER 11 + +typedef struct API_VERSION +{ + USHORT MajorVersion; + USHORT MinorVersion; + USHORT Revision; + USHORT Reserved; +} API_VERSION, *LPAPI_VERSION; + +LPAPI_VERSION +IMAGEAPI +ImagehlpApiVersion( + VOID +); + +LPAPI_VERSION +IMAGEAPI +ImagehlpApiVersionEx( + __in LPAPI_VERSION AppVersion +); + +DWORD +IMAGEAPI +GetTimestampForLoadedLibrary( + __in HMODULE Module +); + +// +// typedefs for function pointers +// +typedef BOOL +(CALLBACK *PSYM_ENUMMODULES_CALLBACK64)( + __in PCSTR ModuleName, + __in DWORD64 BaseOfDll, + __in_opt PVOID UserContext +); + +typedef BOOL +(CALLBACK *PSYM_ENUMMODULES_CALLBACKW64)( + __in PCWSTR ModuleName, + __in DWORD64 BaseOfDll, + __in_opt PVOID UserContext +); + +typedef BOOL +(CALLBACK *PENUMLOADED_MODULES_CALLBACK64)( + __in PCSTR ModuleName, + __in DWORD64 ModuleBase, + __in ULONG ModuleSize, + __in_opt PVOID UserContext +); + +typedef BOOL +(CALLBACK *PENUMLOADED_MODULES_CALLBACKW64)( + __in PCWSTR ModuleName, + __in DWORD64 ModuleBase, + __in ULONG ModuleSize, + __in_opt PVOID UserContext +); + +typedef BOOL +(CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK64)( + __in PCSTR SymbolName, + __in DWORD64 SymbolAddress, + __in ULONG SymbolSize, + __in_opt PVOID UserContext +); + +typedef BOOL +(CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK64W)( + __in PCWSTR SymbolName, + __in DWORD64 SymbolAddress, + __in ULONG SymbolSize, + __in_opt PVOID UserContext +); + +typedef BOOL +(CALLBACK *PSYMBOL_REGISTERED_CALLBACK64)( + __in HANDLE hProcess, + __in ULONG ActionCode, + __in_opt ULONG64 CallbackData, + __in_opt ULONG64 UserContext +); + +typedef +PVOID +(CALLBACK *PSYMBOL_FUNCENTRY_CALLBACK)( + __in HANDLE hProcess, + __in DWORD AddrBase, + __in_opt PVOID UserContext +); + +typedef +PVOID +(CALLBACK *PSYMBOL_FUNCENTRY_CALLBACK64)( + __in HANDLE hProcess, + __in ULONG64 AddrBase, + __in ULONG64 UserContext +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) + +#define PSYM_ENUMMODULES_CALLBACK PSYM_ENUMMODULES_CALLBACK64 +#define PSYM_ENUMSYMBOLS_CALLBACK PSYM_ENUMSYMBOLS_CALLBACK64 +#define PSYM_ENUMSYMBOLS_CALLBACKW PSYM_ENUMSYMBOLS_CALLBACK64W +#define PENUMLOADED_MODULES_CALLBACK PENUMLOADED_MODULES_CALLBACK64 +#define PSYMBOL_REGISTERED_CALLBACK PSYMBOL_REGISTERED_CALLBACK64 +#define PSYMBOL_FUNCENTRY_CALLBACK PSYMBOL_FUNCENTRY_CALLBACK64 + +#else + +typedef BOOL +(CALLBACK *PSYM_ENUMMODULES_CALLBACK)( + __in PCSTR ModuleName, + __in ULONG BaseOfDll, + __in_opt PVOID UserContext +); + +typedef BOOL +(CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK)( + __in PCSTR SymbolName, + __in ULONG SymbolAddress, + __in ULONG SymbolSize, + __in_opt PVOID UserContext +); + +typedef BOOL +(CALLBACK *PSYM_ENUMSYMBOLS_CALLBACKW)( + __in PCWSTR SymbolName, + __in ULONG SymbolAddress, + __in ULONG SymbolSize, + __in_opt PVOID UserContext +); + +typedef BOOL +(CALLBACK *PENUMLOADED_MODULES_CALLBACK)( + __in PCSTR ModuleName, + __in ULONG ModuleBase, + __in ULONG ModuleSize, + __in_opt PVOID UserContext +); + +typedef BOOL +(CALLBACK *PSYMBOL_REGISTERED_CALLBACK)( + __in HANDLE hProcess, + __in ULONG ActionCode, + __in_opt PVOID CallbackData, + __in_opt PVOID UserContext +); + +#endif + + +// values found in SYMBOL_INFO.Tag +// +// This was taken from cvconst.h and should +// not override any values found there. +// +// #define _NO_CVCONST_H_ if you don't +// have access to that file... + +#ifdef _NO_CVCONST_H + +// DIA enums + +enum SymTagEnum +{ + SymTagNull, + SymTagExe, + SymTagCompiland, + SymTagCompilandDetails, + SymTagCompilandEnv, + SymTagFunction, + SymTagBlock, + SymTagData, + SymTagAnnotation, + SymTagLabel, + SymTagPublicSymbol, + SymTagUDT, + SymTagEnum, + SymTagFunctionType, + SymTagPointerType, + SymTagArrayType, + SymTagBaseType, + SymTagTypedef, + SymTagBaseClass, + SymTagFriend, + SymTagFunctionArgType, + SymTagFuncDebugStart, + SymTagFuncDebugEnd, + SymTagUsingNamespace, + SymTagVTableShape, + SymTagVTable, + SymTagCustom, + SymTagThunk, + SymTagCustomType, + SymTagManagedType, + SymTagDimension, + SymTagMax +}; + +#endif + +// +// flags found in SYMBOL_INFO.Flags +// + +#define SYMFLAG_VALUEPRESENT 0x00000001 +#define SYMFLAG_REGISTER 0x00000008 +#define SYMFLAG_REGREL 0x00000010 +#define SYMFLAG_FRAMEREL 0x00000020 +#define SYMFLAG_PARAMETER 0x00000040 +#define SYMFLAG_LOCAL 0x00000080 +#define SYMFLAG_CONSTANT 0x00000100 +#define SYMFLAG_EXPORT 0x00000200 +#define SYMFLAG_FORWARDER 0x00000400 +#define SYMFLAG_FUNCTION 0x00000800 +#define SYMFLAG_VIRTUAL 0x00001000 +#define SYMFLAG_THUNK 0x00002000 +#define SYMFLAG_TLSREL 0x00004000 +#define SYMFLAG_SLOT 0x00008000 +#define SYMFLAG_ILREL 0x00010000 +#define SYMFLAG_METADATA 0x00020000 +#define SYMFLAG_CLR_TOKEN 0x00040000 + +// this resets SymNext/Prev to the beginning +// of the module passed in the address field + +#define SYMFLAG_RESET 0x80000000 + +// +// symbol type enumeration +// +typedef enum +{ + SymNone = 0, + SymCoff, + SymCv, + SymPdb, + SymExport, + SymDeferred, + SymSym, // .sym file + SymDia, + SymVirtual, + NumSymTypes +} SYM_TYPE; + +// +// symbol data structure +// + +typedef struct _IMAGEHLP_SYMBOL64 +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_SYMBOL64) + DWORD64 Address; // virtual address including dll base address + DWORD Size; // estimated size of symbol, can be zero + DWORD Flags; // info about the symbols, see the SYMF defines + DWORD MaxNameLength; // maximum size of symbol name in 'Name' + CHAR Name[1]; // symbol name (null terminated string) +} IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64; + +typedef struct _IMAGEHLP_SYMBOL64_PACKAGE +{ + IMAGEHLP_SYMBOL64 sym; + CHAR name[MAX_SYM_NAME + 1]; +} IMAGEHLP_SYMBOL64_PACKAGE, *PIMAGEHLP_SYMBOL64_PACKAGE; + +typedef struct _IMAGEHLP_SYMBOLW64 +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_SYMBOLW64) + DWORD64 Address; // virtual address including dll base address + DWORD Size; // estimated size of symbol, can be zero + DWORD Flags; // info about the symbols, see the SYMF defines + DWORD MaxNameLength; // maximum size of symbol name in 'Name' + WCHAR Name[1]; // symbol name (null terminated string) +} IMAGEHLP_SYMBOLW64, *PIMAGEHLP_SYMBOLW64; + +typedef struct _IMAGEHLP_SYMBOLW64_PACKAGE +{ + IMAGEHLP_SYMBOLW64 sym; + WCHAR name[MAX_SYM_NAME + 1]; +} IMAGEHLP_SYMBOLW64_PACKAGE, *PIMAGEHLP_SYMBOLW64_PACKAGE; + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) + +#define IMAGEHLP_SYMBOL IMAGEHLP_SYMBOL64 +#define PIMAGEHLP_SYMBOL PIMAGEHLP_SYMBOL64 +#define IMAGEHLP_SYMBOL_PACKAGE IMAGEHLP_SYMBOL64_PACKAGE +#define PIMAGEHLP_SYMBOL_PACKAGE PIMAGEHLP_SYMBOL64_PACKAGE +#define IMAGEHLP_SYMBOLW IMAGEHLP_SYMBOLW64 +#define PIMAGEHLP_SYMBOLW PIMAGEHLP_SYMBOLW64 +#define IMAGEHLP_SYMBOLW_PACKAGE IMAGEHLP_SYMBOLW64_PACKAGE +#define PIMAGEHLP_SYMBOLW_PACKAGE PIMAGEHLP_SYMBOLW64_PACKAGE + +#else + +typedef struct _IMAGEHLP_SYMBOL +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_SYMBOL) + DWORD Address; // virtual address including dll base address + DWORD Size; // estimated size of symbol, can be zero + DWORD Flags; // info about the symbols, see the SYMF defines + DWORD MaxNameLength; // maximum size of symbol name in 'Name' + CHAR Name[1]; // symbol name (null terminated string) +} IMAGEHLP_SYMBOL, *PIMAGEHLP_SYMBOL; + +typedef struct _IMAGEHLP_SYMBOL_PACKAGE +{ + IMAGEHLP_SYMBOL sym; + CHAR name[MAX_SYM_NAME + 1]; +} IMAGEHLP_SYMBOL_PACKAGE, *PIMAGEHLP_SYMBOL_PACKAGE; + +typedef struct _IMAGEHLP_SYMBOLW +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_SYMBOLW) + DWORD Address; // virtual address including dll base address + DWORD Size; // estimated size of symbol, can be zero + DWORD Flags; // info about the symbols, see the SYMF defines + DWORD MaxNameLength; // maximum size of symbol name in 'Name' + WCHAR Name[1]; // symbol name (null terminated string) +} IMAGEHLP_SYMBOLW, *PIMAGEHLP_SYMBOLW; + +typedef struct _IMAGEHLP_SYMBOLW_PACKAGE +{ + IMAGEHLP_SYMBOLW sym; + WCHAR name[MAX_SYM_NAME + 1]; +} IMAGEHLP_SYMBOLW_PACKAGE, *PIMAGEHLP_SYMBOLW_PACKAGE; + +#endif + +// +// module data structure +// + +typedef struct _IMAGEHLP_MODULE64 +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) + DWORD64 BaseOfImage; // base load address of module + DWORD ImageSize; // virtual size of the loaded module + DWORD TimeDateStamp; // date/time stamp from pe header + DWORD CheckSum; // checksum from the pe header + DWORD NumSyms; // number of symbols in the symbol table + SYM_TYPE SymType; // type of symbols loaded + CHAR ModuleName[32]; // module name + CHAR ImageName[256]; // image name + CHAR LoadedImageName[256]; // symbol file name + // new elements: 07-Jun-2002 + CHAR LoadedPdbName[256]; // pdb file name + DWORD CVSig; // Signature of the CV record in the debug directories + CHAR CVData[MAX_PATH * 3]; // Contents of the CV record + DWORD PdbSig; // Signature of PDB + GUID PdbSig70; // Signature of PDB (VC 7 and up) + DWORD PdbAge; // DBI age of pdb + BOOL PdbUnmatched; // loaded an unmatched pdb + BOOL DbgUnmatched; // loaded an unmatched dbg + BOOL LineNumbers; // we have line number information + BOOL GlobalSymbols; // we have internal symbol information + BOOL TypeInfo; // we have type information + // new elements: 17-Dec-2003 + BOOL SourceIndexed; // pdb supports source server + BOOL Publics; // contains public symbols +} IMAGEHLP_MODULE64, *PIMAGEHLP_MODULE64; + +typedef struct _IMAGEHLP_MODULEW64 +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) + DWORD64 BaseOfImage; // base load address of module + DWORD ImageSize; // virtual size of the loaded module + DWORD TimeDateStamp; // date/time stamp from pe header + DWORD CheckSum; // checksum from the pe header + DWORD NumSyms; // number of symbols in the symbol table + SYM_TYPE SymType; // type of symbols loaded + WCHAR ModuleName[32]; // module name + WCHAR ImageName[256]; // image name + // new elements: 07-Jun-2002 + WCHAR LoadedImageName[256]; // symbol file name + WCHAR LoadedPdbName[256]; // pdb file name + DWORD CVSig; // Signature of the CV record in the debug directories + WCHAR CVData[MAX_PATH * 3]; // Contents of the CV record + DWORD PdbSig; // Signature of PDB + GUID PdbSig70; // Signature of PDB (VC 7 and up) + DWORD PdbAge; // DBI age of pdb + BOOL PdbUnmatched; // loaded an unmatched pdb + BOOL DbgUnmatched; // loaded an unmatched dbg + BOOL LineNumbers; // we have line number information + BOOL GlobalSymbols; // we have internal symbol information + BOOL TypeInfo; // we have type information + // new elements: 17-Dec-2003 + BOOL SourceIndexed; // pdb supports source server + BOOL Publics; // contains public symbols +} IMAGEHLP_MODULEW64, *PIMAGEHLP_MODULEW64; + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define IMAGEHLP_MODULE IMAGEHLP_MODULE64 +#define PIMAGEHLP_MODULE PIMAGEHLP_MODULE64 +#define IMAGEHLP_MODULEW IMAGEHLP_MODULEW64 +#define PIMAGEHLP_MODULEW PIMAGEHLP_MODULEW64 +#else +typedef struct _IMAGEHLP_MODULE +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE) + DWORD BaseOfImage; // base load address of module + DWORD ImageSize; // virtual size of the loaded module + DWORD TimeDateStamp; // date/time stamp from pe header + DWORD CheckSum; // checksum from the pe header + DWORD NumSyms; // number of symbols in the symbol table + SYM_TYPE SymType; // type of symbols loaded + CHAR ModuleName[32]; // module name + CHAR ImageName[256]; // image name + CHAR LoadedImageName[256]; // symbol file name +} IMAGEHLP_MODULE, *PIMAGEHLP_MODULE; + +typedef struct _IMAGEHLP_MODULEW +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE) + DWORD BaseOfImage; // base load address of module + DWORD ImageSize; // virtual size of the loaded module + DWORD TimeDateStamp; // date/time stamp from pe header + DWORD CheckSum; // checksum from the pe header + DWORD NumSyms; // number of symbols in the symbol table + SYM_TYPE SymType; // type of symbols loaded + WCHAR ModuleName[32]; // module name + WCHAR ImageName[256]; // image name + WCHAR LoadedImageName[256]; // symbol file name +} IMAGEHLP_MODULEW, *PIMAGEHLP_MODULEW; +#endif + +// +// source file line data structure +// + +typedef struct _IMAGEHLP_LINE64 +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_LINE64) + PVOID Key; // internal + DWORD LineNumber; // line number in file + PCHAR FileName; // full filename + DWORD64 Address; // first instruction of line +} IMAGEHLP_LINE64, *PIMAGEHLP_LINE64; + +typedef struct _IMAGEHLP_LINEW64 +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_LINE64) + PVOID Key; // internal + DWORD LineNumber; // line number in file + PWSTR FileName; // full filename + DWORD64 Address; // first instruction of line +} IMAGEHLP_LINEW64, *PIMAGEHLP_LINEW64; + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define IMAGEHLP_LINE IMAGEHLP_LINE64 +#define PIMAGEHLP_LINE PIMAGEHLP_LINE64 +#else +typedef struct _IMAGEHLP_LINE +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_LINE) + PVOID Key; // internal + DWORD LineNumber; // line number in file + PCHAR FileName; // full filename + DWORD Address; // first instruction of line +} IMAGEHLP_LINE, *PIMAGEHLP_LINE; + +typedef struct _IMAGEHLP_LINEW +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_LINE64) + PVOID Key; // internal + DWORD LineNumber; // line number in file + PCHAR FileName; // full filename + DWORD64 Address; // first instruction of line +} IMAGEHLP_LINEW, *PIMAGEHLP_LINEW; +#endif + +// +// source file structure +// + +typedef struct _SOURCEFILE +{ + DWORD64 ModBase; // base address of loaded module + PCHAR FileName; // full filename of source +} SOURCEFILE, *PSOURCEFILE; + +typedef struct _SOURCEFILEW +{ + DWORD64 ModBase; // base address of loaded module + PWSTR FileName; // full filename of source +} SOURCEFILEW, *PSOURCEFILEW; + +// +// data structures used for registered symbol callbacks +// + +#define CBA_DEFERRED_SYMBOL_LOAD_START 0x00000001 +#define CBA_DEFERRED_SYMBOL_LOAD_COMPLETE 0x00000002 +#define CBA_DEFERRED_SYMBOL_LOAD_FAILURE 0x00000003 +#define CBA_SYMBOLS_UNLOADED 0x00000004 +#define CBA_DUPLICATE_SYMBOL 0x00000005 +#define CBA_READ_MEMORY 0x00000006 +#define CBA_DEFERRED_SYMBOL_LOAD_CANCEL 0x00000007 +#define CBA_SET_OPTIONS 0x00000008 +#define CBA_EVENT 0x00000010 +#define CBA_DEFERRED_SYMBOL_LOAD_PARTIAL 0x00000020 +#define CBA_DEBUG_INFO 0x10000000 +#define CBA_SRCSRV_INFO 0x20000000 +#define CBA_SRCSRV_EVENT 0x40000000 + +typedef struct _IMAGEHLP_CBA_READ_MEMORY +{ + DWORD64 addr; // address to read from + PVOID buf; // buffer to read to + DWORD bytes; // amount of bytes to read + DWORD *bytesread; // pointer to store amount of bytes read +} IMAGEHLP_CBA_READ_MEMORY, *PIMAGEHLP_CBA_READ_MEMORY; + +enum +{ + sevInfo = 0, + sevProblem, + sevAttn, + sevFatal, + sevMax // unused +}; + +#define EVENT_SRCSPEW_START 100 +#define EVENT_SRCSPEW 100 +#define EVENT_SRCSPEW_END 199 + +typedef struct _IMAGEHLP_CBA_EVENT +{ + DWORD severity; // values from sevInfo to sevFatal + DWORD code; // numerical code IDs the error + PCHAR desc; // may contain a text description of the error + PVOID object; // value dependant upon the error code +} IMAGEHLP_CBA_EVENT, *PIMAGEHLP_CBA_EVENT; + +typedef struct _IMAGEHLP_CBA_EVENTW +{ + DWORD severity; // values from sevInfo to sevFatal + DWORD code; // numerical code IDs the error + PCWSTR desc; // may contain a text description of the error + PVOID object; // value dependant upon the error code +} IMAGEHLP_CBA_EVENTW, *PIMAGEHLP_CBA_EVENTW; + +typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOAD64 +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_DEFERRED_SYMBOL_LOAD64) + DWORD64 BaseOfImage; // base load address of module + DWORD CheckSum; // checksum from the pe header + DWORD TimeDateStamp; // date/time stamp from pe header + CHAR FileName[MAX_PATH]; // symbols file or image name + BOOLEAN Reparse; // load failure reparse + HANDLE hFile; // file handle, if passed + DWORD Flags; // +} IMAGEHLP_DEFERRED_SYMBOL_LOAD64, *PIMAGEHLP_DEFERRED_SYMBOL_LOAD64; + +typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOADW64 +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_DEFERRED_SYMBOL_LOADW64) + DWORD64 BaseOfImage; // base load address of module + DWORD CheckSum; // checksum from the pe header + DWORD TimeDateStamp; // date/time stamp from pe header + WCHAR FileName[MAX_PATH + 1]; // symbols file or image name + BOOLEAN Reparse; // load failure reparse + HANDLE hFile; // file handle, if passed + DWORD Flags; // +} IMAGEHLP_DEFERRED_SYMBOL_LOADW64, *PIMAGEHLP_DEFERRED_SYMBOL_LOADW64; + +#define DSLFLAG_MISMATCHED_PDB 0x1 +#define DSLFLAG_MISMATCHED_DBG 0x2 + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define IMAGEHLP_DEFERRED_SYMBOL_LOAD IMAGEHLP_DEFERRED_SYMBOL_LOAD64 +#define PIMAGEHLP_DEFERRED_SYMBOL_LOAD PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 +#else +typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOAD +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_DEFERRED_SYMBOL_LOAD) + DWORD BaseOfImage; // base load address of module + DWORD CheckSum; // checksum from the pe header + DWORD TimeDateStamp; // date/time stamp from pe header + CHAR FileName[MAX_PATH]; // symbols file or image name + BOOLEAN Reparse; // load failure reparse + HANDLE hFile; // file handle, if passed +} IMAGEHLP_DEFERRED_SYMBOL_LOAD, *PIMAGEHLP_DEFERRED_SYMBOL_LOAD; +#endif + +typedef struct _IMAGEHLP_DUPLICATE_SYMBOL64 +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_DUPLICATE_SYMBOL64) + DWORD NumberOfDups; // number of duplicates in the Symbol array + PIMAGEHLP_SYMBOL64 Symbol; // array of duplicate symbols + DWORD SelectedSymbol; // symbol selected (-1 to start) +} IMAGEHLP_DUPLICATE_SYMBOL64, *PIMAGEHLP_DUPLICATE_SYMBOL64; + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define IMAGEHLP_DUPLICATE_SYMBOL IMAGEHLP_DUPLICATE_SYMBOL64 +#define PIMAGEHLP_DUPLICATE_SYMBOL PIMAGEHLP_DUPLICATE_SYMBOL64 +#else +typedef struct _IMAGEHLP_DUPLICATE_SYMBOL +{ + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_DUPLICATE_SYMBOL) + DWORD NumberOfDups; // number of duplicates in the Symbol array + PIMAGEHLP_SYMBOL Symbol; // array of duplicate symbols + DWORD SelectedSymbol; // symbol selected (-1 to start) +} IMAGEHLP_DUPLICATE_SYMBOL, *PIMAGEHLP_DUPLICATE_SYMBOL; +#endif + +// If dbghelp ever needs to display graphical UI, it will use this as the parent window. + +BOOL +IMAGEAPI +SymSetParentWindow( + __in HWND hwnd +); + +PCHAR +IMAGEAPI +SymSetHomeDirectory( + __in_opt HANDLE hProcess, + __in_opt PCSTR dir +); + +PWSTR +IMAGEAPI +SymSetHomeDirectoryW( + __in_opt HANDLE hProcess, + __in_opt PCWSTR dir +); + +PCHAR +IMAGEAPI +SymGetHomeDirectory( + __in DWORD type, + __out_ecount(size) PSTR dir, + __in size_t size +); + +PWSTR +IMAGEAPI +SymGetHomeDirectoryW( + __in DWORD type, + __out_ecount(size) PWSTR dir, + __in size_t size +); + +enum +{ + hdBase = 0, // root directory for dbghelp + hdSym, // where symbols are stored + hdSrc, // where source is stored + hdMax // end marker +}; + +typedef struct _OMAP +{ + ULONG rva; + ULONG rvaTo; +} OMAP, *POMAP; + +BOOL +IMAGEAPI +SymGetOmaps( + __in HANDLE hProcess, + __in DWORD64 BaseOfDll, + __out POMAP *OmapTo, + __out PDWORD64 cOmapTo, + __out POMAP *OmapFrom, + __out PDWORD64 cOmapFrom +); + +// +// options that are set/returned by SymSetOptions() & SymGetOptions() +// these are used as a mask +// +#define SYMOPT_CASE_INSENSITIVE 0x00000001 +#define SYMOPT_UNDNAME 0x00000002 +#define SYMOPT_DEFERRED_LOADS 0x00000004 +#define SYMOPT_NO_CPP 0x00000008 +#define SYMOPT_LOAD_LINES 0x00000010 +#define SYMOPT_OMAP_FIND_NEAREST 0x00000020 +#define SYMOPT_LOAD_ANYTHING 0x00000040 +#define SYMOPT_IGNORE_CVREC 0x00000080 +#define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100 +#define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200 +#define SYMOPT_EXACT_SYMBOLS 0x00000400 +#define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800 +#define SYMOPT_IGNORE_NT_SYMPATH 0x00001000 +#define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000 +#define SYMOPT_PUBLICS_ONLY 0x00004000 +#define SYMOPT_NO_PUBLICS 0x00008000 +#define SYMOPT_AUTO_PUBLICS 0x00010000 +#define SYMOPT_NO_IMAGE_SEARCH 0x00020000 +#define SYMOPT_SECURE 0x00040000 +#define SYMOPT_NO_PROMPTS 0x00080000 +#define SYMOPT_OVERWRITE 0x00100000 +#define SYMOPT_IGNORE_IMAGEDIR 0x00200000 +#define SYMOPT_FLAT_DIRECTORY 0x00400000 +#define SYMOPT_FAVOR_COMPRESSED 0x00800000 +#define SYMOPT_ALLOW_ZERO_ADDRESS 0x01000000 +#define SYMOPT_DISABLE_SYMSRV_AUTODETECT 0x02000000 + +#define SYMOPT_DEBUG 0x80000000 + +DWORD +IMAGEAPI +SymSetOptions( + __in DWORD SymOptions +); + +DWORD +IMAGEAPI +SymGetOptions( + VOID +); + +BOOL +IMAGEAPI +SymCleanup( + __in HANDLE hProcess +); + +BOOL +IMAGEAPI +SymMatchString( + __in PCSTR string, + __in PCSTR expression, + __in BOOL fCase +); + +BOOL +IMAGEAPI +SymMatchStringA( + __in PCSTR string, + __in PCSTR expression, + __in BOOL fCase +); + +BOOL +IMAGEAPI +SymMatchStringW( + __in PCWSTR string, + __in PCWSTR expression, + __in BOOL fCase +); + +typedef BOOL +(CALLBACK *PSYM_ENUMSOURCEFILES_CALLBACK)( + __in PSOURCEFILE pSourceFile, + __in_opt PVOID UserContext +); + +// for backwards compatibility - don't use this +#define PSYM_ENUMSOURCFILES_CALLBACK PSYM_ENUMSOURCEFILES_CALLBACK + +BOOL +IMAGEAPI +SymEnumSourceFiles( + __in HANDLE hProcess, + __in ULONG64 ModBase, + __in_opt PCSTR Mask, + __in PSYM_ENUMSOURCEFILES_CALLBACK cbSrcFiles, + __in_opt PVOID UserContext +); + +typedef BOOL +(CALLBACK *PSYM_ENUMSOURCEFILES_CALLBACKW)( + __in PSOURCEFILEW pSourceFile, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymEnumSourceFilesW( + __in HANDLE hProcess, + __in ULONG64 ModBase, + __in_opt PCWSTR Mask, + __in PSYM_ENUMSOURCEFILES_CALLBACKW cbSrcFiles, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymEnumerateModules64( + __in HANDLE hProcess, + __in PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymEnumerateModulesW64( + __in HANDLE hProcess, + __in PSYM_ENUMMODULES_CALLBACKW64 EnumModulesCallback, + __in_opt PVOID UserContext +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymEnumerateModules SymEnumerateModules64 +#else +BOOL +IMAGEAPI +SymEnumerateModules( + __in HANDLE hProcess, + __in PSYM_ENUMMODULES_CALLBACK EnumModulesCallback, + __in_opt PVOID UserContext +); +#endif + +BOOL +IMAGEAPI +EnumerateLoadedModulesEx( + __in HANDLE hProcess, + __in PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +EnumerateLoadedModulesExW( + __in HANDLE hProcess, + __in PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +EnumerateLoadedModules64( + __in HANDLE hProcess, + __in PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +EnumerateLoadedModulesW64( + __in HANDLE hProcess, + __in PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback, + __in_opt PVOID UserContext +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define EnumerateLoadedModules EnumerateLoadedModules64 +#else +BOOL +IMAGEAPI +EnumerateLoadedModules( + __in HANDLE hProcess, + __in PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback, + __in_opt PVOID UserContext +); +#endif + +PVOID +IMAGEAPI +SymFunctionTableAccess64( + __in HANDLE hProcess, + __in DWORD64 AddrBase +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymFunctionTableAccess SymFunctionTableAccess64 +#else +PVOID +IMAGEAPI +SymFunctionTableAccess( + __in HANDLE hProcess, + __in DWORD AddrBase +); +#endif + +BOOL +IMAGEAPI +SymGetUnwindInfo( + __in HANDLE hProcess, + __in DWORD64 Address, + __out_bcount_opt(*Size) PVOID Buffer, + __inout PULONG Size +); + +BOOL +IMAGEAPI +SymGetModuleInfo64( + __in HANDLE hProcess, + __in DWORD64 qwAddr, + __out PIMAGEHLP_MODULE64 ModuleInfo +); + +BOOL +IMAGEAPI +SymGetModuleInfoW64( + __in HANDLE hProcess, + __in DWORD64 qwAddr, + __out PIMAGEHLP_MODULEW64 ModuleInfo +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetModuleInfo SymGetModuleInfo64 +#define SymGetModuleInfoW SymGetModuleInfoW64 +#else +BOOL +IMAGEAPI +SymGetModuleInfo( + __in HANDLE hProcess, + __in DWORD dwAddr, + __out PIMAGEHLP_MODULE ModuleInfo +); + +BOOL +IMAGEAPI +SymGetModuleInfoW( + __in HANDLE hProcess, + __in DWORD dwAddr, + __out PIMAGEHLP_MODULEW ModuleInfo +); +#endif + +DWORD64 +IMAGEAPI +SymGetModuleBase64( + __in HANDLE hProcess, + __in DWORD64 qwAddr +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetModuleBase SymGetModuleBase64 +#else +DWORD +IMAGEAPI +SymGetModuleBase( + __in HANDLE hProcess, + __in DWORD dwAddr +); +#endif + +typedef struct _SRCCODEINFO +{ + DWORD SizeOfStruct; // set to sizeof(SRCCODEINFO) + PVOID Key; // not used + DWORD64 ModBase; // base address of module this applies to + CHAR Obj[MAX_PATH + 1]; // the object file within the module + CHAR FileName[MAX_PATH + 1]; // full filename + DWORD LineNumber; // line number in file + DWORD64 Address; // first instruction of line +} SRCCODEINFO, *PSRCCODEINFO; + +typedef struct _SRCCODEINFOW +{ + DWORD SizeOfStruct; // set to sizeof(SRCCODEINFO) + PVOID Key; // not used + DWORD64 ModBase; // base address of module this applies to + WCHAR Obj[MAX_PATH + 1]; // the object file within the module + WCHAR FileName[MAX_PATH + 1]; // full filename + DWORD LineNumber; // line number in file + DWORD64 Address; // first instruction of line +} SRCCODEINFOW, *PSRCCODEINFOW; + +typedef BOOL +(CALLBACK *PSYM_ENUMLINES_CALLBACK)( + __in PSRCCODEINFO LineInfo, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymEnumLines( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCSTR Obj, + __in_opt PCSTR File, + __in PSYM_ENUMLINES_CALLBACK EnumLinesCallback, + __in_opt PVOID UserContext +); + +typedef BOOL +(CALLBACK *PSYM_ENUMLINES_CALLBACKW)( + __in PSRCCODEINFOW LineInfo, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymEnumLinesW( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCWSTR Obj, + __in_opt PCWSTR File, + __in PSYM_ENUMLINES_CALLBACKW EnumLinesCallback, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymGetLineFromAddr64( + __in HANDLE hProcess, + __in DWORD64 qwAddr, + __out PDWORD pdwDisplacement, + __out PIMAGEHLP_LINE64 Line64 +); + +BOOL +IMAGEAPI +SymGetLineFromAddrW64( + __in HANDLE hProcess, + __in DWORD64 dwAddr, + __out PDWORD pdwDisplacement, + __out PIMAGEHLP_LINEW64 Line +); + +BOOL +IMAGEAPI +SymEnumSourceLines( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCSTR Obj, + __in_opt PCSTR File, + __in_opt DWORD Line, + __in DWORD Flags, + __in PSYM_ENUMLINES_CALLBACK EnumLinesCallback, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymEnumSourceLinesW( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCWSTR Obj, + __in_opt PCWSTR File, + __in_opt DWORD Line, + __in DWORD Flags, + __in PSYM_ENUMLINES_CALLBACKW EnumLinesCallback, + __in_opt PVOID UserContext +); + +// flags for SymEnumSourceLines + +#define ESLFLAG_FULLPATH 0x1 +#define ESLFLAG_NEAREST 0x2 +#define ESLFLAG_PREV 0x4 +#define ESLFLAG_NEXT 0x8 + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetLineFromAddr SymGetLineFromAddr64 +#define SymGetLineFromAddrW SymGetLineFromAddrW64 +#else +BOOL +IMAGEAPI +SymGetLineFromAddr( + __in HANDLE hProcess, + __in DWORD dwAddr, + __out PDWORD pdwDisplacement, + __out PIMAGEHLP_LINE Line +); + +BOOL +IMAGEAPI +SymGetLineFromAddrW( + __in HANDLE hProcess, + __in DWORD dwAddr, + __out PDWORD pdwDisplacement, + __out PIMAGEHLP_LINEW Line +); +#endif + +BOOL +IMAGEAPI +SymGetLineFromName64( + __in HANDLE hProcess, + __in_opt PCSTR ModuleName, + __in_opt PCSTR FileName, + __in DWORD dwLineNumber, + __out PLONG plDisplacement, + __inout PIMAGEHLP_LINE64 Line +); + +BOOL +IMAGEAPI +SymGetLineFromNameW64( + __in HANDLE hProcess, + __in_opt PCWSTR ModuleName, + __in_opt PCWSTR FileName, + __in DWORD dwLineNumber, + __out PLONG plDisplacement, + __inout PIMAGEHLP_LINEW64 Line +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetLineFromName SymGetLineFromName64 +#else +BOOL +IMAGEAPI +SymGetLineFromName( + __in HANDLE hProcess, + __in_opt PCSTR ModuleName, + __in_opt PCSTR FileName, + __in DWORD dwLineNumber, + __out PLONG plDisplacement, + __inout PIMAGEHLP_LINE Line +); +#endif + +BOOL +IMAGEAPI +SymGetLineNext64( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINE64 Line +); + +BOOL +IMAGEAPI +SymGetLineNextW64( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINEW64 Line +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetLineNext SymGetLineNext64 +#else +BOOL +IMAGEAPI +SymGetLineNext( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINE Line +); + +BOOL +IMAGEAPI +SymGetLineNextW( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINEW Line +); +#endif + +BOOL +IMAGEAPI +SymGetLinePrev64( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINE64 Line +); + +BOOL +IMAGEAPI +SymGetLinePrevW64( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINEW64 Line +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetLinePrev SymGetLinePrev64 +#else +BOOL +IMAGEAPI +SymGetLinePrev( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINE Line +); + +BOOL +IMAGEAPI +SymGetLinePrevW( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINEW Line +); +#endif + +ULONG +IMAGEAPI +SymGetFileLineOffsets64( + __in HANDLE hProcess, + __in_opt PCSTR ModuleName, + __in PCSTR FileName, + __out_ecount(BufferLines) PDWORD64 Buffer, + __in ULONG BufferLines +); + +BOOL +IMAGEAPI +SymMatchFileName( + __in PCSTR FileName, + __in PCSTR Match, + __deref_opt_out PSTR *FileNameStop, + __deref_opt_out PSTR *MatchStop +); + +BOOL +IMAGEAPI +SymMatchFileNameW( + __in PCWSTR FileName, + __in PCWSTR Match, + __deref_opt_out PWSTR *FileNameStop, + __deref_opt_out PWSTR *MatchStop +); + +BOOL +IMAGEAPI +SymGetSourceFile( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCSTR Params, + __in PCSTR FileSpec, + __out_ecount(Size) PSTR FilePath, + __in DWORD Size +); + +BOOL +IMAGEAPI +SymGetSourceFileW( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCWSTR Params, + __in PCWSTR FileSpec, + __out_ecount(Size) PWSTR FilePath, + __in DWORD Size +); + +BOOL +IMAGEAPI +SymGetSourceFileToken( + __in HANDLE hProcess, + __in ULONG64 Base, + __in PCSTR FileSpec, + __deref_out PVOID *Token, + __out DWORD *Size +); + +BOOL +IMAGEAPI +SymGetSourceFileTokenW( + __in HANDLE hProcess, + __in ULONG64 Base, + __in PCWSTR FileSpec, + __deref_out PVOID *Token, + __out DWORD *Size +); + +BOOL +IMAGEAPI +SymGetSourceFileFromToken( + __in HANDLE hProcess, + __in PVOID Token, + __in_opt PCSTR Params, + __out_ecount(Size) PSTR FilePath, + __in DWORD Size +); + +BOOL +IMAGEAPI +SymGetSourceFileFromTokenW( + __in HANDLE hProcess, + __in PVOID Token, + __in_opt PCWSTR Params, + __out_ecount(Size) PWSTR FilePath, + __in DWORD Size +); + +BOOL +IMAGEAPI +SymGetSourceVarFromToken( + __in HANDLE hProcess, + __in PVOID Token, + __in_opt PCSTR Params, + __in PCSTR VarName, + __out_ecount(Size) PSTR Value, + __in DWORD Size +); + +BOOL +IMAGEAPI +SymGetSourceVarFromTokenW( + __in HANDLE hProcess, + __in PVOID Token, + __in_opt PCWSTR Params, + __in PCWSTR VarName, + __out_ecount(Size) PWSTR Value, + __in DWORD Size +); + +typedef BOOL (CALLBACK *PENUMSOURCEFILETOKENSCALLBACK)(__in PVOID token, __in size_t size); + +BOOL +IMAGEAPI +SymEnumSourceFileTokens( + __in HANDLE hProcess, + __in ULONG64 Base, + __in PENUMSOURCEFILETOKENSCALLBACK Callback +); + +BOOL +IMAGEAPI +SymInitialize( + __in HANDLE hProcess, + __in_opt PCSTR UserSearchPath, + __in BOOL fInvadeProcess +); + +BOOL +IMAGEAPI +SymInitializeW( + __in HANDLE hProcess, + __in_opt PCWSTR UserSearchPath, + __in BOOL fInvadeProcess +); + +BOOL +IMAGEAPI +SymGetSearchPath( + __in HANDLE hProcess, + __out_ecount(SearchPathLength) PSTR SearchPath, + __in DWORD SearchPathLength +); + +BOOL +IMAGEAPI +SymGetSearchPathW( + __in HANDLE hProcess, + __out_ecount(SearchPathLength) PWSTR SearchPath, + __in DWORD SearchPathLength +); + +BOOL +IMAGEAPI +SymSetSearchPath( + __in HANDLE hProcess, + __in_opt PCSTR SearchPath +); + +BOOL +IMAGEAPI +SymSetSearchPathW( + __in HANDLE hProcess, + __in_opt PCWSTR SearchPath +); + +#define SLMFLAG_VIRTUAL 0x1 +#define SLMFLAG_ALT_INDEX 0x2 +#define SLMFLAG_NO_SYMBOLS 0x4 + +DWORD64 +IMAGEAPI +SymLoadModuleEx( + __in HANDLE hProcess, + __in_opt HANDLE hFile, + __in_opt PCSTR ImageName, + __in_opt PCSTR ModuleName, + __in DWORD64 BaseOfDll, + __in DWORD DllSize, + __in_opt PMODLOAD_DATA Data, + __in_opt DWORD Flags +); + +DWORD64 +IMAGEAPI +SymLoadModuleExW( + __in HANDLE hProcess, + __in_opt HANDLE hFile, + __in_opt PCWSTR ImageName, + __in_opt PCWSTR ModuleName, + __in DWORD64 BaseOfDll, + __in DWORD DllSize, + __in_opt PMODLOAD_DATA Data, + __in_opt DWORD Flags +); + +BOOL +IMAGEAPI +SymUnloadModule64( + __in HANDLE hProcess, + __in DWORD64 BaseOfDll +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymUnloadModule SymUnloadModule64 +#else +BOOL +IMAGEAPI +SymUnloadModule( + __in HANDLE hProcess, + __in DWORD BaseOfDll +); +#endif + +BOOL +IMAGEAPI +SymUnDName64( + __in PIMAGEHLP_SYMBOL64 sym, // Symbol to undecorate + __out_ecount(UnDecNameLength) PSTR UnDecName, // Buffer to store undecorated name in + __in DWORD UnDecNameLength // Size of the buffer +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymUnDName SymUnDName64 +#else +BOOL +IMAGEAPI +SymUnDName( + __in PIMAGEHLP_SYMBOL sym, // Symbol to undecorate + __out_ecount(UnDecNameLength) PSTR UnDecName, // Buffer to store undecorated name in + __in DWORD UnDecNameLength // Size of the buffer +); +#endif + +BOOL +IMAGEAPI +SymRegisterCallback64( + __in HANDLE hProcess, + __in PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction, + __in ULONG64 UserContext +); + +BOOL +IMAGEAPI +SymRegisterCallbackW64( + __in HANDLE hProcess, + __in PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction, + __in ULONG64 UserContext +); + +BOOL +IMAGEAPI +SymRegisterFunctionEntryCallback64( + __in HANDLE hProcess, + __in PSYMBOL_FUNCENTRY_CALLBACK64 CallbackFunction, + __in ULONG64 UserContext +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymRegisterCallback SymRegisterCallback64 +#define SymRegisterFunctionEntryCallback SymRegisterFunctionEntryCallback64 +#else +BOOL +IMAGEAPI +SymRegisterCallback( + __in HANDLE hProcess, + __in PSYMBOL_REGISTERED_CALLBACK CallbackFunction, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymRegisterFunctionEntryCallback( + __in HANDLE hProcess, + __in PSYMBOL_FUNCENTRY_CALLBACK CallbackFunction, + __in_opt PVOID UserContext +); +#endif + + +typedef struct _IMAGEHLP_SYMBOL_SRC +{ + DWORD sizeofstruct; + DWORD type; + char file[MAX_PATH]; +} IMAGEHLP_SYMBOL_SRC, *PIMAGEHLP_SYMBOL_SRC; + +typedef struct _MODULE_TYPE_INFO // AKA TYPTYP +{ + USHORT dataLength; + USHORT leaf; + BYTE data[1]; +} MODULE_TYPE_INFO, *PMODULE_TYPE_INFO; + +typedef struct _SYMBOL_INFO +{ + ULONG SizeOfStruct; + ULONG TypeIndex; // Type Index of symbol + ULONG64 Reserved[2]; + ULONG Index; + ULONG Size; + ULONG64 ModBase; // Base Address of module comtaining this symbol + ULONG Flags; + ULONG64 Value; // Value of symbol, ValuePresent should be 1 + ULONG64 Address; // Address of symbol including base address of module + ULONG Register; // register holding value or pointer to value + ULONG Scope; // scope of the symbol + ULONG Tag; // pdb classification + ULONG NameLen; // Actual length of name + ULONG MaxNameLen; + CHAR Name[1]; // Name of symbol +} SYMBOL_INFO, *PSYMBOL_INFO; + +typedef struct _SYMBOL_INFO_PACKAGE +{ + SYMBOL_INFO si; + CHAR name[MAX_SYM_NAME + 1]; +} SYMBOL_INFO_PACKAGE, *PSYMBOL_INFO_PACKAGE; + +typedef struct _SYMBOL_INFOW +{ + ULONG SizeOfStruct; + ULONG TypeIndex; // Type Index of symbol + ULONG64 Reserved[2]; + ULONG Index; + ULONG Size; + ULONG64 ModBase; // Base Address of module comtaining this symbol + ULONG Flags; + ULONG64 Value; // Value of symbol, ValuePresent should be 1 + ULONG64 Address; // Address of symbol including base address of module + ULONG Register; // register holding value or pointer to value + ULONG Scope; // scope of the symbol + ULONG Tag; // pdb classification + ULONG NameLen; // Actual length of name + ULONG MaxNameLen; + WCHAR Name[1]; // Name of symbol +} SYMBOL_INFOW, *PSYMBOL_INFOW; + +typedef struct _SYMBOL_INFO_PACKAGEW +{ + SYMBOL_INFOW si; + WCHAR name[MAX_SYM_NAME + 1]; +} SYMBOL_INFO_PACKAGEW, *PSYMBOL_INFO_PACKAGEW; + +typedef struct _IMAGEHLP_STACK_FRAME +{ + ULONG64 InstructionOffset; + ULONG64 ReturnOffset; + ULONG64 FrameOffset; + ULONG64 StackOffset; + ULONG64 BackingStoreOffset; + ULONG64 FuncTableEntry; + ULONG64 Params[4]; + ULONG64 Reserved[5]; + BOOL Virtual; + ULONG Reserved2; +} IMAGEHLP_STACK_FRAME, *PIMAGEHLP_STACK_FRAME; + +typedef VOID IMAGEHLP_CONTEXT, *PIMAGEHLP_CONTEXT; + + +BOOL +IMAGEAPI +SymSetContext( + __in HANDLE hProcess, + __in PIMAGEHLP_STACK_FRAME StackFrame, + __in_opt PIMAGEHLP_CONTEXT Context +); + +BOOL +IMAGEAPI +SymSetScopeFromAddr( + __in HANDLE hProcess, + __in ULONG64 Address +); + +BOOL +IMAGEAPI +SymSetScopeFromIndex( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in DWORD Index +); + +typedef BOOL +(CALLBACK *PSYM_ENUMPROCESSES_CALLBACK)( + __in HANDLE hProcess, + __in PVOID UserContext +); + +BOOL +IMAGEAPI +SymEnumProcesses( + __in PSYM_ENUMPROCESSES_CALLBACK EnumProcessesCallback, + __in PVOID UserContext +); + +BOOL +IMAGEAPI +SymFromAddr( + __in HANDLE hProcess, + __in DWORD64 Address, + __out_opt PDWORD64 Displacement, + __inout PSYMBOL_INFO Symbol +); + +BOOL +IMAGEAPI +SymFromAddrW( + __in HANDLE hProcess, + __in DWORD64 Address, + __out_opt PDWORD64 Displacement, + __inout PSYMBOL_INFOW Symbol +); + +BOOL +IMAGEAPI +SymFromToken( + __in HANDLE hProcess, + __in DWORD64 Base, + __in DWORD Token, + __inout PSYMBOL_INFO Symbol +); + +BOOL +IMAGEAPI +SymFromTokenW( + __in HANDLE hProcess, + __in DWORD64 Base, + __in DWORD Token, + __inout PSYMBOL_INFOW Symbol +); + +BOOL +IMAGEAPI +SymNext( + __in HANDLE hProcess, + __inout PSYMBOL_INFO si +); + +BOOL +IMAGEAPI +SymNextW( + __in HANDLE hProcess, + __inout PSYMBOL_INFOW siw +); + +BOOL +IMAGEAPI +SymPrev( + __in HANDLE hProcess, + __inout PSYMBOL_INFO si +); + +BOOL +IMAGEAPI +SymPrevW( + __in HANDLE hProcess, + __inout PSYMBOL_INFOW siw +); + +// While SymFromName will provide a symbol from a name, +// SymEnumSymbols can provide the same matching information +// for ALL symbols with a matching name, even regular +// expressions. That way you can search across modules +// and differentiate between identically named symbols. + +BOOL +IMAGEAPI +SymFromName( + __in HANDLE hProcess, + __in PCSTR Name, + __inout PSYMBOL_INFO Symbol +); + +BOOL +IMAGEAPI +SymFromNameW( + __in HANDLE hProcess, + __in PCWSTR Name, + __inout PSYMBOL_INFOW Symbol +); + +typedef BOOL +(CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACK)( + __in PSYMBOL_INFO pSymInfo, + __in ULONG SymbolSize, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymEnumSymbols( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt PCSTR Mask, + __in PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, + __in_opt PVOID UserContext +); + +typedef BOOL +(CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACKW)( + __in PSYMBOL_INFOW pSymInfo, + __in ULONG SymbolSize, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymEnumSymbolsW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt PCWSTR Mask, + __in PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymEnumSymbolsForAddr( + __in HANDLE hProcess, + __in DWORD64 Address, + __in PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymEnumSymbolsForAddrW( + __in HANDLE hProcess, + __in DWORD64 Address, + __in PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback, + __in_opt PVOID UserContext +); + +#define SYMSEARCH_MASKOBJS 0x01 // used internally to implement other APIs +#define SYMSEARCH_RECURSE 0X02 // recurse scopes +#define SYMSEARCH_GLOBALSONLY 0X04 // search only for global symbols +#define SYMSEARCH_ALLITEMS 0X08 // search for everything in the pdb, not just normal scoped symbols + +BOOL +IMAGEAPI +SymSearch( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt DWORD Index, + __in_opt DWORD SymTag, + __in_opt PCSTR Mask, + __in_opt DWORD64 Address, + __in PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, + __in_opt PVOID UserContext, + __in DWORD Options +); + +BOOL +IMAGEAPI +SymSearchW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt DWORD Index, + __in_opt DWORD SymTag, + __in_opt PCWSTR Mask, + __in_opt DWORD64 Address, + __in PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback, + __in_opt PVOID UserContext, + __in DWORD Options +); + +BOOL +IMAGEAPI +SymGetScope( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in DWORD Index, + __inout PSYMBOL_INFO Symbol +); + +BOOL +IMAGEAPI +SymGetScopeW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in DWORD Index, + __inout PSYMBOL_INFOW Symbol +); + +BOOL +IMAGEAPI +SymFromIndex( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in DWORD Index, + __inout PSYMBOL_INFO Symbol +); + +BOOL +IMAGEAPI +SymFromIndexW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in DWORD Index, + __inout PSYMBOL_INFOW Symbol +); + +typedef enum _IMAGEHLP_SYMBOL_TYPE_INFO +{ + TI_GET_SYMTAG, + TI_GET_SYMNAME, + TI_GET_LENGTH, + TI_GET_TYPE, + TI_GET_TYPEID, + TI_GET_BASETYPE, + TI_GET_ARRAYINDEXTYPEID, + TI_FINDCHILDREN, + TI_GET_DATAKIND, + TI_GET_ADDRESSOFFSET, + TI_GET_OFFSET, + TI_GET_VALUE, + TI_GET_COUNT, + TI_GET_CHILDRENCOUNT, + TI_GET_BITPOSITION, + TI_GET_VIRTUALBASECLASS, + TI_GET_VIRTUALTABLESHAPEID, + TI_GET_VIRTUALBASEPOINTEROFFSET, + TI_GET_CLASSPARENTID, + TI_GET_NESTED, + TI_GET_SYMINDEX, + TI_GET_LEXICALPARENT, + TI_GET_ADDRESS, + TI_GET_THISADJUST, + TI_GET_UDTKIND, + TI_IS_EQUIV_TO, + TI_GET_CALLING_CONVENTION, + TI_IS_CLOSE_EQUIV_TO, + TI_GTIEX_REQS_VALID, + TI_GET_VIRTUALBASEOFFSET, + TI_GET_VIRTUALBASEDISPINDEX, + TI_GET_IS_REFERENCE, + TI_GET_INDIRECTVIRTUALBASECLASS, + IMAGEHLP_SYMBOL_TYPE_INFO_MAX, +} IMAGEHLP_SYMBOL_TYPE_INFO; + +typedef struct _TI_FINDCHILDREN_PARAMS +{ + ULONG Count; + ULONG Start; + ULONG ChildId[1]; +} TI_FINDCHILDREN_PARAMS; + +BOOL +IMAGEAPI +SymGetTypeInfo( + __in HANDLE hProcess, + __in DWORD64 ModBase, + __in ULONG TypeId, + __in IMAGEHLP_SYMBOL_TYPE_INFO GetType, + __out PVOID pInfo +); + +#define IMAGEHLP_GET_TYPE_INFO_UNCACHED 0x00000001 +#define IMAGEHLP_GET_TYPE_INFO_CHILDREN 0x00000002 + +typedef struct _IMAGEHLP_GET_TYPE_INFO_PARAMS +{ + IN ULONG SizeOfStruct; + IN ULONG Flags; + IN ULONG NumIds; + IN PULONG TypeIds; + IN ULONG64 TagFilter; + IN ULONG NumReqs; + IN IMAGEHLP_SYMBOL_TYPE_INFO* ReqKinds; + IN PULONG_PTR ReqOffsets; + IN PULONG ReqSizes; + IN ULONG_PTR ReqStride; + IN ULONG_PTR BufferSize; + OUT PVOID Buffer; + OUT ULONG EntriesMatched; + OUT ULONG EntriesFilled; + OUT ULONG64 TagsFound; + OUT ULONG64 AllReqsValid; + IN ULONG NumReqsValid; + OUT PULONG64 ReqsValid OPTIONAL; +} IMAGEHLP_GET_TYPE_INFO_PARAMS, *PIMAGEHLP_GET_TYPE_INFO_PARAMS; + +BOOL +IMAGEAPI +SymGetTypeInfoEx( + __in HANDLE hProcess, + __in DWORD64 ModBase, + __inout PIMAGEHLP_GET_TYPE_INFO_PARAMS Params +); + +BOOL +IMAGEAPI +SymEnumTypes( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymEnumTypesW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymEnumTypesByName( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt PCSTR mask, + __in PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymEnumTypesByNameW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt PCWSTR mask, + __in PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback, + __in_opt PVOID UserContext +); + +BOOL +IMAGEAPI +SymGetTypeFromName( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PCSTR Name, + __inout PSYMBOL_INFO Symbol +); + +BOOL +IMAGEAPI +SymGetTypeFromNameW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PCWSTR Name, + __inout PSYMBOL_INFOW Symbol +); + +BOOL +IMAGEAPI +SymAddSymbol( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PCSTR Name, + __in DWORD64 Address, + __in DWORD Size, + __in DWORD Flags +); + +BOOL +IMAGEAPI +SymAddSymbolW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PCWSTR Name, + __in DWORD64 Address, + __in DWORD Size, + __in DWORD Flags +); + +BOOL +IMAGEAPI +SymDeleteSymbol( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt PCSTR Name, + __in DWORD64 Address, + __in DWORD Flags +); + +BOOL +IMAGEAPI +SymDeleteSymbolW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt PCWSTR Name, + __in DWORD64 Address, + __in DWORD Flags +); + +BOOL +IMAGEAPI +SymRefreshModuleList( + __in HANDLE hProcess +); + +BOOL +IMAGEAPI +SymAddSourceStream( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCSTR StreamFile, + __in_bcount_opt(Size) PBYTE Buffer, + __in size_t Size +); + +typedef BOOL (WINAPI *SYMADDSOURCESTREAM)(HANDLE, ULONG64, PCSTR, PBYTE, size_t); + +BOOL +IMAGEAPI +SymAddSourceStreamA( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCSTR StreamFile, + __in_bcount_opt(Size) PBYTE Buffer, + __in size_t Size +); + +typedef BOOL (WINAPI *SYMADDSOURCESTREAMA)(HANDLE, ULONG64, PCSTR, PBYTE, size_t); + +BOOL +IMAGEAPI +SymAddSourceStreamW( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCWSTR FileSpec, + __in_bcount_opt(Size) PBYTE Buffer, + __in size_t Size +); + +BOOL +IMAGEAPI +SymSrvIsStoreW( + __in_opt HANDLE hProcess, + __in PCWSTR path +); + +BOOL +IMAGEAPI +SymSrvIsStore( + __in_opt HANDLE hProcess, + __in PCSTR path +); + +PCSTR +IMAGEAPI +SymSrvDeltaName( + __in HANDLE hProcess, + __in_opt PCSTR SymPath, + __in PCSTR Type, + __in PCSTR File1, + __in PCSTR File2 +); + +PCWSTR +IMAGEAPI +SymSrvDeltaNameW( + __in HANDLE hProcess, + __in_opt PCWSTR SymPath, + __in PCWSTR Type, + __in PCWSTR File1, + __in PCWSTR File2 +); + +PCSTR +IMAGEAPI +SymSrvGetSupplement( + __in HANDLE hProcess, + __in_opt PCSTR SymPath, + __in PCSTR Node, + __in PCSTR File +); + +PCWSTR +IMAGEAPI +SymSrvGetSupplementW( + __in HANDLE hProcess, + __in_opt PCWSTR SymPath, + __in PCWSTR Node, + __in PCWSTR File +); + +BOOL +IMAGEAPI +SymSrvGetFileIndexes( + __in PCSTR File, + __out GUID *Id, + __out PDWORD Val1, + __out_opt PDWORD Val2, + __in DWORD Flags +); + +BOOL +IMAGEAPI +SymSrvGetFileIndexesW( + __in PCWSTR File, + __out GUID *Id, + __out PDWORD Val1, + __out_opt PDWORD Val2, + __in DWORD Flags +); + +BOOL +IMAGEAPI +SymSrvGetFileIndexStringW( + __in HANDLE hProcess, + __in_opt PCWSTR SrvPath, + __in PCWSTR File, + __out_ecount(Size) PWSTR Index, + __in size_t Size, + __in DWORD Flags +); + +BOOL +IMAGEAPI +SymSrvGetFileIndexString( + __in HANDLE hProcess, + __in_opt PCSTR SrvPath, + __in PCSTR File, + __out_ecount(Size) PSTR Index, + __in size_t Size, + __in DWORD Flags +); + +typedef struct +{ + DWORD sizeofstruct; + char file[MAX_PATH +1]; + BOOL stripped; + DWORD timestamp; + DWORD size; + char dbgfile[MAX_PATH +1]; + char pdbfile[MAX_PATH + 1]; + GUID guid; + DWORD sig; + DWORD age; +} SYMSRV_INDEX_INFO, *PSYMSRV_INDEX_INFO; + +typedef struct +{ + DWORD sizeofstruct; + WCHAR file[MAX_PATH +1]; + BOOL stripped; + DWORD timestamp; + DWORD size; + WCHAR dbgfile[MAX_PATH +1]; + WCHAR pdbfile[MAX_PATH + 1]; + GUID guid; + DWORD sig; + DWORD age; +} SYMSRV_INDEX_INFOW, *PSYMSRV_INDEX_INFOW; + +BOOL +IMAGEAPI +SymSrvGetFileIndexInfo( + __in PCSTR File, + __out PSYMSRV_INDEX_INFO Info, + __in DWORD Flags +); + +BOOL +IMAGEAPI +SymSrvGetFileIndexInfoW( + __in PCWSTR File, + __out PSYMSRV_INDEX_INFOW Info, + __in DWORD Flags +); + +PCSTR +IMAGEAPI +SymSrvStoreSupplement( + __in HANDLE hProcess, + __in_opt PCSTR SrvPath, + __in PCSTR Node, + __in PCSTR File, + __in DWORD Flags +); + +PCWSTR +IMAGEAPI +SymSrvStoreSupplementW( + __in HANDLE hProcess, + __in_opt PCWSTR SymPath, + __in PCWSTR Node, + __in PCWSTR File, + __in DWORD Flags +); + +PCSTR +IMAGEAPI +SymSrvStoreFile( + __in HANDLE hProcess, + __in_opt PCSTR SrvPath, + __in PCSTR File, + __in DWORD Flags +); + +PCWSTR +IMAGEAPI +SymSrvStoreFileW( + __in HANDLE hProcess, + __in_opt PCWSTR SrvPath, + __in PCWSTR File, + __in DWORD Flags +); + +// used by SymGetSymbolFile's "Type" parameter + +enum +{ + sfImage = 0, + sfDbg, + sfPdb, + sfMpd, + sfMax +}; + +BOOL +IMAGEAPI +SymGetSymbolFile( + __in_opt HANDLE hProcess, + __in_opt PCSTR SymPath, + __in PCSTR ImageFile, + __in DWORD Type, + __out_ecount(cSymbolFile) PSTR SymbolFile, + __in size_t cSymbolFile, + __out_ecount(cDbgFile) PSTR DbgFile, + __in size_t cDbgFile +); + +BOOL +IMAGEAPI +SymGetSymbolFileW( + __in_opt HANDLE hProcess, + __in_opt PCWSTR SymPath, + __in PCWSTR ImageFile, + __in DWORD Type, + __out_ecount(cSymbolFile) PWSTR SymbolFile, + __in size_t cSymbolFile, + __out_ecount(cDbgFile) PWSTR DbgFile, + __in size_t cDbgFile +); + +// +// Full user-mode dump creation. +// + +typedef BOOL (WINAPI *PDBGHELP_CREATE_USER_DUMP_CALLBACK)( + __in DWORD DataType, + __in PVOID* Data, + __out LPDWORD DataLength, + __in_opt PVOID UserData +); + +BOOL +WINAPI +DbgHelpCreateUserDump( + __in_opt LPCSTR FileName, + __in PDBGHELP_CREATE_USER_DUMP_CALLBACK Callback, + __in_opt PVOID UserData +); + +BOOL +WINAPI +DbgHelpCreateUserDumpW( + __in_opt LPCWSTR FileName, + __in PDBGHELP_CREATE_USER_DUMP_CALLBACK Callback, + __in_opt PVOID UserData +); + +// ----------------------------------------------------------------- +// The following 4 legacy APIs are fully supported, but newer +// ones are recommended. SymFromName and SymFromAddr provide +// much more detailed info on the returned symbol. + +BOOL +IMAGEAPI +SymGetSymFromAddr64( + __in HANDLE hProcess, + __in DWORD64 qwAddr, + __out_opt PDWORD64 pdwDisplacement, + __inout PIMAGEHLP_SYMBOL64 Symbol +); + + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetSymFromAddr SymGetSymFromAddr64 +#else +BOOL +IMAGEAPI +SymGetSymFromAddr( + __in HANDLE hProcess, + __in DWORD dwAddr, + __out_opt PDWORD pdwDisplacement, + __inout PIMAGEHLP_SYMBOL Symbol +); +#endif + +// While following two APIs will provide a symbol from a name, +// SymEnumSymbols can provide the same matching information +// for ALL symbols with a matching name, even regular +// expressions. That way you can search across modules +// and differentiate between identically named symbols. + +BOOL +IMAGEAPI +SymGetSymFromName64( + __in HANDLE hProcess, + __in PCSTR Name, + __inout PIMAGEHLP_SYMBOL64 Symbol +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetSymFromName SymGetSymFromName64 +#else +BOOL +IMAGEAPI +SymGetSymFromName( + __in HANDLE hProcess, + __in PCSTR Name, + __inout PIMAGEHLP_SYMBOL Symbol +); +#endif + + +// Symbol server exports + +typedef BOOL (WINAPI *PSYMBOLSERVERPROC)(PCSTR, PCSTR, PVOID, DWORD, DWORD, PSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERPROCA)(PCSTR, PCSTR, PVOID, DWORD, DWORD, PSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERPROCW)(PCWSTR, PCWSTR, PVOID, DWORD, DWORD, PWSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERBYINDEXPROC)(PCSTR, PCSTR, PCSTR, PSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERBYINDEXPROCA)(PCSTR, PCSTR, PCSTR, PSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERBYINDEXPROCW)(PCWSTR, PCWSTR, PCWSTR, PWSTR); +typedef BOOL (WINAPI *PSYMBOLSERVEROPENPROC)(VOID); +typedef BOOL (WINAPI *PSYMBOLSERVERCLOSEPROC)(VOID); +typedef BOOL (WINAPI *PSYMBOLSERVERSETOPTIONSPROC)(UINT_PTR, ULONG64); +typedef BOOL (WINAPI *PSYMBOLSERVERSETOPTIONSWPROC)(UINT_PTR, ULONG64); +typedef BOOL (CALLBACK WINAPI *PSYMBOLSERVERCALLBACKPROC)(UINT_PTR action, ULONG64 data, ULONG64 context); +typedef UINT_PTR (WINAPI *PSYMBOLSERVERGETOPTIONSPROC)(); +typedef BOOL (WINAPI *PSYMBOLSERVERPINGPROC)(PCSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERPINGPROCA)(PCSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERPINGPROCW)(PCWSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERGETVERSION)(LPAPI_VERSION); +typedef BOOL (WINAPI *PSYMBOLSERVERDELTANAME)(PCSTR, PVOID, DWORD, DWORD, PVOID, DWORD, DWORD, PSTR, size_t); +typedef BOOL (WINAPI *PSYMBOLSERVERDELTANAMEW)(PCWSTR, PVOID, DWORD, DWORD, PVOID, DWORD, DWORD, PWSTR, size_t); +typedef BOOL (WINAPI *PSYMBOLSERVERGETSUPPLEMENT)(PCSTR, PCSTR, PCSTR, PSTR, size_t); +typedef BOOL (WINAPI *PSYMBOLSERVERGETSUPPLEMENTW)(PCWSTR, PCWSTR, PCWSTR, PWSTR, size_t); +typedef BOOL (WINAPI *PSYMBOLSERVERSTORESUPPLEMENT)(PCSTR, PCSTR, PCSTR, PSTR, size_t, DWORD); +typedef BOOL (WINAPI *PSYMBOLSERVERSTORESUPPLEMENTW)(PCWSTR, PCWSTR, PCWSTR, PWSTR, size_t, DWORD); +typedef BOOL (WINAPI *PSYMBOLSERVERGETINDEXSTRING)(PVOID, DWORD, DWORD, PSTR, size_t); +typedef BOOL (WINAPI *PSYMBOLSERVERGETINDEXSTRINGW)(PVOID, DWORD, DWORD, PWSTR, size_t); +typedef BOOL (WINAPI *PSYMBOLSERVERSTOREFILE)(PCSTR, PCSTR, PVOID, DWORD, DWORD, PSTR, size_t, DWORD); +typedef BOOL (WINAPI *PSYMBOLSERVERSTOREFILEW)(PCWSTR, PCWSTR, PVOID, DWORD, DWORD, PWSTR, size_t, DWORD); +typedef BOOL (WINAPI *PSYMBOLSERVERISSTORE)(PCSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERISSTOREW)(PCWSTR); +typedef DWORD (WINAPI *PSYMBOLSERVERVERSION)(); +typedef BOOL (CALLBACK WINAPI *PSYMBOLSERVERMESSAGEPROC)(UINT_PTR action, ULONG64 data, ULONG64 context); + +#define SYMSRV_VERSION 2 + +#define SSRVOPT_CALLBACK 0x00000001 +#define SSRVOPT_DWORD 0x00000002 +#define SSRVOPT_DWORDPTR 0x00000004 +#define SSRVOPT_GUIDPTR 0x00000008 +#define SSRVOPT_OLDGUIDPTR 0x00000010 +#define SSRVOPT_UNATTENDED 0x00000020 +#define SSRVOPT_NOCOPY 0x00000040 +#define SSRVOPT_GETPATH 0x00000040 +#define SSRVOPT_PARENTWIN 0x00000080 +#define SSRVOPT_PARAMTYPE 0x00000100 +#define SSRVOPT_SECURE 0x00000200 +#define SSRVOPT_TRACE 0x00000400 +#define SSRVOPT_SETCONTEXT 0x00000800 +#define SSRVOPT_PROXY 0x00001000 +#define SSRVOPT_DOWNSTREAM_STORE 0x00002000 +#define SSRVOPT_OVERWRITE 0x00004000 +#define SSRVOPT_RESETTOU 0x00008000 +#define SSRVOPT_CALLBACKW 0x00010000 +#define SSRVOPT_FLAT_DEFAULT_STORE 0x00020000 +#define SSRVOPT_PROXYW 0x00040000 +#define SSRVOPT_MESSAGE 0x00080000 +#define SSRVOPT_SERVICE 0x00100000 // deprecated +#define SSRVOPT_FAVOR_COMPRESSED 0x00200000 +#define SSRVOPT_STRING 0x00400000 +#define SSRVOPT_WINHTTP 0x00800000 +#define SSRVOPT_WININET 0x01000000 + +#define SSRVOPT_MAX 0x0100000 + +#define SSRVOPT_RESET ((ULONG_PTR)-1) + + +#define NUM_SSRVOPTS 30 + +#define SSRVACTION_TRACE 1 +#define SSRVACTION_QUERYCANCEL 2 +#define SSRVACTION_EVENT 3 +#define SSRVACTION_EVENTW 4 +#define SSRVACTION_SIZE 5 + +#define SYMSTOREOPT_COMPRESS 0x01 +#define SYMSTOREOPT_OVERWRITE 0x02 +#define SYMSTOREOPT_RETURNINDEX 0x04 +#define SYMSTOREOPT_POINTER 0x08 +#define SYMSTOREOPT_ALT_INDEX 0x10 +#define SYMSTOREOPT_UNICODE 0x20 +#define SYMSTOREOPT_PASS_IF_EXISTS 0x40 + +#ifdef DBGHELP_TRANSLATE_TCHAR +#define SymInitialize SymInitializeW +#define SymAddSymbol SymAddSymbolW +#define SymDeleteSymbol SymDeleteSymbolW +#define SearchTreeForFile SearchTreeForFileW +#define UnDecorateSymbolName UnDecorateSymbolNameW +#define SymGetLineFromName64 SymGetLineFromNameW64 +#define SymGetLineFromAddr64 SymGetLineFromAddrW64 +#define SymGetLineNext64 SymGetLineNextW64 +#define SymGetLinePrev64 SymGetLinePrevW64 +#define SymFromName SymFromNameW +#define SymFindExecutableImage SymFindExecutableImageW +#define FindExecutableImageEx FindExecutableImageExW +#define SymSearch SymSearchW +#define SymEnumLines SymEnumLinesW +#define SymEnumSourceLines SymEnumSourceLinesW +#define SymGetTypeFromName SymGetTypeFromNameW +#define SymEnumSymbolsForAddr SymEnumSymbolsForAddrW +#define SymFromAddr SymFromAddrW +#define SymMatchString SymMatchStringW +#define SymEnumSourceFiles SymEnumSourceFilesW +#define SymEnumSymbols SymEnumSymbolsW +#define SymLoadModuleEx SymLoadModuleExW +#define SymSetSearchPath SymSetSearchPathW +#define SymGetSearchPath SymGetSearchPathW +#define EnumDirTree EnumDirTreeW +#define SymFromToken SymFromTokenW +#define SymFromIndex SymFromIndexW +#define SymGetScope SymGetScopeW +#define SymNext SymNextW +#define SymPrev SymPrevW +#define SymEnumTypes SymEnumTypesW +#define SymEnumTypesByName SymEnumTypesByNameW +#define SymRegisterCallback64 SymRegisterCallbackW64 +#define SymFindDebugInfoFile SymFindDebugInfoFileW +#define FindDebugInfoFileEx FindDebugInfoFileExW +#define SymFindFileInPath SymFindFileInPathW +#define SymEnumerateModules64 SymEnumerateModulesW64 +#define SymSetHomeDirectory SymSetHomeDirectoryW +#define SymGetHomeDirectory SymGetHomeDirectoryW +#define SymGetSourceFile SymGetSourceFileW +#define SymGetSourceFileToken SymGetSourceFileTokenW +#define SymGetSourceFileFromToken SymGetSourceFileFromTokenW +#define SymGetSourceVarFromToken SymGetSourceVarFromTokenW +#define SymGetSourceFileToken SymGetSourceFileTokenW +#define SymGetFileLineOffsets64 SymGetFileLineOffsetsW64 +#define SymFindFileInPath SymFindFileInPathW +#define SymMatchFileName SymMatchFileNameW +#define SymGetSourceFileFromToken SymGetSourceFileFromTokenW +#define SymGetSourceVarFromToken SymGetSourceVarFromTokenW +#define SymGetModuleInfo64 SymGetModuleInfoW64 +#define SymSrvIsStore SymSrvIsStoreW +#define SymSrvDeltaName SymSrvDeltaNameW +#define SymSrvGetSupplement SymSrvGetSupplementW +#define SymSrvStoreSupplement SymSrvStoreSupplementW +#define SymSrvGetFileIndexes SymSrvGetFileIndexes +#define SymSrvGetFileIndexString SymSrvGetFileIndexStringW +#define SymSrvStoreFile SymSrvStoreFileW +#define SymGetSymbolFile SymGetSymbolFileW +#define EnumerateLoadedModules64 EnumerateLoadedModulesW64 +#define EnumerateLoadedModulesEx EnumerateLoadedModulesExW +#define SymSrvGetFileIndexInfo SymSrvGetFileIndexInfoW + +#define IMAGEHLP_LINE64 IMAGEHLP_LINEW64 +#define PIMAGEHLP_LINE64 PIMAGEHLP_LINEW64 +#define SYMBOL_INFO SYMBOL_INFOW +#define PSYMBOL_INFO PSYMBOL_INFOW +#define SYMBOL_INFO_PACKAGE SYMBOL_INFO_PACKAGEW +#define PSYMBOL_INFO_PACKAGE PSYMBOL_INFO_PACKAGEW +#define FIND_EXE_FILE_CALLBACK FIND_EXE_FILE_CALLBACKW +#define PFIND_EXE_FILE_CALLBACK PFIND_EXE_FILE_CALLBACKW +#define SYM_ENUMERATESYMBOLS_CALLBACK SYM_ENUMERATESYMBOLS_CALLBACKW +#define PSYM_ENUMERATESYMBOLS_CALLBACK PSYM_ENUMERATESYMBOLS_CALLBACKW +#define SRCCODEINFO SRCCODEINFOW +#define PSRCCODEINFO PSRCCODEINFOW +#define SOURCEFILE SOURCEFILEW +#define PSOURCEFILE PSOURCEFILEW +#define SYM_ENUMSOURECFILES_CALLBACK SYM_ENUMSOURCEFILES_CALLBACKW +#define PSYM_ENUMSOURCEFILES_CALLBACK PSYM_ENUMSOURECFILES_CALLBACKW +#define IMAGEHLP_CBA_EVENT IMAGEHLP_CBA_EVENTW +#define PIMAGEHLP_CBA_EVENT PIMAGEHLP_CBA_EVENTW +#define PENUMDIRTREE_CALLBACK PENUMDIRTREE_CALLBACKW +#define IMAGEHLP_DEFERRED_SYMBOL_LOAD64 IMAGEHLP_DEFERRED_SYMBOL_LOADW64 +#define PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 PIMAGEHLP_DEFERRED_SYMBOL_LOADW64 +#define PFIND_DEBUG_FILE_CALLBACK PFIND_DEBUG_FILE_CALLBACKW +#define PFINDFILEINPATHCALLBACK PFINDFILEINPATHCALLBACKW +#define IMAGEHLP_MODULE64 IMAGEHLP_MODULEW64 +#define PIMAGEHLP_MODULE64 PIMAGEHLP_MODULEW64 +#define SYMSRV_INDEX_INFO SYMSRV_INDEX_INFOW +#define PSYMSRV_INDEX_INFO PSYMSRV_INDEX_INFOW + +#define PSYMBOLSERVERPROC PSYMBOLSERVERPROCW +#define PSYMBOLSERVERPINGPROC PSYMBOLSERVERPINGPROCW +#endif + +// ----------------------------------------------------------------- +// The following APIs exist only for backwards compatibility +// with a pre-release version documented in an MSDN release. + +// You should use SymFindFileInPath if you want to maintain +// future compatibility. + +DBHLP_DEPRECIATED +BOOL +IMAGEAPI +FindFileInPath( + __in HANDLE hprocess, + __in PCSTR SearchPath, + __in PCSTR FileName, + __in PVOID id, + __in DWORD two, + __in DWORD three, + __in DWORD flags, + __out_ecount(MAX_PATH + 1) PSTR FilePath +); + +// You should use SymFindFileInPath if you want to maintain +// future compatibility. + +DBHLP_DEPRECIATED +BOOL +IMAGEAPI +FindFileInSearchPath( + __in HANDLE hprocess, + __in PCSTR SearchPath, + __in PCSTR FileName, + __in DWORD one, + __in DWORD two, + __in DWORD three, + __out_ecount(MAX_PATH + 1) PSTR FilePath +); + +DBHLP_DEPRECIATED +BOOL +IMAGEAPI +SymEnumSym( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, + __in_opt PVOID UserContext +); + +DBHLP_DEPRECIATED +BOOL +IMAGEAPI +SymEnumerateSymbols64( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback, + __in_opt PVOID UserContext +); + +DBHLP_DEPRECIATED +BOOL +IMAGEAPI +SymEnumerateSymbolsW64( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PSYM_ENUMSYMBOLS_CALLBACK64W EnumSymbolsCallback, + __in_opt PVOID UserContext +); + + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymEnumerateSymbols SymEnumerateSymbols64 +#define SymEnumerateSymbolsW SymEnumerateSymbolsW64 +#else +DBHLP_DEPRECIATED +BOOL +IMAGEAPI +SymEnumerateSymbols( + __in HANDLE hProcess, + __in ULONG BaseOfDll, + __in PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback, + __in_opt PVOID UserContext +); + +DBHLP_DEPRECIATED +BOOL +IMAGEAPI +SymEnumerateSymbolsW( + __in HANDLE hProcess, + __in ULONG BaseOfDll, + __in PSYM_ENUMSYMBOLS_CALLBACKW EnumSymbolsCallback, + __in_opt PVOID UserContext +); +#endif + +// use SymLoadModuleEx + +DWORD64 +IMAGEAPI +SymLoadModule64( + __in HANDLE hProcess, + __in_opt HANDLE hFile, + __in_opt PCSTR ImageName, + __in_opt PCSTR ModuleName, + __in DWORD64 BaseOfDll, + __in DWORD SizeOfDll +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymLoadModule SymLoadModule64 +#else +DWORD +IMAGEAPI +SymLoadModule( + __in HANDLE hProcess, + __in_opt HANDLE hFile, + __in_opt PCSTR ImageName, + __in_opt PCSTR ModuleName, + __in DWORD BaseOfDll, + __in DWORD SizeOfDll +); +#endif + +BOOL +IMAGEAPI +SymGetSymNext64( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOL64 Symbol +); + +BOOL +IMAGEAPI +SymGetSymNextW64( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOLW64 Symbol +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetSymNext SymGetSymNext64 +#define SymGetSymNextW SymGetSymNextW64 +#else +BOOL +IMAGEAPI +SymGetSymNext( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOL Symbol +); + +BOOL +IMAGEAPI +SymGetSymNextW( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOLW Symbol +); +#endif + +BOOL +IMAGEAPI +SymGetSymPrev64( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOL64 Symbol +); + +BOOL +IMAGEAPI +SymGetSymPrevW64( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOLW64 Symbol +); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetSymPrev SymGetSymPrev64 +#define SymGetSymPrevW SymGetSymPrevW64 +#else +BOOL +IMAGEAPI +SymGetSymPrev( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOL Symbol +); + +BOOL +IMAGEAPI +SymGetSymPrevW( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOLW Symbol +); +#endif + + +// These values should not be used. +// They have been replaced by SYMFLAG_ values. + +#define SYMF_OMAP_GENERATED 0x00000001 +#define SYMF_OMAP_MODIFIED 0x00000002 +#define SYMF_REGISTER 0x00000008 +#define SYMF_REGREL 0x00000010 +#define SYMF_FRAMEREL 0x00000020 +#define SYMF_PARAMETER 0x00000040 +#define SYMF_LOCAL 0x00000080 +#define SYMF_CONSTANT 0x00000100 +#define SYMF_EXPORT 0x00000200 +#define SYMF_FORWARDER 0x00000400 +#define SYMF_FUNCTION 0x00000800 +#define SYMF_VIRTUAL 0x00001000 +#define SYMF_THUNK 0x00002000 +#define SYMF_TLSREL 0x00004000 + +// These values should also not be used. +// They have been replaced by SYMFLAG_ values. + +#define IMAGEHLP_SYMBOL_INFO_VALUEPRESENT 1 +#define IMAGEHLP_SYMBOL_INFO_REGISTER SYMF_REGISTER // 0x0008 +#define IMAGEHLP_SYMBOL_INFO_REGRELATIVE SYMF_REGREL // 0x0010 +#define IMAGEHLP_SYMBOL_INFO_FRAMERELATIVE SYMF_FRAMEREL // 0x0020 +#define IMAGEHLP_SYMBOL_INFO_PARAMETER SYMF_PARAMETER // 0x0040 +#define IMAGEHLP_SYMBOL_INFO_LOCAL SYMF_LOCAL // 0x0080 +#define IMAGEHLP_SYMBOL_INFO_CONSTANT SYMF_CONSTANT // 0x0100 +#define IMAGEHLP_SYMBOL_FUNCTION SYMF_FUNCTION // 0x0800 +#define IMAGEHLP_SYMBOL_VIRTUAL SYMF_VIRTUAL // 0x1000 +#define IMAGEHLP_SYMBOL_THUNK SYMF_THUNK // 0x2000 +#define IMAGEHLP_SYMBOL_INFO_TLSRELATIVE SYMF_TLSREL // 0x4000 + +#pragma pack(pop) + + +#pragma pack(push,4) + +#define MINIDUMP_SIGNATURE ('PMDM') +#define MINIDUMP_VERSION (42899) +typedef DWORD RVA; +typedef ULONG64 RVA64; + +typedef struct _MINIDUMP_LOCATION_DESCRIPTOR +{ + ULONG32 DataSize; + RVA Rva; +} MINIDUMP_LOCATION_DESCRIPTOR; + +typedef struct _MINIDUMP_LOCATION_DESCRIPTOR64 +{ + ULONG64 DataSize; + RVA64 Rva; +} MINIDUMP_LOCATION_DESCRIPTOR64; + + +typedef struct _MINIDUMP_MEMORY_DESCRIPTOR +{ + ULONG64 StartOfMemoryRange; + MINIDUMP_LOCATION_DESCRIPTOR Memory; +} MINIDUMP_MEMORY_DESCRIPTOR, *PMINIDUMP_MEMORY_DESCRIPTOR; + +// DESCRIPTOR64 is used for full-memory minidumps where +// all of the raw memory is laid out sequentially at the +// end of the dump. There is no need for individual RVAs +// as the RVA is the base RVA plus the sum of the preceeding +// data blocks. +typedef struct _MINIDUMP_MEMORY_DESCRIPTOR64 +{ + ULONG64 StartOfMemoryRange; + ULONG64 DataSize; +} MINIDUMP_MEMORY_DESCRIPTOR64, *PMINIDUMP_MEMORY_DESCRIPTOR64; + + +typedef struct _MINIDUMP_HEADER +{ + ULONG32 Signature; + ULONG32 Version; + ULONG32 NumberOfStreams; + RVA StreamDirectoryRva; + ULONG32 CheckSum; + union + { + ULONG32 Reserved; + ULONG32 TimeDateStamp; + }; + ULONG64 Flags; +} MINIDUMP_HEADER, *PMINIDUMP_HEADER; + +// +// The MINIDUMP_HEADER field StreamDirectoryRva points to +// an array of MINIDUMP_DIRECTORY structures. +// + +typedef struct _MINIDUMP_DIRECTORY +{ + ULONG32 StreamType; + MINIDUMP_LOCATION_DESCRIPTOR Location; +} MINIDUMP_DIRECTORY, *PMINIDUMP_DIRECTORY; + + +typedef struct _MINIDUMP_STRING +{ + ULONG32 Length; // Length in bytes of the string + WCHAR Buffer [0]; // Variable size buffer +} MINIDUMP_STRING, *PMINIDUMP_STRING; + + + +// +// The MINIDUMP_DIRECTORY field StreamType may be one of the following types. +// Types will be added in the future, so if a program reading the minidump +// header encounters a stream type it does not understand it should ignore +// the data altogether. Any tag above LastReservedStream will not be used by +// the system and is reserved for program-specific information. +// + +typedef enum _MINIDUMP_STREAM_TYPE +{ + + UnusedStream = 0, + ReservedStream0 = 1, + ReservedStream1 = 2, + ThreadListStream = 3, + ModuleListStream = 4, + MemoryListStream = 5, + ExceptionStream = 6, + SystemInfoStream = 7, + ThreadExListStream = 8, + Memory64ListStream = 9, + CommentStreamA = 10, + CommentStreamW = 11, + HandleDataStream = 12, + FunctionTableStream = 13, + UnloadedModuleListStream = 14, + MiscInfoStream = 15, + MemoryInfoListStream = 16, + ThreadInfoListStream = 17, + HandleOperationListStream = 18, + TokenStream = 19, + + ceStreamNull = 0x8000, + ceStreamSystemInfo = 0x8001, + ceStreamException = 0x8002, + ceStreamModuleList = 0x8003, + ceStreamProcessList = 0x8004, + ceStreamThreadList = 0x8005, + ceStreamThreadContextList = 0x8006, + ceStreamThreadCallStackList = 0x8007, + ceStreamMemoryVirtualList = 0x8008, + ceStreamMemoryPhysicalList = 0x8009, + ceStreamBucketParameters = 0x800A, + ceStreamProcessModuleMap = 0x800B, + ceStreamDiagnosisList = 0x800C, + + LastReservedStream = 0xffff + +} MINIDUMP_STREAM_TYPE; + + +// +// The minidump system information contains processor and +// Operating System specific information. +// + +// +// CPU information is obtained from one of two places. +// +// 1) On x86 computers, CPU_INFORMATION is obtained from the CPUID +// instruction. You must use the X86 portion of the union for X86 +// computers. +// +// 2) On non-x86 architectures, CPU_INFORMATION is obtained by calling +// IsProcessorFeatureSupported(). +// + +typedef union _CPU_INFORMATION +{ + + // + // X86 platforms use CPUID function to obtain processor information. + // + + struct + { + + // + // CPUID Subfunction 0, register EAX (VendorId [0]), + // EBX (VendorId [1]) and ECX (VendorId [2]). + // + + ULONG32 VendorId [ 3 ]; + + // + // CPUID Subfunction 1, register EAX + // + + ULONG32 VersionInformation; + + // + // CPUID Subfunction 1, register EDX + // + + ULONG32 FeatureInformation; + + + // + // CPUID, Subfunction 80000001, register EBX. This will only + // be obtained if the vendor id is "AuthenticAMD". + // + + ULONG32 AMDExtendedCpuFeatures; + + } X86CpuInfo; + + // + // Non-x86 platforms use processor feature flags. + // + + struct + { + + ULONG64 ProcessorFeatures [ 2 ]; + + } OtherCpuInfo; + +} CPU_INFORMATION, *PCPU_INFORMATION; + +typedef struct _MINIDUMP_SYSTEM_INFO +{ + + // + // ProcessorArchitecture, ProcessorLevel and ProcessorRevision are all + // taken from the SYSTEM_INFO structure obtained by GetSystemInfo( ). + // + + USHORT ProcessorArchitecture; + USHORT ProcessorLevel; + USHORT ProcessorRevision; + + union + { + USHORT Reserved0; + struct + { + UCHAR NumberOfProcessors; + UCHAR ProductType; + }; + }; + + // + // MajorVersion, MinorVersion, BuildNumber, PlatformId and + // CSDVersion are all taken from the OSVERSIONINFO structure + // returned by GetVersionEx( ). + // + + ULONG32 MajorVersion; + ULONG32 MinorVersion; + ULONG32 BuildNumber; + ULONG32 PlatformId; + + // + // RVA to a CSDVersion string in the string table. + // + + RVA CSDVersionRva; + + union + { + ULONG32 Reserved1; + struct + { + USHORT SuiteMask; + USHORT Reserved2; + }; + }; + + CPU_INFORMATION Cpu; + +} MINIDUMP_SYSTEM_INFO, *PMINIDUMP_SYSTEM_INFO; + + +// +// The minidump thread contains standard thread +// information plus an RVA to the memory for this +// thread and an RVA to the CONTEXT structure for +// this thread. +// + + +// +// ThreadId must be 4 bytes on all architectures. +// + +C_ASSERT (sizeof ( ((PPROCESS_INFORMATION)0)->dwThreadId ) == 4); + +typedef struct _MINIDUMP_THREAD +{ + ULONG32 ThreadId; + ULONG32 SuspendCount; + ULONG32 PriorityClass; + ULONG32 Priority; + ULONG64 Teb; + MINIDUMP_MEMORY_DESCRIPTOR Stack; + MINIDUMP_LOCATION_DESCRIPTOR ThreadContext; +} MINIDUMP_THREAD, *PMINIDUMP_THREAD; + +// +// The thread list is a container of threads. +// + +typedef struct _MINIDUMP_THREAD_LIST +{ + ULONG32 NumberOfThreads; + MINIDUMP_THREAD Threads [0]; +} MINIDUMP_THREAD_LIST, *PMINIDUMP_THREAD_LIST; + + +typedef struct _MINIDUMP_THREAD_EX +{ + ULONG32 ThreadId; + ULONG32 SuspendCount; + ULONG32 PriorityClass; + ULONG32 Priority; + ULONG64 Teb; + MINIDUMP_MEMORY_DESCRIPTOR Stack; + MINIDUMP_LOCATION_DESCRIPTOR ThreadContext; + MINIDUMP_MEMORY_DESCRIPTOR BackingStore; +} MINIDUMP_THREAD_EX, *PMINIDUMP_THREAD_EX; + +// +// The thread list is a container of threads. +// + +typedef struct _MINIDUMP_THREAD_EX_LIST +{ + ULONG32 NumberOfThreads; + MINIDUMP_THREAD_EX Threads [0]; +} MINIDUMP_THREAD_EX_LIST, *PMINIDUMP_THREAD_EX_LIST; + + +// +// The MINIDUMP_EXCEPTION is the same as EXCEPTION on Win64. +// + +typedef struct _MINIDUMP_EXCEPTION +{ + ULONG32 ExceptionCode; + ULONG32 ExceptionFlags; + ULONG64 ExceptionRecord; + ULONG64 ExceptionAddress; + ULONG32 NumberParameters; + ULONG32 __unusedAlignment; + ULONG64 ExceptionInformation [ EXCEPTION_MAXIMUM_PARAMETERS ]; +} MINIDUMP_EXCEPTION, *PMINIDUMP_EXCEPTION; + + +// +// The exception information stream contains the id of the thread that caused +// the exception (ThreadId), the exception record for the exception +// (ExceptionRecord) and an RVA to the thread context where the exception +// occured. +// + +typedef struct MINIDUMP_EXCEPTION_STREAM +{ + ULONG32 ThreadId; + ULONG32 __alignment; + MINIDUMP_EXCEPTION ExceptionRecord; + MINIDUMP_LOCATION_DESCRIPTOR ThreadContext; +} MINIDUMP_EXCEPTION_STREAM, *PMINIDUMP_EXCEPTION_STREAM; + + +// +// The MINIDUMP_MODULE contains information about a +// a specific module. It includes the CheckSum and +// the TimeDateStamp for the module so the module +// can be reloaded during the analysis phase. +// + +typedef struct _MINIDUMP_MODULE +{ + ULONG64 BaseOfImage; + ULONG32 SizeOfImage; + ULONG32 CheckSum; + ULONG32 TimeDateStamp; + RVA ModuleNameRva; + VS_FIXEDFILEINFO VersionInfo; + MINIDUMP_LOCATION_DESCRIPTOR CvRecord; + MINIDUMP_LOCATION_DESCRIPTOR MiscRecord; + ULONG64 Reserved0; // Reserved for future use. + ULONG64 Reserved1; // Reserved for future use. +} MINIDUMP_MODULE, *PMINIDUMP_MODULE; + + +// +// The minidump module list is a container for modules. +// + +typedef struct _MINIDUMP_MODULE_LIST +{ + ULONG32 NumberOfModules; + MINIDUMP_MODULE Modules [ 0 ]; +} MINIDUMP_MODULE_LIST, *PMINIDUMP_MODULE_LIST; + + +// +// Memory Ranges +// + +typedef struct _MINIDUMP_MEMORY_LIST +{ + ULONG32 NumberOfMemoryRanges; + MINIDUMP_MEMORY_DESCRIPTOR MemoryRanges [0]; +} MINIDUMP_MEMORY_LIST, *PMINIDUMP_MEMORY_LIST; + +typedef struct _MINIDUMP_MEMORY64_LIST +{ + ULONG64 NumberOfMemoryRanges; + RVA64 BaseRva; + MINIDUMP_MEMORY_DESCRIPTOR64 MemoryRanges [0]; +} MINIDUMP_MEMORY64_LIST, *PMINIDUMP_MEMORY64_LIST; + + +// +// Support for user supplied exception information. +// + +typedef struct _MINIDUMP_EXCEPTION_INFORMATION +{ + DWORD ThreadId; + PEXCEPTION_POINTERS ExceptionPointers; + BOOL ClientPointers; +} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION; + +typedef struct _MINIDUMP_EXCEPTION_INFORMATION64 +{ + DWORD ThreadId; + ULONG64 ExceptionRecord; + ULONG64 ContextRecord; + BOOL ClientPointers; +} MINIDUMP_EXCEPTION_INFORMATION64, *PMINIDUMP_EXCEPTION_INFORMATION64; + + +// +// Support for capturing system handle state at the time of the dump. +// + +// Per-handle object information varies according to +// the OS, the OS version, the processor type and +// so on. The minidump gives a minidump identifier +// to each possible data format for identification +// purposes but does not control nor describe the actual data. +typedef enum _MINIDUMP_HANDLE_OBJECT_INFORMATION_TYPE +{ + MiniHandleObjectInformationNone, + MiniThreadInformation1, + MiniMutantInformation1, + MiniMutantInformation2, + MiniProcessInformation1, + MiniProcessInformation2, + MiniHandleObjectInformationTypeMax +} MINIDUMP_HANDLE_OBJECT_INFORMATION_TYPE; + +typedef struct _MINIDUMP_HANDLE_OBJECT_INFORMATION +{ + RVA NextInfoRva; + ULONG32 InfoType; + ULONG32 SizeOfInfo; + // Raw information follows. +} MINIDUMP_HANDLE_OBJECT_INFORMATION; + +typedef struct _MINIDUMP_HANDLE_DESCRIPTOR +{ + ULONG64 Handle; + RVA TypeNameRva; + RVA ObjectNameRva; + ULONG32 Attributes; + ULONG32 GrantedAccess; + ULONG32 HandleCount; + ULONG32 PointerCount; +} MINIDUMP_HANDLE_DESCRIPTOR, *PMINIDUMP_HANDLE_DESCRIPTOR; + +typedef struct _MINIDUMP_HANDLE_DESCRIPTOR_2 +{ + ULONG64 Handle; + RVA TypeNameRva; + RVA ObjectNameRva; + ULONG32 Attributes; + ULONG32 GrantedAccess; + ULONG32 HandleCount; + ULONG32 PointerCount; + RVA ObjectInfoRva; + ULONG32 Reserved0; +} MINIDUMP_HANDLE_DESCRIPTOR_2, *PMINIDUMP_HANDLE_DESCRIPTOR_2; + +// The latest MINIDUMP_HANDLE_DESCRIPTOR definition. +typedef MINIDUMP_HANDLE_DESCRIPTOR_2 MINIDUMP_HANDLE_DESCRIPTOR_N; +typedef MINIDUMP_HANDLE_DESCRIPTOR_N *PMINIDUMP_HANDLE_DESCRIPTOR_N; + +typedef struct _MINIDUMP_HANDLE_DATA_STREAM +{ + ULONG32 SizeOfHeader; + ULONG32 SizeOfDescriptor; + ULONG32 NumberOfDescriptors; + ULONG32 Reserved; +} MINIDUMP_HANDLE_DATA_STREAM, *PMINIDUMP_HANDLE_DATA_STREAM; + +// Some operating systems can track the last operations +// performed on a handle. For example, Application Verifier +// can enable this for some versions of Windows. The +// handle operation list collects handle operations +// known for the dump target. +// Each entry is an AVRF_HANDLE_OPERATION. +typedef struct _MINIDUMP_HANDLE_OPERATION_LIST +{ + ULONG32 SizeOfHeader; + ULONG32 SizeOfEntry; + ULONG32 NumberOfEntries; + ULONG32 Reserved; +} MINIDUMP_HANDLE_OPERATION_LIST, *PMINIDUMP_HANDLE_OPERATION_LIST; + + +// +// Support for capturing dynamic function table state at the time of the dump. +// + +typedef struct _MINIDUMP_FUNCTION_TABLE_DESCRIPTOR +{ + ULONG64 MinimumAddress; + ULONG64 MaximumAddress; + ULONG64 BaseAddress; + ULONG32 EntryCount; + ULONG32 SizeOfAlignPad; +} MINIDUMP_FUNCTION_TABLE_DESCRIPTOR, *PMINIDUMP_FUNCTION_TABLE_DESCRIPTOR; + +typedef struct _MINIDUMP_FUNCTION_TABLE_STREAM +{ + ULONG32 SizeOfHeader; + ULONG32 SizeOfDescriptor; + ULONG32 SizeOfNativeDescriptor; + ULONG32 SizeOfFunctionEntry; + ULONG32 NumberOfDescriptors; + ULONG32 SizeOfAlignPad; +} MINIDUMP_FUNCTION_TABLE_STREAM, *PMINIDUMP_FUNCTION_TABLE_STREAM; + + +// +// The MINIDUMP_UNLOADED_MODULE contains information about a +// a specific module that was previously loaded but no +// longer is. This can help with diagnosing problems where +// callers attempt to call code that is no longer loaded. +// + +typedef struct _MINIDUMP_UNLOADED_MODULE +{ + ULONG64 BaseOfImage; + ULONG32 SizeOfImage; + ULONG32 CheckSum; + ULONG32 TimeDateStamp; + RVA ModuleNameRva; +} MINIDUMP_UNLOADED_MODULE, *PMINIDUMP_UNLOADED_MODULE; + + +// +// The minidump unloaded module list is a container for unloaded modules. +// + +typedef struct _MINIDUMP_UNLOADED_MODULE_LIST +{ + ULONG32 SizeOfHeader; + ULONG32 SizeOfEntry; + ULONG32 NumberOfEntries; +} MINIDUMP_UNLOADED_MODULE_LIST, *PMINIDUMP_UNLOADED_MODULE_LIST; + + +// +// The miscellaneous information stream contains a variety +// of small pieces of information. A member is valid if +// it's within the available size and its corresponding +// bit is set. +// + +#define MINIDUMP_MISC1_PROCESS_ID 0x00000001 +#define MINIDUMP_MISC1_PROCESS_TIMES 0x00000002 +#define MINIDUMP_MISC1_PROCESSOR_POWER_INFO 0x00000004 +#define MINIDUMP_MISC3_PROCESS_INTEGRITY 0x00000010 +#define MINIDUMP_MISC3_PROCESS_EXECUTE_FLAGS 0x00000020 +#define MINIDUMP_MISC3_TIMEZONE 0x00000040 +#define MINIDUMP_MISC3_PROTECTED_PROCESS 0x00000080 + +typedef struct _MINIDUMP_MISC_INFO +{ + ULONG32 SizeOfInfo; + ULONG32 Flags1; + ULONG32 ProcessId; + ULONG32 ProcessCreateTime; + ULONG32 ProcessUserTime; + ULONG32 ProcessKernelTime; +} MINIDUMP_MISC_INFO, *PMINIDUMP_MISC_INFO; + +typedef struct _MINIDUMP_MISC_INFO_2 +{ + ULONG32 SizeOfInfo; + ULONG32 Flags1; + ULONG32 ProcessId; + ULONG32 ProcessCreateTime; + ULONG32 ProcessUserTime; + ULONG32 ProcessKernelTime; + ULONG32 ProcessorMaxMhz; + ULONG32 ProcessorCurrentMhz; + ULONG32 ProcessorMhzLimit; + ULONG32 ProcessorMaxIdleState; + ULONG32 ProcessorCurrentIdleState; +} MINIDUMP_MISC_INFO_2, *PMINIDUMP_MISC_INFO_2; + +typedef struct _MINIDUMP_MISC_INFO_3 +{ + ULONG32 SizeOfInfo; + ULONG32 Flags1; + ULONG32 ProcessId; + ULONG32 ProcessCreateTime; + ULONG32 ProcessUserTime; + ULONG32 ProcessKernelTime; + ULONG32 ProcessorMaxMhz; + ULONG32 ProcessorCurrentMhz; + ULONG32 ProcessorMhzLimit; + ULONG32 ProcessorMaxIdleState; + ULONG32 ProcessorCurrentIdleState; + ULONG32 ProcessIntegrityLevel; + ULONG32 ProcessExecuteFlags; + ULONG32 ProtectedProcess; + ULONG32 TimeZoneId; + TIME_ZONE_INFORMATION TimeZone; +} MINIDUMP_MISC_INFO_3, *PMINIDUMP_MISC_INFO_3; + +// The latest MINIDUMP_MISC_INFO definition. +typedef MINIDUMP_MISC_INFO_3 MINIDUMP_MISC_INFO_N; +typedef MINIDUMP_MISC_INFO_N* PMINIDUMP_MISC_INFO_N; + + +// +// The memory information stream contains memory region +// description information. This stream corresponds to +// what VirtualQuery would return for the process the +// dump was created for. +// + +typedef struct _MINIDUMP_MEMORY_INFO +{ + ULONG64 BaseAddress; + ULONG64 AllocationBase; + ULONG32 AllocationProtect; + ULONG32 __alignment1; + ULONG64 RegionSize; + ULONG32 State; + ULONG32 Protect; + ULONG32 Type; + ULONG32 __alignment2; +} MINIDUMP_MEMORY_INFO, *PMINIDUMP_MEMORY_INFO; + +typedef struct _MINIDUMP_MEMORY_INFO_LIST +{ + ULONG SizeOfHeader; + ULONG SizeOfEntry; + ULONG64 NumberOfEntries; +} MINIDUMP_MEMORY_INFO_LIST, *PMINIDUMP_MEMORY_INFO_LIST; + + +// +// The memory information stream contains memory region +// description information. This stream corresponds to +// what VirtualQuery would return for the process the +// dump was created for. +// + +// Thread dump writer status flags. +#define MINIDUMP_THREAD_INFO_ERROR_THREAD 0x00000001 +#define MINIDUMP_THREAD_INFO_WRITING_THREAD 0x00000002 +#define MINIDUMP_THREAD_INFO_EXITED_THREAD 0x00000004 +#define MINIDUMP_THREAD_INFO_INVALID_INFO 0x00000008 +#define MINIDUMP_THREAD_INFO_INVALID_CONTEXT 0x00000010 +#define MINIDUMP_THREAD_INFO_INVALID_TEB 0x00000020 + +typedef struct _MINIDUMP_THREAD_INFO +{ + ULONG32 ThreadId; + ULONG32 DumpFlags; + ULONG32 DumpError; + ULONG32 ExitStatus; + ULONG64 CreateTime; + ULONG64 ExitTime; + ULONG64 KernelTime; + ULONG64 UserTime; + ULONG64 StartAddress; + ULONG64 Affinity; +} MINIDUMP_THREAD_INFO, *PMINIDUMP_THREAD_INFO; + +typedef struct _MINIDUMP_THREAD_INFO_LIST +{ + ULONG SizeOfHeader; + ULONG SizeOfEntry; + ULONG NumberOfEntries; +} MINIDUMP_THREAD_INFO_LIST, *PMINIDUMP_THREAD_INFO_LIST; + +// +// Support for token information. +// +typedef struct _MINIDUMP_TOKEN_INFO_HEADER +{ + ULONG TokenSize; // The size of the token structure. + ULONG TokenId; // The PID in NtOpenProcessToken() call or TID in NtOpenThreadToken() call. + ULONG64 TokenHandle; // The handle value returned. +} MINIDUMP_TOKEN_INFO_HEADER, *PMINIDUMP_TOKEN_INFO_HEADER; + +typedef struct _MINIDUMP_TOKEN_INFO_LIST +{ + ULONG TokenListSize; + ULONG TokenListEntries; + ULONG ListHeaderSize; + ULONG ElementHeaderSize; +} MINIDUMP_TOKEN_INFO_LIST, *PMINIDUMP_TOKEN_INFO_LIST; + +// +// Support for arbitrary user-defined information. +// + +typedef struct _MINIDUMP_USER_RECORD +{ + ULONG32 Type; + MINIDUMP_LOCATION_DESCRIPTOR Memory; +} MINIDUMP_USER_RECORD, *PMINIDUMP_USER_RECORD; + + +typedef struct _MINIDUMP_USER_STREAM +{ + ULONG32 Type; + ULONG BufferSize; + PVOID Buffer; + +} MINIDUMP_USER_STREAM, *PMINIDUMP_USER_STREAM; + + +typedef struct _MINIDUMP_USER_STREAM_INFORMATION +{ + ULONG UserStreamCount; + PMINIDUMP_USER_STREAM UserStreamArray; +} MINIDUMP_USER_STREAM_INFORMATION, *PMINIDUMP_USER_STREAM_INFORMATION; + +// +// Callback support. +// + +typedef enum _MINIDUMP_CALLBACK_TYPE +{ + ModuleCallback, + ThreadCallback, + ThreadExCallback, + IncludeThreadCallback, + IncludeModuleCallback, + MemoryCallback, + CancelCallback, + WriteKernelMinidumpCallback, + KernelMinidumpStatusCallback, + RemoveMemoryCallback, + IncludeVmRegionCallback, + IoStartCallback, + IoWriteAllCallback, + IoFinishCallback, + ReadMemoryFailureCallback, + SecondaryFlagsCallback, +} MINIDUMP_CALLBACK_TYPE; + + +typedef struct _MINIDUMP_THREAD_CALLBACK +{ + ULONG ThreadId; + HANDLE ThreadHandle; + CONTEXT Context; + ULONG SizeOfContext; + ULONG64 StackBase; + ULONG64 StackEnd; +} MINIDUMP_THREAD_CALLBACK, *PMINIDUMP_THREAD_CALLBACK; + + +typedef struct _MINIDUMP_THREAD_EX_CALLBACK +{ + ULONG ThreadId; + HANDLE ThreadHandle; + CONTEXT Context; + ULONG SizeOfContext; + ULONG64 StackBase; + ULONG64 StackEnd; + ULONG64 BackingStoreBase; + ULONG64 BackingStoreEnd; +} MINIDUMP_THREAD_EX_CALLBACK, *PMINIDUMP_THREAD_EX_CALLBACK; + + +typedef struct _MINIDUMP_INCLUDE_THREAD_CALLBACK +{ + ULONG ThreadId; +} MINIDUMP_INCLUDE_THREAD_CALLBACK, *PMINIDUMP_INCLUDE_THREAD_CALLBACK; + + +typedef enum _THREAD_WRITE_FLAGS +{ + ThreadWriteThread = 0x0001, + ThreadWriteStack = 0x0002, + ThreadWriteContext = 0x0004, + ThreadWriteBackingStore = 0x0008, + ThreadWriteInstructionWindow = 0x0010, + ThreadWriteThreadData = 0x0020, + ThreadWriteThreadInfo = 0x0040, +} THREAD_WRITE_FLAGS; + +typedef struct _MINIDUMP_MODULE_CALLBACK +{ + PWCHAR FullPath; + ULONG64 BaseOfImage; + ULONG SizeOfImage; + ULONG CheckSum; + ULONG TimeDateStamp; + VS_FIXEDFILEINFO VersionInfo; + PVOID CvRecord; + ULONG SizeOfCvRecord; + PVOID MiscRecord; + ULONG SizeOfMiscRecord; +} MINIDUMP_MODULE_CALLBACK, *PMINIDUMP_MODULE_CALLBACK; + + +typedef struct _MINIDUMP_INCLUDE_MODULE_CALLBACK +{ + ULONG64 BaseOfImage; +} MINIDUMP_INCLUDE_MODULE_CALLBACK, *PMINIDUMP_INCLUDE_MODULE_CALLBACK; + + +typedef enum _MODULE_WRITE_FLAGS +{ + ModuleWriteModule = 0x0001, + ModuleWriteDataSeg = 0x0002, + ModuleWriteMiscRecord = 0x0004, + ModuleWriteCvRecord = 0x0008, + ModuleReferencedByMemory = 0x0010, + ModuleWriteTlsData = 0x0020, + ModuleWriteCodeSegs = 0x0040, +} MODULE_WRITE_FLAGS; + + +typedef struct _MINIDUMP_IO_CALLBACK +{ + HANDLE Handle; + ULONG64 Offset; + PVOID Buffer; + ULONG BufferBytes; +} MINIDUMP_IO_CALLBACK, *PMINIDUMP_IO_CALLBACK; + + +typedef struct _MINIDUMP_READ_MEMORY_FAILURE_CALLBACK +{ + ULONG64 Offset; + ULONG Bytes; + HRESULT FailureStatus; +} MINIDUMP_READ_MEMORY_FAILURE_CALLBACK, +*PMINIDUMP_READ_MEMORY_FAILURE_CALLBACK; + + +typedef struct _MINIDUMP_CALLBACK_INPUT +{ + ULONG ProcessId; + HANDLE ProcessHandle; + ULONG CallbackType; + union + { + HRESULT Status; + MINIDUMP_THREAD_CALLBACK Thread; + MINIDUMP_THREAD_EX_CALLBACK ThreadEx; + MINIDUMP_MODULE_CALLBACK Module; + MINIDUMP_INCLUDE_THREAD_CALLBACK IncludeThread; + MINIDUMP_INCLUDE_MODULE_CALLBACK IncludeModule; + MINIDUMP_IO_CALLBACK Io; + MINIDUMP_READ_MEMORY_FAILURE_CALLBACK ReadMemoryFailure; + ULONG SecondaryFlags; + }; +} MINIDUMP_CALLBACK_INPUT, *PMINIDUMP_CALLBACK_INPUT; + +typedef struct _MINIDUMP_CALLBACK_OUTPUT +{ + union + { + ULONG ModuleWriteFlags; + ULONG ThreadWriteFlags; + ULONG SecondaryFlags; + struct + { + ULONG64 MemoryBase; + ULONG MemorySize; + }; + struct + { + BOOL CheckCancel; + BOOL Cancel; + }; + HANDLE Handle; + struct + { + MINIDUMP_MEMORY_INFO VmRegion; + BOOL Continue; + }; + HRESULT Status; + }; +} MINIDUMP_CALLBACK_OUTPUT, *PMINIDUMP_CALLBACK_OUTPUT; + + +// +// A normal minidump contains just the information +// necessary to capture stack traces for all of the +// existing threads in a process. +// +// A minidump with data segments includes all of the data +// sections from loaded modules in order to capture +// global variable contents. This can make the dump much +// larger if many modules have global data. +// +// A minidump with full memory includes all of the accessible +// memory in the process and can be very large. A minidump +// with full memory always has the raw memory data at the end +// of the dump so that the initial structures in the dump can +// be mapped directly without having to include the raw +// memory information. +// +// Stack and backing store memory can be filtered to remove +// data unnecessary for stack walking. This can improve +// compression of stacks and also deletes data that may +// be private and should not be stored in a dump. +// Memory can also be scanned to see what modules are +// referenced by stack and backing store memory to allow +// omission of other modules to reduce dump size. +// In either of these modes the ModuleReferencedByMemory flag +// is set for all modules referenced before the base +// module callbacks occur. +// +// On some operating systems a list of modules that were +// recently unloaded is kept in addition to the currently +// loaded module list. This information can be saved in +// the dump if desired. +// +// Stack and backing store memory can be scanned for referenced +// pages in order to pick up data referenced by locals or other +// stack memory. This can increase the size of a dump significantly. +// +// Module paths may contain undesired information such as user names +// or other important directory names so they can be stripped. This +// option reduces the ability to locate the proper image later +// and should only be used in certain situations. +// +// Complete operating system per-process and per-thread information can +// be gathered and stored in the dump. +// +// The virtual address space can be scanned for various types +// of memory to be included in the dump. +// +// Code which is concerned with potentially private information +// getting into the minidump can set a flag that automatically +// modifies all existing and future flags to avoid placing +// unnecessary data in the dump. Basic data, such as stack +// information, will still be included but optional data, such +// as indirect memory, will not. +// +// When doing a full memory dump it's possible to store all +// of the enumerated memory region descriptive information +// in a memory information stream. +// +// Additional thread information beyond the basic thread +// structure can be collected if desired. +// +// A minidump with code segments includes all of the code +// and code-related sections from loaded modules in order +// to capture executable content. +// +// MiniDumpWithoutAuxiliaryState turns off any secondary, +// auxiliary-supported memory gathering. +// +// MiniDumpWithFullAuxiliaryState asks any present auxiliary +// data providers to include all of their state in the dump. +// The exact set of what is provided depends on the auxiliary. +// This can be quite large. +// + +typedef enum _MINIDUMP_TYPE +{ + MiniDumpNormal = 0x00000000, + MiniDumpWithDataSegs = 0x00000001, + MiniDumpWithFullMemory = 0x00000002, + MiniDumpWithHandleData = 0x00000004, + MiniDumpFilterMemory = 0x00000008, + MiniDumpScanMemory = 0x00000010, + MiniDumpWithUnloadedModules = 0x00000020, + MiniDumpWithIndirectlyReferencedMemory = 0x00000040, + MiniDumpFilterModulePaths = 0x00000080, + MiniDumpWithProcessThreadData = 0x00000100, + MiniDumpWithPrivateReadWriteMemory = 0x00000200, + MiniDumpWithoutOptionalData = 0x00000400, + MiniDumpWithFullMemoryInfo = 0x00000800, + MiniDumpWithThreadInfo = 0x00001000, + MiniDumpWithCodeSegs = 0x00002000, + MiniDumpWithoutAuxiliaryState = 0x00004000, + MiniDumpWithFullAuxiliaryState = 0x00008000, + MiniDumpWithPrivateWriteCopyMemory = 0x00010000, + MiniDumpIgnoreInaccessibleMemory = 0x00020000, + MiniDumpWithTokenInformation = 0x00040000, + MiniDumpValidTypeFlags = 0x0007ffff, +} MINIDUMP_TYPE; + +// +// In addition to the primary flags provided to +// MiniDumpWriteDump there are additional, less +// frequently used options queried via the secondary +// flags callback. +// +// MiniSecondaryWithoutPowerInfo suppresses the minidump +// query that retrieves processor power information for +// MINIDUMP_MISC_INFO. +// + +typedef enum _MINIDUMP_SECONDARY_FLAGS +{ + MiniSecondaryWithoutPowerInfo = 0x00000001, + + MiniSecondaryValidFlags = 0x00000001, +} MINIDUMP_SECONDARY_FLAGS; + + +// +// The minidump callback should modify the FieldsToWrite parameter to reflect +// what portions of the specified thread or module should be written to the +// file. +// + +typedef +BOOL +(WINAPI * MINIDUMP_CALLBACK_ROUTINE) ( + __inout PVOID CallbackParam, + __in PMINIDUMP_CALLBACK_INPUT CallbackInput, + __inout PMINIDUMP_CALLBACK_OUTPUT CallbackOutput +); + +typedef struct _MINIDUMP_CALLBACK_INFORMATION +{ + MINIDUMP_CALLBACK_ROUTINE CallbackRoutine; + PVOID CallbackParam; +} MINIDUMP_CALLBACK_INFORMATION, *PMINIDUMP_CALLBACK_INFORMATION; + + + +//++ +// +// PVOID +// RVA_TO_ADDR( +// PVOID Mapping, +// ULONG Rva +// ) +// +// Routine Description: +// +// Map an RVA that is contained within a mapped file to it's associated +// flat address. +// +// Arguments: +// +// Mapping - Base address of mapped file containing the RVA. +// +// Rva - An Rva to fixup. +// +// Return Values: +// +// A pointer to the desired data. +// +//-- + +#define RVA_TO_ADDR(Mapping,Rva) ((PVOID)(((ULONG_PTR) (Mapping)) + (Rva))) + +BOOL +WINAPI +MiniDumpWriteDump( + __in HANDLE hProcess, + __in DWORD ProcessId, + __in HANDLE hFile, + __in MINIDUMP_TYPE DumpType, + __in_opt PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, + __in_opt PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, + __in_opt PMINIDUMP_CALLBACK_INFORMATION CallbackParam +); + +BOOL +WINAPI +MiniDumpReadDumpStream( + __in PVOID BaseOfDump, + __in ULONG StreamNumber, + __deref_out_opt PMINIDUMP_DIRECTORY * Dir, + __deref_out_opt PVOID * StreamPointer, + __out_opt ULONG * StreamSize +); + +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif + + +#endif // _DBGHELP_ + diff --git a/x64_dbg_dbg/dbghelp/dbghelp_x64.a b/x64_dbg_dbg/dbghelp/dbghelp_x64.a new file mode 100644 index 00000000..feaab5ee Binary files /dev/null and b/x64_dbg_dbg/dbghelp/dbghelp_x64.a differ diff --git a/x64_dbg_dbg/dbghelp/dbghelp_x64.lib b/x64_dbg_dbg/dbghelp/dbghelp_x64.lib new file mode 100644 index 00000000..3b41ad7f Binary files /dev/null and b/x64_dbg_dbg/dbghelp/dbghelp_x64.lib differ diff --git a/x64_dbg_dbg/dbghelp/dbghelp_x86.a b/x64_dbg_dbg/dbghelp/dbghelp_x86.a new file mode 100644 index 00000000..b3159337 Binary files /dev/null and b/x64_dbg_dbg/dbghelp/dbghelp_x86.a differ diff --git a/x64_dbg_dbg/dbghelp/dbghelp_x86.lib b/x64_dbg_dbg/dbghelp/dbghelp_x86.lib new file mode 100644 index 00000000..40b3d7ea Binary files /dev/null and b/x64_dbg_dbg/dbghelp/dbghelp_x86.lib differ diff --git a/x64_dbg_dbg/debugger.cpp b/x64_dbg_dbg/debugger.cpp new file mode 100644 index 00000000..aae4ab9c --- /dev/null +++ b/x64_dbg_dbg/debugger.cpp @@ -0,0 +1,1149 @@ +#include "debugger.h" +#include "argument.h" +#include "variable.h" +#include "console.h" +#include "threading.h" +#include "value.h" +#include "instruction.h" +#include "memory.h" +#include "_exports.h" +#include "addrinfo.h" + +static PROCESS_INFORMATION g_pi= {0,0,0,0}; +PROCESS_INFORMATION* fdProcessInfo=&g_pi; +static char szFileName[deflen]=""; +bool bFileIsDll=false; +uint pDebuggedDllBase=0; +BREAKPOINT* bplist=0; +static bool isStepping=false; +static bool isPausedByUser=false; +static bool bScyllaLoaded=false; + +//static functions +static void cbStep(); +static void cbSystemBreakpoint(void* ExceptionData); +static void cbEntryBreakpoint(); +static void cbUserBreakpoint(); + +void dbgdisablebpx() +{ + BREAKPOINT* cur=bplist; + if(!cur or !cur->addr) + return; + bool bNext=true; + while(bNext) + { + if(cur->type==BPNORMAL or cur->type==BPSINGLESHOOT) + if(IsBPXEnabled(cur->addr) and DeleteBPX(cur->addr)) + cur->enabled=false; + cur=cur->next; + if(!cur) + bNext=false; + } +} + +void dbgenablebpx() +{ + BREAKPOINT* cur=bplist; + if(!cur or !cur->addr) + return; + bool bNext=true; + while(bNext) + { + if(cur->type==BPNORMAL or cur->type==BPSINGLESHOOT) + if(!IsBPXEnabled(cur->addr) and SetBPX(cur->addr, cur->type, (void*)cbUserBreakpoint)) + cur->enabled=true; + cur=cur->next; + if(!cur) + bNext=false; + } +} + +bool dbgisrunning() +{ + if(!waitislocked(WAITID_RUN)) + return true; + return false; +} + +void DebugUpdateGui(uint disasm_addr) +{ + GuiUpdateRegisterView(); + GuiDisasmAt(disasm_addr, (duint)GetContextData(UE_CIP)); +} + +static void cbUserBreakpoint() +{ + BREAKPOINT* cur=bpfind(bplist, 0, (uint)GetContextData(UE_CIP), 0, BPNORMAL); + if(!cur) + dputs("breakpoint reached not in list!"); + else + { + const char* apiname=(const char*)ImporterGetAPINameFromDebugee(fdProcessInfo->hProcess, cur->addr); + char log[deflen]=""; + if(apiname) + { + const char* dllname_=(const char*)ImporterGetDLLNameFromDebugee(fdProcessInfo->hProcess, cur->addr); + char dllname[256]=""; + strcpy(dllname, dllname_); + _strlwr(dllname); + int len=strlen(dllname); + for(int i=len-1; i!=0; i--) + if(dllname[i]=='.') + { + dllname[i]=0; + break; + } + if(cur->name) + sprintf(log, "breakpoint \"%s\" at %s.%s ("fhex")!", cur->name, dllname, apiname, cur->addr); + else + sprintf(log, "breakpoint at %s.%s ("fhex")!", dllname, apiname, cur->addr); + } + else + { + if(cur->name) + sprintf(log, "breakpoint \"%s\" at "fhex"!", cur->name, cur->addr); + else + sprintf(log, "breakpoint at "fhex"!", cur->addr); + } + dputs(log); + if(cur->type==BPSINGLESHOOT) + bpdel(bplist, 0, cur->addr, BPNORMAL); + } + DebugUpdateGui(GetContextData(UE_CIP)); + GuiSetDebugState(paused); + //lock + lock(WAITID_RUN); + wait(WAITID_RUN); +} + +static void cbHardwareBreakpoint(void* ExceptionAddress) +{ + uint cip=GetContextData(UE_CIP); + BREAKPOINT* cur=bpfind(bplist, 0, (uint)ExceptionAddress, 0, BPHARDWARE); + if(!cur) + dputs("hardware breakpoint reached not in list!"); + else + { + //TODO: type + char log[50]=""; + if(cur->name) + sprintf(log, "hardware breakpoint \"%s\" "fhex"!", cur->name, cur->addr); + else + sprintf(log, "hardware breakpoint "fhex"!", cur->addr); + dputs(log); + } + DebugUpdateGui(cip); + GuiSetDebugState(paused); + //lock + lock(WAITID_RUN); + wait(WAITID_RUN); +} + +static void cbMemoryBreakpoint(void* ExceptionAddress) +{ + uint cip=GetContextData(UE_CIP); + uint size; + uint base=memfindbaseaddr(fdProcessInfo->hProcess, (uint)ExceptionAddress, &size); + BREAKPOINT* cur=bpfind(bplist, 0, base, 0, BPMEMORY); + if(!cur) + dputs("memory breakpoint reached not in list!"); + else + { + //unsigned char type=cur->oldbytes&0xF; + char log[50]=""; + if(cur->name) + sprintf(log, "memory breakpoint \"%s\" on "fhex"!", cur->name, cur->addr); + else + sprintf(log, "memory breakpoint on "fhex"!", cur->addr); + dputs(log); + } + if(!(cur->oldbytes>>4)) //is auto-restoring? + bpdel(bplist, 0, base, BPMEMORY); //delete from breakpoint list + DebugUpdateGui(cip); + GuiSetDebugState(paused); + //lock + lock(WAITID_RUN); + wait(WAITID_RUN); +} + +static void cbEntryBreakpoint() +{ + pDebuggedDllBase=GetDebuggedDLLBaseAddress(); + dputs("entry point reached!"); + DebugUpdateGui(GetContextData(UE_CIP)); + GuiSetDebugState(paused); + //lock + lock(WAITID_RUN); + wait(WAITID_RUN); +} + +static int ecount=0; + +static void cbException(void* ExceptionData) +{ + EXCEPTION_DEBUG_INFO* edi=(EXCEPTION_DEBUG_INFO*)ExceptionData; + uint addr=(uint)edi->ExceptionRecord.ExceptionAddress; + if(edi->ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT) + { + if(isPausedByUser) + { + dputs("paused!"); + SetNextDbgContinueStatus(DBG_CONTINUE); + DebugUpdateGui(GetContextData(UE_CIP)); + GuiSetDebugState(paused); + //lock + lock(WAITID_RUN); + wait(WAITID_RUN); + return; + } + SetContextData(UE_CIP, (uint)edi->ExceptionRecord.ExceptionAddress); + } + + char msg[1024]=""; + if(edi->dwFirstChance) //first chance exception + { + sprintf(msg, "first chance exception on "fhex" (%.8X)!", addr, edi->ExceptionRecord.ExceptionCode); + SetNextDbgContinueStatus(DBG_EXCEPTION_NOT_HANDLED); + } + else //lock the exception + { + sprintf(msg, "last chance exception on "fhex" (%.8X)!", addr, edi->ExceptionRecord.ExceptionCode); + SetNextDbgContinueStatus(DBG_CONTINUE); + } + + dputs(msg); + DebugUpdateGui(GetContextData(UE_CIP)); + GuiSetDebugState(paused); + //lock + lock(WAITID_RUN); + wait(WAITID_RUN); +} + +static void cbLoadDll(LOAD_DLL_DEBUG_INFO* LoadDll) +{ + void* base=LoadDll->lpBaseOfDll; + char DLLDebugFileName[deflen]=""; + if(!GetMappedFileNameA(fdProcessInfo->hProcess, base, DLLDebugFileName, deflen)) + strcpy(DLLDebugFileName, "??? (GetMappedFileName failed)"); + else + DevicePathToPath(DLLDebugFileName, DLLDebugFileName, deflen); + dprintf("DLL Loaded: "fhex" %s\n", base, DLLDebugFileName); + SymLoadModuleEx(fdProcessInfo->hProcess, LoadDll->hFile, DLLDebugFileName, 0, (DWORD64)base, 0, 0, 0); +} + +static void cbUnloadDll(UNLOAD_DLL_DEBUG_INFO* UnloadDll) +{ + void* base=UnloadDll->lpBaseOfDll; + char DLLDebugFileName[deflen]=""; + if(!GetMappedFileNameA(fdProcessInfo->hProcess, base, DLLDebugFileName, deflen)) + strcpy(DLLDebugFileName, "??? (GetMappedFileName failed)"); + else + DevicePathToPath(DLLDebugFileName, DLLDebugFileName, deflen); + dprintf("DLL Unloaded: "fhex" %s\n", base, DLLDebugFileName); + SymUnloadModule64(fdProcessInfo->hProcess, (DWORD64)base); +} + +static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo) +{ + void* base=CreateProcessInfo->lpBaseOfImage; + char DebugFileName[deflen]=""; + if(!GetMappedFileNameA(fdProcessInfo->hProcess, base, DebugFileName, deflen)) + strcpy(DebugFileName, "??? (GetMappedFileName failed)"); + else + DevicePathToPath(DebugFileName, DebugFileName, deflen); + dprintf("Process Started: "fhex" %s\n", base, DebugFileName); + + SymInitialize(fdProcessInfo->hProcess, 0, false); //initialize symbols + SymLoadModuleEx(fdProcessInfo->hProcess, CreateProcessInfo->hFile, DebugFileName, 0, (DWORD64)base, 0, 0, 0); +} + +static void cbSystemBreakpoint(void* ExceptionData) +{ + //TODO: handle stuff (TLS, main entry, etc) + SetCustomHandler(UE_CH_SYSTEMBREAKPOINT, 0); + dputs("system breakpoint reached!"); + //NOTE: call GUI + DebugUpdateGui(GetContextData(UE_CIP)); + GuiSetDebugState(paused); + //unlock + unlock(WAITID_SYSBREAK); + //lock + lock(WAITID_RUN); + wait(WAITID_RUN); + + /*//my code + + //list memorymap(cbListPage) + ReadMemory(va) + setBP(va, type, callback) + + //gui + GuiChangeCIP(va, base, size) + + + //gui + cbClearMap + cbAddPage(MEMORY_BASIC_INFO, modulename) + cbEndMap + + //dbg + MemoryMap(cbClear, cbAddPage, cbEndMap) + */ +} + +static void cbStep() +{ + isStepping=false; + DebugUpdateGui(GetContextData(UE_CIP)); + GuiSetDebugState(paused); + //lock + lock(WAITID_RUN); + wait(WAITID_RUN); +} + +static void cbRtrFinalStep() +{ + DebugUpdateGui(GetContextData(UE_CIP)); + GuiSetDebugState(paused); + //lock + lock(WAITID_RUN); + wait(WAITID_RUN); +} + +static unsigned char getCIPch() +{ + char ch; + dbgdisablebpx(); + memread(fdProcessInfo->hProcess, (void*)GetContextData(UE_CIP), &ch, 1, 0); + dbgenablebpx(); + return ch; +} + +static void cbRtrStep() +{ + unsigned int cipch=getCIPch(); + if(cipch==0xC3 or cipch==0xC2) + cbRtrFinalStep(); + else + StepOver((void*)cbRtrStep); +} + +static DWORD WINAPI threadDebugLoop(void* lpParameter) +{ + //initialize + INIT_STRUCT* init=(INIT_STRUCT*)lpParameter; + bFileIsDll=IsFileDLL(init->exe, 0); + if(bFileIsDll) + fdProcessInfo=(PROCESS_INFORMATION*)InitDLLDebug(init->exe, false, init->commandline, init->currentfolder, (void*)cbEntryBreakpoint); + else + fdProcessInfo=(PROCESS_INFORMATION*)InitDebugEx(init->exe, init->commandline, init->currentfolder, (void*)cbEntryBreakpoint); + if(!fdProcessInfo) + { + fdProcessInfo=&g_pi; + dputs("error starting process (invalid pe?)!"); + unlock(WAITID_SYSBREAK); + return 0; + } + strcpy(szFileName, init->exe); + efree(init); //free init struct + varset("$hp", (uint)fdProcessInfo->hProcess, true); + varset("$pid", fdProcessInfo->dwProcessId, true); + ecount=0; + bplist=bpinit(bplist); + //NOTE: set custom handlers + SetCustomHandler(UE_CH_CREATEPROCESS, (void*)cbCreateProcess); + SetCustomHandler(UE_CH_SYSTEMBREAKPOINT, (void*)cbSystemBreakpoint); + SetCustomHandler(UE_CH_UNHANDLEDEXCEPTION, (void*)cbException); + SetCustomHandler(UE_CH_LOADDLL, (void*)cbLoadDll); + SetCustomHandler(UE_CH_UNLOADDLL, (void*)cbUnloadDll); + //inform GUI start we started without problems + GuiSetDebugState(initialized); + //run debug loop (returns when process debugging is stopped) + DebugLoop(); + DeleteFileA("DLLLoader.exe"); + //message the user/do final stuff + GuiSetDebugState(stopped); + dputs("debugging stopped!"); + varset("$hp", 0, true); + varset("$pid", 0, true); + waitclear(); + return 0; +} + +CMDRESULT cbDebugInit(const char* cmd) +{ + if(IsFileBeingDebugged()) + { + dputs("already debugging!"); + return STATUS_ERROR; + } + + char arg1[deflen]=""; + if(!argget(cmd, arg1, 0, false)) + return STATUS_ERROR; + if(!FileExists(arg1)) + { + dputs("file does not exsist!"); + return STATUS_ERROR; + } + + char arg2[deflen]=""; + argget(cmd, arg2, 1, true); + char* commandline=0; + if(strlen(arg2)) + commandline=arg2; + + char arg3[deflen]=""; + argget(cmd, arg3, 2, true); + + char currentfolder[deflen]=""; + strcpy(currentfolder, arg1); + int len=strlen(currentfolder); + while(currentfolder[len]!='\\' and len!=0) + len--; + currentfolder[len]=0; + if(DirExists(arg3)) + strcpy(currentfolder, arg3); + INIT_STRUCT* init=(INIT_STRUCT*)emalloc(sizeof(INIT_STRUCT)); + memset(init, 0, sizeof(INIT_STRUCT)); + init->exe=arg1; + init->commandline=commandline; + if(*currentfolder) + init->currentfolder=currentfolder; + + //initialize + waitclear(); //clear waiting flags + lock(WAITID_SYSBREAK); + if(!CreateThread(0, 0, threadDebugLoop, init, 0, 0)) + { + dputs("failed creating debug thread!"); + return STATUS_ERROR; + } + wait(WAITID_SYSBREAK); + return STATUS_CONTINUE; +} + +CMDRESULT cbStopDebug(const char* cmd) +{ + StopDebug(); + unlock(WAITID_RUN); + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugRun(const char* cmd) +{ + if(!waitislocked(WAITID_RUN)) + { + dputs("program is already running"); + return STATUS_ERROR; + } + GuiSetDebugState(running); + unlock(WAITID_RUN); + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugSetBPXOptions(const char* cmd) +{ + char argtype[deflen]=""; + uint type=0; + if(!argget(cmd, argtype, 0, false)) + return STATUS_ERROR; + const char* a=0; + if(strstr(argtype, "long")) + { + a="TYPE_LONG_INT3"; + type=UE_BREAKPOINT_TYPE_LONG_INT3; + } + else if(strstr(argtype, "ud2")) + { + a="TYPE_UD2"; + type=UE_BREAKPOINT_TYPE_UD2; + } + else if(strstr(argtype, "short")) + { + a="TYPE_INT3"; + type=UE_BREAKPOINT_TYPE_INT3; + } + else + { + dputs("invalid type specified!"); + return STATUS_ERROR; + } + SetBPXOptions(type); + dprintf("default breakpoint type set to: %s\n", a); + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugSetBPX(const char* cmd) //bp addr [,name [,type]] +{ + char argaddr[deflen]=""; + if(!argget(cmd, argaddr, 0, true)) + if(!_strnicmp(cmd, "bp", 2)) + return cbBadCmd(cmd); + if(!argget(cmd, argaddr, 0, false)) + return STATUS_ERROR; + char argname[deflen]=""; + argget(cmd, argname, 1, true); + char argtype[deflen]=""; + bool has_arg2=argget(cmd, argtype, 2, true); + if(!has_arg2 and (scmp(argname, "ss") or scmp(argname, "long") or scmp(argname, "ud2"))) + { + strcpy(argtype, argname); + *argname=0; + } + _strlwr(argtype); + uint addr=0; + if(!valfromstring(argaddr, &addr, 0, 0, false, 0)) + { + dprintf("invalid addr: \"%s\"\n", argaddr); + return STATUS_ERROR; + } + if(addr==(uint)(GetPE32Data(szFileName, 0, UE_OEP)+GetPE32Data(szFileName, 0, UE_IMAGEBASE))) + { + dputs("entry breakpoint will be set automatically"); + return STATUS_ERROR; + } + uint type=0; + BP_TYPE list_type; + if(strstr(argtype, "ss")) + { + type|=UE_SINGLESHOOT; + list_type=BPSINGLESHOOT; + } + else + { + type|=UE_BREAKPOINT; + list_type=BPNORMAL; + } + if(strstr(argtype, "long")) + type|=UE_BREAKPOINT_TYPE_LONG_INT3; + else if(strstr(argtype, "ud2")) + type|=UE_BREAKPOINT_TYPE_UD2; + else if(strstr(argtype, "short")) + type|=UE_BREAKPOINT_TYPE_INT3; + short oldbytes; + BREAKPOINT* found=bpfind(bplist, 0, addr, 0, BPNORMAL); + if(IsBPXEnabled(addr) or !memread(fdProcessInfo->hProcess, (void*)addr, &oldbytes, sizeof(short), 0) or found or !SetBPX(addr, type, (void*)cbUserBreakpoint)) + { + dprintf("error setting breakpoint at "fhex"!\n", addr); + return STATUS_ERROR; + } + if(bpnew(bplist, argname, addr, oldbytes, list_type)) + dprintf("breakpoint at "fhex" set!\n", addr); + else + dputs("problem setting breakpoint!"); + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugEnableBPX(const char* cmd) +{ + char arg1[deflen]=""; + if(!argget(cmd, arg1, 0, true)) //enable all breakpoints + { + BREAKPOINT* cur=bplist; + if(!cur or !cur->addr) + { + dputs("no breakpoints!"); + return STATUS_ERROR; + } + bool bNext=true; + CMDRESULT res=STATUS_CONTINUE; + while(bNext) + { + if(!SetBPX(cur->addr, cur->type, (void*)cbUserBreakpoint)) + { + dprintf("could not enable %.8X\n", cur->addr); + res=STATUS_ERROR; + } + else + cur->enabled=true; + cur=cur->next; + if(!cur) + bNext=false; + } + dputs("all breakpoints enabled!"); + return res; + } + BREAKPOINT* bp=bpfind(bplist, arg1, 0, 0, BPNORMAL); + if(!bp) + { + uint addr=0; + if(!valfromstring(arg1, &addr, 0, 0, false, 0)) + { + dprintf("invalid addr: \"%s\"\n", arg1); + return STATUS_ERROR; + } + bp=bpfind(bplist, 0, addr, 0, BPNORMAL); + if(!bp) + { + dprintf("no such breakpoint: \"%s\"\n", arg1); + return STATUS_ERROR; + } + } + if(bp->type!=BPNORMAL and bp->type!=BPSINGLESHOOT) + { + dputs("this breakpoint type cannot be enabled"); + return STATUS_ERROR; + } + if(bp->enabled) + { + dputs("breakpoint already enabled!"); + return STATUS_ERROR; + } + if(!SetBPX(bp->addr, bp->type, (void*)cbUserBreakpoint)) + dputs("could not enable breakpoint"); + else + bp->enabled=true; + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugDisableBPX(const char* cmd) +{ + char arg1[deflen]=""; + if(!argget(cmd, arg1, 0, true)) //disable all breakpoints + { + BREAKPOINT* cur=bplist; + if(!cur or !cur->addr) + { + dputs("no breakpoints!"); + return STATUS_ERROR; + } + bool bNext=true; + CMDRESULT res=STATUS_CONTINUE; + while(bNext) + { + if(!DeleteBPX(cur->addr)) + { + dprintf("could not disable %.8X\n", cur->addr); + res=STATUS_ERROR; + } + else + cur->enabled=false; + cur=cur->next; + if(!cur) + bNext=false; + } + dputs("all breakpoints disabled!"); + return res; + } + BREAKPOINT* bp=bpfind(bplist, arg1, 0, 0, BPNORMAL); + if(!bp) + { + uint addr=0; + if(!valfromstring(arg1, &addr, 0, 0, false, 0)) + { + dprintf("invalid addr: \"%s\"\n", arg1); + return STATUS_ERROR; + } + bp=bpfind(bplist, 0, addr, 0, BPNORMAL); + if(!bp) + { + dprintf("no such breakpoint: \"%s\"\n", arg1); + return STATUS_ERROR; + } + } + if(bp->type!=BPNORMAL and bp->type!=BPSINGLESHOOT) + { + dputs("this breakpoint type cannot be disabled"); + return STATUS_ERROR; + } + if(!bp->enabled) + { + dputs("breakpoint already disabled!"); + return STATUS_ERROR; + } + if(!DeleteBPX(bp->addr)) + dputs("could not disable breakpoint"); + else + bp->enabled=false; + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugToggleBPX(const char* cmd) +{ + char arg1[deflen]=""; + if(!argget(cmd, arg1, 0, false)) + return STATUS_ERROR; + BREAKPOINT* bp=bpfind(bplist, arg1, 0, 0, BPNORMAL); + if(!bp) + { + uint addr=0; + if(!valfromstring(arg1, &addr, 0, 0, false, 0)) + { + dprintf("invalid addr: \"%s\"\n", arg1); + return STATUS_ERROR; + } + bp=bpfind(bplist, 0, addr, 0, BPNORMAL); + if(!bp) + { + dprintf("no such breakpoint: \"%s\"\n", arg1); + return STATUS_ERROR; + } + } + if(bp->type!=BPNORMAL and bp->type!=BPSINGLESHOOT) + { + dputs("this breakpoint type cannot be toggled"); + return STATUS_ERROR; + } + bool disable=bp->enabled; + if(disable) + { + if(!DeleteBPX(bp->addr)) + { + dputs("could not disable breakpoint"); + return STATUS_ERROR; + } + else + { + bp->enabled=false; + dputs("breakpoint disabled!"); + } + } + else + { + if(!SetBPX(bp->addr, bp->type, (void*)cbUserBreakpoint)) + { + dputs("could not disable breakpoint"); + return STATUS_ERROR; + } + else + { + bp->enabled=true; + dputs("breakpoint enabled!"); + } + } + varset("$res", (uint)disable, false); + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugDeleteBPX(const char* cmd) +{ + char arg1[deflen]=""; + if(!argget(cmd, arg1, 0, true)) //delete all breakpoints + { + BREAKPOINT* cur=bplist; + if(!cur or !cur->addr) + { + dputs("no breakpoints!"); + return STATUS_ERROR; + } + bool bNext=true; + while(bNext) + { + BREAKPOINT* next=cur->next; + if(cur->type==BPNORMAL or cur->type==BPSINGLESHOOT) + { + DeleteBPX(cur->addr); + bpdel(bplist, 0, cur->addr, BPNORMAL); + } + cur=next; + if(!cur) + bNext=false; + } + //memset(bplist, 0, sizeof(BREAKPOINT)); + dputs("all breakpoints deleted!"); + return STATUS_CONTINUE; + } + BREAKPOINT* bp=bpfind(bplist, arg1, 0, 0, BPNORMAL); + if(!bp) + { + uint addr=0; + if(!valfromstring(arg1, &addr, 0, 0, false, 0)) + { + dprintf("invalid addr: \"%s\"\n", arg1); + return STATUS_ERROR; + } + bp=bpfind(bplist, 0, addr, 0, BPNORMAL); + if(!bp) + { + dprintf("no such breakpoint: \"%s\"\n", arg1); + return STATUS_ERROR; + } + } + if(!DeleteBPX(bp->addr)) + { + dprintf("delete breakpoint failed: "fhex"\n", bp->addr); + return STATUS_ERROR; + } + bpdel(bplist, 0, bp->addr, BPNORMAL); + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugBplist(const char* cmd) +{ + BREAKPOINT* cur=bplist; + if(!cur or !cur->addr) + { + dputs("no breakpoints!"); + return STATUS_CONTINUE; + } + bool bNext=true; + while(bNext) + { + const char* type=0; + if(cur->type==BPNORMAL) + type="BP"; + if(cur->type==BPSINGLESHOOT) + type="SS"; + if(cur->type==BPHARDWARE) + type="HW"; + if(cur->type==BPMEMORY) + type="GP"; + bool enabled=cur->enabled; + if(cur->name) + dprintf("%d:%s:"fhex":\"%s\"\n", enabled, type, cur->addr, cur->name); + else + dprintf("%d:%s:"fhex"\n", enabled, type, cur->addr); + cur=cur->next; + if(!cur) + bNext=false; + } + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugStepInto(const char* cmd) +{ + StepInto((void*)cbStep); + isStepping=true; + return cbDebugRun(cmd); +} + +CMDRESULT cbDebugStepOver(const char* cmd) +{ + StepOver((void*)cbStep); + isStepping=true; + return cbDebugRun(cmd); +} + +CMDRESULT cbDebugSingleStep(const char* cmd) +{ + char arg1[deflen]=""; + uint stepcount=1; + if(argget(cmd, arg1, 0, true)) + { + if(!valfromstring(arg1, &stepcount, 0, 0, true, 0)) + stepcount=1; + } + + SingleStep((DWORD)stepcount, (void*)cbStep); + isStepping=true; + return cbDebugRun(cmd); +} + +CMDRESULT cbDebugHide(const char* cmd) +{ + if(HideDebugger(fdProcessInfo->hProcess, UE_HIDE_BASIC)) + dputs("debugger hidden"); + else + dputs("something went wrong"); + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugDisasm(const char* cmd) +{ + char arg1[deflen]=""; + uint addr=GetContextData(UE_CIP); + if(argget(cmd, arg1, 0, true)) + if(!valfromstring(arg1, &addr, 0, 0, true, 0)) + addr=GetContextData(UE_CIP); + DebugUpdateGui(addr); + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugMemoryBpx(const char* cmd) +{ + char arg1[deflen]=""; //addr + if(!argget(cmd, arg1, 0, false)) + return STATUS_ERROR; + uint addr; + if(!valfromstring(arg1, &addr, 0, 0, false, 0)) + return STATUS_ERROR; + bool restore=false; + char arg2[deflen]=""; //restore + char arg3[deflen]=""; //type + argget(cmd, arg3, 2, true); + if(argget(cmd, arg2, 1, true)) + { + if(*arg2=='1') + restore=true; + else if(*arg2=='0') + restore=false; + else + strcpy(arg3, arg2); + } + uint type=UE_MEMORY; + if(*arg3) + { + switch(*arg3) + { + case 'r': + type=UE_MEMORY_READ; + break; + case 'w': + type=UE_MEMORY_WRITE; + break; + case 'x': + type=UE_MEMORY_EXECUTE; //EXECUTE + break; + default: + dputs("invalid type (argument ignored)"); + break; + } + } + uint size=0; + uint base=memfindbaseaddr(fdProcessInfo->hProcess, addr, &size); + BREAKPOINT* found=bpfind(bplist, 0, base, 0, BPMEMORY); + if(found or !SetMemoryBPXEx(base, size, type, restore, (void*)cbMemoryBreakpoint)) + { + dputs("error setting memory breakpoint!"); + return STATUS_ERROR; + } + if(bpnew(bplist, 0, addr, (restore<<4)|type, BPMEMORY)) + dprintf("memory breakpoint at "fhex" set!\n", addr); + else + dputs("problem setting breakpoint (report please)!"); + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugRtr(const char* cmd) +{ + StepOver((void*)cbRtrStep); + cbDebugRun(cmd); + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugSetHardwareBreakpoint(const char* cmd) +{ + char arg1[deflen]=""; //addr + if(!argget(cmd, arg1, 0, false)) + return STATUS_ERROR; + uint addr; + if(!valfromstring(arg1, &addr, 0, 0, false, 0)) + return STATUS_ERROR; + uint type=UE_HARDWARE_EXECUTE; + char arg2[deflen]=""; //type + if(argget(cmd, arg2, 1, true)) + { + switch(*arg2) + { + case 'r': + type=UE_HARDWARE_READWRITE; + break; + case 'w': + type=UE_HARDWARE_WRITE; + break; + case 'x': + break; + default: + dputs("invlalid type, assuming 'x'"); + break; + } + } + char arg3[deflen]=""; //size + uint size=UE_HARDWARE_SIZE_1; + if(argget(cmd, arg3, 2, true)) + { + if(!valfromstring(arg3, &size, 0, 0, false, 0)) + return STATUS_ERROR; + switch(size) + { + case 2: + size=UE_HARDWARE_SIZE_2; + break; + case 4: + size=UE_HARDWARE_SIZE_4; + break; +#ifdef _WIN64 + case 8: + size=UE_HARDWARE_SIZE_8; + break; +#endif // _WIN64 + default: + dputs("invalid size, using 1"); + break; + } + if(addr%size) + { + dprintf("address not aligned to %d\n", size); + return STATUS_ERROR; + } + } + DWORD drx=0; + if(!GetUnusedHardwareBreakPointRegister(&drx)) + { + dputs("no free debug register"); + return STATUS_ERROR; + } + BREAKPOINT* found=bpfind(bplist, 0, addr, 0, BPHARDWARE); + if(found or !SetHardwareBreakPoint(addr, drx, type, size, (void*)cbHardwareBreakpoint)) + { + dputs("error setting hardware breakpoint!"); + return STATUS_ERROR; + } + if(bpnew(bplist, 0, addr, (drx<<8)|(type<<4)|size, BPHARDWARE)) + dprintf("hardware breakpoint at "fhex" set!\n", addr); + else + dputs("problem setting breakpoint (report please)!"); + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugAlloc(const char* cmd) +{ + char arg1[deflen]=""; //size + uint size=0x1000; + if(argget(cmd, arg1, 0, true)) + if(!valfromstring(arg1, &size, 0, 0, false, 0)) + return STATUS_ERROR; + uint mem=(uint)memalloc(fdProcessInfo->hProcess, 0, size, PAGE_EXECUTE_READWRITE); + if(!mem) + dputs("VirtualAllocEx failed"); + else + dprintf(fhex"\n", mem); + if(mem) + varset("$lastalloc", mem, true); + varset("$res", mem, false); + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugFree(const char* cmd) +{ + uint lastalloc; + varget("$lastalloc", &lastalloc, 0, 0); + char arg1[deflen]=""; //addr + uint addr=lastalloc; + if(argget(cmd, arg1, 0, true)) + { + if(!valfromstring(arg1, &addr, 0, 0, false, 0)) + return STATUS_ERROR; + } + else if(!lastalloc) + dputs("lastalloc is zero, provide a page address"); + if(addr==lastalloc) + varset("$lastalloc", 0, true); + bool ok=VirtualFreeEx(fdProcessInfo->hProcess, (void*)addr, 0, MEM_RELEASE); + if(!ok) + dputs("VirtualFreeEx failed"); + varset("$res", ok, false); + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugMemset(const char* cmd) +{ + char arg1[deflen]=""; //addr + char arg2[deflen]=""; //value + char arg3[deflen]=""; //size + uint addr; + uint value; + uint size; + if(!argget(cmd, arg1, 0, false) or !argget(cmd, arg2, 1, false)) + return STATUS_ERROR; + if(!valfromstring(arg1, &addr, 0, 0, false, 0) or !valfromstring(arg2, &value, 0, 0, false, 0)) + return STATUS_ERROR; + if(argget(cmd, arg3, 2, true)) + { + if(!valfromstring(arg3, &size, 0, 0, false, 0)) + return STATUS_ERROR; + } + else + { + uint base=memfindbaseaddr(fdProcessInfo->hProcess, addr, &size); + if(!base) + { + dputs("invalid address specified"); + return STATUS_ERROR; + } + uint diff=addr-base; + addr=base+diff; + size-=diff; + } + BYTE fi=value&0xFF; + if(!Fill((void*)addr, size&0xFFFFFFFF, &fi)) + dputs("memset failed"); + else + dprintf("memory "fhex" (size: %.8X) set to %.2X\n", addr, size&0xFFFFFFFF, value&0xFF); + return STATUS_CONTINUE; +} + +CMDRESULT cbBenchmark(const char* cmd) +{ + char arg1[deflen]=""; + if(!argget(cmd, arg1, 0, false)) + return STATUS_ERROR; + uint addr=0; + if(!valfromstring(arg1, &addr, 0, 0, false, 0)) + return STATUS_ERROR; + uint ticks=GetTickCount(); + for(int i=0; i<1000; i++) + { + unsigned char dest[0x1000]; + _dbg_memread(addr, dest, 0x1000, 0); + } + dprintf("%ums\n", GetTickCount()-ticks); + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugPause(const char* cmd) +{ + if(waitislocked(WAITID_RUN)) + { + dputs("program is not running"); + return STATUS_ERROR; + } + isPausedByUser=true; + DebugBreakProcess(fdProcessInfo->hProcess); + return STATUS_CONTINUE; +} + +CMDRESULT cbMemWrite(const char* cmd) +{ + char arg1[deflen]=""; + if(!argget(cmd, arg1, 0, false)) + return STATUS_ERROR; + uint addr=0; + if(!valfromstring(arg1, &addr, 0, 0, false, 0)) + return STATUS_ERROR; + unsigned char* blub=(unsigned char*)emalloc(0x2123); + memread(fdProcessInfo->hProcess, (const void*)addr, blub, 0x2123, 0); + //memwrite(fdProcessInfo->hProcess, (void*)addr, blub, 0x2123, 0); + return STATUS_CONTINUE; +} + +DWORD WINAPI scyllaThread(void* lpParam) +{ + typedef INT (WINAPI * SCYLLASTARTGUI)(DWORD pid, HINSTANCE mod); + SCYLLASTARTGUI ScyllaStartGui=0; + HINSTANCE hScylla=LoadLibraryA("Scylla.dll"); + if(!hScylla) + { + dputs("error loading Scylla.dll!"); + bScyllaLoaded=false; + return 0; + } + ScyllaStartGui=(SCYLLASTARTGUI)GetProcAddress(hScylla, "ScyllaStartGui"); + if(!ScyllaStartGui) + { + dputs("could not find export 'ScyllaStartGui' inside Scylla.dll"); + bScyllaLoaded=false; + return 0; + } + if(bFileIsDll) + ScyllaStartGui(fdProcessInfo->dwProcessId, (HINSTANCE)pDebuggedDllBase); + else + ScyllaStartGui(fdProcessInfo->dwProcessId, 0); + FreeLibrary(hScylla); + bScyllaLoaded=false; + return 0; +} + +CMDRESULT cbStartScylla(const char* cmd) +{ + if(bScyllaLoaded) + { + dputs("Scylla is already loaded"); + return STATUS_ERROR; + } + bScyllaLoaded=true; + CreateThread(0, 0, scyllaThread, 0, 0, 0); + return STATUS_CONTINUE; +} diff --git a/x64_dbg_dbg/debugger.h b/x64_dbg_dbg/debugger.h new file mode 100644 index 00000000..e8a94dc6 --- /dev/null +++ b/x64_dbg_dbg/debugger.h @@ -0,0 +1,53 @@ +#ifndef _DEBUGGER_H +#define _DEBUGGER_H + +#include "_global.h" +#include "TitanEngine\TitanEngine.h" +#include "command.h" +#include "breakpoint.h" + +//structures +struct INIT_STRUCT +{ + char* exe; + char* commandline; + char* currentfolder; +}; + +//functions +void dbgdisablebpx(); +void dbgenablebpx(); +bool dbgisrunning(); +void DebugUpdateGui(uint disasm_addr); +//callbacks +CMDRESULT cbDebugInit(const char* cmd); +CMDRESULT cbStopDebug(const char* cmd); +CMDRESULT cbDebugRun(const char* cmd); +CMDRESULT cbDebugSetBPXOptions(const char* cmd); +CMDRESULT cbDebugSetBPX(const char* cmd); +CMDRESULT cbDebugEnableBPX(const char* cmd); +CMDRESULT cbDebugDisableBPX(const char* cmd); +CMDRESULT cbDebugToggleBPX(const char* cmd); +CMDRESULT cbDebugDeleteBPX(const char* cmd); +CMDRESULT cbDebugBplist(const char* cmd); +CMDRESULT cbDebugStepInto(const char* cmd); +CMDRESULT cbDebugStepOver(const char* cmd); +CMDRESULT cbDebugSingleStep(const char* cmd); +CMDRESULT cbDebugHide(const char* cmd); +CMDRESULT cbDebugDisasm(const char* cmd); +CMDRESULT cbDebugMemoryBpx(const char* cmd); +CMDRESULT cbDebugRtr(const char* cmd); +CMDRESULT cbDebugSetHardwareBreakpoint(const char* cmd); +CMDRESULT cbDebugAlloc(const char* cmd); +CMDRESULT cbDebugFree(const char* cmd); +CMDRESULT cbDebugMemset(const char* cmd); +CMDRESULT cbBenchmark(const char* cmd); +CMDRESULT cbDebugPause(const char* cmd); +CMDRESULT cbMemWrite(const char* cmd); +CMDRESULT cbStartScylla(const char* cmd); + +//variables +extern PROCESS_INFORMATION* fdProcessInfo; +extern BREAKPOINT* bplist; + +#endif // _DEBUGGER_H diff --git a/x64_dbg_dbg/instruction.cpp b/x64_dbg_dbg/instruction.cpp new file mode 100644 index 00000000..fc043bf0 --- /dev/null +++ b/x64_dbg_dbg/instruction.cpp @@ -0,0 +1,211 @@ +#include "instruction.h" +#include "argument.h" +#include "variable.h" +#include "console.h" +#include "value.h" +#include "command.h" + +CMDRESULT cbBadCmd(const char* cmd) +{ + uint value=0; + int valsize=0; + bool isvar=false; + bool hexonly=false; + if(valfromstring(cmd, &value, &valsize, &isvar, false, &hexonly)) //dump variable/value/register/etc + { + //dprintf("[DEBUG] valsize: %d\n", valsize); + if(valsize) + valsize*=2; + else + valsize=1; + char format_str[deflen]=""; + if(isvar)// and *cmd!='.' and *cmd!='x') //prevent stupid 0=0 stuff + { + if(value>15 and !hexonly) + { + if(!valuesignedcalc()) //signed numbers + sprintf(format_str, "%%s=%%.%d"fext"X (%%"fext"ud)\n", valsize); + else + sprintf(format_str, "%%s=%%.%d"fext"X (%%"fext"d)\n", valsize); + dprintf(format_str, cmd, value, value); + } + else + { + sprintf(format_str, "%%s=%%.%d"fext"X\n", valsize); + dprintf(format_str, cmd, value); + } + } + else + { + if(value>15 and !hexonly) + { + if(!valuesignedcalc()) //signed numbers + sprintf(format_str, "%%s=%%.%d"fext"X (%%"fext"ud)\n", valsize); + else + sprintf(format_str, "%%s=%%.%d"fext"X (%%"fext"d)\n", valsize); + sprintf(format_str, "%%.%d"fext"X (%%"fext"ud)\n", valsize); + dprintf(format_str, value, value); + } + else + { + sprintf(format_str, "%%.%d"fext"X\n", valsize); + dprintf(format_str, value); + } + } + } + else //unknown command + { + dprintf("unknown command/expression: \"%s\"\n", cmd); + return STATUS_ERROR; + } + return STATUS_CONTINUE; +} + +CMDRESULT cbInstrVar(const char* cmd) +{ + char arg1[deflen]=""; + char arg2[deflen]=""; + if(!argget(cmd, arg1, 0, false)) //var name + return STATUS_ERROR; + argget(cmd, arg2, 1, true); //var value (optional) + uint value=0; + int add=0; + if(*arg1=='$') + add++; + if(valfromstring(arg1+add, &value, 0, 0, true, 0)) + { + dprintf("invalid variable name \"%s\"\n", arg1); + return STATUS_ERROR; + } + if(!valfromstring(arg2, &value, 0, 0, false, 0)) + { + dprintf("invalid value \"%s\"\n", arg2); + return STATUS_ERROR; + } + if(!varnew(arg1, value, VAR_USER)) + { + dprintf("error creating variable \"%s\"\n", arg1); + return STATUS_ERROR; + } + else + { + if(value>15) + dprintf("%s=%"fext"X (%"fext"ud)\n", arg1, value, value); + else + dprintf("%s=%"fext"X\n", arg1, value); + } + return STATUS_CONTINUE; +} + +CMDRESULT cbInstrVarDel(const char* cmd) +{ + char arg1[deflen]=""; + if(!argget(cmd, arg1, 0, false)) //var name + return STATUS_ERROR; + if(!vardel(arg1, false)) + dprintf("could not delete variable \"%s\"\n", arg1); + else + dprintf("deleted variable \"%s\"\n", arg1); + return STATUS_CONTINUE; +} + +CMDRESULT cbInstrMov(const char* cmd) +{ + char arg1[deflen]=""; + char arg2[deflen]=""; + if(!argget(cmd, arg1, 0, false)) //dest name + return STATUS_ERROR; + if(!argget(cmd, arg2, 1, false)) //src name + return STATUS_ERROR; + uint set_value=0; + if(!valfromstring(arg2, &set_value, 0, 0, false, 0)) + { + dprintf("invalid src \"%s\"\n", arg2); + return STATUS_ERROR; + } + bool isvar=false; + uint temp; + valfromstring(arg1, &temp, 0, &isvar, true, 0); + if(!isvar or !valtostring(arg1, &set_value, false)) + { + uint value; + if(valfromstring(arg1, &value, 0, 0, true, 0)) + { + dprintf("invalid dest \"%s\"\n", arg1); + return STATUS_ERROR; + } + varnew(arg1, set_value, VAR_USER); + } + cbBadCmd(arg1); + return STATUS_CONTINUE; +} + +CMDRESULT cbInstrVarList(const char* cmd) +{ + char arg1[deflen]=""; + argget(cmd, arg1, 0, true); + int filter=0; + if(!_stricmp(arg1, "USER")) + filter=VAR_USER; + else if(!_stricmp(arg1, "READONLY")) + filter=VAR_READONLY; + else if(!_stricmp(arg1, "SYSTEM")) + filter=VAR_SYSTEM; + VAR* cur=vargetptr(); + if(!cur or !cur->name) + { + dputs("no variables"); + return STATUS_CONTINUE; + } + + bool bNext=true; + while(bNext) + { + char name[deflen]=""; + strcpy(name, cur->name); + int len=strlen(name); + for(int i=0; ivalue.value; + if(cur->type!=VAR_HIDDEN) + { + if(filter) + { + if(cur->type==filter) + { + if(value>15) + dprintf("%s=%"fext"X (%"fext"ud)\n", name, value, value); + else + dprintf("%s=%"fext"X\n", name, value); + } + } + else + { + if(value>15) + dprintf("%s=%"fext"X (%"fext"ud)\n", name, value, value); + else + dprintf("%s=%"fext"X\n", name, value); + } + } + cur=cur->next; + if(!cur) + bNext=false; + } + return STATUS_CONTINUE; +} + +CMDRESULT cbInstrChd(const char* cmd) +{ + char arg1[deflen]=""; + if(!argget(cmd, arg1, 0, false)) + return STATUS_ERROR; + if(!DirExists(arg1)) + { + dputs("directory doesn't exist"); + return STATUS_ERROR; + } + SetCurrentDirectoryA(arg1); + dputs("current directory changed!"); + return STATUS_CONTINUE; +} diff --git a/x64_dbg_dbg/instruction.h b/x64_dbg_dbg/instruction.h new file mode 100644 index 00000000..3d903792 --- /dev/null +++ b/x64_dbg_dbg/instruction.h @@ -0,0 +1,15 @@ +#ifndef _INSTRUCTIONS_H +#define _INSTRUCTIONS_H + +#include "_global.h" +#include "command.h" + +//functions +CMDRESULT cbBadCmd(const char* cmd); +CMDRESULT cbInstrVar(const char* cmd); +CMDRESULT cbInstrVarDel(const char* cmd); +CMDRESULT cbInstrMov(const char* cmd); +CMDRESULT cbInstrVarList(const char* cmd); +CMDRESULT cbInstrChd(const char* cmd); + +#endif // _INSTRUCTIONS_H diff --git a/x64_dbg_dbg/libdbg_x32.a b/x64_dbg_dbg/libdbg_x32.a new file mode 100644 index 00000000..df27b8f2 Binary files /dev/null and b/x64_dbg_dbg/libdbg_x32.a differ diff --git a/x64_dbg_dbg/libdbg_x64.a b/x64_dbg_dbg/libdbg_x64.a new file mode 100644 index 00000000..b0fb34da Binary files /dev/null and b/x64_dbg_dbg/libdbg_x64.a differ diff --git a/x64_dbg_dbg/main.cpp b/x64_dbg_dbg/main.cpp new file mode 100644 index 00000000..314552cf --- /dev/null +++ b/x64_dbg_dbg/main.cpp @@ -0,0 +1,8 @@ +#include "_global.h" + +extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + if(fdwReason==DLL_PROCESS_ATTACH) + hInst=hinstDLL; + return TRUE; +} diff --git a/x64_dbg_dbg/math.cpp b/x64_dbg_dbg/math.cpp new file mode 100644 index 00000000..4d1c40de --- /dev/null +++ b/x64_dbg_dbg/math.cpp @@ -0,0 +1,425 @@ +#include "math.h" +#include "value.h" + +struct BRACKET_PAIR +{ + int openpos; + int closepos; + int layer; + int isset; //0=free, 1=open, 2=close +}; + +struct EXPRESSION +{ + BRACKET_PAIR* pairs; + int total_pairs; + char* expression; +}; + +/* +operator precedence +1 ( ) +2 ~ (NOT) +3 * / % (MUL DIV) +4 + - (ADD SUB) +5 < > (SHL SHR) +6 & (AND) +7 ^ (XOR) +8 | (OR) +*/ + +int mathisoperator(char ch) +{ + if(ch=='(' or ch==')') + return 1; + else if(ch=='~') + return 2; + else if(ch=='*' or ch=='#' or ch=='/' or ch=='%') + return 3; + else if(ch=='+' or ch=='-') + return 4; + else if(ch=='<' or ch=='>') + return 5; + else if(ch=='&') + return 6; + else if(ch=='^') + return 7; + else if(ch=='|') + return 8; + return 0; +} + +/* +mathformat: +- remove doubles +*/ +void mathformat(char* text) +{ + int len=strlen(text); + char* temp=(char*)emalloc(len+1); + memset(temp, 0, len+1); + for(int i=0,j=0; i>64); +} + +static inline long long mulhi(long long x, long long y) +{ + return (long long)(((__int128_t)x*y)>>64); +} +#elif _WIN64 +#include +static inline unsigned long long umulhi(unsigned long long x, unsigned long long y) +{ + unsigned __int64 res; + _umul128(x,y,&res); + return res; +} + +static inline long long mulhi(long long x, long long y) +{ + __int64 res; + _mul128(x,y,&res); + return res; +} +#else +static inline unsigned int umulhi(unsigned int x, unsigned int y) +{ + return (unsigned int)(((unsigned long long)x*y)>>32); +} + +static inline int mulhi(int x, int y) +{ + return (int)(((long long)x*y)>>32); +} +#endif //__MINGW64__ + +bool mathdounsignedoperation(char op, uint left, uint right, uint* result) +{ + switch(op) + { + case '*': + *result=left*right; + return true; + case '#': + *result=umulhi(left, right); + return true; + case '/': + if(right) + { + *result=left/right; + return true; + } + return false; + case '%': + if(right) + { + *result=left%right; + return true; + } + return false; + case '+': + *result=left+right; + return true; + case '-': + *result=left-right; + return true; + case '<': + *result=left<': + *result=left>>right; + return true; + case '&': + *result=left&right; + return true; + case '^': + *result=left^right; + return true; + case '|': + *result=left|right; + return true; + } + return false; +} + +bool mathdosignedoperation(char op, sint left, sint right, sint* result) +{ + switch(op) + { + case '*': + *result=left*right; + return true; + case '#': + *result=mulhi(left, right); + return true; + case '/': + if(right) + { + *result=left/right; + return true; + } + return false; + case '%': + if(right) + { + *result=left%right; + return true; + } + return false; + case '+': + *result=left+right; + return true; + case '-': + *result=left-right; + return true; + case '<': + *result=left<': + *result=left>>right; + return true; + case '&': + *result=left&right; + return true; + case '^': + *result=left^right; + return true; + case '|': + *result=left|right; + return true; + } + return false; +} + +static void fillpair(EXPRESSION* expstruct, int pos, int layer) +{ + for(int i=0; itotal_pairs; i++) + { + if(!expstruct->pairs[i].isset) + { + expstruct->pairs[i].layer=layer; + expstruct->pairs[i].openpos=pos; + expstruct->pairs[i].isset=1; + break; + } + else if(expstruct->pairs[i].layer==layer and expstruct->pairs[i].isset==1) + { + expstruct->pairs[i].closepos=pos; + expstruct->pairs[i].isset=2; + break; + } + } +} + + +static int matchpairs(EXPRESSION* expstruct, char* expression, int endlayer) +{ + int layer=endlayer; + int len=strlen(expression); + for(int i=0; iexpression; + fillpair(expstruct, pos, layer); + i+=matchpairs(expstruct, expression+i+1, layer); + } + else if(expression[i]==')') + { + if(layer==endlayer) + { + int pos=expression+i-expstruct->expression; + fillpair(expstruct, pos, layer); + return i; + } + layer--; + } + + } + return 0; +} + +static int expressionformat(char* exp) +{ + int len=strlen(exp); + int open=0; + int close=0; + for(int i=0; iopen) + return -1; + int add=open-close; + if(add) + { + memset(exp+len, ')', add); + exp[len+add]=0; + } + return open; +} + +static void adjustpairs(EXPRESSION* exps, int cur_open, int cur_close, int cur_len, int new_len) +{ + for(int i=0; itotal_pairs; i++) + { + if(exps->pairs[i].openpos>cur_open) + exps->pairs[i].openpos+=new_len-cur_len; + if(exps->pairs[i].closepos>cur_close) + exps->pairs[i].closepos+=new_len-cur_len; + } +} + +static bool printlayer(char* exp, EXPRESSION* exps, int layer) +{ + for(int i=0; itotal_pairs; i++) + { + if(exps->pairs[i].layer==layer) + { + char temp[256]=""; + char backup[256]=""; + + int open=exps->pairs[i].openpos; + int close=exps->pairs[i].closepos; + int len=close-open; + strncpy(temp, exp+open+1, len-1); + + strcpy(backup, exp+open+len+1); + + uint value; + if(!mathfromstring(temp, &value, 0, 0)) + return false; + + adjustpairs(exps, open, close, len+1, sprintf(exp+open, "%X", value)); + + if(*backup) + strcat(exp, backup); + + } + } + return true; +} + +bool mathhandlebrackets(char* expression) +{ + EXPRESSION expstruct; + expstruct.expression=expression; + int total_pairs=expressionformat(expression); + if(total_pairs==-1) + return false; + else if(!total_pairs) + return true; + expstruct.total_pairs=total_pairs; + + expstruct.pairs=(BRACKET_PAIR*)emalloc(expstruct.total_pairs*sizeof(BRACKET_PAIR)); + memset(expstruct.pairs, 0, expstruct.total_pairs*sizeof(BRACKET_PAIR)); + matchpairs(&expstruct, expression, 0); + int deepest=0; + for(int i=0; ideepest) + deepest=expstruct.pairs[i].layer; + + for(int i=deepest; i>0; i--) + if(!printlayer(expression, &expstruct, i)) + return false; + + efree(expstruct.pairs); + return true; +} + +/* +- handle math +*/ +bool mathfromstring(const char* string, uint* value, int* value_size, bool* isvar) +{ + int highestop=0; + int highestop_pos=0; + int len=strlen(string); + for(int i=0; i1 and curop>highestop) + { + highestop=curop; + highestop_pos=i; + } + } + if(!highestop) + { + if(!valfromstring(string, value, value_size, isvar, false, 0)) + return false; + return true; + } + char* strleft=(char*)emalloc(len+1); + char* strright=(char*)emalloc(len+1); + memset(strleft, 0, len+1); + memset(strright, 0, len+1); + strncpy(strleft, string, highestop_pos); + strcpy(strright, string+highestop_pos+1); + //dprintf("left: %s, right: %s, op: %c\n", strleft, strright, string[highestop_pos]); + if(!*strright) + { + efree(strleft); + efree(strright); + return false; + } + uint right=0; + if(!valfromstring(strright, &right, 0, 0, false, 0)) + { + efree(strleft); + efree(strright); + return false; + } + if(string[highestop_pos]=='~') + { + right=~right; + if(!strlen(strleft)) + { + *value=right; + efree(strleft); + efree(strright); + return true; + } + } + uint left=0; + if(!valfromstring(strleft, &left, 0, 0, false, 0)) + { + efree(strleft); + efree(strright); + return false; + } + bool math_ok; + if(valuesignedcalc()) + math_ok=mathdosignedoperation(string[highestop_pos], left, right, (sint*)value); + else + math_ok=mathdounsignedoperation(string[highestop_pos], left, right, value); + efree(strleft); + efree(strright); + return math_ok; +} + diff --git a/x64_dbg_dbg/math.h b/x64_dbg_dbg/math.h new file mode 100644 index 00000000..65f7fac3 --- /dev/null +++ b/x64_dbg_dbg/math.h @@ -0,0 +1,14 @@ +#ifndef _MATH_H +#define _MATH_H + +#include "_global.h" + +int mathisoperator(char ch); +void mathformat(char* text); +bool mathcontains(const char* text); +bool mathhandlebrackets(char* expression); +bool mathfromstring(const char* string, uint* value, int* value_size, bool* isvar); +bool mathdounsignedoperation(char op, uint left, uint right, uint* result); +bool mathdosignedoperation(char op, sint left, sint right, sint* result); + +#endif // _MATH_H diff --git a/x64_dbg_dbg/memory.cpp b/x64_dbg_dbg/memory.cpp new file mode 100644 index 00000000..abf3cee9 --- /dev/null +++ b/x64_dbg_dbg/memory.cpp @@ -0,0 +1,69 @@ +#include "memory.h" + +uint memfindbaseaddr(HANDLE hProcess, uint addr, uint* size) +{ + MEMORY_BASIC_INFORMATION mbi; + DWORD numBytes; + uint MyAddress=0, newAddress=0; + do + { + numBytes=VirtualQueryEx(hProcess, (LPCVOID)MyAddress, &mbi, sizeof(mbi)); + newAddress=(uint)mbi.BaseAddress+mbi.RegionSize; + if(mbi.State==MEM_COMMIT and addr=MyAddress) + { + if(size) + *size=mbi.RegionSize; + return (uint)mbi.BaseAddress; + } + if(newAddress<=MyAddress) + numBytes=0; + else + MyAddress=newAddress; + } + while(numBytes); + return 0; +} + +bool memread(HANDLE hProcess, const void* lpBaseAddress, void* lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead) +{ + if(!hProcess or !lpBaseAddress or !lpBuffer or !nSize) + return false; + + uint addr=(uint)lpBaseAddress; + uint startRva=addr&(PAGE_SIZE-1); //get start rva + uint addrStart=addr-startRva; //round down one page + uint pages=nSize/PAGE_SIZE+1; + SIZE_T sizeRead=0; + unsigned char curPage[PAGE_SIZE]; //current page memory + unsigned char* destBuffer=(unsigned char*)lpBuffer; + + for(uint i=0; inSize) //do not overflow the buffer + memcpy(destBuffer, curPage+startRva, nSize-sizeRead); + else //default case + memcpy(destBuffer, curPage+startRva, PAGE_SIZE-startRva); + sizeRead+=(PAGE_SIZE-startRva); + destBuffer+=(PAGE_SIZE-startRva); + if(!i) + startRva=0; + } + return true; +} + +void* memalloc(HANDLE hProcess, uint addr, DWORD size, DWORD fdProtect) +{ + return VirtualAllocEx(hProcess, (void*)addr, size, MEM_RESERVE|MEM_COMMIT, fdProtect); +} diff --git a/x64_dbg_dbg/memory.h b/x64_dbg_dbg/memory.h new file mode 100644 index 00000000..56dfcff1 --- /dev/null +++ b/x64_dbg_dbg/memory.h @@ -0,0 +1,12 @@ +#ifndef _MEMORY_H +#define _MEMORY_H + +#include "_global.h" + +#define PAGE_SIZE 0x1000 + +uint memfindbaseaddr(HANDLE hProcess, uint addr, uint* size); +bool memread(HANDLE hProcess, const void* lpBaseAddress, void* lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead); +void* memalloc(HANDLE hProcess, uint addr, DWORD size, DWORD fdProtect); + +#endif // _MEMORY_H diff --git a/x64_dbg_dbg/msgqueue.cpp b/x64_dbg_dbg/msgqueue.cpp new file mode 100644 index 00000000..6d4746ff --- /dev/null +++ b/x64_dbg_dbg/msgqueue.cpp @@ -0,0 +1,83 @@ +#include "msgqueue.h" +#include + +//allocate a message (internal) +static MESSAGE* msgalloc() +{ + return (MESSAGE*)emalloc(sizeof(MESSAGE)); +} + +//free a message (internal) +static void msgfree(MESSAGE* msg) +{ + efree(msg); +} + +//allocate a message stack +MESSAGE_STACK* msgallocstack() +{ + MESSAGE_STACK* msgstack=(MESSAGE_STACK*)emalloc(sizeof(MESSAGE_STACK)); + if(!msgstack) + return 0; + memset(msgstack, 0, sizeof(MESSAGE_STACK)); + InitializeCriticalSection(&msgstack->cr); + return msgstack; +} + +//free a message stack +void msgfreestack(MESSAGE_STACK* msgstack) +{ + DeleteCriticalSection(&msgstack->cr); + int stackpos=msgstack->stackpos; + for(int i=0; imsg[i]); + efree(msgstack); +} + +//add a message to the stack +bool msgsend(MESSAGE_STACK* msgstack, int msg, uint param1, uint param2) +{ + int stackpos=msgstack->stackpos; + if(stackpos>=MAX_MESSAGES) + return false; + MESSAGE* newmsg=msgalloc(); + if(!newmsg) + return false; + newmsg->msg=msg; + newmsg->param1=param1; + newmsg->param2=param2; + CRITICAL_SECTION* cr=&msgstack->cr; + EnterCriticalSection(cr); + msgstack->msg[stackpos]=newmsg; + msgstack->stackpos++; //increase stack pointer + LeaveCriticalSection(cr); + return true; +} + +//get a message from the stack (will return false when there are no messages) +bool msgget(MESSAGE_STACK* msgstack, MESSAGE* msg) +{ + CRITICAL_SECTION* cr=&msgstack->cr; + EnterCriticalSection(cr); + int stackpos=msgstack->stackpos; + if(!msgstack->stackpos) //no messages to process + { + LeaveCriticalSection(cr); + return false; + } + msgstack->stackpos--; //current message is at stackpos-1 + stackpos--; + MESSAGE* stackmsg=msgstack->msg[stackpos]; + memcpy(msg, stackmsg, sizeof(MESSAGE)); + msgfree(stackmsg); + msgstack->msg[stackpos]=0; + LeaveCriticalSection(cr); + return true; +} + +//wait for a message on the specified stack +void msgwait(MESSAGE_STACK* msgstack, MESSAGE* msg) +{ + while(!msgget(msgstack, msg)) + Sleep(1); +} diff --git a/x64_dbg_dbg/msgqueue.h b/x64_dbg_dbg/msgqueue.h new file mode 100644 index 00000000..542e6426 --- /dev/null +++ b/x64_dbg_dbg/msgqueue.h @@ -0,0 +1,32 @@ +#ifndef _MSGQUEUE_H +#define _MSGQUEUE_H + +#include "_global.h" +#include + +#define MAX_MESSAGES 4096 + +//message structure +struct MESSAGE +{ + int msg; + uint param1; + uint param2; +}; + +//message stack structure +struct MESSAGE_STACK +{ + CRITICAL_SECTION cr; + int stackpos; + MESSAGE* msg[MAX_MESSAGES]; +}; + +//function definitions +MESSAGE_STACK* msgallocstack(); +void msgfreestack(MESSAGE_STACK* msgstack); +bool msgsend(MESSAGE_STACK* msgstack, int msg, uint param1, uint param2); +bool msgget(MESSAGE_STACK* msgstack, MESSAGE* msg); +void msgwait(MESSAGE_STACK* msgstack, MESSAGE* msg); + +#endif // _MSGQUEUE_H diff --git a/x64_dbg_dbg/script_commands.txt b/x64_dbg_dbg/script_commands.txt new file mode 100644 index 00000000..d8ba4db1 --- /dev/null +++ b/x64_dbg_dbg/script_commands.txt @@ -0,0 +1,180 @@ +odbgscript commands: + +general purpose: +$result +$result_1 +$result_2 +$result_3 +$result_4 +$version +**eval +refresh +*var +*varlist +*help + +assembly: +*asm +*asmtxt +**exec +ende +*opcode +preop + +automation: +an +**cmt +*dbh +*dbs +key +***lbl +**lc +**lclr +opendump +opentrace +tc + +breakpoints: +*bc +*bd +*bp +bpcnd +*bpd +***bpgoto +*bphwc +*bphws +bpl +bplcnd +*bpmc +*bprm +*bpwm +*bpx +cob +coe +eob +eoe +gpmb +gbpr + +mathematic, binary operands: +*add +*and +*dec +*div +*inc +*mov +*mul +*neg +*not +*or +*rev +*rol +*ror +*shl +*shr +*sub +*test +*xor +*xchg + +jump, call, conditional jumps: +call +*cmp +cret +goto +ifa +ifae +ifb +ifbe +ifeq +ifneq +ja +jae +jb +jbe +je +jg +jge +jl +jle +jmp +jne +jnz +jz +ret + +log commands: +#log +**log +**logbuf +***wrt +***wrta + +strings: +*atoi +buf +*itoa +*len +readstr +scmp +scmpi +*str + +stepping: +ai +ao +*erun +*esti +*esto +*go +*rtr +**rtu +*run +*sti +*sto +ti +ticnd +to +tocnd + +information: +gapi +*gci +gcmt +gma +*gmemi +*gmi +gn +*gpa +gpi +gro +**ref +tick + +memory: +*alloc +*dm +*dma +*dpe +*fill +*free +*lm +*memcpy +*pop +*push + +search: +*find +**findcalls +**findcmd +*findop +*findmem +gref +*repl + +user interface: +***ask +***msg +***msgyn +***pause +setoption \ No newline at end of file diff --git a/x64_dbg_dbg/simplescript.cpp b/x64_dbg_dbg/simplescript.cpp new file mode 100644 index 00000000..4a3c630f --- /dev/null +++ b/x64_dbg_dbg/simplescript.cpp @@ -0,0 +1,57 @@ +#include "simplescript.h" +#include "command.h" +#include "console.h" +#include "instruction.h" + +static int total=0; +static char found[1024][1024]; +static COMMAND* command_list=0; + +static CMDRESULT cbRet(const char* cmd) +{ + return STATUS_EXIT; +} + +static bool cbCommandProvider(char* cmd, int maxlen) +{ + fgets(cmd, maxlen, stdin); + cmd[strlen(cmd)-1]=0; + return true; +} + +static CMDRESULT cbCollect(const char* cmd) +{ + strcpy(found[total], cmd); + total++; + if(total>=1024) + return STATUS_EXIT; + return STATUS_CONTINUE; +} + +void scriptSetList(COMMAND* cmd_list) +{ + command_list=cmd_list; +} + +static int i=0; + +static bool provider(char* cmd, int size) +{ + strcpy(cmd, found[i]); + i++; + if(i>total) + return false; + return true; +} + +CMDRESULT cbScript(const char* cmd) +{ + total=0; + i=0; + COMMAND* cmd_list=cmdinit(); + cmdnew(cmd_list, "ret", cbRet, false); + cmdloop(cmd_list, cbCollect, cbCommandProvider, 0, false); + cmdfree(cmd_list); + cmdloop(command_list, cbBadCmd, provider, cmdfindmain, true); + return STATUS_CONTINUE; +} diff --git a/x64_dbg_dbg/simplescript.h b/x64_dbg_dbg/simplescript.h new file mode 100644 index 00000000..4e98e44f --- /dev/null +++ b/x64_dbg_dbg/simplescript.h @@ -0,0 +1,9 @@ +#ifndef _SIMPLESCRIPT_H +#define _SIMPLESCRIPT_H + +#include "command.h" + +CMDRESULT cbScript(const char* cmd); +void scriptSetList(COMMAND* cmd_list); + +#endif // _SIMPLESCRIPT_H diff --git a/x64_dbg_dbg/sqlite/libsqlite32.a b/x64_dbg_dbg/sqlite/libsqlite32.a new file mode 100644 index 00000000..b048228f Binary files /dev/null and b/x64_dbg_dbg/sqlite/libsqlite32.a differ diff --git a/x64_dbg_dbg/sqlite/libsqlite64.a b/x64_dbg_dbg/sqlite/libsqlite64.a new file mode 100644 index 00000000..23c73910 Binary files /dev/null and b/x64_dbg_dbg/sqlite/libsqlite64.a differ diff --git a/x64_dbg_dbg/sqlite/sqlite3.h b/x64_dbg_dbg/sqlite/sqlite3.h new file mode 100644 index 00000000..a52d55c3 --- /dev/null +++ b/x64_dbg_dbg/sqlite/sqlite3.h @@ -0,0 +1,7315 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the interface that the SQLite library +** presents to client programs. If a C-function, structure, datatype, +** or constant definition does not appear in this file, then it is +** not a published API of SQLite, is subject to change without +** notice, and should not be referenced by programs that use SQLite. +** +** Some of the definitions that are in this file are marked as +** "experimental". Experimental interfaces are normally new +** features recently added to SQLite. We do not anticipate changes +** to experimental interfaces but reserve the right to make minor changes +** if experience from use "in the wild" suggest such changes are prudent. +** +** The official C-language API documentation for SQLite is derived +** from comments in this file. This file is the authoritative source +** on how SQLite interfaces are suppose to operate. +** +** The name of this file under configuration management is "sqlite.h.in". +** The makefile makes some minor changes to this file (such as inserting +** the version number) and changes its name to "sqlite3.h" as +** part of the build process. +*/ +#ifndef _SQLITE3_H_ +#define _SQLITE3_H_ +#include /* Needed for the definition of va_list */ + +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +extern "C" { +#endif + + +/* +** Add the ability to override 'extern' +*/ +#ifndef SQLITE_EXTERN +# define SQLITE_EXTERN extern +#endif + +#ifndef SQLITE_API +# define SQLITE_API +#endif + + +/* +** These no-op macros are used in front of interfaces to mark those +** interfaces as either deprecated or experimental. New applications +** should not use deprecated interfaces - they are support for backwards +** compatibility only. Application writers should be aware that +** experimental interfaces are subject to change in point releases. +** +** These macros used to resolve to various kinds of compiler magic that +** would generate warning messages when they were used. But that +** compiler magic ended up generating such a flurry of bug reports +** that we have taken it all out and gone back to using simple +** noop macros. +*/ +#define SQLITE_DEPRECATED +#define SQLITE_EXPERIMENTAL + +/* +** Ensure these symbols were not defined by some previous header file. +*/ +#ifdef SQLITE_VERSION +# undef SQLITE_VERSION +#endif +#ifdef SQLITE_VERSION_NUMBER +# undef SQLITE_VERSION_NUMBER +#endif + +/* +** CAPI3REF: Compile-Time Library Version Numbers +** +** ^(The [SQLITE_VERSION] C preprocessor macro in the sqlite3.h header +** evaluates to a string literal that is the SQLite version in the +** format "X.Y.Z" where X is the major version number (always 3 for +** SQLite3) and Y is the minor version number and Z is the release number.)^ +** ^(The [SQLITE_VERSION_NUMBER] C preprocessor macro resolves to an integer +** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same +** numbers used in [SQLITE_VERSION].)^ +** The SQLITE_VERSION_NUMBER for any given release of SQLite will also +** be larger than the release from which it is derived. Either Y will +** be held constant and Z will be incremented or else Y will be incremented +** and Z will be reset to zero. +** +** Since version 3.6.18, SQLite source code has been stored in the +** Fossil configuration management +** system. ^The SQLITE_SOURCE_ID macro evaluates to +** a string which identifies a particular check-in of SQLite +** within its configuration management system. ^The SQLITE_SOURCE_ID +** string contains the date and time of the check-in (UTC) and an SHA1 +** hash of the entire source tree. +** +** See also: [sqlite3_libversion()], +** [sqlite3_libversion_number()], [sqlite3_sourceid()], +** [sqlite_version()] and [sqlite_source_id()]. +*/ +#define SQLITE_VERSION "3.8.1" +#define SQLITE_VERSION_NUMBER 3008001 +#define SQLITE_SOURCE_ID "2013-10-17 12:57:35 c78be6d786c19073b3a6730dfe3fb1be54f5657a" + +/* +** CAPI3REF: Run-Time Library Version Numbers +** KEYWORDS: sqlite3_version, sqlite3_sourceid +** +** These interfaces provide the same information as the [SQLITE_VERSION], +** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros +** but are associated with the library instead of the header file. ^(Cautious +** programmers might include assert() statements in their application to +** verify that values returned by these interfaces match the macros in +** the header, and thus insure that the application is +** compiled with matching library and header files. +** +**
+** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
+** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 );
+** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
+** 
)^ +** +** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] +** macro. ^The sqlite3_libversion() function returns a pointer to the +** to the sqlite3_version[] string constant. The sqlite3_libversion() +** function is provided for use in DLLs since DLL users usually do not have +** direct access to string constants within the DLL. ^The +** sqlite3_libversion_number() function returns an integer equal to +** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns +** a pointer to a string constant whose value is the same as the +** [SQLITE_SOURCE_ID] C preprocessor macro. +** +** See also: [sqlite_version()] and [sqlite_source_id()]. +*/ +SQLITE_API SQLITE_EXTERN const char sqlite3_version[]; +SQLITE_API const char *sqlite3_libversion(void); +SQLITE_API const char *sqlite3_sourceid(void); +SQLITE_API int sqlite3_libversion_number(void); + +/* +** CAPI3REF: Run-Time Library Compilation Options Diagnostics +** +** ^The sqlite3_compileoption_used() function returns 0 or 1 +** indicating whether the specified option was defined at +** compile time. ^The SQLITE_ prefix may be omitted from the +** option name passed to sqlite3_compileoption_used(). +** +** ^The sqlite3_compileoption_get() function allows iterating +** over the list of options that were defined at compile time by +** returning the N-th compile time option string. ^If N is out of range, +** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ +** prefix is omitted from any strings returned by +** sqlite3_compileoption_get(). +** +** ^Support for the diagnostic functions sqlite3_compileoption_used() +** and sqlite3_compileoption_get() may be omitted by specifying the +** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. +** +** See also: SQL functions [sqlite_compileoption_used()] and +** [sqlite_compileoption_get()] and the [compile_options pragma]. +*/ +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS +SQLITE_API int sqlite3_compileoption_used(const char *zOptName); +SQLITE_API const char *sqlite3_compileoption_get(int N); +#endif + +/* +** CAPI3REF: Test To See If The Library Is Threadsafe +** +** ^The sqlite3_threadsafe() function returns zero if and only if +** SQLite was compiled with mutexing code omitted due to the +** [SQLITE_THREADSAFE] compile-time option being set to 0. +** +** SQLite can be compiled with or without mutexes. When +** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes +** are enabled and SQLite is threadsafe. When the +** [SQLITE_THREADSAFE] macro is 0, +** the mutexes are omitted. Without the mutexes, it is not safe +** to use SQLite concurrently from more than one thread. +** +** Enabling mutexes incurs a measurable performance penalty. +** So if speed is of utmost importance, it makes sense to disable +** the mutexes. But for maximum safety, mutexes should be enabled. +** ^The default behavior is for mutexes to be enabled. +** +** This interface can be used by an application to make sure that the +** version of SQLite that it is linking against was compiled with +** the desired setting of the [SQLITE_THREADSAFE] macro. +** +** This interface only reports on the compile-time mutex setting +** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with +** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but +** can be fully or partially disabled using a call to [sqlite3_config()] +** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], +** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the +** sqlite3_threadsafe() function shows only the compile-time setting of +** thread safety, not any run-time changes to that setting made by +** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() +** is unchanged by calls to sqlite3_config().)^ +** +** See the [threading mode] documentation for additional information. +*/ +SQLITE_API int sqlite3_threadsafe(void); + +/* +** CAPI3REF: Database Connection Handle +** KEYWORDS: {database connection} {database connections} +** +** Each open SQLite database is represented by a pointer to an instance of +** the opaque structure named "sqlite3". It is useful to think of an sqlite3 +** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and +** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()] +** and [sqlite3_close_v2()] are its destructors. There are many other +** interfaces (such as +** [sqlite3_prepare_v2()], [sqlite3_create_function()], and +** [sqlite3_busy_timeout()] to name but three) that are methods on an +** sqlite3 object. +*/ +typedef struct sqlite3 sqlite3; + +/* +** CAPI3REF: 64-Bit Integer Types +** KEYWORDS: sqlite_int64 sqlite_uint64 +** +** Because there is no cross-platform way to specify 64-bit integer types +** SQLite includes typedefs for 64-bit signed and unsigned integers. +** +** The sqlite3_int64 and sqlite3_uint64 are the preferred type definitions. +** The sqlite_int64 and sqlite_uint64 types are supported for backwards +** compatibility only. +** +** ^The sqlite3_int64 and sqlite_int64 types can store integer values +** between -9223372036854775808 and +9223372036854775807 inclusive. ^The +** sqlite3_uint64 and sqlite_uint64 types can store integer values +** between 0 and +18446744073709551615 inclusive. +*/ +#ifdef SQLITE_INT64_TYPE +typedef SQLITE_INT64_TYPE sqlite_int64; +typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; +#elif defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 sqlite_int64; +typedef unsigned __int64 sqlite_uint64; +#else +typedef long long int sqlite_int64; +typedef unsigned long long int sqlite_uint64; +#endif +typedef sqlite_int64 sqlite3_int64; +typedef sqlite_uint64 sqlite3_uint64; + +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point. +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite3_int64 +#endif + +/* +** CAPI3REF: Closing A Database Connection +** +** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors +** for the [sqlite3] object. +** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if +** the [sqlite3] object is successfully destroyed and all associated +** resources are deallocated. +** +** ^If the database connection is associated with unfinalized prepared +** statements or unfinished sqlite3_backup objects then sqlite3_close() +** will leave the database connection open and return [SQLITE_BUSY]. +** ^If sqlite3_close_v2() is called with unfinalized prepared statements +** and unfinished sqlite3_backups, then the database connection becomes +** an unusable "zombie" which will automatically be deallocated when the +** last prepared statement is finalized or the last sqlite3_backup is +** finished. The sqlite3_close_v2() interface is intended for use with +** host languages that are garbage collected, and where the order in which +** destructors are called is arbitrary. +** +** Applications should [sqlite3_finalize | finalize] all [prepared statements], +** [sqlite3_blob_close | close] all [BLOB handles], and +** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated +** with the [sqlite3] object prior to attempting to close the object. ^If +** sqlite3_close_v2() is called on a [database connection] that still has +** outstanding [prepared statements], [BLOB handles], and/or +** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation +** of resources is deferred until all [prepared statements], [BLOB handles], +** and [sqlite3_backup] objects are also destroyed. +** +** ^If an [sqlite3] object is destroyed while a transaction is open, +** the transaction is automatically rolled back. +** +** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)] +** must be either a NULL +** pointer or an [sqlite3] object pointer obtained +** from [sqlite3_open()], [sqlite3_open16()], or +** [sqlite3_open_v2()], and not previously closed. +** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer +** argument is a harmless no-op. +*/ +SQLITE_API int sqlite3_close(sqlite3*); +SQLITE_API int sqlite3_close_v2(sqlite3*); + +/* +** The type for a callback function. +** This is legacy and deprecated. It is included for historical +** compatibility and is not documented. +*/ +typedef int (*sqlite3_callback)(void*,int,char**, char**); + +/* +** CAPI3REF: One-Step Query Execution Interface +** +** The sqlite3_exec() interface is a convenience wrapper around +** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], +** that allows an application to run multiple statements of SQL +** without having to use a lot of C code. +** +** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded, +** semicolon-separate SQL statements passed into its 2nd argument, +** in the context of the [database connection] passed in as its 1st +** argument. ^If the callback function of the 3rd argument to +** sqlite3_exec() is not NULL, then it is invoked for each result row +** coming out of the evaluated SQL statements. ^The 4th argument to +** sqlite3_exec() is relayed through to the 1st argument of each +** callback invocation. ^If the callback pointer to sqlite3_exec() +** is NULL, then no callback is ever invoked and result rows are +** ignored. +** +** ^If an error occurs while evaluating the SQL statements passed into +** sqlite3_exec(), then execution of the current statement stops and +** subsequent statements are skipped. ^If the 5th parameter to sqlite3_exec() +** is not NULL then any error message is written into memory obtained +** from [sqlite3_malloc()] and passed back through the 5th parameter. +** To avoid memory leaks, the application should invoke [sqlite3_free()] +** on error message strings returned through the 5th parameter of +** of sqlite3_exec() after the error message string is no longer needed. +** ^If the 5th parameter to sqlite3_exec() is not NULL and no errors +** occur, then sqlite3_exec() sets the pointer in its 5th parameter to +** NULL before returning. +** +** ^If an sqlite3_exec() callback returns non-zero, the sqlite3_exec() +** routine returns SQLITE_ABORT without invoking the callback again and +** without running any subsequent SQL statements. +** +** ^The 2nd argument to the sqlite3_exec() callback function is the +** number of columns in the result. ^The 3rd argument to the sqlite3_exec() +** callback is an array of pointers to strings obtained as if from +** [sqlite3_column_text()], one for each column. ^If an element of a +** result row is NULL then the corresponding string pointer for the +** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the +** sqlite3_exec() callback is an array of pointers to strings where each +** entry represents the name of corresponding result column as obtained +** from [sqlite3_column_name()]. +** +** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer +** to an empty string, or a pointer that contains only whitespace and/or +** SQL comments, then no SQL statements are evaluated and the database +** is not changed. +** +** Restrictions: +** +**
    +**
  • The application must insure that the 1st parameter to sqlite3_exec() +** is a valid and open [database connection]. +**
  • The application must not close [database connection] specified by +** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running. +**
  • The application must not modify the SQL statement text passed into +** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. +**
+*/ +SQLITE_API int sqlite3_exec( + sqlite3*, /* An open database */ + const char *sql, /* SQL to be evaluated */ + int (*callback)(void*,int,char**,char**), /* Callback function */ + void *, /* 1st argument to callback */ + char **errmsg /* Error msg written here */ +); + +/* +** CAPI3REF: Result Codes +** KEYWORDS: SQLITE_OK {error code} {error codes} +** KEYWORDS: {result code} {result codes} +** +** Many SQLite functions return an integer result code from the set shown +** here in order to indicate success or failure. +** +** New error codes may be added in future versions of SQLite. +** +** See also: [SQLITE_IOERR_READ | extended result codes], +** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes]. +*/ +#define SQLITE_OK 0 /* Successful result */ +/* beginning-of-error-codes */ +#define SQLITE_ERROR 1 /* SQL error or missing database */ +#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ +#define SQLITE_PERM 3 /* Access permission denied */ +#define SQLITE_ABORT 4 /* Callback routine requested an abort */ +#define SQLITE_BUSY 5 /* The database file is locked */ +#define SQLITE_LOCKED 6 /* A table in the database is locked */ +#define SQLITE_NOMEM 7 /* A malloc() failed */ +#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ +#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ +#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ +#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ +#define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */ +#define SQLITE_FULL 13 /* Insertion failed because database is full */ +#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ +#define SQLITE_PROTOCOL 15 /* Database lock protocol error */ +#define SQLITE_EMPTY 16 /* Database is empty */ +#define SQLITE_SCHEMA 17 /* The database schema changed */ +#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ +#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ +#define SQLITE_MISMATCH 20 /* Data type mismatch */ +#define SQLITE_MISUSE 21 /* Library used incorrectly */ +#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ +#define SQLITE_AUTH 23 /* Authorization denied */ +#define SQLITE_FORMAT 24 /* Auxiliary database format error */ +#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ +#define SQLITE_NOTADB 26 /* File opened that is not a database file */ +#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */ +#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */ +#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ +#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ +/* end-of-error-codes */ + +/* +** CAPI3REF: Extended Result Codes +** KEYWORDS: {extended error code} {extended error codes} +** KEYWORDS: {extended result code} {extended result codes} +** +** In its default configuration, SQLite API routines return one of 26 integer +** [SQLITE_OK | result codes]. However, experience has shown that many of +** these result codes are too coarse-grained. They do not provide as +** much information about problems as programmers might like. In an effort to +** address this, newer versions of SQLite (version 3.3.8 and later) include +** support for additional result codes that provide more detailed information +** about errors. The extended result codes are enabled or disabled +** on a per database connection basis using the +** [sqlite3_extended_result_codes()] API. +** +** Some of the available extended result codes are listed here. +** One may expect the number of extended result codes will be expand +** over time. Software that uses extended result codes should expect +** to see new result codes in future releases of SQLite. +** +** The SQLITE_OK result code will never be extended. It will always +** be exactly zero. +*/ +#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) +#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) +#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) +#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) +#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) +#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) +#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) +#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) +#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) +#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) +#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) +#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) +#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8)) +#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8)) +#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8)) +#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8)) +#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8)) +#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8)) +#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8)) +#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) +#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) +#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) +#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8)) +#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) +#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8)) +#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8)) +#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) +#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) +#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) +#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) +#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) +#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) +#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) +#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) +#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) +#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) +#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) +#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) +#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) +#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) +#define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8)) +#define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8)) +#define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8)) +#define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8)) +#define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8)) +#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) +#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) +#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) +#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) +#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) + +/* +** CAPI3REF: Flags For File Open Operations +** +** These bit values are intended for use in the +** 3rd parameter to the [sqlite3_open_v2()] interface and +** in the 4th parameter to the [sqlite3_vfs.xOpen] method. +*/ +#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ +#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ +#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ +#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_MEMORY 0x00000080 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ +#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ +#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ +#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ +#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ +#define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ +#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ +#define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ + +/* Reserved: 0x00F00000 */ + +/* +** CAPI3REF: Device Characteristics +** +** The xDeviceCharacteristics method of the [sqlite3_io_methods] +** object returns an integer which is a vector of these +** bit values expressing I/O characteristics of the mass storage +** device that holds the file that the [sqlite3_io_methods] +** refers to. +** +** The SQLITE_IOCAP_ATOMIC property means that all writes of +** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values +** mean that writes of blocks that are nnn bytes in size and +** are aligned to an address which is an integer multiple of +** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means +** that when data is appended to a file, the data is appended +** first then the size of the file is extended, never the other +** way around. The SQLITE_IOCAP_SEQUENTIAL property means that +** information is written to disk in the same order as calls +** to xWrite(). The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that +** after reboot following a crash or power loss, the only bytes in a +** file that were written at the application level might have changed +** and that adjacent bytes, even bytes within the same sector are +** guaranteed to be unchanged. +*/ +#define SQLITE_IOCAP_ATOMIC 0x00000001 +#define SQLITE_IOCAP_ATOMIC512 0x00000002 +#define SQLITE_IOCAP_ATOMIC1K 0x00000004 +#define SQLITE_IOCAP_ATOMIC2K 0x00000008 +#define SQLITE_IOCAP_ATOMIC4K 0x00000010 +#define SQLITE_IOCAP_ATOMIC8K 0x00000020 +#define SQLITE_IOCAP_ATOMIC16K 0x00000040 +#define SQLITE_IOCAP_ATOMIC32K 0x00000080 +#define SQLITE_IOCAP_ATOMIC64K 0x00000100 +#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 +#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 +#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 +#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 + +/* +** CAPI3REF: File Locking Levels +** +** SQLite uses one of these integer values as the second +** argument to calls it makes to the xLock() and xUnlock() methods +** of an [sqlite3_io_methods] object. +*/ +#define SQLITE_LOCK_NONE 0 +#define SQLITE_LOCK_SHARED 1 +#define SQLITE_LOCK_RESERVED 2 +#define SQLITE_LOCK_PENDING 3 +#define SQLITE_LOCK_EXCLUSIVE 4 + +/* +** CAPI3REF: Synchronization Type Flags +** +** When SQLite invokes the xSync() method of an +** [sqlite3_io_methods] object it uses a combination of +** these integer values as the second argument. +** +** When the SQLITE_SYNC_DATAONLY flag is used, it means that the +** sync operation only needs to flush data to mass storage. Inode +** information need not be flushed. If the lower four bits of the flag +** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics. +** If the lower four bits equal SQLITE_SYNC_FULL, that means +** to use Mac OS X style fullsync instead of fsync(). +** +** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags +** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL +** settings. The [synchronous pragma] determines when calls to the +** xSync VFS method occur and applies uniformly across all platforms. +** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how +** energetic or rigorous or forceful the sync operations are and +** only make a difference on Mac OSX for the default SQLite code. +** (Third-party VFS implementations might also make the distinction +** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the +** operating systems natively supported by SQLite, only Mac OSX +** cares about the difference.) +*/ +#define SQLITE_SYNC_NORMAL 0x00002 +#define SQLITE_SYNC_FULL 0x00003 +#define SQLITE_SYNC_DATAONLY 0x00010 + +/* +** CAPI3REF: OS Interface Open File Handle +** +** An [sqlite3_file] object represents an open file in the +** [sqlite3_vfs | OS interface layer]. Individual OS interface +** implementations will +** want to subclass this object by appending additional fields +** for their own use. The pMethods entry is a pointer to an +** [sqlite3_io_methods] object that defines methods for performing +** I/O operations on the open file. +*/ +typedef struct sqlite3_file sqlite3_file; +struct sqlite3_file +{ + const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ +}; + +/* +** CAPI3REF: OS Interface File Virtual Methods Object +** +** Every file opened by the [sqlite3_vfs.xOpen] method populates an +** [sqlite3_file] object (or, more commonly, a subclass of the +** [sqlite3_file] object) with a pointer to an instance of this object. +** This object defines the methods used to perform various operations +** against the open file represented by the [sqlite3_file] object. +** +** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element +** to a non-NULL pointer, then the sqlite3_io_methods.xClose method +** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The +** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen] +** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element +** to NULL. +** +** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or +** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). +** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY] +** flag may be ORed in to indicate that only the data of the file +** and not its inode needs to be synced. +** +** The integer values to xLock() and xUnlock() are one of +**
    +**
  • [SQLITE_LOCK_NONE], +**
  • [SQLITE_LOCK_SHARED], +**
  • [SQLITE_LOCK_RESERVED], +**
  • [SQLITE_LOCK_PENDING], or +**
  • [SQLITE_LOCK_EXCLUSIVE]. +**
+** xLock() increases the lock. xUnlock() decreases the lock. +** The xCheckReservedLock() method checks whether any database connection, +** either in this process or in some other process, is holding a RESERVED, +** PENDING, or EXCLUSIVE lock on the file. It returns true +** if such a lock exists and false otherwise. +** +** The xFileControl() method is a generic interface that allows custom +** VFS implementations to directly control an open file using the +** [sqlite3_file_control()] interface. The second "op" argument is an +** integer opcode. The third argument is a generic pointer intended to +** point to a structure that may contain arguments or space in which to +** write return values. Potential uses for xFileControl() might be +** functions to enable blocking locks with timeouts, to change the +** locking strategy (for example to use dot-file locks), to inquire +** about the status of a lock, or to break stale locks. The SQLite +** core reserves all opcodes less than 100 for its own use. +** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. +** Applications that define a custom xFileControl method should use opcodes +** greater than 100 to avoid conflicts. VFS implementations should +** return [SQLITE_NOTFOUND] for file control opcodes that they do not +** recognize. +** +** The xSectorSize() method returns the sector size of the +** device that underlies the file. The sector size is the +** minimum write that can be performed without disturbing +** other bytes in the file. The xDeviceCharacteristics() +** method returns a bit vector describing behaviors of the +** underlying device: +** +**
    +**
  • [SQLITE_IOCAP_ATOMIC] +**
  • [SQLITE_IOCAP_ATOMIC512] +**
  • [SQLITE_IOCAP_ATOMIC1K] +**
  • [SQLITE_IOCAP_ATOMIC2K] +**
  • [SQLITE_IOCAP_ATOMIC4K] +**
  • [SQLITE_IOCAP_ATOMIC8K] +**
  • [SQLITE_IOCAP_ATOMIC16K] +**
  • [SQLITE_IOCAP_ATOMIC32K] +**
  • [SQLITE_IOCAP_ATOMIC64K] +**
  • [SQLITE_IOCAP_SAFE_APPEND] +**
  • [SQLITE_IOCAP_SEQUENTIAL] +**
+** +** The SQLITE_IOCAP_ATOMIC property means that all writes of +** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values +** mean that writes of blocks that are nnn bytes in size and +** are aligned to an address which is an integer multiple of +** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means +** that when data is appended to a file, the data is appended +** first then the size of the file is extended, never the other +** way around. The SQLITE_IOCAP_SEQUENTIAL property means that +** information is written to disk in the same order as calls +** to xWrite(). +** +** If xRead() returns SQLITE_IOERR_SHORT_READ it must also fill +** in the unread portions of the buffer with zeros. A VFS that +** fails to zero-fill short reads might seem to work. However, +** failure to zero-fill short reads will eventually lead to +** database corruption. +*/ +typedef struct sqlite3_io_methods sqlite3_io_methods; +struct sqlite3_io_methods +{ + int iVersion; + int (*xClose)(sqlite3_file*); + int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); + int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); + int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); + int (*xSync)(sqlite3_file*, int flags); + int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); + int (*xLock)(sqlite3_file*, int); + int (*xUnlock)(sqlite3_file*, int); + int (*xCheckReservedLock)(sqlite3_file*, int *pResOut); + int (*xFileControl)(sqlite3_file*, int op, void *pArg); + int (*xSectorSize)(sqlite3_file*); + int (*xDeviceCharacteristics)(sqlite3_file*); + /* Methods above are valid for version 1 */ + int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); + int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); + void (*xShmBarrier)(sqlite3_file*); + int (*xShmUnmap)(sqlite3_file*, int deleteFlag); + /* Methods above are valid for version 2 */ + int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); + int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p); + /* Methods above are valid for version 3 */ + /* Additional methods may be added in future releases */ +}; + +/* +** CAPI3REF: Standard File Control Opcodes +** +** These integer constants are opcodes for the xFileControl method +** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()] +** interface. +** +** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This +** opcode causes the xFileControl method to write the current state of +** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], +** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) +** into an integer that the pArg argument points to. This capability +** is used during testing and only needs to be supported when SQLITE_TEST +** is defined. +**
    +**
  • [[SQLITE_FCNTL_SIZE_HINT]] +** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS +** layer a hint of how large the database file will grow to be during the +** current transaction. This hint is not guaranteed to be accurate but it +** is often close. The underlying VFS might choose to preallocate database +** file space based on this hint in order to help writes to the database +** file run faster. +** +**
  • [[SQLITE_FCNTL_CHUNK_SIZE]] +** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS +** extends and truncates the database file in chunks of a size specified +** by the user. The fourth argument to [sqlite3_file_control()] should +** point to an integer (type int) containing the new chunk-size to use +** for the nominated database. Allocating database file space in large +** chunks (say 1MB at a time), may reduce file-system fragmentation and +** improve performance on some systems. +** +**
  • [[SQLITE_FCNTL_FILE_POINTER]] +** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer +** to the [sqlite3_file] object associated with a particular database +** connection. See the [sqlite3_file_control()] documentation for +** additional information. +** +**
  • [[SQLITE_FCNTL_SYNC_OMITTED]] +** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by +** SQLite and sent to all VFSes in place of a call to the xSync method +** when the database connection has [PRAGMA synchronous] set to OFF.)^ +** Some specialized VFSes need this signal in order to operate correctly +** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most +** VFSes do not need this signal and should silently ignore this opcode. +** Applications should not call [sqlite3_file_control()] with this +** opcode as doing so may disrupt the operation of the specialized VFSes +** that do require it. +** +**
  • [[SQLITE_FCNTL_WIN32_AV_RETRY]] +** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic +** retry counts and intervals for certain disk I/O operations for the +** windows [VFS] in order to provide robustness in the presence of +** anti-virus programs. By default, the windows VFS will retry file read, +** file write, and file delete operations up to 10 times, with a delay +** of 25 milliseconds before the first retry and with the delay increasing +** by an additional 25 milliseconds with each subsequent retry. This +** opcode allows these two values (10 retries and 25 milliseconds of delay) +** to be adjusted. The values are changed for all database connections +** within the same process. The argument is a pointer to an array of two +** integers where the first integer i the new retry count and the second +** integer is the delay. If either integer is negative, then the setting +** is not changed but instead the prior value of that setting is written +** into the array entry, allowing the current retry settings to be +** interrogated. The zDbName parameter is ignored. +** +**
  • [[SQLITE_FCNTL_PERSIST_WAL]] +** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the +** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary +** write ahead log and shared memory files used for transaction control +** are automatically deleted when the latest connection to the database +** closes. Setting persistent WAL mode causes those files to persist after +** close. Persisting the files is useful when other processes that do not +** have write permission on the directory containing the database file want +** to read the database file, as the WAL and shared memory files must exist +** in order for the database to be readable. The fourth parameter to +** [sqlite3_file_control()] for this opcode should be a pointer to an integer. +** That integer is 0 to disable persistent WAL mode or 1 to enable persistent +** WAL mode. If the integer is -1, then it is overwritten with the current +** WAL persistence setting. +** +**
  • [[SQLITE_FCNTL_POWERSAFE_OVERWRITE]] +** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the +** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting +** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the +** xDeviceCharacteristics methods. The fourth parameter to +** [sqlite3_file_control()] for this opcode should be a pointer to an integer. +** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage +** mode. If the integer is -1, then it is overwritten with the current +** zero-damage mode setting. +** +**
  • [[SQLITE_FCNTL_OVERWRITE]] +** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening +** a write transaction to indicate that, unless it is rolled back for some +** reason, the entire database file will be overwritten by the current +** transaction. This is used by VACUUM operations. +** +**
  • [[SQLITE_FCNTL_VFSNAME]] +** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of +** all [VFSes] in the VFS stack. The names are of all VFS shims and the +** final bottom-level VFS are written into memory obtained from +** [sqlite3_malloc()] and the result is stored in the char* variable +** that the fourth parameter of [sqlite3_file_control()] points to. +** The caller is responsible for freeing the memory when done. As with +** all file-control actions, there is no guarantee that this will actually +** do anything. Callers should initialize the char* variable to a NULL +** pointer in case this file-control is not implemented. This file-control +** is intended for diagnostic use only. +** +**
  • [[SQLITE_FCNTL_PRAGMA]] +** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] +** file control is sent to the open [sqlite3_file] object corresponding +** to the database file to which the pragma statement refers. ^The argument +** to the [SQLITE_FCNTL_PRAGMA] file control is an array of +** pointers to strings (char**) in which the second element of the array +** is the name of the pragma and the third element is the argument to the +** pragma or NULL if the pragma has no argument. ^The handler for an +** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element +** of the char** argument point to a string obtained from [sqlite3_mprintf()] +** or the equivalent and that string will become the result of the pragma or +** the error message if the pragma fails. ^If the +** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal +** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] +** file control returns [SQLITE_OK], then the parser assumes that the +** VFS has handled the PRAGMA itself and the parser generates a no-op +** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns +** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means +** that the VFS encountered an error while handling the [PRAGMA] and the +** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] +** file control occurs at the beginning of pragma statement analysis and so +** it is able to override built-in [PRAGMA] statements. +** +**
  • [[SQLITE_FCNTL_BUSYHANDLER]] +** ^The [SQLITE_FCNTL_BUSYHANDLER] +** file-control may be invoked by SQLite on the database file handle +** shortly after it is opened in order to provide a custom VFS with access +** to the connections busy-handler callback. The argument is of type (void **) +** - an array of two (void *) values. The first (void *) actually points +** to a function of type (int (*)(void *)). In order to invoke the connections +** busy-handler, this function should be invoked with the second (void *) in +** the array as the only argument. If it returns non-zero, then the operation +** should be retried. If it returns zero, the custom VFS should abandon the +** current operation. +** +**
  • [[SQLITE_FCNTL_TEMPFILENAME]] +** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control +** to have SQLite generate a +** temporary filename using the same algorithm that is followed to generate +** temporary filenames for TEMP tables and other internal uses. The +** argument should be a char** which will be filled with the filename +** written into memory obtained from [sqlite3_malloc()]. The caller should +** invoke [sqlite3_free()] on the result to avoid a memory leak. +** +**
  • [[SQLITE_FCNTL_MMAP_SIZE]] +** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the +** maximum number of bytes that will be used for memory-mapped I/O. +** The argument is a pointer to a value of type sqlite3_int64 that +** is an advisory maximum number of bytes in the file to memory map. The +** pointer is overwritten with the old value. The limit is not changed if +** the value originally pointed to is negative, and so the current limit +** can be queried by passing in a pointer to a negative number. This +** file-control is used internally to implement [PRAGMA mmap_size]. +** +**
+*/ +#define SQLITE_FCNTL_LOCKSTATE 1 +#define SQLITE_GET_LOCKPROXYFILE 2 +#define SQLITE_SET_LOCKPROXYFILE 3 +#define SQLITE_LAST_ERRNO 4 +#define SQLITE_FCNTL_SIZE_HINT 5 +#define SQLITE_FCNTL_CHUNK_SIZE 6 +#define SQLITE_FCNTL_FILE_POINTER 7 +#define SQLITE_FCNTL_SYNC_OMITTED 8 +#define SQLITE_FCNTL_WIN32_AV_RETRY 9 +#define SQLITE_FCNTL_PERSIST_WAL 10 +#define SQLITE_FCNTL_OVERWRITE 11 +#define SQLITE_FCNTL_VFSNAME 12 +#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 +#define SQLITE_FCNTL_PRAGMA 14 +#define SQLITE_FCNTL_BUSYHANDLER 15 +#define SQLITE_FCNTL_TEMPFILENAME 16 +#define SQLITE_FCNTL_MMAP_SIZE 18 + +/* +** CAPI3REF: Mutex Handle +** +** The mutex module within SQLite defines [sqlite3_mutex] to be an +** abstract type for a mutex object. The SQLite core never looks +** at the internal representation of an [sqlite3_mutex]. It only +** deals with pointers to the [sqlite3_mutex] object. +** +** Mutexes are created using [sqlite3_mutex_alloc()]. +*/ +typedef struct sqlite3_mutex sqlite3_mutex; + +/* +** CAPI3REF: OS Interface Object +** +** An instance of the sqlite3_vfs object defines the interface between +** the SQLite core and the underlying operating system. The "vfs" +** in the name of the object stands for "virtual file system". See +** the [VFS | VFS documentation] for further information. +** +** The value of the iVersion field is initially 1 but may be larger in +** future versions of SQLite. Additional fields may be appended to this +** object when the iVersion value is increased. Note that the structure +** of the sqlite3_vfs object changes in the transaction between +** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not +** modified. +** +** The szOsFile field is the size of the subclassed [sqlite3_file] +** structure used by this VFS. mxPathname is the maximum length of +** a pathname in this VFS. +** +** Registered sqlite3_vfs objects are kept on a linked list formed by +** the pNext pointer. The [sqlite3_vfs_register()] +** and [sqlite3_vfs_unregister()] interfaces manage this list +** in a thread-safe way. The [sqlite3_vfs_find()] interface +** searches the list. Neither the application code nor the VFS +** implementation should use the pNext pointer. +** +** The pNext field is the only field in the sqlite3_vfs +** structure that SQLite will ever modify. SQLite will only access +** or modify this field while holding a particular static mutex. +** The application should never modify anything within the sqlite3_vfs +** object once the object has been registered. +** +** The zName field holds the name of the VFS module. The name must +** be unique across all VFS modules. +** +** [[sqlite3_vfs.xOpen]] +** ^SQLite guarantees that the zFilename parameter to xOpen +** is either a NULL pointer or string obtained +** from xFullPathname() with an optional suffix added. +** ^If a suffix is added to the zFilename parameter, it will +** consist of a single "-" character followed by no more than +** 11 alphanumeric and/or "-" characters. +** ^SQLite further guarantees that +** the string will be valid and unchanged until xClose() is +** called. Because of the previous sentence, +** the [sqlite3_file] can safely store a pointer to the +** filename if it needs to remember the filename for some reason. +** If the zFilename parameter to xOpen is a NULL pointer then xOpen +** must invent its own temporary name for the file. ^Whenever the +** xFilename parameter is NULL it will also be the case that the +** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE]. +** +** The flags argument to xOpen() includes all bits set in +** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] +** or [sqlite3_open16()] is used, then flags includes at least +** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. +** If xOpen() opens a file read-only then it sets *pOutFlags to +** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set. +** +** ^(SQLite will also add one of the following flags to the xOpen() +** call, depending on the object being opened: +** +**
    +**
  • [SQLITE_OPEN_MAIN_DB] +**
  • [SQLITE_OPEN_MAIN_JOURNAL] +**
  • [SQLITE_OPEN_TEMP_DB] +**
  • [SQLITE_OPEN_TEMP_JOURNAL] +**
  • [SQLITE_OPEN_TRANSIENT_DB] +**
  • [SQLITE_OPEN_SUBJOURNAL] +**
  • [SQLITE_OPEN_MASTER_JOURNAL] +**
  • [SQLITE_OPEN_WAL] +**
)^ +** +** The file I/O implementation can use the object type flags to +** change the way it deals with files. For example, an application +** that does not care about crash recovery or rollback might make +** the open of a journal file a no-op. Writes to this journal would +** also be no-ops, and any attempt to read the journal would return +** SQLITE_IOERR. Or the implementation might recognize that a database +** file will be doing page-aligned sector reads and writes in a random +** order and set up its I/O subsystem accordingly. +** +** SQLite might also add one of the following flags to the xOpen method: +** +**
    +**
  • [SQLITE_OPEN_DELETEONCLOSE] +**
  • [SQLITE_OPEN_EXCLUSIVE] +**
+** +** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be +** deleted when it is closed. ^The [SQLITE_OPEN_DELETEONCLOSE] +** will be set for TEMP databases and their journals, transient +** databases, and subjournals. +** +** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction +** with the [SQLITE_OPEN_CREATE] flag, which are both directly +** analogous to the O_EXCL and O_CREAT flags of the POSIX open() +** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the +** SQLITE_OPEN_CREATE, is used to indicate that file should always +** be created, and that it is an error if it already exists. +** It is not used to indicate the file should be opened +** for exclusive access. +** +** ^At least szOsFile bytes of memory are allocated by SQLite +** to hold the [sqlite3_file] structure passed as the third +** argument to xOpen. The xOpen method does not have to +** allocate the structure; it should just fill it in. Note that +** the xOpen method must set the sqlite3_file.pMethods to either +** a valid [sqlite3_io_methods] object or to NULL. xOpen must do +** this even if the open fails. SQLite expects that the sqlite3_file.pMethods +** element will be valid after xOpen returns regardless of the success +** or failure of the xOpen call. +** +** [[sqlite3_vfs.xAccess]] +** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] +** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to +** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] +** to test whether a file is at least readable. The file can be a +** directory. +** +** ^SQLite will always allocate at least mxPathname+1 bytes for the +** output buffer xFullPathname. The exact size of the output buffer +** is also passed as a parameter to both methods. If the output buffer +** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is +** handled as a fatal error by SQLite, vfs implementations should endeavor +** to prevent this by setting mxPathname to a sufficiently large value. +** +** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64() +** interfaces are not strictly a part of the filesystem, but they are +** included in the VFS structure for completeness. +** The xRandomness() function attempts to return nBytes bytes +** of good-quality randomness into zOut. The return value is +** the actual number of bytes of randomness obtained. +** The xSleep() method causes the calling thread to sleep for at +** least the number of microseconds given. ^The xCurrentTime() +** method returns a Julian Day Number for the current date and time as +** a floating point value. +** ^The xCurrentTimeInt64() method returns, as an integer, the Julian +** Day Number multiplied by 86400000 (the number of milliseconds in +** a 24-hour day). +** ^SQLite will use the xCurrentTimeInt64() method to get the current +** date and time if that method is available (if iVersion is 2 or +** greater and the function pointer is not NULL) and will fall back +** to xCurrentTime() if xCurrentTimeInt64() is unavailable. +** +** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces +** are not used by the SQLite core. These optional interfaces are provided +** by some VFSes to facilitate testing of the VFS code. By overriding +** system calls with functions under its control, a test program can +** simulate faults and error conditions that would otherwise be difficult +** or impossible to induce. The set of system calls that can be overridden +** varies from one VFS to another, and from one version of the same VFS to the +** next. Applications that use these interfaces must be prepared for any +** or all of these interfaces to be NULL or for their behavior to change +** from one release to the next. Applications must not attempt to access +** any of these methods if the iVersion of the VFS is less than 3. +*/ +typedef struct sqlite3_vfs sqlite3_vfs; +typedef void (*sqlite3_syscall_ptr)(void); +struct sqlite3_vfs +{ + int iVersion; /* Structure version number (currently 3) */ + int szOsFile; /* Size of subclassed sqlite3_file */ + int mxPathname; /* Maximum file pathname length */ + sqlite3_vfs *pNext; /* Next registered VFS */ + const char *zName; /* Name of this virtual file system */ + void *pAppData; /* Pointer to application-specific data */ + int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, + int flags, int *pOutFlags); + int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); + int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); + int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); + void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); + void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); + void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); + void (*xDlClose)(sqlite3_vfs*, void*); + int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); + int (*xSleep)(sqlite3_vfs*, int microseconds); + int (*xCurrentTime)(sqlite3_vfs*, double*); + int (*xGetLastError)(sqlite3_vfs*, int, char *); + /* + ** The methods above are in version 1 of the sqlite_vfs object + ** definition. Those that follow are added in version 2 or later + */ + int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*); + /* + ** The methods above are in versions 1 and 2 of the sqlite_vfs object. + ** Those below are for version 3 and greater. + */ + int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr); + sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); + const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); + /* + ** The methods above are in versions 1 through 3 of the sqlite_vfs object. + ** New fields may be appended in figure versions. The iVersion + ** value will increment whenever this happens. + */ +}; + +/* +** CAPI3REF: Flags for the xAccess VFS method +** +** These integer constants can be used as the third parameter to +** the xAccess method of an [sqlite3_vfs] object. They determine +** what kind of permissions the xAccess method is looking for. +** With SQLITE_ACCESS_EXISTS, the xAccess method +** simply checks whether the file exists. +** With SQLITE_ACCESS_READWRITE, the xAccess method +** checks whether the named directory is both readable and writable +** (in other words, if files can be added, removed, and renamed within +** the directory). +** The SQLITE_ACCESS_READWRITE constant is currently used only by the +** [temp_store_directory pragma], though this could change in a future +** release of SQLite. +** With SQLITE_ACCESS_READ, the xAccess method +** checks whether the file is readable. The SQLITE_ACCESS_READ constant is +** currently unused, though it might be used in a future release of +** SQLite. +*/ +#define SQLITE_ACCESS_EXISTS 0 +#define SQLITE_ACCESS_READWRITE 1 /* Used by PRAGMA temp_store_directory */ +#define SQLITE_ACCESS_READ 2 /* Unused */ + +/* +** CAPI3REF: Flags for the xShmLock VFS method +** +** These integer constants define the various locking operations +** allowed by the xShmLock method of [sqlite3_io_methods]. The +** following are the only legal combinations of flags to the +** xShmLock method: +** +**
    +**
  • SQLITE_SHM_LOCK | SQLITE_SHM_SHARED +**
  • SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE +**
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED +**
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE +**
+** +** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as +** was given no the corresponding lock. +** +** The xShmLock method can transition between unlocked and SHARED or +** between unlocked and EXCLUSIVE. It cannot transition between SHARED +** and EXCLUSIVE. +*/ +#define SQLITE_SHM_UNLOCK 1 +#define SQLITE_SHM_LOCK 2 +#define SQLITE_SHM_SHARED 4 +#define SQLITE_SHM_EXCLUSIVE 8 + +/* +** CAPI3REF: Maximum xShmLock index +** +** The xShmLock method on [sqlite3_io_methods] may use values +** between 0 and this upper bound as its "offset" argument. +** The SQLite core will never attempt to acquire or release a +** lock outside of this range +*/ +#define SQLITE_SHM_NLOCK 8 + + +/* +** CAPI3REF: Initialize The SQLite Library +** +** ^The sqlite3_initialize() routine initializes the +** SQLite library. ^The sqlite3_shutdown() routine +** deallocates any resources that were allocated by sqlite3_initialize(). +** These routines are designed to aid in process initialization and +** shutdown on embedded systems. Workstation applications using +** SQLite normally do not need to invoke either of these routines. +** +** A call to sqlite3_initialize() is an "effective" call if it is +** the first time sqlite3_initialize() is invoked during the lifetime of +** the process, or if it is the first time sqlite3_initialize() is invoked +** following a call to sqlite3_shutdown(). ^(Only an effective call +** of sqlite3_initialize() does any initialization. All other calls +** are harmless no-ops.)^ +** +** A call to sqlite3_shutdown() is an "effective" call if it is the first +** call to sqlite3_shutdown() since the last sqlite3_initialize(). ^(Only +** an effective call to sqlite3_shutdown() does any deinitialization. +** All other valid calls to sqlite3_shutdown() are harmless no-ops.)^ +** +** The sqlite3_initialize() interface is threadsafe, but sqlite3_shutdown() +** is not. The sqlite3_shutdown() interface must only be called from a +** single thread. All open [database connections] must be closed and all +** other SQLite resources must be deallocated prior to invoking +** sqlite3_shutdown(). +** +** Among other things, ^sqlite3_initialize() will invoke +** sqlite3_os_init(). Similarly, ^sqlite3_shutdown() +** will invoke sqlite3_os_end(). +** +** ^The sqlite3_initialize() routine returns [SQLITE_OK] on success. +** ^If for some reason, sqlite3_initialize() is unable to initialize +** the library (perhaps it is unable to allocate a needed resource such +** as a mutex) it returns an [error code] other than [SQLITE_OK]. +** +** ^The sqlite3_initialize() routine is called internally by many other +** SQLite interfaces so that an application usually does not need to +** invoke sqlite3_initialize() directly. For example, [sqlite3_open()] +** calls sqlite3_initialize() so the SQLite library will be automatically +** initialized when [sqlite3_open()] is called if it has not be initialized +** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT] +** compile-time option, then the automatic calls to sqlite3_initialize() +** are omitted and the application must call sqlite3_initialize() directly +** prior to using any other SQLite interface. For maximum portability, +** it is recommended that applications always invoke sqlite3_initialize() +** directly prior to using any other SQLite interface. Future releases +** of SQLite may require this. In other words, the behavior exhibited +** when SQLite is compiled with [SQLITE_OMIT_AUTOINIT] might become the +** default behavior in some future release of SQLite. +** +** The sqlite3_os_init() routine does operating-system specific +** initialization of the SQLite library. The sqlite3_os_end() +** routine undoes the effect of sqlite3_os_init(). Typical tasks +** performed by these routines include allocation or deallocation +** of static resources, initialization of global variables, +** setting up a default [sqlite3_vfs] module, or setting up +** a default configuration using [sqlite3_config()]. +** +** The application should never invoke either sqlite3_os_init() +** or sqlite3_os_end() directly. The application should only invoke +** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init() +** interface is called automatically by sqlite3_initialize() and +** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate +** implementations for sqlite3_os_init() and sqlite3_os_end() +** are built into SQLite when it is compiled for Unix, Windows, or OS/2. +** When [custom builds | built for other platforms] +** (using the [SQLITE_OS_OTHER=1] compile-time +** option) the application must supply a suitable implementation for +** sqlite3_os_init() and sqlite3_os_end(). An application-supplied +** implementation of sqlite3_os_init() or sqlite3_os_end() +** must return [SQLITE_OK] on success and some other [error code] upon +** failure. +*/ +SQLITE_API int sqlite3_initialize(void); +SQLITE_API int sqlite3_shutdown(void); +SQLITE_API int sqlite3_os_init(void); +SQLITE_API int sqlite3_os_end(void); + +/* +** CAPI3REF: Configuring The SQLite Library +** +** The sqlite3_config() interface is used to make global configuration +** changes to SQLite in order to tune SQLite to the specific needs of +** the application. The default configuration is recommended for most +** applications and so this routine is usually not necessary. It is +** provided to support rare applications with unusual needs. +** +** The sqlite3_config() interface is not threadsafe. The application +** must insure that no other SQLite interfaces are invoked by other +** threads while sqlite3_config() is running. Furthermore, sqlite3_config() +** may only be invoked prior to library initialization using +** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. +** ^If sqlite3_config() is called after [sqlite3_initialize()] and before +** [sqlite3_shutdown()] then it will return SQLITE_MISUSE. +** Note, however, that ^sqlite3_config() can be called as part of the +** implementation of an application-defined [sqlite3_os_init()]. +** +** The first argument to sqlite3_config() is an integer +** [configuration option] that determines +** what property of SQLite is to be configured. Subsequent arguments +** vary depending on the [configuration option] +** in the first argument. +** +** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK]. +** ^If the option is unknown or SQLite is unable to set the option +** then this routine returns a non-zero [error code]. +*/ +SQLITE_API int sqlite3_config(int, ...); + +/* +** CAPI3REF: Configure database connections +** +** The sqlite3_db_config() interface is used to make configuration +** changes to a [database connection]. The interface is similar to +** [sqlite3_config()] except that the changes apply to a single +** [database connection] (specified in the first argument). +** +** The second argument to sqlite3_db_config(D,V,...) is the +** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code +** that indicates what aspect of the [database connection] is being configured. +** Subsequent arguments vary depending on the configuration verb. +** +** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if +** the call is considered successful. +*/ +SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...); + +/* +** CAPI3REF: Memory Allocation Routines +** +** An instance of this object defines the interface between SQLite +** and low-level memory allocation routines. +** +** This object is used in only one place in the SQLite interface. +** A pointer to an instance of this object is the argument to +** [sqlite3_config()] when the configuration option is +** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC]. +** By creating an instance of this object +** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC]) +** during configuration, an application can specify an alternative +** memory allocation subsystem for SQLite to use for all of its +** dynamic memory needs. +** +** Note that SQLite comes with several [built-in memory allocators] +** that are perfectly adequate for the overwhelming majority of applications +** and that this object is only useful to a tiny minority of applications +** with specialized memory allocation requirements. This object is +** also used during testing of SQLite in order to specify an alternative +** memory allocator that simulates memory out-of-memory conditions in +** order to verify that SQLite recovers gracefully from such +** conditions. +** +** The xMalloc, xRealloc, and xFree methods must work like the +** malloc(), realloc() and free() functions from the standard C library. +** ^SQLite guarantees that the second argument to +** xRealloc is always a value returned by a prior call to xRoundup. +** +** xSize should return the allocated size of a memory allocation +** previously obtained from xMalloc or xRealloc. The allocated size +** is always at least as big as the requested size but may be larger. +** +** The xRoundup method returns what would be the allocated size of +** a memory allocation given a particular requested size. Most memory +** allocators round up memory allocations at least to the next multiple +** of 8. Some allocators round up to a larger multiple or to a power of 2. +** Every memory allocation request coming in through [sqlite3_malloc()] +** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, +** that causes the corresponding memory allocation to fail. +** +** The xInit method initializes the memory allocator. (For example, +** it might allocate any require mutexes or initialize internal data +** structures. The xShutdown method is invoked (indirectly) by +** [sqlite3_shutdown()] and should deallocate any resources acquired +** by xInit. The pAppData pointer is used as the only parameter to +** xInit and xShutdown. +** +** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes +** the xInit method, so the xInit method need not be threadsafe. The +** xShutdown method is only called from [sqlite3_shutdown()] so it does +** not need to be threadsafe either. For all other methods, SQLite +** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the +** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which +** it is by default) and so the methods are automatically serialized. +** However, if [SQLITE_CONFIG_MEMSTATUS] is disabled, then the other +** methods must be threadsafe or else make their own arrangements for +** serialization. +** +** SQLite will never invoke xInit() more than once without an intervening +** call to xShutdown(). +*/ +typedef struct sqlite3_mem_methods sqlite3_mem_methods; +struct sqlite3_mem_methods +{ + void *(*xMalloc)(int); /* Memory allocation function */ + void (*xFree)(void*); /* Free a prior allocation */ + void *(*xRealloc)(void*,int); /* Resize an allocation */ + int (*xSize)(void*); /* Return the size of an allocation */ + int (*xRoundup)(int); /* Round up request size to allocation size */ + int (*xInit)(void*); /* Initialize the memory allocator */ + void (*xShutdown)(void*); /* Deinitialize the memory allocator */ + void *pAppData; /* Argument to xInit() and xShutdown() */ +}; + +/* +** CAPI3REF: Configuration Options +** KEYWORDS: {configuration option} +** +** These constants are the available integer configuration options that +** can be passed as the first argument to the [sqlite3_config()] interface. +** +** New configuration options may be added in future releases of SQLite. +** Existing configuration options might be discontinued. Applications +** should check the return code from [sqlite3_config()] to make sure that +** the call worked. The [sqlite3_config()] interface will return a +** non-zero [error code] if a discontinued or unsupported configuration option +** is invoked. +** +**
+** [[SQLITE_CONFIG_SINGLETHREAD]]
SQLITE_CONFIG_SINGLETHREAD
+**
There are no arguments to this option. ^This option sets the +** [threading mode] to Single-thread. In other words, it disables +** all mutexing and puts SQLite into a mode where it can only be used +** by a single thread. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** it is not possible to change the [threading mode] from its default +** value of Single-thread and so [sqlite3_config()] will return +** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD +** configuration option.
+** +** [[SQLITE_CONFIG_MULTITHREAD]]
SQLITE_CONFIG_MULTITHREAD
+**
There are no arguments to this option. ^This option sets the +** [threading mode] to Multi-thread. In other words, it disables +** mutexing on [database connection] and [prepared statement] objects. +** The application is responsible for serializing access to +** [database connections] and [prepared statements]. But other mutexes +** are enabled so that SQLite will be safe to use in a multi-threaded +** environment as long as no two threads attempt to use the same +** [database connection] at the same time. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** it is not possible to set the Multi-thread [threading mode] and +** [sqlite3_config()] will return [SQLITE_ERROR] if called with the +** SQLITE_CONFIG_MULTITHREAD configuration option.
+** +** [[SQLITE_CONFIG_SERIALIZED]]
SQLITE_CONFIG_SERIALIZED
+**
There are no arguments to this option. ^This option sets the +** [threading mode] to Serialized. In other words, this option enables +** all mutexes including the recursive +** mutexes on [database connection] and [prepared statement] objects. +** In this mode (which is the default when SQLite is compiled with +** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access +** to [database connections] and [prepared statements] so that the +** application is free to use the same [database connection] or the +** same [prepared statement] in different threads at the same time. +** ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** it is not possible to set the Serialized [threading mode] and +** [sqlite3_config()] will return [SQLITE_ERROR] if called with the +** SQLITE_CONFIG_SERIALIZED configuration option.
+** +** [[SQLITE_CONFIG_MALLOC]]
SQLITE_CONFIG_MALLOC
+**
^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mem_methods] structure. The argument specifies +** alternative low-level memory allocation routines to be used in place of +** the memory allocation routines built into SQLite.)^ ^SQLite makes +** its own private copy of the content of the [sqlite3_mem_methods] structure +** before the [sqlite3_config()] call returns.
+** +** [[SQLITE_CONFIG_GETMALLOC]]
SQLITE_CONFIG_GETMALLOC
+**
^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods] +** structure is filled with the currently defined memory allocation routines.)^ +** This option can be used to overload the default memory allocation +** routines with a wrapper that simulations memory allocation failure or +** tracks memory usage, for example.
+** +** [[SQLITE_CONFIG_MEMSTATUS]]
SQLITE_CONFIG_MEMSTATUS
+**
^This option takes single argument of type int, interpreted as a +** boolean, which enables or disables the collection of memory allocation +** statistics. ^(When memory allocation statistics are disabled, the +** following SQLite interfaces become non-operational: +**
    +**
  • [sqlite3_memory_used()] +**
  • [sqlite3_memory_highwater()] +**
  • [sqlite3_soft_heap_limit64()] +**
  • [sqlite3_status()] +**
)^ +** ^Memory allocation statistics are enabled by default unless SQLite is +** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory +** allocation statistics are disabled by default. +**
+** +** [[SQLITE_CONFIG_SCRATCH]]
SQLITE_CONFIG_SCRATCH
+**
^This option specifies a static memory buffer that SQLite can use for +** scratch memory. There are three arguments: A pointer an 8-byte +** aligned memory buffer from which the scratch allocations will be +** drawn, the size of each scratch allocation (sz), +** and the maximum number of scratch allocations (N). The sz +** argument must be a multiple of 16. +** The first argument must be a pointer to an 8-byte aligned buffer +** of at least sz*N bytes of memory. +** ^SQLite will use no more than two scratch buffers per thread. So +** N should be set to twice the expected maximum number of threads. +** ^SQLite will never require a scratch buffer that is more than 6 +** times the database page size. ^If SQLite needs needs additional +** scratch memory beyond what is provided by this configuration option, then +** [sqlite3_malloc()] will be used to obtain the memory needed.
+** +** [[SQLITE_CONFIG_PAGECACHE]]
SQLITE_CONFIG_PAGECACHE
+**
^This option specifies a static memory buffer that SQLite can use for +** the database page cache with the default page cache implementation. +** This configuration should not be used if an application-define page +** cache implementation is loaded using the SQLITE_CONFIG_PCACHE2 option. +** There are three arguments to this option: A pointer to 8-byte aligned +** memory, the size of each page buffer (sz), and the number of pages (N). +** The sz argument should be the size of the largest database page +** (a power of two between 512 and 32768) plus a little extra for each +** page header. ^The page header size is 20 to 40 bytes depending on +** the host architecture. ^It is harmless, apart from the wasted memory, +** to make sz a little too large. The first +** argument should point to an allocation of at least sz*N bytes of memory. +** ^SQLite will use the memory provided by the first argument to satisfy its +** memory needs for the first N pages that it adds to cache. ^If additional +** page cache memory is needed beyond what is provided by this option, then +** SQLite goes to [sqlite3_malloc()] for the additional storage space. +** The pointer in the first argument must +** be aligned to an 8-byte boundary or subsequent behavior of SQLite +** will be undefined.
+** +** [[SQLITE_CONFIG_HEAP]]
SQLITE_CONFIG_HEAP
+**
^This option specifies a static memory buffer that SQLite will use +** for all of its dynamic memory allocation needs beyond those provided +** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. +** There are three arguments: An 8-byte aligned pointer to the memory, +** the number of bytes in the memory buffer, and the minimum allocation size. +** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts +** to using its default memory allocator (the system malloc() implementation), +** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the +** memory pointer is not NULL and either [SQLITE_ENABLE_MEMSYS3] or +** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory +** allocator is engaged to handle all of SQLites memory allocation needs. +** The first pointer (the memory pointer) must be aligned to an 8-byte +** boundary or subsequent behavior of SQLite will be undefined. +** The minimum allocation size is capped at 2**12. Reasonable values +** for the minimum allocation size are 2**5 through 2**8.
+** +** [[SQLITE_CONFIG_MUTEX]]
SQLITE_CONFIG_MUTEX
+**
^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mutex_methods] structure. The argument specifies +** alternative low-level mutex routines to be used in place +** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the +** content of the [sqlite3_mutex_methods] structure before the call to +** [sqlite3_config()] returns. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** the entire mutexing subsystem is omitted from the build and hence calls to +** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will +** return [SQLITE_ERROR].
+** +** [[SQLITE_CONFIG_GETMUTEX]]
SQLITE_CONFIG_GETMUTEX
+**
^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mutex_methods] structure. The +** [sqlite3_mutex_methods] +** structure is filled with the currently defined mutex routines.)^ +** This option can be used to overload the default mutex allocation +** routines with a wrapper used to track mutex usage for performance +** profiling or testing, for example. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** the entire mutexing subsystem is omitted from the build and hence calls to +** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will +** return [SQLITE_ERROR].
+** +** [[SQLITE_CONFIG_LOOKASIDE]]
SQLITE_CONFIG_LOOKASIDE
+**
^(This option takes two arguments that determine the default +** memory allocation for the lookaside memory allocator on each +** [database connection]. The first argument is the +** size of each lookaside buffer slot and the second is the number of +** slots allocated to each database connection.)^ ^(This option sets the +** default lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] +** verb to [sqlite3_db_config()] can be used to change the lookaside +** configuration on individual connections.)^
+** +** [[SQLITE_CONFIG_PCACHE2]]
SQLITE_CONFIG_PCACHE2
+**
^(This option takes a single argument which is a pointer to +** an [sqlite3_pcache_methods2] object. This object specifies the interface +** to a custom page cache implementation.)^ ^SQLite makes a copy of the +** object and uses it for page cache memory allocations.
+** +** [[SQLITE_CONFIG_GETPCACHE2]]
SQLITE_CONFIG_GETPCACHE2
+**
^(This option takes a single argument which is a pointer to an +** [sqlite3_pcache_methods2] object. SQLite copies of the current +** page cache implementation into that object.)^
+** +** [[SQLITE_CONFIG_LOG]]
SQLITE_CONFIG_LOG
+**
The SQLITE_CONFIG_LOG option is used to configure the SQLite +** global [error log]. +** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a +** function with a call signature of void(*)(void*,int,const char*), +** and a pointer to void. ^If the function pointer is not NULL, it is +** invoked by [sqlite3_log()] to process each logging event. ^If the +** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op. +** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is +** passed through as the first parameter to the application-defined logger +** function whenever that function is invoked. ^The second parameter to +** the logger function is a copy of the first parameter to the corresponding +** [sqlite3_log()] call and is intended to be a [result code] or an +** [extended result code]. ^The third parameter passed to the logger is +** log message after formatting via [sqlite3_snprintf()]. +** The SQLite logging interface is not reentrant; the logger function +** supplied by the application must not invoke any SQLite interface. +** In a multi-threaded application, the application-defined logger +** function must be threadsafe.
+** +** [[SQLITE_CONFIG_URI]]
SQLITE_CONFIG_URI +**
^(This option takes a single argument of type int. If non-zero, then +** URI handling is globally enabled. If the parameter is zero, then URI handling +** is globally disabled.)^ ^If URI handling is globally enabled, all filenames +** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or +** specified as part of [ATTACH] commands are interpreted as URIs, regardless +** of whether or not the [SQLITE_OPEN_URI] flag is set when the database +** connection is opened. ^If it is globally disabled, filenames are +** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the +** database connection is opened. ^(By default, URI handling is globally +** disabled. The default value may be changed by compiling with the +** [SQLITE_USE_URI] symbol defined.)^ +** +** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]]
SQLITE_CONFIG_COVERING_INDEX_SCAN +**
^This option takes a single integer argument which is interpreted as +** a boolean in order to enable or disable the use of covering indices for +** full table scans in the query optimizer. ^The default setting is determined +** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" +** if that compile-time option is omitted. +** The ability to disable the use of covering indices for full table scans +** is because some incorrectly coded legacy applications might malfunction +** when the optimization is enabled. Providing the ability to +** disable the optimization allows the older, buggy application code to work +** without change even with newer versions of SQLite. +** +** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] +**
SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE +**
These options are obsolete and should not be used by new code. +** They are retained for backwards compatibility but are now no-ops. +**
+** +** [[SQLITE_CONFIG_SQLLOG]] +**
SQLITE_CONFIG_SQLLOG +**
This option is only available if sqlite is compiled with the +** [SQLITE_ENABLE_SQLLOG] pre-processor macro defined. The first argument should +** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int). +** The second should be of type (void*). The callback is invoked by the library +** in three separate circumstances, identified by the value passed as the +** fourth parameter. If the fourth parameter is 0, then the database connection +** passed as the second argument has just been opened. The third argument +** points to a buffer containing the name of the main database file. If the +** fourth parameter is 1, then the SQL statement that the third parameter +** points to has just been executed. Or, if the fourth parameter is 2, then +** the connection being passed as the second parameter is being closed. The +** third parameter is passed NULL In this case. An example of using this +** configuration option can be seen in the "test_sqllog.c" source file in +** the canonical SQLite source tree.
+** +** [[SQLITE_CONFIG_MMAP_SIZE]] +**
SQLITE_CONFIG_MMAP_SIZE +**
^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values +** that are the default mmap size limit (the default setting for +** [PRAGMA mmap_size]) and the maximum allowed mmap size limit. +** ^The default setting can be overridden by each database connection using +** either the [PRAGMA mmap_size] command, or by using the +** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size +** cannot be changed at run-time. Nor may the maximum allowed mmap size +** exceed the compile-time maximum mmap size set by the +** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^ +** ^If either argument to this option is negative, then that argument is +** changed to its compile-time default. +**
+*/ +#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ +#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ +#define SQLITE_CONFIG_SERIALIZED 3 /* nil */ +#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ +#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ +#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ +#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */ +#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ +#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ +#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ +#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ +/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ +#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ +#define SQLITE_CONFIG_PCACHE 14 /* no-op */ +#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ +#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ +#define SQLITE_CONFIG_URI 17 /* int */ +#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ +#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ +#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ +#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ +#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ + +/* +** CAPI3REF: Database Connection Configuration Options +** +** These constants are the available integer configuration options that +** can be passed as the second argument to the [sqlite3_db_config()] interface. +** +** New configuration options may be added in future releases of SQLite. +** Existing configuration options might be discontinued. Applications +** should check the return code from [sqlite3_db_config()] to make sure that +** the call worked. ^The [sqlite3_db_config()] interface will return a +** non-zero [error code] if a discontinued or unsupported configuration option +** is invoked. +** +**
+**
SQLITE_DBCONFIG_LOOKASIDE
+**
^This option takes three additional arguments that determine the +** [lookaside memory allocator] configuration for the [database connection]. +** ^The first argument (the third parameter to [sqlite3_db_config()] is a +** pointer to a memory buffer to use for lookaside memory. +** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb +** may be NULL in which case SQLite will allocate the +** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the +** size of each lookaside buffer slot. ^The third argument is the number of +** slots. The size of the buffer in the first argument must be greater than +** or equal to the product of the second and third arguments. The buffer +** must be aligned to an 8-byte boundary. ^If the second argument to +** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally +** rounded down to the next smaller multiple of 8. ^(The lookaside memory +** configuration for a database connection can only be changed when that +** connection is not currently using lookaside memory, or in other words +** when the "current value" returned by +** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero. +** Any attempt to change the lookaside memory configuration when lookaside +** memory is in use leaves the configuration unchanged and returns +** [SQLITE_BUSY].)^
+** +**
SQLITE_DBCONFIG_ENABLE_FKEY
+**
^This option is used to enable or disable the enforcement of +** [foreign key constraints]. There should be two additional arguments. +** The first argument is an integer which is 0 to disable FK enforcement, +** positive to enable FK enforcement or negative to leave FK enforcement +** unchanged. The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether FK enforcement is off or on +** following this call. The second parameter may be a NULL pointer, in +** which case the FK enforcement setting is not reported back.
+** +**
SQLITE_DBCONFIG_ENABLE_TRIGGER
+**
^This option is used to enable or disable [CREATE TRIGGER | triggers]. +** There should be two additional arguments. +** The first argument is an integer which is 0 to disable triggers, +** positive to enable triggers or negative to leave the setting unchanged. +** The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether triggers are disabled or enabled +** following this call. The second parameter may be a NULL pointer, in +** which case the trigger setting is not reported back.
+** +**
+*/ +#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ +#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ +#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ + + +/* +** CAPI3REF: Enable Or Disable Extended Result Codes +** +** ^The sqlite3_extended_result_codes() routine enables or disables the +** [extended result codes] feature of SQLite. ^The extended result +** codes are disabled by default for historical compatibility. +*/ +SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); + +/* +** CAPI3REF: Last Insert Rowid +** +** ^Each entry in an SQLite table has a unique 64-bit signed +** integer key called the [ROWID | "rowid"]. ^The rowid is always available +** as an undeclared column named ROWID, OID, or _ROWID_ as long as those +** names are not also used by explicitly declared columns. ^If +** the table has a column of type [INTEGER PRIMARY KEY] then that column +** is another alias for the rowid. +** +** ^This routine returns the [rowid] of the most recent +** successful [INSERT] into the database from the [database connection] +** in the first argument. ^As of SQLite version 3.7.7, this routines +** records the last insert rowid of both ordinary tables and [virtual tables]. +** ^If no successful [INSERT]s +** have ever occurred on that database connection, zero is returned. +** +** ^(If an [INSERT] occurs within a trigger or within a [virtual table] +** method, then this routine will return the [rowid] of the inserted +** row as long as the trigger or virtual table method is running. +** But once the trigger or virtual table method ends, the value returned +** by this routine reverts to what it was before the trigger or virtual +** table method began.)^ +** +** ^An [INSERT] that fails due to a constraint violation is not a +** successful [INSERT] and does not change the value returned by this +** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, +** and INSERT OR ABORT make no changes to the return value of this +** routine when their insertion fails. ^(When INSERT OR REPLACE +** encounters a constraint violation, it does not fail. The +** INSERT continues to completion after deleting rows that caused +** the constraint problem so INSERT OR REPLACE will always change +** the return value of this interface.)^ +** +** ^For the purposes of this routine, an [INSERT] is considered to +** be successful even if it is subsequently rolled back. +** +** This function is accessible to SQL statements via the +** [last_insert_rowid() SQL function]. +** +** If a separate thread performs a new [INSERT] on the same +** database connection while the [sqlite3_last_insert_rowid()] +** function is running and thus changes the last insert [rowid], +** then the value returned by [sqlite3_last_insert_rowid()] is +** unpredictable and might not equal either the old or the new +** last insert [rowid]. +*/ +SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); + +/* +** CAPI3REF: Count The Number Of Rows Modified +** +** ^This function returns the number of database rows that were changed +** or inserted or deleted by the most recently completed SQL statement +** on the [database connection] specified by the first parameter. +** ^(Only changes that are directly specified by the [INSERT], [UPDATE], +** or [DELETE] statement are counted. Auxiliary changes caused by +** triggers or [foreign key actions] are not counted.)^ Use the +** [sqlite3_total_changes()] function to find the total number of changes +** including changes caused by triggers and foreign key actions. +** +** ^Changes to a view that are simulated by an [INSTEAD OF trigger] +** are not counted. Only real table changes are counted. +** +** ^(A "row change" is a change to a single row of a single table +** caused by an INSERT, DELETE, or UPDATE statement. Rows that +** are changed as side effects of [REPLACE] constraint resolution, +** rollback, ABORT processing, [DROP TABLE], or by any other +** mechanisms do not count as direct row changes.)^ +** +** A "trigger context" is a scope of execution that begins and +** ends with the script of a [CREATE TRIGGER | trigger]. +** Most SQL statements are +** evaluated outside of any trigger. This is the "top level" +** trigger context. If a trigger fires from the top level, a +** new trigger context is entered for the duration of that one +** trigger. Subtriggers create subcontexts for their duration. +** +** ^Calling [sqlite3_exec()] or [sqlite3_step()] recursively does +** not create a new trigger context. +** +** ^This function returns the number of direct row changes in the +** most recent INSERT, UPDATE, or DELETE statement within the same +** trigger context. +** +** ^Thus, when called from the top level, this function returns the +** number of changes in the most recent INSERT, UPDATE, or DELETE +** that also occurred at the top level. ^(Within the body of a trigger, +** the sqlite3_changes() interface can be called to find the number of +** changes in the most recently completed INSERT, UPDATE, or DELETE +** statement within the body of the same trigger. +** However, the number returned does not include changes +** caused by subtriggers since those have their own context.)^ +** +** See also the [sqlite3_total_changes()] interface, the +** [count_changes pragma], and the [changes() SQL function]. +** +** If a separate thread makes changes on the same database connection +** while [sqlite3_changes()] is running then the value returned +** is unpredictable and not meaningful. +*/ +SQLITE_API int sqlite3_changes(sqlite3*); + +/* +** CAPI3REF: Total Number Of Rows Modified +** +** ^This function returns the number of row changes caused by [INSERT], +** [UPDATE] or [DELETE] statements since the [database connection] was opened. +** ^(The count returned by sqlite3_total_changes() includes all changes +** from all [CREATE TRIGGER | trigger] contexts and changes made by +** [foreign key actions]. However, +** the count does not include changes used to implement [REPLACE] constraints, +** do rollbacks or ABORT processing, or [DROP TABLE] processing. The +** count does not include rows of views that fire an [INSTEAD OF trigger], +** though if the INSTEAD OF trigger makes changes of its own, those changes +** are counted.)^ +** ^The sqlite3_total_changes() function counts the changes as soon as +** the statement that makes them is completed (when the statement handle +** is passed to [sqlite3_reset()] or [sqlite3_finalize()]). +** +** See also the [sqlite3_changes()] interface, the +** [count_changes pragma], and the [total_changes() SQL function]. +** +** If a separate thread makes changes on the same database connection +** while [sqlite3_total_changes()] is running then the value +** returned is unpredictable and not meaningful. +*/ +SQLITE_API int sqlite3_total_changes(sqlite3*); + +/* +** CAPI3REF: Interrupt A Long-Running Query +** +** ^This function causes any pending database operation to abort and +** return at its earliest opportunity. This routine is typically +** called in response to a user action such as pressing "Cancel" +** or Ctrl-C where the user wants a long query operation to halt +** immediately. +** +** ^It is safe to call this routine from a thread different from the +** thread that is currently running the database operation. But it +** is not safe to call this routine with a [database connection] that +** is closed or might close before sqlite3_interrupt() returns. +** +** ^If an SQL operation is very nearly finished at the time when +** sqlite3_interrupt() is called, then it might not have an opportunity +** to be interrupted and might continue to completion. +** +** ^An SQL operation that is interrupted will return [SQLITE_INTERRUPT]. +** ^If the interrupted SQL operation is an INSERT, UPDATE, or DELETE +** that is inside an explicit transaction, then the entire transaction +** will be rolled back automatically. +** +** ^The sqlite3_interrupt(D) call is in effect until all currently running +** SQL statements on [database connection] D complete. ^Any new SQL statements +** that are started after the sqlite3_interrupt() call and before the +** running statements reaches zero are interrupted as if they had been +** running prior to the sqlite3_interrupt() call. ^New SQL statements +** that are started after the running statement count reaches zero are +** not effected by the sqlite3_interrupt(). +** ^A call to sqlite3_interrupt(D) that occurs when there are no running +** SQL statements is a no-op and has no effect on SQL statements +** that are started after the sqlite3_interrupt() call returns. +** +** If the database connection closes while [sqlite3_interrupt()] +** is running then bad things will likely happen. +*/ +SQLITE_API void sqlite3_interrupt(sqlite3*); + +/* +** CAPI3REF: Determine If An SQL Statement Is Complete +** +** These routines are useful during command-line input to determine if the +** currently entered text seems to form a complete SQL statement or +** if additional input is needed before sending the text into +** SQLite for parsing. ^These routines return 1 if the input string +** appears to be a complete SQL statement. ^A statement is judged to be +** complete if it ends with a semicolon token and is not a prefix of a +** well-formed CREATE TRIGGER statement. ^Semicolons that are embedded within +** string literals or quoted identifier names or comments are not +** independent tokens (they are part of the token in which they are +** embedded) and thus do not count as a statement terminator. ^Whitespace +** and comments that follow the final semicolon are ignored. +** +** ^These routines return 0 if the statement is incomplete. ^If a +** memory allocation fails, then SQLITE_NOMEM is returned. +** +** ^These routines do not parse the SQL statements thus +** will not detect syntactically incorrect SQL. +** +** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior +** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked +** automatically by sqlite3_complete16(). If that initialization fails, +** then the return value from sqlite3_complete16() will be non-zero +** regardless of whether or not the input SQL is complete.)^ +** +** The input to [sqlite3_complete()] must be a zero-terminated +** UTF-8 string. +** +** The input to [sqlite3_complete16()] must be a zero-terminated +** UTF-16 string in native byte order. +*/ +SQLITE_API int sqlite3_complete(const char *sql); +SQLITE_API int sqlite3_complete16(const void *sql); + +/* +** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors +** +** ^This routine sets a callback function that might be invoked whenever +** an attempt is made to open a database table that another thread +** or process has locked. +** +** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] +** is returned immediately upon encountering the lock. ^If the busy callback +** is not NULL, then the callback might be invoked with two arguments. +** +** ^The first argument to the busy handler is a copy of the void* pointer which +** is the third argument to sqlite3_busy_handler(). ^The second argument to +** the busy handler callback is the number of times that the busy handler has +** been invoked for this locking event. ^If the +** busy callback returns 0, then no additional attempts are made to +** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. +** ^If the callback returns non-zero, then another attempt +** is made to open the database for reading and the cycle repeats. +** +** The presence of a busy handler does not guarantee that it will be invoked +** when there is lock contention. ^If SQLite determines that invoking the busy +** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY] +** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler. +** Consider a scenario where one process is holding a read lock that +** it is trying to promote to a reserved lock and +** a second process is holding a reserved lock that it is trying +** to promote to an exclusive lock. The first process cannot proceed +** because it is blocked by the second and the second process cannot +** proceed because it is blocked by the first. If both processes +** invoke the busy handlers, neither will make any progress. Therefore, +** SQLite returns [SQLITE_BUSY] for the first process, hoping that this +** will induce the first process to release its read lock and allow +** the second process to proceed. +** +** ^The default busy callback is NULL. +** +** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] +** when SQLite is in the middle of a large transaction where all the +** changes will not fit into the in-memory cache. SQLite will +** already hold a RESERVED lock on the database file, but it needs +** to promote this lock to EXCLUSIVE so that it can spill cache +** pages into the database file without harm to concurrent +** readers. ^If it is unable to promote the lock, then the in-memory +** cache will be left in an inconsistent state and so the error +** code is promoted from the relatively benign [SQLITE_BUSY] to +** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion +** forces an automatic rollback of the changes. See the +** +** CorruptionFollowingBusyError wiki page for a discussion of why +** this is important. +** +** ^(There can only be a single busy handler defined for each +** [database connection]. Setting a new busy handler clears any +** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()] +** will also set or clear the busy handler. +** +** The busy callback should not take any actions which modify the +** database connection that invoked the busy handler. Any such actions +** result in undefined behavior. +** +** A busy handler must not close the database connection +** or [prepared statement] that invoked the busy handler. +*/ +SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); + +/* +** CAPI3REF: Set A Busy Timeout +** +** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps +** for a specified amount of time when a table is locked. ^The handler +** will sleep multiple times until at least "ms" milliseconds of sleeping +** have accumulated. ^After at least "ms" milliseconds of sleeping, +** the handler returns 0 which causes [sqlite3_step()] to return +** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. +** +** ^Calling this routine with an argument less than or equal to zero +** turns off all busy handlers. +** +** ^(There can only be a single busy handler for a particular +** [database connection] any any given moment. If another busy handler +** was defined (using [sqlite3_busy_handler()]) prior to calling +** this routine, that other busy handler is cleared.)^ +*/ +SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); + +/* +** CAPI3REF: Convenience Routines For Running Queries +** +** This is a legacy interface that is preserved for backwards compatibility. +** Use of this interface is not recommended. +** +** Definition: A result table is memory data structure created by the +** [sqlite3_get_table()] interface. A result table records the +** complete query results from one or more queries. +** +** The table conceptually has a number of rows and columns. But +** these numbers are not part of the result table itself. These +** numbers are obtained separately. Let N be the number of rows +** and M be the number of columns. +** +** A result table is an array of pointers to zero-terminated UTF-8 strings. +** There are (N+1)*M elements in the array. The first M pointers point +** to zero-terminated strings that contain the names of the columns. +** The remaining entries all point to query results. NULL values result +** in NULL pointers. All other values are in their UTF-8 zero-terminated +** string representation as returned by [sqlite3_column_text()]. +** +** A result table might consist of one or more memory allocations. +** It is not safe to pass a result table directly to [sqlite3_free()]. +** A result table should be deallocated using [sqlite3_free_table()]. +** +** ^(As an example of the result table format, suppose a query result +** is as follows: +** +**
+**        Name        | Age
+**        -----------------------
+**        Alice       | 43
+**        Bob         | 28
+**        Cindy       | 21
+** 
+** +** There are two column (M==2) and three rows (N==3). Thus the +** result table has 8 entries. Suppose the result table is stored +** in an array names azResult. Then azResult holds this content: +** +**
+**        azResult[0] = "Name";
+**        azResult[1] = "Age";
+**        azResult[2] = "Alice";
+**        azResult[3] = "43";
+**        azResult[4] = "Bob";
+**        azResult[5] = "28";
+**        azResult[6] = "Cindy";
+**        azResult[7] = "21";
+** 
)^ +** +** ^The sqlite3_get_table() function evaluates one or more +** semicolon-separated SQL statements in the zero-terminated UTF-8 +** string of its 2nd parameter and returns a result table to the +** pointer given in its 3rd parameter. +** +** After the application has finished with the result from sqlite3_get_table(), +** it must pass the result table pointer to sqlite3_free_table() in order to +** release the memory that was malloced. Because of the way the +** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling +** function must not try to call [sqlite3_free()] directly. Only +** [sqlite3_free_table()] is able to release the memory properly and safely. +** +** The sqlite3_get_table() interface is implemented as a wrapper around +** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access +** to any internal data structures of SQLite. It uses only the public +** interface defined here. As a consequence, errors that occur in the +** wrapper layer outside of the internal [sqlite3_exec()] call are not +** reflected in subsequent calls to [sqlite3_errcode()] or +** [sqlite3_errmsg()]. +*/ +SQLITE_API int sqlite3_get_table( + sqlite3 *db, /* An open database */ + const char *zSql, /* SQL to be evaluated */ + char ***pazResult, /* Results of the query */ + int *pnRow, /* Number of result rows written here */ + int *pnColumn, /* Number of result columns written here */ + char **pzErrmsg /* Error msg written here */ +); +SQLITE_API void sqlite3_free_table(char **result); + +/* +** CAPI3REF: Formatted String Printing Functions +** +** These routines are work-alikes of the "printf()" family of functions +** from the standard C library. +** +** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their +** results into memory obtained from [sqlite3_malloc()]. +** The strings returned by these two routines should be +** released by [sqlite3_free()]. ^Both routines return a +** NULL pointer if [sqlite3_malloc()] is unable to allocate enough +** memory to hold the resulting string. +** +** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from +** the standard C library. The result is written into the +** buffer supplied as the second parameter whose size is given by +** the first parameter. Note that the order of the +** first two parameters is reversed from snprintf().)^ This is an +** historical accident that cannot be fixed without breaking +** backwards compatibility. ^(Note also that sqlite3_snprintf() +** returns a pointer to its buffer instead of the number of +** characters actually written into the buffer.)^ We admit that +** the number of characters written would be a more useful return +** value but we cannot change the implementation of sqlite3_snprintf() +** now without breaking compatibility. +** +** ^As long as the buffer size is greater than zero, sqlite3_snprintf() +** guarantees that the buffer is always zero-terminated. ^The first +** parameter "n" is the total size of the buffer, including space for +** the zero terminator. So the longest string that can be completely +** written will be n-1 characters. +** +** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf(). +** +** These routines all implement some additional formatting +** options that are useful for constructing SQL statements. +** All of the usual printf() formatting options apply. In addition, there +** is are "%q", "%Q", and "%z" options. +** +** ^(The %q option works like %s in that it substitutes a nul-terminated +** string from the argument list. But %q also doubles every '\'' character. +** %q is designed for use inside a string literal.)^ By doubling each '\'' +** character it escapes that character and allows it to be inserted into +** the string. +** +** For example, assume the string variable zText contains text as follows: +** +**
+**  char *zText = "It's a happy day!";
+** 
+** +** One can use this text in an SQL statement as follows: +** +**
+**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
+**  sqlite3_exec(db, zSQL, 0, 0, 0);
+**  sqlite3_free(zSQL);
+** 
+** +** Because the %q format string is used, the '\'' character in zText +** is escaped and the SQL generated is as follows: +** +**
+**  INSERT INTO table1 VALUES('It''s a happy day!')
+** 
+** +** This is correct. Had we used %s instead of %q, the generated SQL +** would have looked like this: +** +**
+**  INSERT INTO table1 VALUES('It's a happy day!');
+** 
+** +** This second example is an SQL syntax error. As a general rule you should +** always use %q instead of %s when inserting text into a string literal. +** +** ^(The %Q option works like %q except it also adds single quotes around +** the outside of the total string. Additionally, if the parameter in the +** argument list is a NULL pointer, %Q substitutes the text "NULL" (without +** single quotes).)^ So, for example, one could say: +** +**
+**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
+**  sqlite3_exec(db, zSQL, 0, 0, 0);
+**  sqlite3_free(zSQL);
+** 
+** +** The code above will render a correct SQL statement in the zSQL +** variable even if the zText variable is a NULL pointer. +** +** ^(The "%z" formatting option works like "%s" but with the +** addition that after the string has been read and copied into +** the result, [sqlite3_free()] is called on the input string.)^ +*/ +SQLITE_API char *sqlite3_mprintf(const char*,...); +SQLITE_API char *sqlite3_vmprintf(const char*, va_list); +SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); +SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); + +/* +** CAPI3REF: Memory Allocation Subsystem +** +** The SQLite core uses these three routines for all of its own +** internal memory allocation needs. "Core" in the previous sentence +** does not include operating-system specific VFS implementation. The +** Windows VFS uses native malloc() and free() for some operations. +** +** ^The sqlite3_malloc() routine returns a pointer to a block +** of memory at least N bytes in length, where N is the parameter. +** ^If sqlite3_malloc() is unable to obtain sufficient free +** memory, it returns a NULL pointer. ^If the parameter N to +** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns +** a NULL pointer. +** +** ^Calling sqlite3_free() with a pointer previously returned +** by sqlite3_malloc() or sqlite3_realloc() releases that memory so +** that it might be reused. ^The sqlite3_free() routine is +** a no-op if is called with a NULL pointer. Passing a NULL pointer +** to sqlite3_free() is harmless. After being freed, memory +** should neither be read nor written. Even reading previously freed +** memory might result in a segmentation fault or other severe error. +** Memory corruption, a segmentation fault, or other severe error +** might result if sqlite3_free() is called with a non-NULL pointer that +** was not obtained from sqlite3_malloc() or sqlite3_realloc(). +** +** ^(The sqlite3_realloc() interface attempts to resize a +** prior memory allocation to be at least N bytes, where N is the +** second parameter. The memory allocation to be resized is the first +** parameter.)^ ^ If the first parameter to sqlite3_realloc() +** is a NULL pointer then its behavior is identical to calling +** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). +** ^If the second parameter to sqlite3_realloc() is zero or +** negative then the behavior is exactly the same as calling +** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). +** ^sqlite3_realloc() returns a pointer to a memory allocation +** of at least N bytes in size or NULL if sufficient memory is unavailable. +** ^If M is the size of the prior allocation, then min(N,M) bytes +** of the prior allocation are copied into the beginning of buffer returned +** by sqlite3_realloc() and the prior allocation is freed. +** ^If sqlite3_realloc() returns NULL, then the prior allocation +** is not freed. +** +** ^The memory returned by sqlite3_malloc() and sqlite3_realloc() +** is always aligned to at least an 8 byte boundary, or to a +** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time +** option is used. +** +** In SQLite version 3.5.0 and 3.5.1, it was possible to define +** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in +** implementation of these routines to be omitted. That capability +** is no longer provided. Only built-in memory allocators can be used. +** +** Prior to SQLite version 3.7.10, the Windows OS interface layer called +** the system malloc() and free() directly when converting +** filenames between the UTF-8 encoding used by SQLite +** and whatever filename encoding is used by the particular Windows +** installation. Memory allocation errors were detected, but +** they were reported back as [SQLITE_CANTOPEN] or +** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. +** +** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] +** must be either NULL or else pointers obtained from a prior +** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have +** not yet been released. +** +** The application must not read or write any part of +** a block of memory after it has been released using +** [sqlite3_free()] or [sqlite3_realloc()]. +*/ +SQLITE_API void *sqlite3_malloc(int); +SQLITE_API void *sqlite3_realloc(void*, int); +SQLITE_API void sqlite3_free(void*); + +/* +** CAPI3REF: Memory Allocator Statistics +** +** SQLite provides these two interfaces for reporting on the status +** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()] +** routines, which form the built-in memory allocation subsystem. +** +** ^The [sqlite3_memory_used()] routine returns the number of bytes +** of memory currently outstanding (malloced but not freed). +** ^The [sqlite3_memory_highwater()] routine returns the maximum +** value of [sqlite3_memory_used()] since the high-water mark +** was last reset. ^The values returned by [sqlite3_memory_used()] and +** [sqlite3_memory_highwater()] include any overhead +** added by SQLite in its implementation of [sqlite3_malloc()], +** but not overhead added by the any underlying system library +** routines that [sqlite3_malloc()] may call. +** +** ^The memory high-water mark is reset to the current value of +** [sqlite3_memory_used()] if and only if the parameter to +** [sqlite3_memory_highwater()] is true. ^The value returned +** by [sqlite3_memory_highwater(1)] is the high-water mark +** prior to the reset. +*/ +SQLITE_API sqlite3_int64 sqlite3_memory_used(void); +SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); + +/* +** CAPI3REF: Pseudo-Random Number Generator +** +** SQLite contains a high-quality pseudo-random number generator (PRNG) used to +** select random [ROWID | ROWIDs] when inserting new records into a table that +** already uses the largest possible [ROWID]. The PRNG is also used for +** the build-in random() and randomblob() SQL functions. This interface allows +** applications to access the same PRNG for other purposes. +** +** ^A call to this routine stores N bytes of randomness into buffer P. +** +** ^The first time this routine is invoked (either internally or by +** the application) the PRNG is seeded using randomness obtained +** from the xRandomness method of the default [sqlite3_vfs] object. +** ^On all subsequent invocations, the pseudo-randomness is generated +** internally and without recourse to the [sqlite3_vfs] xRandomness +** method. +*/ +SQLITE_API void sqlite3_randomness(int N, void *P); + +/* +** CAPI3REF: Compile-Time Authorization Callbacks +** +** ^This routine registers an authorizer callback with a particular +** [database connection], supplied in the first argument. +** ^The authorizer callback is invoked as SQL statements are being compiled +** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], +** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. ^At various +** points during the compilation process, as logic is being created +** to perform various actions, the authorizer callback is invoked to +** see if those actions are allowed. ^The authorizer callback should +** return [SQLITE_OK] to allow the action, [SQLITE_IGNORE] to disallow the +** specific action but allow the SQL statement to continue to be +** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be +** rejected with an error. ^If the authorizer callback returns +** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] +** then the [sqlite3_prepare_v2()] or equivalent call that triggered +** the authorizer will fail with an error message. +** +** When the callback returns [SQLITE_OK], that means the operation +** requested is ok. ^When the callback returns [SQLITE_DENY], the +** [sqlite3_prepare_v2()] or equivalent call that triggered the +** authorizer will fail with an error message explaining that +** access is denied. +** +** ^The first parameter to the authorizer callback is a copy of the third +** parameter to the sqlite3_set_authorizer() interface. ^The second parameter +** to the callback is an integer [SQLITE_COPY | action code] that specifies +** the particular action to be authorized. ^The third through sixth parameters +** to the callback are zero-terminated strings that contain additional +** details about the action to be authorized. +** +** ^If the action code is [SQLITE_READ] +** and the callback returns [SQLITE_IGNORE] then the +** [prepared statement] statement is constructed to substitute +** a NULL value in place of the table column that would have +** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] +** return can be used to deny an untrusted user access to individual +** columns of a table. +** ^If the action code is [SQLITE_DELETE] and the callback returns +** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the +** [truncate optimization] is disabled and all rows are deleted individually. +** +** An authorizer is used when [sqlite3_prepare | preparing] +** SQL statements from an untrusted source, to ensure that the SQL statements +** do not try to access data they are not allowed to see, or that they do not +** try to execute malicious statements that damage the database. For +** example, an application may allow a user to enter arbitrary +** SQL queries for evaluation by a database. But the application does +** not want the user to be able to make arbitrary changes to the +** database. An authorizer could then be put in place while the +** user-entered SQL is being [sqlite3_prepare | prepared] that +** disallows everything except [SELECT] statements. +** +** Applications that need to process SQL from untrusted sources +** might also consider lowering resource limits using [sqlite3_limit()] +** and limiting database size using the [max_page_count] [PRAGMA] +** in addition to using an authorizer. +** +** ^(Only a single authorizer can be in place on a database connection +** at a time. Each call to sqlite3_set_authorizer overrides the +** previous call.)^ ^Disable the authorizer by installing a NULL callback. +** The authorizer is disabled by default. +** +** The authorizer callback must not do anything that will modify +** the database connection that invoked the authorizer callback. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the +** statement might be re-prepared during [sqlite3_step()] due to a +** schema change. Hence, the application should ensure that the +** correct authorizer callback remains in place during the [sqlite3_step()]. +** +** ^Note that the authorizer callback is invoked only during +** [sqlite3_prepare()] or its variants. Authorization is not +** performed during statement evaluation in [sqlite3_step()], unless +** as stated in the previous paragraph, sqlite3_step() invokes +** sqlite3_prepare_v2() to reprepare a statement after a schema change. +*/ +SQLITE_API int sqlite3_set_authorizer( + sqlite3*, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pUserData +); + +/* +** CAPI3REF: Authorizer Return Codes +** +** The [sqlite3_set_authorizer | authorizer callback function] must +** return either [SQLITE_OK] or one of these two constants in order +** to signal SQLite whether or not the action is permitted. See the +** [sqlite3_set_authorizer | authorizer documentation] for additional +** information. +** +** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code] +** from the [sqlite3_vtab_on_conflict()] interface. +*/ +#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ +#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ + +/* +** CAPI3REF: Authorizer Action Codes +** +** The [sqlite3_set_authorizer()] interface registers a callback function +** that is invoked to authorize certain SQL statement actions. The +** second parameter to the callback is an integer code that specifies +** what action is being authorized. These are the integer action codes that +** the authorizer callback may be passed. +** +** These action code values signify what kind of operation is to be +** authorized. The 3rd and 4th parameters to the authorization +** callback function will be parameters or NULL depending on which of these +** codes is used as the second parameter. ^(The 5th parameter to the +** authorizer callback is the name of the database ("main", "temp", +** etc.) if applicable.)^ ^The 6th parameter to the authorizer callback +** is the name of the inner-most trigger or view that is responsible for +** the access attempt or NULL if this access attempt is directly from +** top-level SQL code. +*/ +/******************************************* 3rd ************ 4th ***********/ +#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ +#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ +#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ +#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ +#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ +#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ +#define SQLITE_DELETE 9 /* Table Name NULL */ +#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ +#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ +#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ +#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ +#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ +#define SQLITE_DROP_VIEW 17 /* View Name NULL */ +#define SQLITE_INSERT 18 /* Table Name NULL */ +#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ +#define SQLITE_READ 20 /* Table Name Column Name */ +#define SQLITE_SELECT 21 /* NULL NULL */ +#define SQLITE_TRANSACTION 22 /* Operation NULL */ +#define SQLITE_UPDATE 23 /* Table Name Column Name */ +#define SQLITE_ATTACH 24 /* Filename NULL */ +#define SQLITE_DETACH 25 /* Database Name NULL */ +#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ +#define SQLITE_REINDEX 27 /* Index Name NULL */ +#define SQLITE_ANALYZE 28 /* Table Name NULL */ +#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ +#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ +#define SQLITE_FUNCTION 31 /* NULL Function Name */ +#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ +#define SQLITE_COPY 0 /* No longer used */ + +/* +** CAPI3REF: Tracing And Profiling Functions +** +** These routines register callback functions that can be used for +** tracing and profiling the execution of SQL statements. +** +** ^The callback function registered by sqlite3_trace() is invoked at +** various times when an SQL statement is being run by [sqlite3_step()]. +** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the +** SQL statement text as the statement first begins executing. +** ^(Additional sqlite3_trace() callbacks might occur +** as each triggered subprogram is entered. The callbacks for triggers +** contain a UTF-8 SQL comment that identifies the trigger.)^ +** +** The [SQLITE_TRACE_SIZE_LIMIT] compile-time option can be used to limit +** the length of [bound parameter] expansion in the output of sqlite3_trace(). +** +** ^The callback function registered by sqlite3_profile() is invoked +** as each SQL statement finishes. ^The profile callback contains +** the original statement text and an estimate of wall-clock time +** of how long that statement took to run. ^The profile callback +** time is in units of nanoseconds, however the current implementation +** is only capable of millisecond resolution so the six least significant +** digits in the time are meaningless. Future versions of SQLite +** might provide greater resolution on the profiler callback. The +** sqlite3_profile() function is considered experimental and is +** subject to change in future versions of SQLite. +*/ +SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); +SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, + void(*xProfile)(void*,const char*,sqlite3_uint64), void*); + +/* +** CAPI3REF: Query Progress Callbacks +** +** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback +** function X to be invoked periodically during long running calls to +** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for +** database connection D. An example use for this +** interface is to keep a GUI updated during a large query. +** +** ^The parameter P is passed through as the only parameter to the +** callback function X. ^The parameter N is the approximate number of +** [virtual machine instructions] that are evaluated between successive +** invocations of the callback X. ^If N is less than one then the progress +** handler is disabled. +** +** ^Only a single progress handler may be defined at one time per +** [database connection]; setting a new progress handler cancels the +** old one. ^Setting parameter X to NULL disables the progress handler. +** ^The progress handler is also disabled by setting N to a value less +** than 1. +** +** ^If the progress callback returns non-zero, the operation is +** interrupted. This feature can be used to implement a +** "Cancel" button on a GUI progress dialog box. +** +** The progress handler callback must not do anything that will modify +** the database connection that invoked the progress handler. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +*/ +SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); + +/* +** CAPI3REF: Opening A New Database Connection +** +** ^These routines open an SQLite database file as specified by the +** filename argument. ^The filename argument is interpreted as UTF-8 for +** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte +** order for sqlite3_open16(). ^(A [database connection] handle is usually +** returned in *ppDb, even if an error occurs. The only exception is that +** if SQLite is unable to allocate memory to hold the [sqlite3] object, +** a NULL will be written into *ppDb instead of a pointer to the [sqlite3] +** object.)^ ^(If the database is opened (and/or created) successfully, then +** [SQLITE_OK] is returned. Otherwise an [error code] is returned.)^ ^The +** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain +** an English language description of the error following a failure of any +** of the sqlite3_open() routines. +** +** ^The default encoding for the database will be UTF-8 if +** sqlite3_open() or sqlite3_open_v2() is called and +** UTF-16 in the native byte order if sqlite3_open16() is used. +** +** Whether or not an error occurs when it is opened, resources +** associated with the [database connection] handle should be released by +** passing it to [sqlite3_close()] when it is no longer required. +** +** The sqlite3_open_v2() interface works like sqlite3_open() +** except that it accepts two additional parameters for additional control +** over the new database connection. ^(The flags parameter to +** sqlite3_open_v2() can take one of +** the following three values, optionally combined with the +** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE], +** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^ +** +**
+** ^(
[SQLITE_OPEN_READONLY]
+**
The database is opened in read-only mode. If the database does not +** already exist, an error is returned.
)^ +** +** ^(
[SQLITE_OPEN_READWRITE]
+**
The database is opened for reading and writing if possible, or reading +** only if the file is write protected by the operating system. In either +** case the database must already exist, otherwise an error is returned.
)^ +** +** ^(
[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]
+**
The database is opened for reading and writing, and is created if +** it does not already exist. This is the behavior that is always used for +** sqlite3_open() and sqlite3_open16().
)^ +**
+** +** If the 3rd parameter to sqlite3_open_v2() is not one of the +** combinations shown above optionally combined with other +** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] +** then the behavior is undefined. +** +** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection +** opens in the multi-thread [threading mode] as long as the single-thread +** mode has not been set at compile-time or start-time. ^If the +** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens +** in the serialized [threading mode] unless single-thread was +** previously selected at compile-time or start-time. +** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be +** eligible to use [shared cache mode], regardless of whether or not shared +** cache is enabled using [sqlite3_enable_shared_cache()]. ^The +** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not +** participate in [shared cache mode] even if it is enabled. +** +** ^The fourth parameter to sqlite3_open_v2() is the name of the +** [sqlite3_vfs] object that defines the operating system interface that +** the new database connection should use. ^If the fourth parameter is +** a NULL pointer then the default [sqlite3_vfs] object is used. +** +** ^If the filename is ":memory:", then a private, temporary in-memory database +** is created for the connection. ^This in-memory database will vanish when +** the database connection is closed. Future versions of SQLite might +** make use of additional special filenames that begin with the ":" character. +** It is recommended that when a database filename actually does begin with +** a ":" character you should prefix the filename with a pathname such as +** "./" to avoid ambiguity. +** +** ^If the filename is an empty string, then a private, temporary +** on-disk database will be created. ^This private database will be +** automatically deleted as soon as the database connection is closed. +** +** [[URI filenames in sqlite3_open()]]

URI Filenames

+** +** ^If [URI filename] interpretation is enabled, and the filename argument +** begins with "file:", then the filename is interpreted as a URI. ^URI +** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is +** set in the fourth argument to sqlite3_open_v2(), or if it has +** been enabled globally using the [SQLITE_CONFIG_URI] option with the +** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option. +** As of SQLite version 3.7.7, URI filename interpretation is turned off +** by default, but future releases of SQLite might enable URI filename +** interpretation by default. See "[URI filenames]" for additional +** information. +** +** URI filenames are parsed according to RFC 3986. ^If the URI contains an +** authority, then it must be either an empty string or the string +** "localhost". ^If the authority is not an empty string or "localhost", an +** error is returned to the caller. ^The fragment component of a URI, if +** present, is ignored. +** +** ^SQLite uses the path component of the URI as the name of the disk file +** which contains the database. ^If the path begins with a '/' character, +** then it is interpreted as an absolute path. ^If the path does not begin +** with a '/' (meaning that the authority section is omitted from the URI) +** then the path is interpreted as a relative path. +** ^On windows, the first component of an absolute path +** is a drive specification (e.g. "C:"). +** +** [[core URI query parameters]] +** The query component of a URI may contain parameters that are interpreted +** either by SQLite itself, or by a [VFS | custom VFS implementation]. +** SQLite interprets the following three query parameters: +** +**
    +**
  • vfs: ^The "vfs" parameter may be used to specify the name of +** a VFS object that provides the operating system interface that should +** be used to access the database file on disk. ^If this option is set to +** an empty string the default VFS object is used. ^Specifying an unknown +** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is +** present, then the VFS specified by the option takes precedence over +** the value passed as the fourth parameter to sqlite3_open_v2(). +** +**
  • mode: ^(The mode parameter may be set to either "ro", "rw", +** "rwc", or "memory". Attempting to set it to any other value is +** an error)^. +** ^If "ro" is specified, then the database is opened for read-only +** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the +** third argument to sqlite3_open_v2(). ^If the mode option is set to +** "rw", then the database is opened for read-write (but not create) +** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had +** been set. ^Value "rwc" is equivalent to setting both +** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is +** set to "memory" then a pure [in-memory database] that never reads +** or writes from disk is used. ^It is an error to specify a value for +** the mode parameter that is less restrictive than that specified by +** the flags passed in the third parameter to sqlite3_open_v2(). +** +**
  • cache: ^The cache parameter may be set to either "shared" or +** "private". ^Setting it to "shared" is equivalent to setting the +** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to +** sqlite3_open_v2(). ^Setting the cache parameter to "private" is +** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. +** ^If sqlite3_open_v2() is used and the "cache" parameter is present in +** a URI filename, its value overrides any behavior requested by setting +** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. +**
+** +** ^Specifying an unknown parameter in the query component of a URI is not an +** error. Future versions of SQLite might understand additional query +** parameters. See "[query parameters with special meaning to SQLite]" for +** additional information. +** +** [[URI filename examples]]

URI filename examples

+** +** +**
URI filenames Results +**
file:data.db +** Open the file "data.db" in the current directory. +**
file:/home/fred/data.db
+** file:///home/fred/data.db
+** file://localhost/home/fred/data.db
+** Open the database file "/home/fred/data.db". +**
file://darkstar/home/fred/data.db +** An error. "darkstar" is not a recognized authority. +**
+** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db +** Windows only: Open the file "data.db" on fred's desktop on drive +** C:. Note that the %20 escaping in this example is not strictly +** necessary - space characters can be used literally +** in URI filenames. +**
file:data.db?mode=ro&cache=private +** Open file "data.db" in the current directory for read-only access. +** Regardless of whether or not shared-cache mode is enabled by +** default, use a private cache. +**
file:/home/fred/data.db?vfs=unix-nolock +** Open file "/home/fred/data.db". Use the special VFS "unix-nolock". +**
file:data.db?mode=readonly +** An error. "readonly" is not a valid option for the "mode" parameter. +**
+** +** ^URI hexadecimal escape sequences (%HH) are supported within the path and +** query components of a URI. A hexadecimal escape sequence consists of a +** percent sign - "%" - followed by exactly two hexadecimal digits +** specifying an octet value. ^Before the path or query components of a +** URI filename are interpreted, they are encoded using UTF-8 and all +** hexadecimal escape sequences replaced by a single byte containing the +** corresponding octet. If this process generates an invalid UTF-8 encoding, +** the results are undefined. +** +** Note to Windows users: The encoding used for the filename argument +** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever +** codepage is currently defined. Filenames containing international +** characters must be converted to UTF-8 prior to passing them into +** sqlite3_open() or sqlite3_open_v2(). +** +** Note to Windows Runtime users: The temporary directory must be set +** prior to calling sqlite3_open() or sqlite3_open_v2(). Otherwise, various +** features that require the use of temporary files may fail. +** +** See also: [sqlite3_temp_directory] +*/ +SQLITE_API int sqlite3_open( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +SQLITE_API int sqlite3_open16( + const void *filename, /* Database filename (UTF-16) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +SQLITE_API int sqlite3_open_v2( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs /* Name of VFS module to use */ +); + +/* +** CAPI3REF: Obtain Values For URI Parameters +** +** These are utility routines, useful to VFS implementations, that check +** to see if a database file was a URI that contained a specific query +** parameter, and if so obtains the value of that query parameter. +** +** If F is the database filename pointer passed into the xOpen() method of +** a VFS implementation when the flags parameter to xOpen() has one or +** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and +** P is the name of the query parameter, then +** sqlite3_uri_parameter(F,P) returns the value of the P +** parameter if it exists or a NULL pointer if P does not appear as a +** query parameter on F. If P is a query parameter of F +** has no explicit value, then sqlite3_uri_parameter(F,P) returns +** a pointer to an empty string. +** +** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean +** parameter and returns true (1) or false (0) according to the value +** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the +** value of query parameter P is one of "yes", "true", or "on" in any +** case or if the value begins with a non-zero number. The +** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of +** query parameter P is one of "no", "false", or "off" in any case or +** if the value begins with a numeric zero. If P is not a query +** parameter on F or if the value of P is does not match any of the +** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0). +** +** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a +** 64-bit signed integer and returns that integer, or D if P does not +** exist. If the value of P is something other than an integer, then +** zero is returned. +** +** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and +** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and +** is not a database file pathname pointer that SQLite passed into the xOpen +** VFS method, then the behavior of this routine is undefined and probably +** undesirable. +*/ +SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); +SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); +SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); + + +/* +** CAPI3REF: Error Codes And Messages +** +** ^The sqlite3_errcode() interface returns the numeric [result code] or +** [extended result code] for the most recent failed sqlite3_* API call +** associated with a [database connection]. If a prior API call failed +** but the most recent API call succeeded, the return value from +** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode() +** interface is the same except that it always returns the +** [extended result code] even when extended result codes are +** disabled. +** +** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language +** text that describes the error, as either UTF-8 or UTF-16 respectively. +** ^(Memory to hold the error message string is managed internally. +** The application does not need to worry about freeing the result. +** However, the error string might be overwritten or deallocated by +** subsequent calls to other SQLite interface functions.)^ +** +** ^The sqlite3_errstr() interface returns the English-language text +** that describes the [result code], as UTF-8. +** ^(Memory to hold the error message string is managed internally +** and must not be freed by the application)^. +** +** When the serialized [threading mode] is in use, it might be the +** case that a second error occurs on a separate thread in between +** the time of the first error and the call to these interfaces. +** When that happens, the second error will be reported since these +** interfaces always report the most recent result. To avoid +** this, each thread can obtain exclusive use of the [database connection] D +** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning +** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after +** all calls to the interfaces listed here are completed. +** +** If an interface fails with SQLITE_MISUSE, that means the interface +** was invoked incorrectly by the application. In that case, the +** error code and message may or may not be set. +*/ +SQLITE_API int sqlite3_errcode(sqlite3 *db); +SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); +SQLITE_API const char *sqlite3_errmsg(sqlite3*); +SQLITE_API const void *sqlite3_errmsg16(sqlite3*); +SQLITE_API const char *sqlite3_errstr(int); + +/* +** CAPI3REF: SQL Statement Object +** KEYWORDS: {prepared statement} {prepared statements} +** +** An instance of this object represents a single SQL statement. +** This object is variously known as a "prepared statement" or a +** "compiled SQL statement" or simply as a "statement". +** +** The life of a statement object goes something like this: +** +**
    +**
  1. Create the object using [sqlite3_prepare_v2()] or a related +** function. +**
  2. Bind values to [host parameters] using the sqlite3_bind_*() +** interfaces. +**
  3. Run the SQL by calling [sqlite3_step()] one or more times. +**
  4. Reset the statement using [sqlite3_reset()] then go back +** to step 2. Do this zero or more times. +**
  5. Destroy the object using [sqlite3_finalize()]. +**
+** +** Refer to documentation on individual methods above for additional +** information. +*/ +typedef struct sqlite3_stmt sqlite3_stmt; + +/* +** CAPI3REF: Run-time Limits +** +** ^(This interface allows the size of various constructs to be limited +** on a connection by connection basis. The first parameter is the +** [database connection] whose limit is to be set or queried. The +** second parameter is one of the [limit categories] that define a +** class of constructs to be size limited. The third parameter is the +** new limit for that construct.)^ +** +** ^If the new limit is a negative number, the limit is unchanged. +** ^(For each limit category SQLITE_LIMIT_NAME there is a +** [limits | hard upper bound] +** set at compile-time by a C preprocessor macro called +** [limits | SQLITE_MAX_NAME]. +** (The "_LIMIT_" in the name is changed to "_MAX_".))^ +** ^Attempts to increase a limit above its hard upper bound are +** silently truncated to the hard upper bound. +** +** ^Regardless of whether or not the limit was changed, the +** [sqlite3_limit()] interface returns the prior value of the limit. +** ^Hence, to find the current value of a limit without changing it, +** simply invoke this interface with the third parameter set to -1. +** +** Run-time limits are intended for use in applications that manage +** both their own internal database and also databases that are controlled +** by untrusted external sources. An example application might be a +** web browser that has its own databases for storing history and +** separate databases controlled by JavaScript applications downloaded +** off the Internet. The internal databases can be given the +** large, default limits. Databases managed by external sources can +** be given much smaller limits designed to prevent a denial of service +** attack. Developers might also want to use the [sqlite3_set_authorizer()] +** interface to further control untrusted SQL. The size of the database +** created by an untrusted script can be contained using the +** [max_page_count] [PRAGMA]. +** +** New run-time limit categories may be added in future releases. +*/ +SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); + +/* +** CAPI3REF: Run-Time Limit Categories +** KEYWORDS: {limit category} {*limit categories} +** +** These constants define various performance limits +** that can be lowered at run-time using [sqlite3_limit()]. +** The synopsis of the meanings of the various limits is shown below. +** Additional information is available at [limits | Limits in SQLite]. +** +**
+** [[SQLITE_LIMIT_LENGTH]] ^(
SQLITE_LIMIT_LENGTH
+**
The maximum size of any string or BLOB or table row, in bytes.
)^ +** +** [[SQLITE_LIMIT_SQL_LENGTH]] ^(
SQLITE_LIMIT_SQL_LENGTH
+**
The maximum length of an SQL statement, in bytes.
)^ +** +** [[SQLITE_LIMIT_COLUMN]] ^(
SQLITE_LIMIT_COLUMN
+**
The maximum number of columns in a table definition or in the +** result set of a [SELECT] or the maximum number of columns in an index +** or in an ORDER BY or GROUP BY clause.
)^ +** +** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(
SQLITE_LIMIT_EXPR_DEPTH
+**
The maximum depth of the parse tree on any expression.
)^ +** +** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(
SQLITE_LIMIT_COMPOUND_SELECT
+**
The maximum number of terms in a compound SELECT statement.
)^ +** +** [[SQLITE_LIMIT_VDBE_OP]] ^(
SQLITE_LIMIT_VDBE_OP
+**
The maximum number of instructions in a virtual machine program +** used to implement an SQL statement. This limit is not currently +** enforced, though that might be added in some future release of +** SQLite.
)^ +** +** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(
SQLITE_LIMIT_FUNCTION_ARG
+**
The maximum number of arguments on a function.
)^ +** +** [[SQLITE_LIMIT_ATTACHED]] ^(
SQLITE_LIMIT_ATTACHED
+**
The maximum number of [ATTACH | attached databases].)^
+** +** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]] +** ^(
SQLITE_LIMIT_LIKE_PATTERN_LENGTH
+**
The maximum length of the pattern argument to the [LIKE] or +** [GLOB] operators.
)^ +** +** [[SQLITE_LIMIT_VARIABLE_NUMBER]] +** ^(
SQLITE_LIMIT_VARIABLE_NUMBER
+**
The maximum index number of any [parameter] in an SQL statement.)^ +** +** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(
SQLITE_LIMIT_TRIGGER_DEPTH
+**
The maximum depth of recursion for triggers.
)^ +**
+*/ +#define SQLITE_LIMIT_LENGTH 0 +#define SQLITE_LIMIT_SQL_LENGTH 1 +#define SQLITE_LIMIT_COLUMN 2 +#define SQLITE_LIMIT_EXPR_DEPTH 3 +#define SQLITE_LIMIT_COMPOUND_SELECT 4 +#define SQLITE_LIMIT_VDBE_OP 5 +#define SQLITE_LIMIT_FUNCTION_ARG 6 +#define SQLITE_LIMIT_ATTACHED 7 +#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 +#define SQLITE_LIMIT_VARIABLE_NUMBER 9 +#define SQLITE_LIMIT_TRIGGER_DEPTH 10 + +/* +** CAPI3REF: Compiling An SQL Statement +** KEYWORDS: {SQL statement compiler} +** +** To execute an SQL query, it must first be compiled into a byte-code +** program using one of these routines. +** +** The first argument, "db", is a [database connection] obtained from a +** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or +** [sqlite3_open16()]. The database connection must not have been closed. +** +** The second argument, "zSql", is the statement to be compiled, encoded +** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() +** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2() +** use UTF-16. +** +** ^If the nByte argument is less than zero, then zSql is read up to the +** first zero terminator. ^If nByte is non-negative, then it is the maximum +** number of bytes read from zSql. ^When nByte is non-negative, the +** zSql string ends at either the first '\000' or '\u0000' character or +** the nByte-th byte, whichever comes first. If the caller knows +** that the supplied string is nul-terminated, then there is a small +** performance advantage to be gained by passing an nByte parameter that +** is equal to the number of bytes in the input string including +** the nul-terminator bytes as this saves SQLite from having to +** make a copy of the input string. +** +** ^If pzTail is not NULL then *pzTail is made to point to the first byte +** past the end of the first SQL statement in zSql. These routines only +** compile the first statement in zSql, so *pzTail is left pointing to +** what remains uncompiled. +** +** ^*ppStmt is left pointing to a compiled [prepared statement] that can be +** executed using [sqlite3_step()]. ^If there is an error, *ppStmt is set +** to NULL. ^If the input text contains no SQL (if the input is an empty +** string or a comment) then *ppStmt is set to NULL. +** The calling procedure is responsible for deleting the compiled +** SQL statement using [sqlite3_finalize()] after it has finished with it. +** ppStmt may not be NULL. +** +** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK]; +** otherwise an [error code] is returned. +** +** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are +** recommended for all new programs. The two older interfaces are retained +** for backwards compatibility, but their use is discouraged. +** ^In the "v2" interfaces, the prepared statement +** that is returned (the [sqlite3_stmt] object) contains a copy of the +** original SQL text. This causes the [sqlite3_step()] interface to +** behave differently in three ways: +** +**
    +**
  1. +** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it +** always used to do, [sqlite3_step()] will automatically recompile the SQL +** statement and try to run it again. As many as [SQLITE_MAX_SCHEMA_RETRY] +** retries will occur before sqlite3_step() gives up and returns an error. +**
  2. +** +**
  3. +** ^When an error occurs, [sqlite3_step()] will return one of the detailed +** [error codes] or [extended error codes]. ^The legacy behavior was that +** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code +** and the application would have to make a second call to [sqlite3_reset()] +** in order to find the underlying cause of the problem. With the "v2" prepare +** interfaces, the underlying reason for the error is returned immediately. +**
  4. +** +**
  5. +** ^If the specific value bound to [parameter | host parameter] in the +** WHERE clause might influence the choice of query plan for a statement, +** then the statement will be automatically recompiled, as if there had been +** a schema change, on the first [sqlite3_step()] call following any change +** to the [sqlite3_bind_text | bindings] of that [parameter]. +** ^The specific value of WHERE-clause [parameter] might influence the +** choice of query plan if the parameter is the left-hand side of a [LIKE] +** or [GLOB] operator or if the parameter is compared to an indexed column +** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. +** the +**
  6. +**
+*/ +SQLITE_API int sqlite3_prepare( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int sqlite3_prepare_v2( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int sqlite3_prepare16( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int sqlite3_prepare16_v2( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); + +/* +** CAPI3REF: Retrieving Statement SQL +** +** ^This interface can be used to retrieve a saved copy of the original +** SQL text used to create a [prepared statement] if that statement was +** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()]. +*/ +SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Determine If An SQL Statement Writes The Database +** +** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if +** and only if the [prepared statement] X makes no direct changes to +** the content of the database file. +** +** Note that [application-defined SQL functions] or +** [virtual tables] might change the database indirectly as a side effect. +** ^(For example, if an application defines a function "eval()" that +** calls [sqlite3_exec()], then the following SQL statement would +** change the database file through side-effects: +** +**
+**    SELECT eval('DELETE FROM t1') FROM t2;
+** 
+** +** But because the [SELECT] statement does not change the database file +** directly, sqlite3_stmt_readonly() would still return true.)^ +** +** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK], +** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true, +** since the statements themselves do not actually modify the database but +** rather they control the timing of when other statements modify the +** database. ^The [ATTACH] and [DETACH] statements also cause +** sqlite3_stmt_readonly() to return true since, while those statements +** change the configuration of a database connection, they do not make +** changes to the content of the database files on disk. +*/ +SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Determine If A Prepared Statement Has Been Reset +** +** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the +** [prepared statement] S has been stepped at least once using +** [sqlite3_step(S)] but has not run to completion and/or has not +** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S) +** interface returns false if S is a NULL pointer. If S is not a +** NULL pointer and is not a pointer to a valid [prepared statement] +** object, then the behavior is undefined and probably undesirable. +** +** This interface can be used in combination [sqlite3_next_stmt()] +** to locate all prepared statements associated with a database +** connection that are in need of being reset. This can be used, +** for example, in diagnostic routines to search for prepared +** statements that are holding a transaction open. +*/ +SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); + +/* +** CAPI3REF: Dynamically Typed Value Object +** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value} +** +** SQLite uses the sqlite3_value object to represent all values +** that can be stored in a database table. SQLite uses dynamic typing +** for the values it stores. ^Values stored in sqlite3_value objects +** can be integers, floating point values, strings, BLOBs, or NULL. +** +** An sqlite3_value object may be either "protected" or "unprotected". +** Some interfaces require a protected sqlite3_value. Other interfaces +** will accept either a protected or an unprotected sqlite3_value. +** Every interface that accepts sqlite3_value arguments specifies +** whether or not it requires a protected sqlite3_value. +** +** The terms "protected" and "unprotected" refer to whether or not +** a mutex is held. An internal mutex is held for a protected +** sqlite3_value object but no mutex is held for an unprotected +** sqlite3_value object. If SQLite is compiled to be single-threaded +** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0) +** or if SQLite is run in one of reduced mutex modes +** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD] +** then there is no distinction between protected and unprotected +** sqlite3_value objects and they can be used interchangeably. However, +** for maximum code portability it is recommended that applications +** still make the distinction between protected and unprotected +** sqlite3_value objects even when not strictly required. +** +** ^The sqlite3_value objects that are passed as parameters into the +** implementation of [application-defined SQL functions] are protected. +** ^The sqlite3_value object returned by +** [sqlite3_column_value()] is unprotected. +** Unprotected sqlite3_value objects may only be used with +** [sqlite3_result_value()] and [sqlite3_bind_value()]. +** The [sqlite3_value_blob | sqlite3_value_type()] family of +** interfaces require protected sqlite3_value objects. +*/ +typedef struct Mem sqlite3_value; + +/* +** CAPI3REF: SQL Function Context Object +** +** The context in which an SQL function executes is stored in an +** sqlite3_context object. ^A pointer to an sqlite3_context object +** is always first parameter to [application-defined SQL functions]. +** The application-defined SQL function implementation will pass this +** pointer through into calls to [sqlite3_result_int | sqlite3_result()], +** [sqlite3_aggregate_context()], [sqlite3_user_data()], +** [sqlite3_context_db_handle()], [sqlite3_get_auxdata()], +** and/or [sqlite3_set_auxdata()]. +*/ +typedef struct sqlite3_context sqlite3_context; + +/* +** CAPI3REF: Binding Values To Prepared Statements +** KEYWORDS: {host parameter} {host parameters} {host parameter name} +** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} +** +** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants, +** literals may be replaced by a [parameter] that matches one of following +** templates: +** +**
    +**
  • ? +**
  • ?NNN +**
  • :VVV +**
  • @VVV +**
  • $VVV +**
+** +** In the templates above, NNN represents an integer literal, +** and VVV represents an alphanumeric identifier.)^ ^The values of these +** parameters (also called "host parameter names" or "SQL parameters") +** can be set using the sqlite3_bind_*() routines defined here. +** +** ^The first argument to the sqlite3_bind_*() routines is always +** a pointer to the [sqlite3_stmt] object returned from +** [sqlite3_prepare_v2()] or its variants. +** +** ^The second argument is the index of the SQL parameter to be set. +** ^The leftmost SQL parameter has an index of 1. ^When the same named +** SQL parameter is used more than once, second and subsequent +** occurrences have the same index as the first occurrence. +** ^The index for named parameters can be looked up using the +** [sqlite3_bind_parameter_index()] API if desired. ^The index +** for "?NNN" parameters is the value of NNN. +** ^The NNN value must be between 1 and the [sqlite3_limit()] +** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999). +** +** ^The third argument is the value to bind to the parameter. +** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16() +** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter +** is ignored and the end result is the same as sqlite3_bind_null(). +** +** ^(In those routines that have a fourth argument, its value is the +** number of bytes in the parameter. To be clear: the value is the +** number of bytes in the value, not the number of characters.)^ +** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16() +** is negative, then the length of the string is +** the number of bytes up to the first zero terminator. +** If the fourth parameter to sqlite3_bind_blob() is negative, then +** the behavior is undefined. +** If a non-negative fourth parameter is provided to sqlite3_bind_text() +** or sqlite3_bind_text16() then that parameter must be the byte offset +** where the NUL terminator would occur assuming the string were NUL +** terminated. If any NUL characters occur at byte offsets less than +** the value of the fourth parameter then the resulting string value will +** contain embedded NULs. The result of expressions involving strings +** with embedded NULs is undefined. +** +** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and +** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or +** string after SQLite has finished with it. ^The destructor is called +** to dispose of the BLOB or string even if the call to sqlite3_bind_blob(), +** sqlite3_bind_text(), or sqlite3_bind_text16() fails. +** ^If the fifth argument is +** the special value [SQLITE_STATIC], then SQLite assumes that the +** information is in static, unmanaged space and does not need to be freed. +** ^If the fifth argument has the value [SQLITE_TRANSIENT], then +** SQLite makes its own private copy of the data immediately, before +** the sqlite3_bind_*() routine returns. +** +** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that +** is filled with zeroes. ^A zeroblob uses a fixed amount of memory +** (just an integer to hold its size) while it is being processed. +** Zeroblobs are intended to serve as placeholders for BLOBs whose +** content is later written using +** [sqlite3_blob_open | incremental BLOB I/O] routines. +** ^A negative value for the zeroblob results in a zero-length BLOB. +** +** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer +** for the [prepared statement] or with a prepared statement for which +** [sqlite3_step()] has been called more recently than [sqlite3_reset()], +** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_() +** routine is passed a [prepared statement] that has been finalized, the +** result is undefined and probably harmful. +** +** ^Bindings are not cleared by the [sqlite3_reset()] routine. +** ^Unbound parameters are interpreted as NULL. +** +** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an +** [error code] if anything goes wrong. +** ^[SQLITE_RANGE] is returned if the parameter +** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails. +** +** See also: [sqlite3_bind_parameter_count()], +** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); +SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); +SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); +SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); + +/* +** CAPI3REF: Number Of SQL Parameters +** +** ^This routine can be used to find the number of [SQL parameters] +** in a [prepared statement]. SQL parameters are tokens of the +** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as +** placeholders for values that are [sqlite3_bind_blob | bound] +** to the parameters at a later time. +** +** ^(This routine actually returns the index of the largest (rightmost) +** parameter. For all forms except ?NNN, this will correspond to the +** number of unique parameters. If parameters of the ?NNN form are used, +** there may be gaps in the list.)^ +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_name()], and +** [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); + +/* +** CAPI3REF: Name Of A Host Parameter +** +** ^The sqlite3_bind_parameter_name(P,N) interface returns +** the name of the N-th [SQL parameter] in the [prepared statement] P. +** ^(SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA" +** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA" +** respectively. +** In other words, the initial ":" or "$" or "@" or "?" +** is included as part of the name.)^ +** ^Parameters of the form "?" without a following integer have no name +** and are referred to as "nameless" or "anonymous parameters". +** +** ^The first host parameter has an index of 1, not 0. +** +** ^If the value N is out of range or if the N-th parameter is +** nameless, then NULL is returned. ^The returned string is +** always in UTF-8 encoding even if the named parameter was +** originally specified as UTF-16 in [sqlite3_prepare16()] or +** [sqlite3_prepare16_v2()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); + +/* +** CAPI3REF: Index Of A Parameter With A Given Name +** +** ^Return the index of an SQL parameter given its name. ^The +** index value returned is suitable for use as the second +** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero +** is returned if no matching parameter is found. ^The parameter +** name must be given in UTF-8 even if the original statement +** was prepared from UTF-16 text using [sqlite3_prepare16_v2()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); + +/* +** CAPI3REF: Reset All Bindings On A Prepared Statement +** +** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset +** the [sqlite3_bind_blob | bindings] on a [prepared statement]. +** ^Use this routine to reset all host parameters to NULL. +*/ +SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); + +/* +** CAPI3REF: Number Of Columns In A Result Set +** +** ^Return the number of columns in the result set returned by the +** [prepared statement]. ^This routine returns 0 if pStmt is an SQL +** statement that does not return data (for example an [UPDATE]). +** +** See also: [sqlite3_data_count()] +*/ +SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Column Names In A Result Set +** +** ^These routines return the name assigned to a particular column +** in the result set of a [SELECT] statement. ^The sqlite3_column_name() +** interface returns a pointer to a zero-terminated UTF-8 string +** and sqlite3_column_name16() returns a pointer to a zero-terminated +** UTF-16 string. ^The first parameter is the [prepared statement] +** that implements the [SELECT] statement. ^The second parameter is the +** column number. ^The leftmost column is number 0. +** +** ^The returned string pointer is valid until either the [prepared statement] +** is destroyed by [sqlite3_finalize()] or until the statement is automatically +** reprepared by the first call to [sqlite3_step()] for a particular run +** or until the next call to +** sqlite3_column_name() or sqlite3_column_name16() on the same column. +** +** ^If sqlite3_malloc() fails during the processing of either routine +** (for example during a conversion from UTF-8 to UTF-16) then a +** NULL pointer is returned. +** +** ^The name of a result column is the value of the "AS" clause for +** that column, if there is an AS clause. If there is no AS clause +** then the name of the column is unspecified and may change from +** one release of SQLite to the next. +*/ +SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); +SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); + +/* +** CAPI3REF: Source Of Data In A Query Result +** +** ^These routines provide a means to determine the database, table, and +** table column that is the origin of a particular result column in +** [SELECT] statement. +** ^The name of the database or table or column can be returned as +** either a UTF-8 or UTF-16 string. ^The _database_ routines return +** the database name, the _table_ routines return the table name, and +** the origin_ routines return the column name. +** ^The returned string is valid until the [prepared statement] is destroyed +** using [sqlite3_finalize()] or until the statement is automatically +** reprepared by the first call to [sqlite3_step()] for a particular run +** or until the same information is requested +** again in a different encoding. +** +** ^The names returned are the original un-aliased names of the +** database, table, and column. +** +** ^The first argument to these interfaces is a [prepared statement]. +** ^These functions return information about the Nth result column returned by +** the statement, where N is the second function argument. +** ^The left-most column is column 0 for these routines. +** +** ^If the Nth column returned by the statement is an expression or +** subquery and is not a column value, then all of these functions return +** NULL. ^These routine might also return NULL if a memory allocation error +** occurs. ^Otherwise, they return the name of the attached database, table, +** or column that query result column was extracted from. +** +** ^As with all other SQLite APIs, those whose names end with "16" return +** UTF-16 encoded strings and the other functions return UTF-8. +** +** ^These APIs are only available if the library was compiled with the +** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol. +** +** If two or more threads call one or more of these routines against the same +** prepared statement and column at the same time then the results are +** undefined. +** +** If two or more threads call one or more +** [sqlite3_column_database_name | column metadata interfaces] +** for the same [prepared statement] and result column +** at the same time then the results are undefined. +*/ +SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Declared Datatype Of A Query Result +** +** ^(The first parameter is a [prepared statement]. +** If this statement is a [SELECT] statement and the Nth column of the +** returned result set of that [SELECT] is a table column (not an +** expression or subquery) then the declared type of the table +** column is returned.)^ ^If the Nth column of the result set is an +** expression or subquery, then a NULL pointer is returned. +** ^The returned string is always UTF-8 encoded. +** +** ^(For example, given the database schema: +** +** CREATE TABLE t1(c1 VARIANT); +** +** and the following statement to be compiled: +** +** SELECT c1 + 1, c1 FROM t1; +** +** this routine would return the string "VARIANT" for the second result +** column (i==1), and a NULL pointer for the first result column (i==0).)^ +** +** ^SQLite uses dynamic run-time typing. ^So just because a column +** is declared to contain a particular type does not mean that the +** data stored in that column is of the declared type. SQLite is +** strongly typed, but the typing is dynamic not static. ^Type +** is associated with individual values, not with the containers +** used to hold those values. +*/ +SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Evaluate An SQL Statement +** +** After a [prepared statement] has been prepared using either +** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy +** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function +** must be called one or more times to evaluate the statement. +** +** The details of the behavior of the sqlite3_step() interface depend +** on whether the statement was prepared using the newer "v2" interface +** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy +** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the +** new "v2" interface is recommended for new applications but the legacy +** interface will continue to be supported. +** +** ^In the legacy interface, the return value will be either [SQLITE_BUSY], +** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. +** ^With the "v2" interface, any of the other [result codes] or +** [extended result codes] might be returned as well. +** +** ^[SQLITE_BUSY] means that the database engine was unable to acquire the +** database locks it needs to do its job. ^If the statement is a [COMMIT] +** or occurs outside of an explicit transaction, then you can retry the +** statement. If the statement is not a [COMMIT] and occurs within an +** explicit transaction then you should rollback the transaction before +** continuing. +** +** ^[SQLITE_DONE] means that the statement has finished executing +** successfully. sqlite3_step() should not be called again on this virtual +** machine without first calling [sqlite3_reset()] to reset the virtual +** machine back to its initial state. +** +** ^If the SQL statement being executed returns any data, then [SQLITE_ROW] +** is returned each time a new row of data is ready for processing by the +** caller. The values may be accessed using the [column access functions]. +** sqlite3_step() is called again to retrieve the next row of data. +** +** ^[SQLITE_ERROR] means that a run-time error (such as a constraint +** violation) has occurred. sqlite3_step() should not be called again on +** the VM. More information may be found by calling [sqlite3_errmsg()]. +** ^With the legacy interface, a more specific error code (for example, +** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) +** can be obtained by calling [sqlite3_reset()] on the +** [prepared statement]. ^In the "v2" interface, +** the more specific error code is returned directly by sqlite3_step(). +** +** [SQLITE_MISUSE] means that the this routine was called inappropriately. +** Perhaps it was called on a [prepared statement] that has +** already been [sqlite3_finalize | finalized] or on one that had +** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could +** be the case that the same database connection is being used by two or +** more threads at the same moment in time. +** +** For all versions of SQLite up to and including 3.6.23.1, a call to +** [sqlite3_reset()] was required after sqlite3_step() returned anything +** other than [SQLITE_ROW] before any subsequent invocation of +** sqlite3_step(). Failure to reset the prepared statement using +** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from +** sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began +** calling [sqlite3_reset()] automatically in this circumstance rather +** than returning [SQLITE_MISUSE]. This is not considered a compatibility +** break because any application that ever receives an SQLITE_MISUSE error +** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option +** can be used to restore the legacy behavior. +** +** Goofy Interface Alert: In the legacy interface, the sqlite3_step() +** API always returns a generic error code, [SQLITE_ERROR], following any +** error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call +** [sqlite3_reset()] or [sqlite3_finalize()] in order to find one of the +** specific [error codes] that better describes the error. +** We admit that this is a goofy design. The problem has been fixed +** with the "v2" interface. If you prepare all of your SQL statements +** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead +** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces, +** then the more specific [error codes] are returned directly +** by sqlite3_step(). The use of the "v2" interface is recommended. +*/ +SQLITE_API int sqlite3_step(sqlite3_stmt*); + +/* +** CAPI3REF: Number of columns in a result set +** +** ^The sqlite3_data_count(P) interface returns the number of columns in the +** current row of the result set of [prepared statement] P. +** ^If prepared statement P does not have results ready to return +** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of +** interfaces) then sqlite3_data_count(P) returns 0. +** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer. +** ^The sqlite3_data_count(P) routine returns 0 if the previous call to +** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P) +** will return non-zero if previous call to [sqlite3_step](P) returned +** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum] +** where it always returns zero since each step of that multi-step +** pragma returns 0 columns of data. +** +** See also: [sqlite3_column_count()] +*/ +SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Fundamental Datatypes +** KEYWORDS: SQLITE_TEXT +** +** ^(Every value in SQLite has one of five fundamental datatypes: +** +**
    +**
  • 64-bit signed integer +**
  • 64-bit IEEE floating point number +**
  • string +**
  • BLOB +**
  • NULL +**
)^ +** +** These constants are codes for each of those types. +** +** Note that the SQLITE_TEXT constant was also used in SQLite version 2 +** for a completely different meaning. Software that links against both +** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT, not +** SQLITE_TEXT. +*/ +#define SQLITE_INTEGER 1 +#define SQLITE_FLOAT 2 +#define SQLITE_BLOB 4 +#define SQLITE_NULL 5 +#ifdef SQLITE_TEXT +# undef SQLITE_TEXT +#else +# define SQLITE_TEXT 3 +#endif +#define SQLITE3_TEXT 3 + +/* +** CAPI3REF: Result Values From A Query +** KEYWORDS: {column access functions} +** +** These routines form the "result set" interface. +** +** ^These routines return information about a single column of the current +** result row of a query. ^In every case the first argument is a pointer +** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*] +** that was returned from [sqlite3_prepare_v2()] or one of its variants) +** and the second argument is the index of the column for which information +** should be returned. ^The leftmost column of the result set has the index 0. +** ^The number of columns in the result can be determined using +** [sqlite3_column_count()]. +** +** If the SQL statement does not currently point to a valid row, or if the +** column index is out of range, the result is undefined. +** These routines may only be called when the most recent call to +** [sqlite3_step()] has returned [SQLITE_ROW] and neither +** [sqlite3_reset()] nor [sqlite3_finalize()] have been called subsequently. +** If any of these routines are called after [sqlite3_reset()] or +** [sqlite3_finalize()] or after [sqlite3_step()] has returned +** something other than [SQLITE_ROW], the results are undefined. +** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] +** are called from a different thread while any of these routines +** are pending, then the results are undefined. +** +** ^The sqlite3_column_type() routine returns the +** [SQLITE_INTEGER | datatype code] for the initial data type +** of the result column. ^The returned value is one of [SQLITE_INTEGER], +** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value +** returned by sqlite3_column_type() is only meaningful if no type +** conversions have occurred as described below. After a type conversion, +** the value returned by sqlite3_column_type() is undefined. Future +** versions of SQLite may change the behavior of sqlite3_column_type() +** following a type conversion. +** +** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() +** routine returns the number of bytes in that BLOB or string. +** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts +** the string to UTF-8 and then returns the number of bytes. +** ^If the result is a numeric value then sqlite3_column_bytes() uses +** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns +** the number of bytes in that string. +** ^If the result is NULL, then sqlite3_column_bytes() returns zero. +** +** ^If the result is a BLOB or UTF-16 string then the sqlite3_column_bytes16() +** routine returns the number of bytes in that BLOB or string. +** ^If the result is a UTF-8 string, then sqlite3_column_bytes16() converts +** the string to UTF-16 and then returns the number of bytes. +** ^If the result is a numeric value then sqlite3_column_bytes16() uses +** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns +** the number of bytes in that string. +** ^If the result is NULL, then sqlite3_column_bytes16() returns zero. +** +** ^The values returned by [sqlite3_column_bytes()] and +** [sqlite3_column_bytes16()] do not include the zero terminators at the end +** of the string. ^For clarity: the values returned by +** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of +** bytes in the string, not the number of characters. +** +** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(), +** even empty strings, are always zero-terminated. ^The return +** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer. +** +** ^The object returned by [sqlite3_column_value()] is an +** [unprotected sqlite3_value] object. An unprotected sqlite3_value object +** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()]. +** If the [unprotected sqlite3_value] object returned by +** [sqlite3_column_value()] is used in any other way, including calls +** to routines like [sqlite3_value_int()], [sqlite3_value_text()], +** or [sqlite3_value_bytes()], then the behavior is undefined. +** +** These routines attempt to convert the value where appropriate. ^For +** example, if the internal representation is FLOAT and a text result +** is requested, [sqlite3_snprintf()] is used internally to perform the +** conversion automatically. ^(The following table details the conversions +** that are applied: +** +**
+** +**
Internal
Type
Requested
Type
Conversion +** +**
NULL INTEGER Result is 0 +**
NULL FLOAT Result is 0.0 +**
NULL TEXT Result is NULL pointer +**
NULL BLOB Result is NULL pointer +**
INTEGER FLOAT Convert from integer to float +**
INTEGER TEXT ASCII rendering of the integer +**
INTEGER BLOB Same as INTEGER->TEXT +**
FLOAT INTEGER Convert from float to integer +**
FLOAT TEXT ASCII rendering of the float +**
FLOAT BLOB Same as FLOAT->TEXT +**
TEXT INTEGER Use atoi() +**
TEXT FLOAT Use atof() +**
TEXT BLOB No change +**
BLOB INTEGER Convert to TEXT then use atoi() +**
BLOB FLOAT Convert to TEXT then use atof() +**
BLOB TEXT Add a zero terminator if needed +**
+**
)^ +** +** The table above makes reference to standard C library functions atoi() +** and atof(). SQLite does not really use these functions. It has its +** own equivalent internal routines. The atoi() and atof() names are +** used in the table for brevity and because they are familiar to most +** C programmers. +** +** Note that when type conversions occur, pointers returned by prior +** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or +** sqlite3_column_text16() may be invalidated. +** Type conversions and pointer invalidations might occur +** in the following cases: +** +**
    +**
  • The initial content is a BLOB and sqlite3_column_text() or +** sqlite3_column_text16() is called. A zero-terminator might +** need to be added to the string.
  • +**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or +** sqlite3_column_text16() is called. The content must be converted +** to UTF-16.
  • +**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or +** sqlite3_column_text() is called. The content must be converted +** to UTF-8.
  • +**
+** +** ^Conversions between UTF-16be and UTF-16le are always done in place and do +** not invalidate a prior pointer, though of course the content of the buffer +** that the prior pointer references will have been modified. Other kinds +** of conversion are done in place when it is possible, but sometimes they +** are not possible and in those cases prior pointers are invalidated. +** +** The safest and easiest to remember policy is to invoke these routines +** in one of the following ways: +** +**
    +**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • +**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • +**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • +**
+** +** In other words, you should call sqlite3_column_text(), +** sqlite3_column_blob(), or sqlite3_column_text16() first to force the result +** into the desired format, then invoke sqlite3_column_bytes() or +** sqlite3_column_bytes16() to find the size of the result. Do not mix calls +** to sqlite3_column_text() or sqlite3_column_blob() with calls to +** sqlite3_column_bytes16(), and do not mix calls to sqlite3_column_text16() +** with calls to sqlite3_column_bytes(). +** +** ^The pointers returned are valid until a type conversion occurs as +** described above, or until [sqlite3_step()] or [sqlite3_reset()] or +** [sqlite3_finalize()] is called. ^The memory space used to hold strings +** and BLOBs is freed automatically. Do not pass the pointers returned +** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into +** [sqlite3_free()]. +** +** ^(If a memory allocation error occurs during the evaluation of any +** of these routines, a default value is returned. The default value +** is either the integer 0, the floating point number 0.0, or a NULL +** pointer. Subsequent calls to [sqlite3_errcode()] will return +** [SQLITE_NOMEM].)^ +*/ +SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); +SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); +SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); + +/* +** CAPI3REF: Destroy A Prepared Statement Object +** +** ^The sqlite3_finalize() function is called to delete a [prepared statement]. +** ^If the most recent evaluation of the statement encountered no errors +** or if the statement is never been evaluated, then sqlite3_finalize() returns +** SQLITE_OK. ^If the most recent evaluation of statement S failed, then +** sqlite3_finalize(S) returns the appropriate [error code] or +** [extended error code]. +** +** ^The sqlite3_finalize(S) routine can be called at any point during +** the life cycle of [prepared statement] S: +** before statement S is ever evaluated, after +** one or more calls to [sqlite3_reset()], or after any call +** to [sqlite3_step()] regardless of whether or not the statement has +** completed execution. +** +** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op. +** +** The application must finalize every [prepared statement] in order to avoid +** resource leaks. It is a grievous error for the application to try to use +** a prepared statement after it has been finalized. Any use of a prepared +** statement after it has been finalized can result in undefined and +** undesirable behavior such as segfaults and heap corruption. +*/ +SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Reset A Prepared Statement Object +** +** The sqlite3_reset() function is called to reset a [prepared statement] +** object back to its initial state, ready to be re-executed. +** ^Any SQL statement variables that had values bound to them using +** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. +** Use [sqlite3_clear_bindings()] to reset the bindings. +** +** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S +** back to the beginning of its program. +** +** ^If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], +** or if [sqlite3_step(S)] has never before been called on S, +** then [sqlite3_reset(S)] returns [SQLITE_OK]. +** +** ^If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S indicated an error, then +** [sqlite3_reset(S)] returns an appropriate [error code]. +** +** ^The [sqlite3_reset(S)] interface does not change the values +** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. +*/ +SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Create Or Redefine SQL Functions +** KEYWORDS: {function creation routines} +** KEYWORDS: {application-defined SQL function} +** KEYWORDS: {application-defined SQL functions} +** +** ^These functions (collectively known as "function creation routines") +** are used to add SQL functions or aggregates or to redefine the behavior +** of existing SQL functions or aggregates. The only differences between +** these routines are the text encoding expected for +** the second parameter (the name of the function being created) +** and the presence or absence of a destructor callback for +** the application data pointer. +** +** ^The first parameter is the [database connection] to which the SQL +** function is to be added. ^If an application uses more than one database +** connection then application-defined SQL functions must be added +** to each database connection separately. +** +** ^The second parameter is the name of the SQL function to be created or +** redefined. ^The length of the name is limited to 255 bytes in a UTF-8 +** representation, exclusive of the zero-terminator. ^Note that the name +** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes. +** ^Any attempt to create a function with a longer name +** will result in [SQLITE_MISUSE] being returned. +** +** ^The third parameter (nArg) +** is the number of arguments that the SQL function or +** aggregate takes. ^If this parameter is -1, then the SQL function or +** aggregate may take any number of arguments between 0 and the limit +** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third +** parameter is less than -1 or greater than 127 then the behavior is +** undefined. +** +** ^The fourth parameter, eTextRep, specifies what +** [SQLITE_UTF8 | text encoding] this SQL function prefers for +** its parameters. Every SQL function implementation must be able to work +** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be +** more efficient with one encoding than another. ^An application may +** invoke sqlite3_create_function() or sqlite3_create_function16() multiple +** times with the same function but with different values of eTextRep. +** ^When multiple implementations of the same function are available, SQLite +** will pick the one that involves the least amount of data conversion. +** If there is only a single implementation which does not care what text +** encoding is used, then the fourth argument should be [SQLITE_ANY]. +** +** ^(The fifth parameter is an arbitrary pointer. The implementation of the +** function can gain access to this pointer using [sqlite3_user_data()].)^ +** +** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are +** pointers to C-language functions that implement the SQL function or +** aggregate. ^A scalar SQL function requires an implementation of the xFunc +** callback only; NULL pointers must be passed as the xStep and xFinal +** parameters. ^An aggregate SQL function requires an implementation of xStep +** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing +** SQL function or aggregate, pass NULL pointers for all three function +** callbacks. +** +** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL, +** then it is destructor for the application data pointer. +** The destructor is invoked when the function is deleted, either by being +** overloaded or when the database connection closes.)^ +** ^The destructor is also invoked if the call to +** sqlite3_create_function_v2() fails. +** ^When the destructor callback of the tenth parameter is invoked, it +** is passed a single argument which is a copy of the application data +** pointer which was the fifth parameter to sqlite3_create_function_v2(). +** +** ^It is permitted to register multiple implementations of the same +** functions with the same name but with either differing numbers of +** arguments or differing preferred text encodings. ^SQLite will use +** the implementation that most closely matches the way in which the +** SQL function is used. ^A function implementation with a non-negative +** nArg parameter is a better match than a function implementation with +** a negative nArg. ^A function where the preferred text encoding +** matches the database encoding is a better +** match than a function where the encoding is different. +** ^A function where the encoding difference is between UTF16le and UTF16be +** is a closer match than a function where the encoding difference is +** between UTF8 and UTF16. +** +** ^Built-in functions may be overloaded by new application-defined functions. +** +** ^An application-defined function is permitted to call other +** SQLite interfaces. However, such calls must not +** close the database connection nor finalize or reset the prepared +** statement in which the function is running. +*/ +SQLITE_API int sqlite3_create_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +SQLITE_API int sqlite3_create_function16( + sqlite3 *db, + const void *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +SQLITE_API int sqlite3_create_function_v2( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*), + void(*xDestroy)(void*) +); + +/* +** CAPI3REF: Text Encodings +** +** These constant define integer codes that represent the various +** text encodings supported by SQLite. +*/ +#define SQLITE_UTF8 1 +#define SQLITE_UTF16LE 2 +#define SQLITE_UTF16BE 3 +#define SQLITE_UTF16 4 /* Use native byte order */ +#define SQLITE_ANY 5 /* sqlite3_create_function only */ +#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ + +/* +** CAPI3REF: Deprecated Functions +** DEPRECATED +** +** These functions are [deprecated]. In order to maintain +** backwards compatibility with older code, these functions continue +** to be supported. However, new applications should avoid +** the use of these functions. To help encourage people to avoid +** using these functions, we are not going to tell you what they do. +*/ +#ifndef SQLITE_OMIT_DEPRECATED +SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); +SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); +SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), + void*,sqlite3_int64); +#endif + +/* +** CAPI3REF: Obtaining SQL Function Parameter Values +** +** The C-language implementation of SQL functions and aggregates uses +** this set of interface routines to access the parameter values on +** the function or aggregate. +** +** The xFunc (for scalar functions) or xStep (for aggregates) parameters +** to [sqlite3_create_function()] and [sqlite3_create_function16()] +** define callbacks that implement the SQL functions and aggregates. +** The 3rd parameter to these callbacks is an array of pointers to +** [protected sqlite3_value] objects. There is one [sqlite3_value] object for +** each parameter to the SQL function. These routines are used to +** extract values from the [sqlite3_value] objects. +** +** These routines work only with [protected sqlite3_value] objects. +** Any attempt to use these routines on an [unprotected sqlite3_value] +** object results in undefined behavior. +** +** ^These routines work just like the corresponding [column access functions] +** except that these routines take a single [protected sqlite3_value] object +** pointer instead of a [sqlite3_stmt*] pointer and an integer column number. +** +** ^The sqlite3_value_text16() interface extracts a UTF-16 string +** in the native byte-order of the host machine. ^The +** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces +** extract UTF-16 strings as big-endian and little-endian respectively. +** +** ^(The sqlite3_value_numeric_type() interface attempts to apply +** numeric affinity to the value. This means that an attempt is +** made to convert the value to an integer or floating point. If +** such a conversion is possible without loss of information (in other +** words, if the value is a string that looks like a number) +** then the conversion is performed. Otherwise no conversion occurs. +** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ +** +** Please pay particular attention to the fact that the pointer returned +** from [sqlite3_value_blob()], [sqlite3_value_text()], or +** [sqlite3_value_text16()] can be invalidated by a subsequent call to +** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], +** or [sqlite3_value_text16()]. +** +** These routines must be called from the same thread as +** the SQL function that supplied the [sqlite3_value*] parameters. +*/ +SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); +SQLITE_API double sqlite3_value_double(sqlite3_value*); +SQLITE_API int sqlite3_value_int(sqlite3_value*); +SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); +SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); +SQLITE_API int sqlite3_value_type(sqlite3_value*); +SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); + +/* +** CAPI3REF: Obtain Aggregate Function Context +** +** Implementations of aggregate SQL functions use this +** routine to allocate memory for storing their state. +** +** ^The first time the sqlite3_aggregate_context(C,N) routine is called +** for a particular aggregate function, SQLite +** allocates N of memory, zeroes out that memory, and returns a pointer +** to the new memory. ^On second and subsequent calls to +** sqlite3_aggregate_context() for the same aggregate function instance, +** the same buffer is returned. Sqlite3_aggregate_context() is normally +** called once for each invocation of the xStep callback and then one +** last time when the xFinal callback is invoked. ^(When no rows match +** an aggregate query, the xStep() callback of the aggregate function +** implementation is never called and xFinal() is called exactly once. +** In those cases, sqlite3_aggregate_context() might be called for the +** first time from within xFinal().)^ +** +** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer +** when first called if N is less than or equal to zero or if a memory +** allocate error occurs. +** +** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is +** determined by the N parameter on first successful call. Changing the +** value of N in subsequent call to sqlite3_aggregate_context() within +** the same aggregate function instance will not resize the memory +** allocation.)^ Within the xFinal callback, it is customary to set +** N=0 in calls to sqlite3_aggregate_context(C,N) so that no +** pointless memory allocations occur. +** +** ^SQLite automatically frees the memory allocated by +** sqlite3_aggregate_context() when the aggregate query concludes. +** +** The first parameter must be a copy of the +** [sqlite3_context | SQL function context] that is the first parameter +** to the xStep or xFinal callback routine that implements the aggregate +** function. +** +** This routine must be called from the same thread in which +** the aggregate SQL function is running. +*/ +SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); + +/* +** CAPI3REF: User Data For Functions +** +** ^The sqlite3_user_data() interface returns a copy of +** the pointer that was the pUserData parameter (the 5th parameter) +** of the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. +** +** This routine must be called from the same thread in which +** the application-defined function is running. +*/ +SQLITE_API void *sqlite3_user_data(sqlite3_context*); + +/* +** CAPI3REF: Database Connection For Functions +** +** ^The sqlite3_context_db_handle() interface returns a copy of +** the pointer to the [database connection] (the 1st parameter) +** of the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. +*/ +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); + +/* +** CAPI3REF: Function Auxiliary Data +** +** These functions may be used by (non-aggregate) SQL functions to +** associate metadata with argument values. If the same value is passed to +** multiple invocations of the same SQL function during query execution, under +** some circumstances the associated metadata may be preserved. An example +** of where this might be useful is in a regular-expression matching +** function. The compiled version of the regular expression can be stored as +** metadata associated with the pattern string. +** Then as long as the pattern string remains the same, +** the compiled regular expression can be reused on multiple +** invocations of the same function. +** +** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata +** associated by the sqlite3_set_auxdata() function with the Nth argument +** value to the application-defined function. ^If there is no metadata +** associated with the function argument, this sqlite3_get_auxdata() interface +** returns a NULL pointer. +** +** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th +** argument of the application-defined function. ^Subsequent +** calls to sqlite3_get_auxdata(C,N) return P from the most recent +** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or +** NULL if the metadata has been discarded. +** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL, +** SQLite will invoke the destructor function X with parameter P exactly +** once, when the metadata is discarded. +** SQLite is free to discard the metadata at any time, including:
    +**
  • when the corresponding function parameter changes, or +**
  • when [sqlite3_reset()] or [sqlite3_finalize()] is called for the +** SQL statement, or +**
  • when sqlite3_set_auxdata() is invoked again on the same parameter, or +**
  • during the original sqlite3_set_auxdata() call when a memory +** allocation error occurs.
)^ +** +** Note the last bullet in particular. The destructor X in +** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the +** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata() +** should be called near the end of the function implementation and the +** function implementation should not make any use of P after +** sqlite3_set_auxdata() has been called. +** +** ^(In practice, metadata is preserved between function calls for +** function parameters that are compile-time constants, including literal +** values and [parameters] and expressions composed from the same.)^ +** +** These routines must be called from the same thread in which +** the SQL function is running. +*/ +SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); +SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); + + +/* +** CAPI3REF: Constants Defining Special Destructor Behavior +** +** These are special values for the destructor that is passed in as the +** final argument to routines like [sqlite3_result_blob()]. ^If the destructor +** argument is SQLITE_STATIC, it means that the content pointer is constant +** and will never change. It does not need to be destroyed. ^The +** SQLITE_TRANSIENT value means that the content will likely change in +** the near future and that SQLite should make its own private copy of +** the content before returning. +** +** The typedef is necessary to work around problems in certain +** C++ compilers. +*/ +typedef void (*sqlite3_destructor_type)(void*); +#define SQLITE_STATIC ((sqlite3_destructor_type)0) +#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) + +/* +** CAPI3REF: Setting The Result Of An SQL Function +** +** These routines are used by the xFunc or xFinal callbacks that +** implement SQL functions and aggregates. See +** [sqlite3_create_function()] and [sqlite3_create_function16()] +** for additional information. +** +** These functions work very much like the [parameter binding] family of +** functions used to bind values to host parameters in prepared statements. +** Refer to the [SQL parameter] documentation for additional information. +** +** ^The sqlite3_result_blob() interface sets the result from +** an application-defined function to be the BLOB whose content is pointed +** to by the second parameter and which is N bytes long where N is the +** third parameter. +** +** ^The sqlite3_result_zeroblob() interfaces set the result of +** the application-defined function to be a BLOB containing all zero +** bytes and N bytes in size, where N is the value of the 2nd parameter. +** +** ^The sqlite3_result_double() interface sets the result from +** an application-defined function to be a floating point value specified +** by its 2nd argument. +** +** ^The sqlite3_result_error() and sqlite3_result_error16() functions +** cause the implemented SQL function to throw an exception. +** ^SQLite uses the string pointed to by the +** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() +** as the text of an error message. ^SQLite interprets the error +** message string from sqlite3_result_error() as UTF-8. ^SQLite +** interprets the string from sqlite3_result_error16() as UTF-16 in native +** byte order. ^If the third parameter to sqlite3_result_error() +** or sqlite3_result_error16() is negative then SQLite takes as the error +** message all text up through the first zero character. +** ^If the third parameter to sqlite3_result_error() or +** sqlite3_result_error16() is non-negative then SQLite takes that many +** bytes (not characters) from the 2nd parameter as the error message. +** ^The sqlite3_result_error() and sqlite3_result_error16() +** routines make a private copy of the error message text before +** they return. Hence, the calling function can deallocate or +** modify the text after they return without harm. +** ^The sqlite3_result_error_code() function changes the error code +** returned by SQLite as a result of an error in a function. ^By default, +** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error() +** or sqlite3_result_error16() resets the error code to SQLITE_ERROR. +** +** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an +** error indicating that a string or BLOB is too long to represent. +** +** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an +** error indicating that a memory allocation failed. +** +** ^The sqlite3_result_int() interface sets the return value +** of the application-defined function to be the 32-bit signed integer +** value given in the 2nd argument. +** ^The sqlite3_result_int64() interface sets the return value +** of the application-defined function to be the 64-bit signed integer +** value given in the 2nd argument. +** +** ^The sqlite3_result_null() interface sets the return value +** of the application-defined function to be NULL. +** +** ^The sqlite3_result_text(), sqlite3_result_text16(), +** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces +** set the return value of the application-defined function to be +** a text string which is represented as UTF-8, UTF-16 native byte order, +** UTF-16 little endian, or UTF-16 big endian, respectively. +** ^SQLite takes the text result from the application from +** the 2nd parameter of the sqlite3_result_text* interfaces. +** ^If the 3rd parameter to the sqlite3_result_text* interfaces +** is negative, then SQLite takes result text from the 2nd parameter +** through the first zero character. +** ^If the 3rd parameter to the sqlite3_result_text* interfaces +** is non-negative, then as many bytes (not characters) of the text +** pointed to by the 2nd parameter are taken as the application-defined +** function result. If the 3rd parameter is non-negative, then it +** must be the byte offset into the string where the NUL terminator would +** appear if the string where NUL terminated. If any NUL characters occur +** in the string at a byte offset that is less than the value of the 3rd +** parameter, then the resulting string will contain embedded NULs and the +** result of expressions operating on strings with embedded NULs is undefined. +** ^If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that +** function as the destructor on the text or BLOB result when it has +** finished using that result. +** ^If the 4th parameter to the sqlite3_result_text* interfaces or to +** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite +** assumes that the text or BLOB result is in constant space and does not +** copy the content of the parameter nor call a destructor on the content +** when it has finished using that result. +** ^If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT +** then SQLite makes a copy of the result into space obtained from +** from [sqlite3_malloc()] before it returns. +** +** ^The sqlite3_result_value() interface sets the result of +** the application-defined function to be a copy the +** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The +** sqlite3_result_value() interface makes a copy of the [sqlite3_value] +** so that the [sqlite3_value] specified in the parameter may change or +** be deallocated after sqlite3_result_value() returns without harm. +** ^A [protected sqlite3_value] object may always be used where an +** [unprotected sqlite3_value] object is required, so either +** kind of [sqlite3_value] object can be used with this interface. +** +** If these routines are called from within the different thread +** than the one containing the application-defined function that received +** the [sqlite3_context] pointer, the results are undefined. +*/ +SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_double(sqlite3_context*, double); +SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); +SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); +SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); +SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); +SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +SQLITE_API void sqlite3_result_null(sqlite3_context*); +SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); + +/* +** CAPI3REF: Define New Collating Sequences +** +** ^These functions add, remove, or modify a [collation] associated +** with the [database connection] specified as the first argument. +** +** ^The name of the collation is a UTF-8 string +** for sqlite3_create_collation() and sqlite3_create_collation_v2() +** and a UTF-16 string in native byte order for sqlite3_create_collation16(). +** ^Collation names that compare equal according to [sqlite3_strnicmp()] are +** considered to be the same name. +** +** ^(The third argument (eTextRep) must be one of the constants: +**
    +**
  • [SQLITE_UTF8], +**
  • [SQLITE_UTF16LE], +**
  • [SQLITE_UTF16BE], +**
  • [SQLITE_UTF16], or +**
  • [SQLITE_UTF16_ALIGNED]. +**
)^ +** ^The eTextRep argument determines the encoding of strings passed +** to the collating function callback, xCallback. +** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep +** force strings to be UTF16 with native byte order. +** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin +** on an even byte address. +** +** ^The fourth argument, pArg, is an application data pointer that is passed +** through as the first argument to the collating function callback. +** +** ^The fifth argument, xCallback, is a pointer to the collating function. +** ^Multiple collating functions can be registered using the same name but +** with different eTextRep parameters and SQLite will use whichever +** function requires the least amount of data transformation. +** ^If the xCallback argument is NULL then the collating function is +** deleted. ^When all collating functions having the same name are deleted, +** that collation is no longer usable. +** +** ^The collating function callback is invoked with a copy of the pArg +** application data pointer and with two strings in the encoding specified +** by the eTextRep argument. The collating function must return an +** integer that is negative, zero, or positive +** if the first string is less than, equal to, or greater than the second, +** respectively. A collating function must always return the same answer +** given the same inputs. If two or more collating functions are registered +** to the same collation name (using different eTextRep values) then all +** must give an equivalent answer when invoked with equivalent strings. +** The collating function must obey the following properties for all +** strings A, B, and C: +** +**
    +**
  1. If A==B then B==A. +**
  2. If A==B and B==C then A==C. +**
  3. If A<B THEN B>A. +**
  4. If A<B and B<C then A<C. +**
+** +** If a collating function fails any of the above constraints and that +** collating function is registered and used, then the behavior of SQLite +** is undefined. +** +** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation() +** with the addition that the xDestroy callback is invoked on pArg when +** the collating function is deleted. +** ^Collating functions are deleted when they are overridden by later +** calls to the collation creation functions or when the +** [database connection] is closed using [sqlite3_close()]. +** +** ^The xDestroy callback is not called if the +** sqlite3_create_collation_v2() function fails. Applications that invoke +** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should +** check the return code and dispose of the application data pointer +** themselves rather than expecting SQLite to deal with it for them. +** This is different from every other SQLite interface. The inconsistency +** is unfortunate but cannot be changed without breaking backwards +** compatibility. +** +** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. +*/ +SQLITE_API int sqlite3_create_collation( + sqlite3*, + const char *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*) +); +SQLITE_API int sqlite3_create_collation_v2( + sqlite3*, + const char *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDestroy)(void*) +); +SQLITE_API int sqlite3_create_collation16( + sqlite3*, + const void *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*) +); + +/* +** CAPI3REF: Collation Needed Callbacks +** +** ^To avoid having to register all collation sequences before a database +** can be used, a single callback function may be registered with the +** [database connection] to be invoked whenever an undefined collation +** sequence is required. +** +** ^If the function is registered using the sqlite3_collation_needed() API, +** then it is passed the names of undefined collation sequences as strings +** encoded in UTF-8. ^If sqlite3_collation_needed16() is used, +** the names are passed as UTF-16 in machine native byte order. +** ^A call to either function replaces the existing collation-needed callback. +** +** ^(When the callback is invoked, the first argument passed is a copy +** of the second argument to sqlite3_collation_needed() or +** sqlite3_collation_needed16(). The second argument is the database +** connection. The third argument is one of [SQLITE_UTF8], [SQLITE_UTF16BE], +** or [SQLITE_UTF16LE], indicating the most desirable form of the collation +** sequence function required. The fourth parameter is the name of the +** required collation sequence.)^ +** +** The callback function should register the desired collation using +** [sqlite3_create_collation()], [sqlite3_create_collation16()], or +** [sqlite3_create_collation_v2()]. +*/ +SQLITE_API int sqlite3_collation_needed( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const char*) +); +SQLITE_API int sqlite3_collation_needed16( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const void*) +); + +#ifdef SQLITE_HAS_CODEC +/* +** Specify the key for an encrypted database. This routine should be +** called right after sqlite3_open(). +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +SQLITE_API int sqlite3_key( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The key */ +); +SQLITE_API int sqlite3_key_v2( + sqlite3 *db, /* Database to be rekeyed */ + const char *zDbName, /* Name of the database */ + const void *pKey, int nKey /* The key */ +); + +/* +** Change the key on an open database. If the current database is not +** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the +** database is decrypted. +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +SQLITE_API int sqlite3_rekey( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The new key */ +); +SQLITE_API int sqlite3_rekey_v2( + sqlite3 *db, /* Database to be rekeyed */ + const char *zDbName, /* Name of the database */ + const void *pKey, int nKey /* The new key */ +); + +/* +** Specify the activation key for a SEE database. Unless +** activated, none of the SEE routines will work. +*/ +SQLITE_API void sqlite3_activate_see( + const char *zPassPhrase /* Activation phrase */ +); +#endif + +#ifdef SQLITE_ENABLE_CEROD +/* +** Specify the activation key for a CEROD database. Unless +** activated, none of the CEROD routines will work. +*/ +SQLITE_API void sqlite3_activate_cerod( + const char *zPassPhrase /* Activation phrase */ +); +#endif + +/* +** CAPI3REF: Suspend Execution For A Short Time +** +** The sqlite3_sleep() function causes the current thread to suspend execution +** for at least a number of milliseconds specified in its parameter. +** +** If the operating system does not support sleep requests with +** millisecond time resolution, then the time will be rounded up to +** the nearest second. The number of milliseconds of sleep actually +** requested from the operating system is returned. +** +** ^SQLite implements this interface by calling the xSleep() +** method of the default [sqlite3_vfs] object. If the xSleep() method +** of the default VFS is not implemented correctly, or not implemented at +** all, then the behavior of sqlite3_sleep() may deviate from the description +** in the previous paragraphs. +*/ +SQLITE_API int sqlite3_sleep(int); + +/* +** CAPI3REF: Name Of The Folder Holding Temporary Files +** +** ^(If this global variable is made to point to a string which is +** the name of a folder (a.k.a. directory), then all temporary files +** created by SQLite when using a built-in [sqlite3_vfs | VFS] +** will be placed in that directory.)^ ^If this variable +** is a NULL pointer, then SQLite performs a search for an appropriate +** temporary file directory. +** +** It is not safe to read or modify this variable in more than one +** thread at a time. It is not safe to read or modify this variable +** if a [database connection] is being used at the same time in a separate +** thread. +** It is intended that this variable be set once +** as part of process initialization and before any SQLite interface +** routines have been called and that this variable remain unchanged +** thereafter. +** +** ^The [temp_store_directory pragma] may modify this variable and cause +** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, +** the [temp_store_directory pragma] always assumes that any string +** that this variable points to is held in memory obtained from +** [sqlite3_malloc] and the pragma may attempt to free that memory +** using [sqlite3_free]. +** Hence, if this variable is modified directly, either it should be +** made NULL or made to point to memory obtained from [sqlite3_malloc] +** or else the use of the [temp_store_directory pragma] should be avoided. +** +** Note to Windows Runtime users: The temporary directory must be set +** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various +** features that require the use of temporary files may fail. Here is an +** example of how to do this using C++ with the Windows Runtime: +** +**
+** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->
+**       TemporaryFolder->Path->Data();
+** char zPathBuf[MAX_PATH + 1];
+** memset(zPathBuf, 0, sizeof(zPathBuf));
+** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),
+**       NULL, NULL);
+** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);
+** 
+*/ +SQLITE_API SQLITE_EXTERN char *sqlite3_temp_directory; + +/* +** CAPI3REF: Name Of The Folder Holding Database Files +** +** ^(If this global variable is made to point to a string which is +** the name of a folder (a.k.a. directory), then all database files +** specified with a relative pathname and created or accessed by +** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed +** to be relative to that directory.)^ ^If this variable is a NULL +** pointer, then SQLite assumes that all database files specified +** with a relative pathname are relative to the current directory +** for the process. Only the windows VFS makes use of this global +** variable; it is ignored by the unix VFS. +** +** Changing the value of this variable while a database connection is +** open can result in a corrupt database. +** +** It is not safe to read or modify this variable in more than one +** thread at a time. It is not safe to read or modify this variable +** if a [database connection] is being used at the same time in a separate +** thread. +** It is intended that this variable be set once +** as part of process initialization and before any SQLite interface +** routines have been called and that this variable remain unchanged +** thereafter. +** +** ^The [data_store_directory pragma] may modify this variable and cause +** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, +** the [data_store_directory pragma] always assumes that any string +** that this variable points to is held in memory obtained from +** [sqlite3_malloc] and the pragma may attempt to free that memory +** using [sqlite3_free]. +** Hence, if this variable is modified directly, either it should be +** made NULL or made to point to memory obtained from [sqlite3_malloc] +** or else the use of the [data_store_directory pragma] should be avoided. +*/ +SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory; + +/* +** CAPI3REF: Test For Auto-Commit Mode +** KEYWORDS: {autocommit mode} +** +** ^The sqlite3_get_autocommit() interface returns non-zero or +** zero if the given database connection is or is not in autocommit mode, +** respectively. ^Autocommit mode is on by default. +** ^Autocommit mode is disabled by a [BEGIN] statement. +** ^Autocommit mode is re-enabled by a [COMMIT] or [ROLLBACK]. +** +** If certain kinds of errors occur on a statement within a multi-statement +** transaction (errors including [SQLITE_FULL], [SQLITE_IOERR], +** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the +** transaction might be rolled back automatically. The only way to +** find out whether SQLite automatically rolled back the transaction after +** an error is to use this function. +** +** If another thread changes the autocommit status of the database +** connection while this routine is running, then the return value +** is undefined. +*/ +SQLITE_API int sqlite3_get_autocommit(sqlite3*); + +/* +** CAPI3REF: Find The Database Handle Of A Prepared Statement +** +** ^The sqlite3_db_handle interface returns the [database connection] handle +** to which a [prepared statement] belongs. ^The [database connection] +** returned by sqlite3_db_handle is the same [database connection] +** that was the first argument +** to the [sqlite3_prepare_v2()] call (or its variants) that was used to +** create the statement in the first place. +*/ +SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); + +/* +** CAPI3REF: Return The Filename For A Database Connection +** +** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename +** associated with database N of connection D. ^The main database file +** has the name "main". If there is no attached database N on the database +** connection D, or if database N is a temporary or in-memory database, then +** a NULL pointer is returned. +** +** ^The filename returned by this function is the output of the +** xFullPathname method of the [VFS]. ^In other words, the filename +** will be an absolute pathname, even if the filename used +** to open the database originally was a URI or relative pathname. +*/ +SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); + +/* +** CAPI3REF: Determine if a database is read-only +** +** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N +** of connection D is read-only, 0 if it is read/write, or -1 if N is not +** the name of a database on connection D. +*/ +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); + +/* +** CAPI3REF: Find the next prepared statement +** +** ^This interface returns a pointer to the next [prepared statement] after +** pStmt associated with the [database connection] pDb. ^If pStmt is NULL +** then this interface returns a pointer to the first prepared statement +** associated with the database connection pDb. ^If no prepared statement +** satisfies the conditions of this routine, it returns NULL. +** +** The [database connection] pointer D in a call to +** [sqlite3_next_stmt(D,S)] must refer to an open database +** connection and in particular must not be a NULL pointer. +*/ +SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Commit And Rollback Notification Callbacks +** +** ^The sqlite3_commit_hook() interface registers a callback +** function to be invoked whenever a transaction is [COMMIT | committed]. +** ^Any callback set by a previous call to sqlite3_commit_hook() +** for the same database connection is overridden. +** ^The sqlite3_rollback_hook() interface registers a callback +** function to be invoked whenever a transaction is [ROLLBACK | rolled back]. +** ^Any callback set by a previous call to sqlite3_rollback_hook() +** for the same database connection is overridden. +** ^The pArg argument is passed through to the callback. +** ^If the callback on a commit hook function returns non-zero, +** then the commit is converted into a rollback. +** +** ^The sqlite3_commit_hook(D,C,P) and sqlite3_rollback_hook(D,C,P) functions +** return the P argument from the previous call of the same function +** on the same [database connection] D, or NULL for +** the first call for each function on D. +** +** The commit and rollback hook callbacks are not reentrant. +** The callback implementation must not do anything that will modify +** the database connection that invoked the callback. Any actions +** to modify the database connection must be deferred until after the +** completion of the [sqlite3_step()] call that triggered the commit +** or rollback hook in the first place. +** Note that running any other SQL statements, including SELECT statements, +** or merely calling [sqlite3_prepare_v2()] and [sqlite3_step()] will modify +** the database connections for the meaning of "modify" in this paragraph. +** +** ^Registering a NULL function disables the callback. +** +** ^When the commit hook callback routine returns zero, the [COMMIT] +** operation is allowed to continue normally. ^If the commit hook +** returns non-zero, then the [COMMIT] is converted into a [ROLLBACK]. +** ^The rollback hook is invoked on a rollback that results from a commit +** hook returning non-zero, just as it would be with any other rollback. +** +** ^For the purposes of this API, a transaction is said to have been +** rolled back if an explicit "ROLLBACK" statement is executed, or +** an error or constraint causes an implicit rollback to occur. +** ^The rollback callback is not invoked if a transaction is +** automatically rolled back because the database connection is closed. +** +** See also the [sqlite3_update_hook()] interface. +*/ +SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); + +/* +** CAPI3REF: Data Change Notification Callbacks +** +** ^The sqlite3_update_hook() interface registers a callback function +** with the [database connection] identified by the first argument +** to be invoked whenever a row is updated, inserted or deleted. +** ^Any callback set by a previous call to this function +** for the same database connection is overridden. +** +** ^The second argument is a pointer to the function to invoke when a +** row is updated, inserted or deleted. +** ^The first argument to the callback is a copy of the third argument +** to sqlite3_update_hook(). +** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE], +** or [SQLITE_UPDATE], depending on the operation that caused the callback +** to be invoked. +** ^The third and fourth arguments to the callback contain pointers to the +** database and table name containing the affected row. +** ^The final callback parameter is the [rowid] of the row. +** ^In the case of an update, this is the [rowid] after the update takes place. +** +** ^(The update hook is not invoked when internal system tables are +** modified (i.e. sqlite_master and sqlite_sequence).)^ +** +** ^In the current implementation, the update hook +** is not invoked when duplication rows are deleted because of an +** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook +** invoked when rows are deleted using the [truncate optimization]. +** The exceptions defined in this paragraph might change in a future +** release of SQLite. +** +** The update hook implementation must not do anything that will modify +** the database connection that invoked the update hook. Any actions +** to modify the database connection must be deferred until after the +** completion of the [sqlite3_step()] call that triggered the update hook. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +** ^The sqlite3_update_hook(D,C,P) function +** returns the P argument from the previous call +** on the same [database connection] D, or NULL for +** the first call on D. +** +** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()] +** interfaces. +*/ +SQLITE_API void *sqlite3_update_hook( + sqlite3*, + void(*)(void *,int ,char const *,char const *,sqlite3_int64), + void* +); + +/* +** CAPI3REF: Enable Or Disable Shared Pager Cache +** +** ^(This routine enables or disables the sharing of the database cache +** and schema data structures between [database connection | connections] +** to the same database. Sharing is enabled if the argument is true +** and disabled if the argument is false.)^ +** +** ^Cache sharing is enabled and disabled for an entire process. +** This is a change as of SQLite version 3.5.0. In prior versions of SQLite, +** sharing was enabled or disabled for each thread separately. +** +** ^(The cache sharing mode set by this interface effects all subsequent +** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. +** Existing database connections continue use the sharing mode +** that was in effect at the time they were opened.)^ +** +** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled +** successfully. An [error code] is returned otherwise.)^ +** +** ^Shared cache is disabled by default. But this might change in +** future releases of SQLite. Applications that care about shared +** cache setting should set it explicitly. +** +** This interface is threadsafe on processors where writing a +** 32-bit integer is atomic. +** +** See Also: [SQLite Shared-Cache Mode] +*/ +SQLITE_API int sqlite3_enable_shared_cache(int); + +/* +** CAPI3REF: Attempt To Free Heap Memory +** +** ^The sqlite3_release_memory() interface attempts to free N bytes +** of heap memory by deallocating non-essential memory allocations +** held by the database library. Memory used to cache database +** pages to improve performance is an example of non-essential memory. +** ^sqlite3_release_memory() returns the number of bytes actually freed, +** which might be more or less than the amount requested. +** ^The sqlite3_release_memory() routine is a no-op returning zero +** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT]. +** +** See also: [sqlite3_db_release_memory()] +*/ +SQLITE_API int sqlite3_release_memory(int); + +/* +** CAPI3REF: Free Memory Used By A Database Connection +** +** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap +** memory as possible from database connection D. Unlike the +** [sqlite3_release_memory()] interface, this interface is effect even +** when then [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is +** omitted. +** +** See also: [sqlite3_release_memory()] +*/ +SQLITE_API int sqlite3_db_release_memory(sqlite3*); + +/* +** CAPI3REF: Impose A Limit On Heap Size +** +** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the +** soft limit on the amount of heap memory that may be allocated by SQLite. +** ^SQLite strives to keep heap memory utilization below the soft heap +** limit by reducing the number of pages held in the page cache +** as heap memory usages approaches the limit. +** ^The soft heap limit is "soft" because even though SQLite strives to stay +** below the limit, it will exceed the limit rather than generate +** an [SQLITE_NOMEM] error. In other words, the soft heap limit +** is advisory only. +** +** ^The return value from sqlite3_soft_heap_limit64() is the size of +** the soft heap limit prior to the call, or negative in the case of an +** error. ^If the argument N is negative +** then no change is made to the soft heap limit. Hence, the current +** size of the soft heap limit can be determined by invoking +** sqlite3_soft_heap_limit64() with a negative argument. +** +** ^If the argument N is zero then the soft heap limit is disabled. +** +** ^(The soft heap limit is not enforced in the current implementation +** if one or more of following conditions are true: +** +**
    +**
  • The soft heap limit is set to zero. +**
  • Memory accounting is disabled using a combination of the +** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and +** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option. +**
  • An alternative page cache implementation is specified using +** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...). +**
  • The page cache allocates from its own memory pool supplied +** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than +** from the heap. +**
)^ +** +** Beginning with SQLite version 3.7.3, the soft heap limit is enforced +** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT] +** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT], +** the soft heap limit is enforced on every memory allocation. Without +** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced +** when memory is allocated by the page cache. Testing suggests that because +** the page cache is the predominate memory user in SQLite, most +** applications will achieve adequate soft heap limit enforcement without +** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT]. +** +** The circumstances under which SQLite will enforce the soft heap limit may +** changes in future releases of SQLite. +*/ +SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); + +/* +** CAPI3REF: Deprecated Soft Heap Limit Interface +** DEPRECATED +** +** This is a deprecated version of the [sqlite3_soft_heap_limit64()] +** interface. This routine is provided for historical compatibility +** only. All new applications should use the +** [sqlite3_soft_heap_limit64()] interface rather than this one. +*/ +SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); + + +/* +** CAPI3REF: Extract Metadata About A Column Of A Table +** +** ^This routine returns metadata about a specific column of a specific +** database table accessible using the [database connection] handle +** passed as the first function argument. +** +** ^The column is identified by the second, third and fourth parameters to +** this function. ^The second parameter is either the name of the database +** (i.e. "main", "temp", or an attached database) containing the specified +** table or NULL. ^If it is NULL, then all attached databases are searched +** for the table using the same algorithm used by the database engine to +** resolve unqualified table references. +** +** ^The third and fourth parameters to this function are the table and column +** name of the desired column, respectively. Neither of these parameters +** may be NULL. +** +** ^Metadata is returned by writing to the memory locations passed as the 5th +** and subsequent parameters to this function. ^Any of these arguments may be +** NULL, in which case the corresponding element of metadata is omitted. +** +** ^(
+** +**
Parameter Output
Type
Description +** +**
5th const char* Data type +**
6th const char* Name of default collation sequence +**
7th int True if column has a NOT NULL constraint +**
8th int True if column is part of the PRIMARY KEY +**
9th int True if column is [AUTOINCREMENT] +**
+**
)^ +** +** ^The memory pointed to by the character pointers returned for the +** declaration type and collation sequence is valid only until the next +** call to any SQLite API function. +** +** ^If the specified table is actually a view, an [error code] is returned. +** +** ^If the specified column is "rowid", "oid" or "_rowid_" and an +** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output +** parameters are set for the explicitly declared column. ^(If there is no +** explicitly declared [INTEGER PRIMARY KEY] column, then the output +** parameters are set as follows: +** +**
+**     data type: "INTEGER"
+**     collation sequence: "BINARY"
+**     not null: 0
+**     primary key: 1
+**     auto increment: 0
+** 
)^ +** +** ^(This function may load one or more schemas from database files. If an +** error occurs during this process, or if the requested table or column +** cannot be found, an [error code] is returned and an error message left +** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^ +** +** ^This API is only available if the library was compiled with the +** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. +*/ +SQLITE_API int sqlite3_table_column_metadata( + sqlite3 *db, /* Connection handle */ + const char *zDbName, /* Database name or NULL */ + const char *zTableName, /* Table name */ + const char *zColumnName, /* Column name */ + char const **pzDataType, /* OUTPUT: Declared data type */ + char const **pzCollSeq, /* OUTPUT: Collation sequence name */ + int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ + int *pPrimaryKey, /* OUTPUT: True if column part of PK */ + int *pAutoinc /* OUTPUT: True if column is auto-increment */ +); + +/* +** CAPI3REF: Load An Extension +** +** ^This interface loads an SQLite extension library from the named file. +** +** ^The sqlite3_load_extension() interface attempts to load an +** [SQLite extension] library contained in the file zFile. If +** the file cannot be loaded directly, attempts are made to load +** with various operating-system specific extensions added. +** So for example, if "samplelib" cannot be loaded, then names like +** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might +** be tried also. +** +** ^The entry point is zProc. +** ^(zProc may be 0, in which case SQLite will try to come up with an +** entry point name on its own. It first tries "sqlite3_extension_init". +** If that does not work, it constructs a name "sqlite3_X_init" where the +** X is consists of the lower-case equivalent of all ASCII alphabetic +** characters in the filename from the last "/" to the first following +** "." and omitting any initial "lib".)^ +** ^The sqlite3_load_extension() interface returns +** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. +** ^If an error occurs and pzErrMsg is not 0, then the +** [sqlite3_load_extension()] interface shall attempt to +** fill *pzErrMsg with error message text stored in memory +** obtained from [sqlite3_malloc()]. The calling function +** should free this memory by calling [sqlite3_free()]. +** +** ^Extension loading must be enabled using +** [sqlite3_enable_load_extension()] prior to calling this API, +** otherwise an error will be returned. +** +** See also the [load_extension() SQL function]. +*/ +SQLITE_API int sqlite3_load_extension( + sqlite3 *db, /* Load the extension into this database connection */ + const char *zFile, /* Name of the shared library containing extension */ + const char *zProc, /* Entry point. Derived from zFile if 0 */ + char **pzErrMsg /* Put error message here if not 0 */ +); + +/* +** CAPI3REF: Enable Or Disable Extension Loading +** +** ^So as not to open security holes in older applications that are +** unprepared to deal with [extension loading], and as a means of disabling +** [extension loading] while evaluating user-entered SQL, the following API +** is provided to turn the [sqlite3_load_extension()] mechanism on and off. +** +** ^Extension loading is off by default. +** ^Call the sqlite3_enable_load_extension() routine with onoff==1 +** to turn extension loading on and call it with onoff==0 to turn +** it back off again. +*/ +SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); + +/* +** CAPI3REF: Automatically Load Statically Linked Extensions +** +** ^This interface causes the xEntryPoint() function to be invoked for +** each new [database connection] that is created. The idea here is that +** xEntryPoint() is the entry point for a statically linked [SQLite extension] +** that is to be automatically loaded into all new database connections. +** +** ^(Even though the function prototype shows that xEntryPoint() takes +** no arguments and returns void, SQLite invokes xEntryPoint() with three +** arguments and expects and integer result as if the signature of the +** entry point where as follows: +** +**
+**    int xEntryPoint(
+**      sqlite3 *db,
+**      const char **pzErrMsg,
+**      const struct sqlite3_api_routines *pThunk
+**    );
+** 
)^ +** +** If the xEntryPoint routine encounters an error, it should make *pzErrMsg +** point to an appropriate error message (obtained from [sqlite3_mprintf()]) +** and return an appropriate [error code]. ^SQLite ensures that *pzErrMsg +** is NULL before calling the xEntryPoint(). ^SQLite will invoke +** [sqlite3_free()] on *pzErrMsg after xEntryPoint() returns. ^If any +** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()], +** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail. +** +** ^Calling sqlite3_auto_extension(X) with an entry point X that is already +** on the list of automatic extensions is a harmless no-op. ^No entry point +** will be called more than once for each database connection that is opened. +** +** See also: [sqlite3_reset_auto_extension()] +** and [sqlite3_cancel_auto_extension()] +*/ +SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); + +/* +** CAPI3REF: Cancel Automatic Extension Loading +** +** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the +** initialization routine X that was registered using a prior call to +** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)] +** routine returns 1 if initialization routine X was successfully +** unregistered and it returns 0 if X was not on the list of initialization +** routines. +*/ +SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); + +/* +** CAPI3REF: Reset Automatic Extension Loading +** +** ^This interface disables all automatic extensions previously +** registered using [sqlite3_auto_extension()]. +*/ +SQLITE_API void sqlite3_reset_auto_extension(void); + +/* +** The interface to the virtual-table mechanism is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ + +/* +** Structures used by the virtual table interface +*/ +typedef struct sqlite3_vtab sqlite3_vtab; +typedef struct sqlite3_index_info sqlite3_index_info; +typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; +typedef struct sqlite3_module sqlite3_module; + +/* +** CAPI3REF: Virtual Table Object +** KEYWORDS: sqlite3_module {virtual table module} +** +** This structure, sometimes called a "virtual table module", +** defines the implementation of a [virtual tables]. +** This structure consists mostly of methods for the module. +** +** ^A virtual table module is created by filling in a persistent +** instance of this structure and passing a pointer to that instance +** to [sqlite3_create_module()] or [sqlite3_create_module_v2()]. +** ^The registration remains valid until it is replaced by a different +** module or until the [database connection] closes. The content +** of this structure must not change while it is registered with +** any database connection. +*/ +struct sqlite3_module +{ + int iVersion; + int (*xCreate)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xConnect)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); + int (*xDisconnect)(sqlite3_vtab *pVTab); + int (*xDestroy)(sqlite3_vtab *pVTab); + int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); + int (*xClose)(sqlite3_vtab_cursor*); + int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, + int argc, sqlite3_value **argv); + int (*xNext)(sqlite3_vtab_cursor*); + int (*xEof)(sqlite3_vtab_cursor*); + int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); + int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); + int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); + int (*xBegin)(sqlite3_vtab *pVTab); + int (*xSync)(sqlite3_vtab *pVTab); + int (*xCommit)(sqlite3_vtab *pVTab); + int (*xRollback)(sqlite3_vtab *pVTab); + int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg); + int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); + /* The methods above are in version 1 of the sqlite_module object. Those + ** below are for version 2 and greater. */ + int (*xSavepoint)(sqlite3_vtab *pVTab, int); + int (*xRelease)(sqlite3_vtab *pVTab, int); + int (*xRollbackTo)(sqlite3_vtab *pVTab, int); +}; + +/* +** CAPI3REF: Virtual Table Indexing Information +** KEYWORDS: sqlite3_index_info +** +** The sqlite3_index_info structure and its substructures is used as part +** of the [virtual table] interface to +** pass information into and receive the reply from the [xBestIndex] +** method of a [virtual table module]. The fields under **Inputs** are the +** inputs to xBestIndex and are read-only. xBestIndex inserts its +** results into the **Outputs** fields. +** +** ^(The aConstraint[] array records WHERE clause constraints of the form: +** +**
column OP expr
+** +** where OP is =, <, <=, >, or >=.)^ ^(The particular operator is +** stored in aConstraint[].op using one of the +** [SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_ values].)^ +** ^(The index of the column is stored in +** aConstraint[].iColumn.)^ ^(aConstraint[].usable is TRUE if the +** expr on the right-hand side can be evaluated (and thus the constraint +** is usable) and false if it cannot.)^ +** +** ^The optimizer automatically inverts terms of the form "expr OP column" +** and makes other simplifications to the WHERE clause in an attempt to +** get as many WHERE clause terms into the form shown above as possible. +** ^The aConstraint[] array only reports WHERE clause terms that are +** relevant to the particular virtual table being queried. +** +** ^Information about the ORDER BY clause is stored in aOrderBy[]. +** ^Each term of aOrderBy records a column of the ORDER BY clause. +** +** The [xBestIndex] method must fill aConstraintUsage[] with information +** about what parameters to pass to xFilter. ^If argvIndex>0 then +** the right-hand side of the corresponding aConstraint[] is evaluated +** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit +** is true, then the constraint is assumed to be fully handled by the +** virtual table and is not checked again by SQLite.)^ +** +** ^The idxNum and idxPtr values are recorded and passed into the +** [xFilter] method. +** ^[sqlite3_free()] is used to free idxPtr if and only if +** needToFreeIdxPtr is true. +** +** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in +** the correct order to satisfy the ORDER BY clause so that no separate +** sorting step is required. +** +** ^The estimatedCost value is an estimate of the cost of doing the +** particular lookup. A full scan of a table with N entries should have +** a cost of N. A binary search of a table of N entries should have a +** cost of approximately log(N). +*/ +struct sqlite3_index_info +{ + /* Inputs */ + int nConstraint; /* Number of entries in aConstraint */ + struct sqlite3_index_constraint + { + int iColumn; /* Column on left-hand side of constraint */ + unsigned char op; /* Constraint operator */ + unsigned char usable; /* True if this constraint is usable */ + int iTermOffset; /* Used internally - xBestIndex should ignore */ + } *aConstraint; /* Table of WHERE clause constraints */ + int nOrderBy; /* Number of terms in the ORDER BY clause */ + struct sqlite3_index_orderby + { + int iColumn; /* Column number */ + unsigned char desc; /* True for DESC. False for ASC. */ + } *aOrderBy; /* The ORDER BY clause */ + /* Outputs */ + struct sqlite3_index_constraint_usage + { + int argvIndex; /* if >0, constraint is part of argv to xFilter */ + unsigned char omit; /* Do not code a test for this constraint */ + } *aConstraintUsage; + int idxNum; /* Number used to identify the index */ + char *idxStr; /* String, possibly obtained from sqlite3_malloc */ + int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ + int orderByConsumed; /* True if output is already ordered */ + double estimatedCost; /* Estimated cost of using this index */ +}; + +/* +** CAPI3REF: Virtual Table Constraint Operator Codes +** +** These macros defined the allowed values for the +** [sqlite3_index_info].aConstraint[].op field. Each value represents +** an operator that is part of a constraint term in the wHERE clause of +** a query that uses a [virtual table]. +*/ +#define SQLITE_INDEX_CONSTRAINT_EQ 2 +#define SQLITE_INDEX_CONSTRAINT_GT 4 +#define SQLITE_INDEX_CONSTRAINT_LE 8 +#define SQLITE_INDEX_CONSTRAINT_LT 16 +#define SQLITE_INDEX_CONSTRAINT_GE 32 +#define SQLITE_INDEX_CONSTRAINT_MATCH 64 + +/* +** CAPI3REF: Register A Virtual Table Implementation +** +** ^These routines are used to register a new [virtual table module] name. +** ^Module names must be registered before +** creating a new [virtual table] using the module and before using a +** preexisting [virtual table] for the module. +** +** ^The module name is registered on the [database connection] specified +** by the first parameter. ^The name of the module is given by the +** second parameter. ^The third parameter is a pointer to +** the implementation of the [virtual table module]. ^The fourth +** parameter is an arbitrary client data pointer that is passed through +** into the [xCreate] and [xConnect] methods of the virtual table module +** when a new virtual table is be being created or reinitialized. +** +** ^The sqlite3_create_module_v2() interface has a fifth parameter which +** is a pointer to a destructor for the pClientData. ^SQLite will +** invoke the destructor function (if it is not NULL) when SQLite +** no longer needs the pClientData pointer. ^The destructor will also +** be invoked if the call to sqlite3_create_module_v2() fails. +** ^The sqlite3_create_module() +** interface is equivalent to sqlite3_create_module_v2() with a NULL +** destructor. +*/ +SQLITE_API int sqlite3_create_module( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData /* Client data for xCreate/xConnect */ +); +SQLITE_API int sqlite3_create_module_v2( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData, /* Client data for xCreate/xConnect */ + void(*xDestroy)(void*) /* Module destructor function */ +); + +/* +** CAPI3REF: Virtual Table Instance Object +** KEYWORDS: sqlite3_vtab +** +** Every [virtual table module] implementation uses a subclass +** of this object to describe a particular instance +** of the [virtual table]. Each subclass will +** be tailored to the specific needs of the module implementation. +** The purpose of this superclass is to define certain fields that are +** common to all module implementations. +** +** ^Virtual tables methods can set an error message by assigning a +** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should +** take care that any prior string is freed by a call to [sqlite3_free()] +** prior to assigning a new string to zErrMsg. ^After the error message +** is delivered up to the client application, the string will be automatically +** freed by sqlite3_free() and the zErrMsg field will be zeroed. +*/ +struct sqlite3_vtab +{ + const sqlite3_module *pModule; /* The module for this virtual table */ + int nRef; /* NO LONGER USED */ + char *zErrMsg; /* Error message from sqlite3_mprintf() */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* +** CAPI3REF: Virtual Table Cursor Object +** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor} +** +** Every [virtual table module] implementation uses a subclass of the +** following structure to describe cursors that point into the +** [virtual table] and are used +** to loop through the virtual table. Cursors are created using the +** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed +** by the [sqlite3_module.xClose | xClose] method. Cursors are used +** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods +** of the module. Each module implementation will define +** the content of a cursor structure to suit its own needs. +** +** This superclass exists in order to define fields of the cursor that +** are common to all implementations. +*/ +struct sqlite3_vtab_cursor +{ + sqlite3_vtab *pVtab; /* Virtual table of this cursor */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* +** CAPI3REF: Declare The Schema Of A Virtual Table +** +** ^The [xCreate] and [xConnect] methods of a +** [virtual table module] call this interface +** to declare the format (the names and datatypes of the columns) of +** the virtual tables they implement. +*/ +SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL); + +/* +** CAPI3REF: Overload A Function For A Virtual Table +** +** ^(Virtual tables can provide alternative implementations of functions +** using the [xFindFunction] method of the [virtual table module]. +** But global versions of those functions +** must exist in order to be overloaded.)^ +** +** ^(This API makes sure a global version of a function with a particular +** name and number of parameters exists. If no such function exists +** before this API is called, a new function is created.)^ ^The implementation +** of the new function always causes an exception to be thrown. So +** the new function is not good for anything by itself. Its only +** purpose is to be a placeholder function that can be overloaded +** by a [virtual table]. +*/ +SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); + +/* +** The interface to the virtual-table mechanism defined above (back up +** to a comment remarkably similar to this one) is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ + +/* +** CAPI3REF: A Handle To An Open BLOB +** KEYWORDS: {BLOB handle} {BLOB handles} +** +** An instance of this object represents an open BLOB on which +** [sqlite3_blob_open | incremental BLOB I/O] can be performed. +** ^Objects of this type are created by [sqlite3_blob_open()] +** and destroyed by [sqlite3_blob_close()]. +** ^The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces +** can be used to read or write small subsections of the BLOB. +** ^The [sqlite3_blob_bytes()] interface returns the size of the BLOB in bytes. +*/ +typedef struct sqlite3_blob sqlite3_blob; + +/* +** CAPI3REF: Open A BLOB For Incremental I/O +** +** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located +** in row iRow, column zColumn, table zTable in database zDb; +** in other words, the same BLOB that would be selected by: +** +**
+**     SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
+** 
)^ +** +** ^If the flags parameter is non-zero, then the BLOB is opened for read +** and write access. ^If it is zero, the BLOB is opened for read access. +** ^It is not possible to open a column that is part of an index or primary +** key for writing. ^If [foreign key constraints] are enabled, it is +** not possible to open a column that is part of a [child key] for writing. +** +** ^Note that the database name is not the filename that contains +** the database but rather the symbolic name of the database that +** appears after the AS keyword when the database is connected using [ATTACH]. +** ^For the main database file, the database name is "main". +** ^For TEMP tables, the database name is "temp". +** +** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is written +** to *ppBlob. Otherwise an [error code] is returned and *ppBlob is set +** to be a null pointer.)^ +** ^This function sets the [database connection] error code and message +** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()] and related +** functions. ^Note that the *ppBlob variable is always initialized in a +** way that makes it safe to invoke [sqlite3_blob_close()] on *ppBlob +** regardless of the success or failure of this routine. +** +** ^(If the row that a BLOB handle points to is modified by an +** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects +** then the BLOB handle is marked as "expired". +** This is true if any column of the row is changed, even a column +** other than the one the BLOB handle is open on.)^ +** ^Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for +** an expired BLOB handle fail with a return code of [SQLITE_ABORT]. +** ^(Changes written into a BLOB prior to the BLOB expiring are not +** rolled back by the expiration of the BLOB. Such changes will eventually +** commit if the transaction continues to completion.)^ +** +** ^Use the [sqlite3_blob_bytes()] interface to determine the size of +** the opened blob. ^The size of a blob may not be changed by this +** interface. Use the [UPDATE] SQL command to change the size of a +** blob. +** +** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces +** and the built-in [zeroblob] SQL function can be used, if desired, +** to create an empty, zero-filled blob in which to read or write using +** this interface. +** +** To avoid a resource leak, every open [BLOB handle] should eventually +** be released by a call to [sqlite3_blob_close()]. +*/ +SQLITE_API int sqlite3_blob_open( + sqlite3*, + const char *zDb, + const char *zTable, + const char *zColumn, + sqlite3_int64 iRow, + int flags, + sqlite3_blob **ppBlob +); + +/* +** CAPI3REF: Move a BLOB Handle to a New Row +** +** ^This function is used to move an existing blob handle so that it points +** to a different row of the same database table. ^The new row is identified +** by the rowid value passed as the second argument. Only the row can be +** changed. ^The database, table and column on which the blob handle is open +** remain the same. Moving an existing blob handle to a new row can be +** faster than closing the existing handle and opening a new one. +** +** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] - +** it must exist and there must be either a blob or text value stored in +** the nominated column.)^ ^If the new row is not present in the table, or if +** it does not contain a blob or text value, or if another error occurs, an +** SQLite error code is returned and the blob handle is considered aborted. +** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or +** [sqlite3_blob_reopen()] on an aborted blob handle immediately return +** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle +** always returns zero. +** +** ^This function sets the database handle error code and message. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); + +/* +** CAPI3REF: Close A BLOB Handle +** +** ^Closes an open [BLOB handle]. +** +** ^Closing a BLOB shall cause the current transaction to commit +** if there are no other BLOBs, no pending prepared statements, and the +** database connection is in [autocommit mode]. +** ^If any writes were made to the BLOB, they might be held in cache +** until the close operation if they will fit. +** +** ^(Closing the BLOB often forces the changes +** out to disk and so if any I/O errors occur, they will likely occur +** at the time when the BLOB is closed. Any errors that occur during +** closing are reported as a non-zero return value.)^ +** +** ^(The BLOB is closed unconditionally. Even if this routine returns +** an error code, the BLOB is still closed.)^ +** +** ^Calling this routine with a null pointer (such as would be returned +** by a failed call to [sqlite3_blob_open()]) is a harmless no-op. +*/ +SQLITE_API int sqlite3_blob_close(sqlite3_blob *); + +/* +** CAPI3REF: Return The Size Of An Open BLOB +** +** ^Returns the size in bytes of the BLOB accessible via the +** successfully opened [BLOB handle] in its only argument. ^The +** incremental blob I/O routines can only read or overwriting existing +** blob content; they cannot change the size of a blob. +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +*/ +SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); + +/* +** CAPI3REF: Read Data From A BLOB Incrementally +** +** ^(This function is used to read data from an open [BLOB handle] into a +** caller-supplied buffer. N bytes of data are copied into buffer Z +** from the open BLOB, starting at offset iOffset.)^ +** +** ^If offset iOffset is less than N bytes from the end of the BLOB, +** [SQLITE_ERROR] is returned and no data is read. ^If N or iOffset is +** less than zero, [SQLITE_ERROR] is returned and no data is read. +** ^The size of the blob (and hence the maximum value of N+iOffset) +** can be determined using the [sqlite3_blob_bytes()] interface. +** +** ^An attempt to read from an expired [BLOB handle] fails with an +** error code of [SQLITE_ABORT]. +** +** ^(On success, sqlite3_blob_read() returns SQLITE_OK. +** Otherwise, an [error code] or an [extended error code] is returned.)^ +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +** +** See also: [sqlite3_blob_write()]. +*/ +SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); + +/* +** CAPI3REF: Write Data Into A BLOB Incrementally +** +** ^This function is used to write data into an open [BLOB handle] from a +** caller-supplied buffer. ^N bytes of data are copied from the buffer Z +** into the open BLOB, starting at offset iOffset. +** +** ^If the [BLOB handle] passed as the first argument was not opened for +** writing (the flags parameter to [sqlite3_blob_open()] was zero), +** this function returns [SQLITE_READONLY]. +** +** ^This function may only modify the contents of the BLOB; it is +** not possible to increase the size of a BLOB using this API. +** ^If offset iOffset is less than N bytes from the end of the BLOB, +** [SQLITE_ERROR] is returned and no data is written. ^If N is +** less than zero [SQLITE_ERROR] is returned and no data is written. +** The size of the BLOB (and hence the maximum value of N+iOffset) +** can be determined using the [sqlite3_blob_bytes()] interface. +** +** ^An attempt to write to an expired [BLOB handle] fails with an +** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred +** before the [BLOB handle] expired are not rolled back by the +** expiration of the handle, though of course those changes might +** have been overwritten by the statement that expired the BLOB handle +** or by other independent statements. +** +** ^(On success, sqlite3_blob_write() returns SQLITE_OK. +** Otherwise, an [error code] or an [extended error code] is returned.)^ +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +** +** See also: [sqlite3_blob_read()]. +*/ +SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); + +/* +** CAPI3REF: Virtual File System Objects +** +** A virtual filesystem (VFS) is an [sqlite3_vfs] object +** that SQLite uses to interact +** with the underlying operating system. Most SQLite builds come with a +** single default VFS that is appropriate for the host computer. +** New VFSes can be registered and existing VFSes can be unregistered. +** The following interfaces are provided. +** +** ^The sqlite3_vfs_find() interface returns a pointer to a VFS given its name. +** ^Names are case sensitive. +** ^Names are zero-terminated UTF-8 strings. +** ^If there is no match, a NULL pointer is returned. +** ^If zVfsName is NULL then the default VFS is returned. +** +** ^New VFSes are registered with sqlite3_vfs_register(). +** ^Each new VFS becomes the default VFS if the makeDflt flag is set. +** ^The same VFS can be registered multiple times without injury. +** ^To make an existing VFS into the default VFS, register it again +** with the makeDflt flag set. If two different VFSes with the +** same name are registered, the behavior is undefined. If a +** VFS is registered with a name that is NULL or an empty string, +** then the behavior is undefined. +** +** ^Unregister a VFS with the sqlite3_vfs_unregister() interface. +** ^(If the default VFS is unregistered, another VFS is chosen as +** the default. The choice for the new VFS is arbitrary.)^ +*/ +SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); +SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); +SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); + +/* +** CAPI3REF: Mutexes +** +** The SQLite core uses these routines for thread +** synchronization. Though they are intended for internal +** use by SQLite, code that links against SQLite is +** permitted to use any of these routines. +** +** The SQLite source code contains multiple implementations +** of these mutex routines. An appropriate implementation +** is selected automatically at compile-time. ^(The following +** implementations are available in the SQLite core: +** +**
    +**
  • SQLITE_MUTEX_PTHREADS +**
  • SQLITE_MUTEX_W32 +**
  • SQLITE_MUTEX_NOOP +**
)^ +** +** ^The SQLITE_MUTEX_NOOP implementation is a set of routines +** that does no real locking and is appropriate for use in +** a single-threaded application. ^The SQLITE_MUTEX_PTHREADS and +** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix +** and Windows. +** +** ^(If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor +** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex +** implementation is included with the library. In this case the +** application must supply a custom mutex implementation using the +** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function +** before calling sqlite3_initialize() or any other public sqlite3_ +** function that calls sqlite3_initialize().)^ +** +** ^The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. ^If it returns NULL +** that means that a mutex could not be allocated. ^SQLite +** will unwind its stack and return an error. ^(The argument +** to sqlite3_mutex_alloc() is one of these integer constants: +** +**
    +**
  • SQLITE_MUTEX_FAST +**
  • SQLITE_MUTEX_RECURSIVE +**
  • SQLITE_MUTEX_STATIC_MASTER +**
  • SQLITE_MUTEX_STATIC_MEM +**
  • SQLITE_MUTEX_STATIC_MEM2 +**
  • SQLITE_MUTEX_STATIC_PRNG +**
  • SQLITE_MUTEX_STATIC_LRU +**
  • SQLITE_MUTEX_STATIC_LRU2 +**
)^ +** +** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) +** cause sqlite3_mutex_alloc() to create +** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** is used but not necessarily so when SQLITE_MUTEX_FAST is used. +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. ^SQLite will only request a recursive mutex in +** cases where it really needs one. ^If a faster non-recursive mutex +** implementation is available on the host platform, the mutex subsystem +** might return such a mutex in response to SQLITE_MUTEX_FAST. +** +** ^The other allowed parameters to sqlite3_mutex_alloc() (anything other +** than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return +** a pointer to a static preexisting mutex. ^Six static mutexes are +** used by the current version of SQLite. Future versions of SQLite +** may add additional static mutexes. Static mutexes are for internal +** use by SQLite only. Applications that use SQLite mutexes should +** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or +** SQLITE_MUTEX_RECURSIVE. +** +** ^Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST +** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() +** returns a different mutex on every call. ^But for the static +** mutex types, the same mutex is returned on every call that has +** the same type number. +** +** ^The sqlite3_mutex_free() routine deallocates a previously +** allocated dynamic mutex. ^SQLite is careful to deallocate every +** dynamic mutex that it allocates. The dynamic mutexes must not be in +** use when they are deallocated. Attempting to deallocate a static +** mutex results in undefined behavior. ^SQLite never deallocates +** a static mutex. +** +** ^The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. ^If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. ^The sqlite3_mutex_try() interface returns [SQLITE_OK] +** upon successful entry. ^(Mutexes created using +** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. +** In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter.)^ ^(If the same thread tries to enter any other +** kind of mutex more than once, the behavior is undefined. +** SQLite will never exhibit +** such behavior in its own use of mutexes.)^ +** +** ^(Some systems (for example, Windows 95) do not support the operation +** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() +** will always return SQLITE_BUSY. The SQLite core only ever uses +** sqlite3_mutex_try() as an optimization so this is acceptable behavior.)^ +** +** ^The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. ^(The behavior +** is undefined if the mutex is not currently entered by the +** calling thread or is not currently allocated. SQLite will +** never do either.)^ +** +** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or +** sqlite3_mutex_leave() is a NULL pointer, then all three routines +** behave as no-ops. +** +** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. +*/ +SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int); +SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*); + +/* +** CAPI3REF: Mutex Methods Object +** +** An instance of this structure defines the low-level routines +** used to allocate and use mutexes. +** +** Usually, the default mutex implementations provided by SQLite are +** sufficient, however the user has the option of substituting a custom +** implementation for specialized deployments or systems for which SQLite +** does not provide a suitable implementation. In this case, the user +** creates and populates an instance of this structure to pass +** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option. +** Additionally, an instance of this structure can be used as an +** output variable when querying the system for the current mutex +** implementation, using the [SQLITE_CONFIG_GETMUTEX] option. +** +** ^The xMutexInit method defined by this structure is invoked as +** part of system initialization by the sqlite3_initialize() function. +** ^The xMutexInit routine is called by SQLite exactly once for each +** effective call to [sqlite3_initialize()]. +** +** ^The xMutexEnd method defined by this structure is invoked as +** part of system shutdown by the sqlite3_shutdown() function. The +** implementation of this method is expected to release all outstanding +** resources obtained by the mutex methods implementation, especially +** those obtained by the xMutexInit method. ^The xMutexEnd() +** interface is invoked exactly once for each call to [sqlite3_shutdown()]. +** +** ^(The remaining seven methods defined by this structure (xMutexAlloc, +** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and +** xMutexNotheld) implement the following interfaces (respectively): +** +**
    +**
  • [sqlite3_mutex_alloc()]
  • +**
  • [sqlite3_mutex_free()]
  • +**
  • [sqlite3_mutex_enter()]
  • +**
  • [sqlite3_mutex_try()]
  • +**
  • [sqlite3_mutex_leave()]
  • +**
  • [sqlite3_mutex_held()]
  • +**
  • [sqlite3_mutex_notheld()]
  • +**
)^ +** +** The only difference is that the public sqlite3_XXX functions enumerated +** above silently ignore any invocations that pass a NULL pointer instead +** of a valid mutex handle. The implementations of the methods defined +** by this structure are not required to handle this case, the results +** of passing a NULL pointer instead of a valid mutex handle are undefined +** (i.e. it is acceptable to provide an implementation that segfaults if +** it is passed a NULL pointer). +** +** The xMutexInit() method must be threadsafe. ^It must be harmless to +** invoke xMutexInit() multiple times within the same process and without +** intervening calls to xMutexEnd(). Second and subsequent calls to +** xMutexInit() must be no-ops. +** +** ^xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()] +** and its associates). ^Similarly, xMutexAlloc() must not use SQLite memory +** allocation for a static mutex. ^However xMutexAlloc() may use SQLite +** memory allocation for a fast or recursive mutex. +** +** ^SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is +** called, but only if the prior call to xMutexInit returned SQLITE_OK. +** If xMutexInit fails in any way, it is expected to clean up after itself +** prior to returning. +*/ +typedef struct sqlite3_mutex_methods sqlite3_mutex_methods; +struct sqlite3_mutex_methods +{ + int (*xMutexInit)(void); + int (*xMutexEnd)(void); + sqlite3_mutex *(*xMutexAlloc)(int); + void (*xMutexFree)(sqlite3_mutex *); + void (*xMutexEnter)(sqlite3_mutex *); + int (*xMutexTry)(sqlite3_mutex *); + void (*xMutexLeave)(sqlite3_mutex *); + int (*xMutexHeld)(sqlite3_mutex *); + int (*xMutexNotheld)(sqlite3_mutex *); +}; + +/* +** CAPI3REF: Mutex Verification Routines +** +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines +** are intended for use inside assert() statements. ^The SQLite core +** never uses these routines except inside an assert() and applications +** are advised to follow the lead of the core. ^The SQLite core only +** provides implementations for these routines when it is compiled +** with the SQLITE_DEBUG flag. ^External mutex implementations +** are only required to provide these routines if SQLITE_DEBUG is +** defined and if NDEBUG is not defined. +** +** ^These routines should return true if the mutex in their argument +** is held or not held, respectively, by the calling thread. +** +** ^The implementation is not required to provide versions of these +** routines that actually work. If the implementation does not provide working +** versions of these routines, it should at least provide stubs that always +** return true so that one does not get spurious assertion failures. +** +** ^If the argument to sqlite3_mutex_held() is a NULL pointer then +** the routine should return 1. This seems counter-intuitive since +** clearly the mutex cannot be held if it does not exist. But +** the reason the mutex does not exist is because the build is not +** using mutexes. And we do not want the assert() containing the +** call to sqlite3_mutex_held() to fail, so a non-zero return is +** the appropriate thing to do. ^The sqlite3_mutex_notheld() +** interface should also return 1 when given a NULL pointer. +*/ +#ifndef NDEBUG +SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); +#endif + +/* +** CAPI3REF: Mutex Types +** +** The [sqlite3_mutex_alloc()] interface takes a single argument +** which is one of these integer constants. +** +** The set of static mutexes may change from one SQLite release to the +** next. Applications that override the built-in mutex logic must be +** prepared to accommodate additional static mutexes. +*/ +#define SQLITE_MUTEX_FAST 0 +#define SQLITE_MUTEX_RECURSIVE 1 +#define SQLITE_MUTEX_STATIC_MASTER 2 +#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ +#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */ +#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */ +#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ +#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ +#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */ +#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */ + +/* +** CAPI3REF: Retrieve the mutex for a database connection +** +** ^This interface returns a pointer the [sqlite3_mutex] object that +** serializes access to the [database connection] given in the argument +** when the [threading mode] is Serialized. +** ^If the [threading mode] is Single-thread or Multi-thread then this +** routine returns a NULL pointer. +*/ +SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); + +/* +** CAPI3REF: Low-Level Control Of Database Files +** +** ^The [sqlite3_file_control()] interface makes a direct call to the +** xFileControl method for the [sqlite3_io_methods] object associated +** with a particular database identified by the second argument. ^The +** name of the database is "main" for the main database or "temp" for the +** TEMP database, or the name that appears after the AS keyword for +** databases that are added using the [ATTACH] SQL command. +** ^A NULL pointer can be used in place of "main" to refer to the +** main database file. +** ^The third and fourth parameters to this routine +** are passed directly through to the second and third parameters of +** the xFileControl method. ^The return value of the xFileControl +** method becomes the return value of this routine. +** +** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes +** a pointer to the underlying [sqlite3_file] object to be written into +** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER +** case is a short-circuit path which does not actually invoke the +** underlying sqlite3_io_methods.xFileControl method. +** +** ^If the second parameter (zDbName) does not match the name of any +** open database file, then SQLITE_ERROR is returned. ^This error +** code is not remembered and will not be recalled by [sqlite3_errcode()] +** or [sqlite3_errmsg()]. The underlying xFileControl method might +** also return SQLITE_ERROR. There is no way to distinguish between +** an incorrect zDbName and an SQLITE_ERROR return from the underlying +** xFileControl method. +** +** See also: [SQLITE_FCNTL_LOCKSTATE] +*/ +SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); + +/* +** CAPI3REF: Testing Interface +** +** ^The sqlite3_test_control() interface is used to read out internal +** state of SQLite and to inject faults into SQLite for testing +** purposes. ^The first parameter is an operation code that determines +** the number, meaning, and operation of all subsequent parameters. +** +** This interface is not for use by applications. It exists solely +** for verifying the correct operation of the SQLite library. Depending +** on how the SQLite library is compiled, this interface might not exist. +** +** The details of the operation codes, their meanings, the parameters +** they take, and what they do are all subject to change without notice. +** Unlike most of the SQLite API, this function is not guaranteed to +** operate consistently from one release to the next. +*/ +SQLITE_API int sqlite3_test_control(int op, ...); + +/* +** CAPI3REF: Testing Interface Operation Codes +** +** These constants are the valid operation code parameters used +** as the first argument to [sqlite3_test_control()]. +** +** These parameters and their meanings are subject to change +** without notice. These values are for testing purposes only. +** Applications should not use any of these parameters or the +** [sqlite3_test_control()] interface. +*/ +#define SQLITE_TESTCTRL_FIRST 5 +#define SQLITE_TESTCTRL_PRNG_SAVE 5 +#define SQLITE_TESTCTRL_PRNG_RESTORE 6 +#define SQLITE_TESTCTRL_PRNG_RESET 7 +#define SQLITE_TESTCTRL_BITVEC_TEST 8 +#define SQLITE_TESTCTRL_FAULT_INSTALL 9 +#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 +#define SQLITE_TESTCTRL_PENDING_BYTE 11 +#define SQLITE_TESTCTRL_ASSERT 12 +#define SQLITE_TESTCTRL_ALWAYS 13 +#define SQLITE_TESTCTRL_RESERVE 14 +#define SQLITE_TESTCTRL_OPTIMIZATIONS 15 +#define SQLITE_TESTCTRL_ISKEYWORD 16 +#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 +#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 +#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 +#define SQLITE_TESTCTRL_LAST 19 + +/* +** CAPI3REF: SQLite Runtime Status +** +** ^This interface is used to retrieve runtime status information +** about the performance of SQLite, and optionally to reset various +** highwater marks. ^The first argument is an integer code for +** the specific parameter to measure. ^(Recognized integer codes +** are of the form [status parameters | SQLITE_STATUS_...].)^ +** ^The current value of the parameter is returned into *pCurrent. +** ^The highest recorded value is returned in *pHighwater. ^If the +** resetFlag is true, then the highest record value is reset after +** *pHighwater is written. ^(Some parameters do not record the highest +** value. For those parameters +** nothing is written into *pHighwater and the resetFlag is ignored.)^ +** ^(Other parameters record only the highwater mark and not the current +** value. For these latter parameters nothing is written into *pCurrent.)^ +** +** ^The sqlite3_status() routine returns SQLITE_OK on success and a +** non-zero [error code] on failure. +** +** This routine is threadsafe but is not atomic. This routine can be +** called while other threads are running the same or different SQLite +** interfaces. However the values returned in *pCurrent and +** *pHighwater reflect the status of SQLite at different points in time +** and it is possible that another thread might change the parameter +** in between the times when *pCurrent and *pHighwater are written. +** +** See also: [sqlite3_db_status()] +*/ +SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); + + +/* +** CAPI3REF: Status Parameters +** KEYWORDS: {status parameters} +** +** These integer constants designate various run-time status parameters +** that can be returned by [sqlite3_status()]. +** +**
+** [[SQLITE_STATUS_MEMORY_USED]] ^(
SQLITE_STATUS_MEMORY_USED
+**
This parameter is the current amount of memory checked out +** using [sqlite3_malloc()], either directly or indirectly. The +** figure includes calls made to [sqlite3_malloc()] by the application +** and internal memory usage by the SQLite library. Scratch memory +** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache +** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in +** this parameter. The amount returned is the sum of the allocation +** sizes as reported by the xSize method in [sqlite3_mem_methods].
)^ +** +** [[SQLITE_STATUS_MALLOC_SIZE]] ^(
SQLITE_STATUS_MALLOC_SIZE
+**
This parameter records the largest memory allocation request +** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their +** internal equivalents). Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
)^ +** +** [[SQLITE_STATUS_MALLOC_COUNT]] ^(
SQLITE_STATUS_MALLOC_COUNT
+**
This parameter records the number of separate memory allocations +** currently checked out.
)^ +** +** [[SQLITE_STATUS_PAGECACHE_USED]] ^(
SQLITE_STATUS_PAGECACHE_USED
+**
This parameter returns the number of pages used out of the +** [pagecache memory allocator] that was configured using +** [SQLITE_CONFIG_PAGECACHE]. The +** value returned is in pages, not in bytes.
)^ +** +** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] +** ^(
SQLITE_STATUS_PAGECACHE_OVERFLOW
+**
This parameter returns the number of bytes of page cache +** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE] +** buffer and where forced to overflow to [sqlite3_malloc()]. The +** returned value includes allocations that overflowed because they +** where too large (they were larger than the "sz" parameter to +** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because +** no space was left in the page cache.
)^ +** +** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(
SQLITE_STATUS_PAGECACHE_SIZE
+**
This parameter records the largest memory allocation request +** handed to [pagecache memory allocator]. Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
)^ +** +** [[SQLITE_STATUS_SCRATCH_USED]] ^(
SQLITE_STATUS_SCRATCH_USED
+**
This parameter returns the number of allocations used out of the +** [scratch memory allocator] configured using +** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not +** in bytes. Since a single thread may only have one scratch allocation +** outstanding at time, this parameter also reports the number of threads +** using scratch memory at the same time.
)^ +** +** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(
SQLITE_STATUS_SCRATCH_OVERFLOW
+**
This parameter returns the number of bytes of scratch memory +** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH] +** buffer and where forced to overflow to [sqlite3_malloc()]. The values +** returned include overflows because the requested allocation was too +** larger (that is, because the requested allocation was larger than the +** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer +** slots were available. +**
)^ +** +** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(
SQLITE_STATUS_SCRATCH_SIZE
+**
This parameter records the largest memory allocation request +** handed to [scratch memory allocator]. Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
)^ +** +** [[SQLITE_STATUS_PARSER_STACK]] ^(
SQLITE_STATUS_PARSER_STACK
+**
This parameter records the deepest parser stack. It is only +** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].
)^ +**
+** +** New status parameters may be added from time to time. +*/ +#define SQLITE_STATUS_MEMORY_USED 0 +#define SQLITE_STATUS_PAGECACHE_USED 1 +#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 +#define SQLITE_STATUS_SCRATCH_USED 3 +#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 +#define SQLITE_STATUS_MALLOC_SIZE 5 +#define SQLITE_STATUS_PARSER_STACK 6 +#define SQLITE_STATUS_PAGECACHE_SIZE 7 +#define SQLITE_STATUS_SCRATCH_SIZE 8 +#define SQLITE_STATUS_MALLOC_COUNT 9 + +/* +** CAPI3REF: Database Connection Status +** +** ^This interface is used to retrieve runtime status information +** about a single [database connection]. ^The first argument is the +** database connection object to be interrogated. ^The second argument +** is an integer constant, taken from the set of +** [SQLITE_DBSTATUS options], that +** determines the parameter to interrogate. The set of +** [SQLITE_DBSTATUS options] is likely +** to grow in future releases of SQLite. +** +** ^The current value of the requested parameter is written into *pCur +** and the highest instantaneous value is written into *pHiwtr. ^If +** the resetFlg is true, then the highest instantaneous value is +** reset back down to the current value. +** +** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a +** non-zero [error code] on failure. +** +** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. +*/ +SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); + +/* +** CAPI3REF: Status Parameters for database connections +** KEYWORDS: {SQLITE_DBSTATUS options} +** +** These constants are the available integer "verbs" that can be passed as +** the second argument to the [sqlite3_db_status()] interface. +** +** New verbs may be added in future releases of SQLite. Existing verbs +** might be discontinued. Applications should check the return code from +** [sqlite3_db_status()] to make sure that the call worked. +** The [sqlite3_db_status()] interface will return a non-zero error code +** if a discontinued or unsupported verb is invoked. +** +**
+** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(
SQLITE_DBSTATUS_LOOKASIDE_USED
+**
This parameter returns the number of lookaside memory slots currently +** checked out.
)^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(
SQLITE_DBSTATUS_LOOKASIDE_HIT
+**
This parameter returns the number malloc attempts that were +** satisfied using lookaside memory. Only the high-water value is meaningful; +** the current value is always zero.)^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]] +** ^(
SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
+**
This parameter returns the number malloc attempts that might have +** been satisfied using lookaside memory but failed due to the amount of +** memory requested being larger than the lookaside slot size. +** Only the high-water value is meaningful; +** the current value is always zero.)^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]] +** ^(
SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL
+**
This parameter returns the number malloc attempts that might have +** been satisfied using lookaside memory but failed due to all lookaside +** memory already being in use. +** Only the high-water value is meaningful; +** the current value is always zero.)^ +** +** [[SQLITE_DBSTATUS_CACHE_USED]] ^(
SQLITE_DBSTATUS_CACHE_USED
+**
This parameter returns the approximate number of of bytes of heap +** memory used by all pager caches associated with the database connection.)^ +** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0. +** +** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(
SQLITE_DBSTATUS_SCHEMA_USED
+**
This parameter returns the approximate number of of bytes of heap +** memory used to store the schema for all databases associated +** with the connection - main, temp, and any [ATTACH]-ed databases.)^ +** ^The full amount of memory used by the schemas is reported, even if the +** schema memory is shared with other database connections due to +** [shared cache mode] being enabled. +** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0. +** +** [[SQLITE_DBSTATUS_STMT_USED]] ^(
SQLITE_DBSTATUS_STMT_USED
+**
This parameter returns the approximate number of of bytes of heap +** and lookaside memory used by all prepared statements associated with +** the database connection.)^ +** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0. +**
+** +** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(
SQLITE_DBSTATUS_CACHE_HIT
+**
This parameter returns the number of pager cache hits that have +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT +** is always 0. +**
+** +** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(
SQLITE_DBSTATUS_CACHE_MISS
+**
This parameter returns the number of pager cache misses that have +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS +** is always 0. +**
+** +** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(
SQLITE_DBSTATUS_CACHE_WRITE
+**
This parameter returns the number of dirty cache entries that have +** been written to disk. Specifically, the number of pages written to the +** wal file in wal mode databases, or the number of pages written to the +** database file in rollback mode databases. Any pages written as part of +** transaction rollback or database recovery operations are not included. +** If an IO or other error occurs while writing a page to disk, the effect +** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The +** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. +**
+** +** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(
SQLITE_DBSTATUS_DEFERRED_FKS
+**
This parameter returns zero for the current value if and only if +** all foreign key constraints (deferred or immediate) have been +** resolved.)^ ^The highwater mark is always 0. +**
+**
+*/ +#define SQLITE_DBSTATUS_LOOKASIDE_USED 0 +#define SQLITE_DBSTATUS_CACHE_USED 1 +#define SQLITE_DBSTATUS_SCHEMA_USED 2 +#define SQLITE_DBSTATUS_STMT_USED 3 +#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 +#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 +#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 +#define SQLITE_DBSTATUS_CACHE_HIT 7 +#define SQLITE_DBSTATUS_CACHE_MISS 8 +#define SQLITE_DBSTATUS_CACHE_WRITE 9 +#define SQLITE_DBSTATUS_DEFERRED_FKS 10 +#define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */ + + +/* +** CAPI3REF: Prepared Statement Status +** +** ^(Each prepared statement maintains various +** [SQLITE_STMTSTATUS counters] that measure the number +** of times it has performed specific operations.)^ These counters can +** be used to monitor the performance characteristics of the prepared +** statements. For example, if the number of table steps greatly exceeds +** the number of table searches or result rows, that would tend to indicate +** that the prepared statement is using a full table scan rather than +** an index. +** +** ^(This interface is used to retrieve and reset counter values from +** a [prepared statement]. The first argument is the prepared statement +** object to be interrogated. The second argument +** is an integer code for a specific [SQLITE_STMTSTATUS counter] +** to be interrogated.)^ +** ^The current value of the requested counter is returned. +** ^If the resetFlg is true, then the counter is reset to zero after this +** interface call returns. +** +** See also: [sqlite3_status()] and [sqlite3_db_status()]. +*/ +SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); + +/* +** CAPI3REF: Status Parameters for prepared statements +** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters} +** +** These preprocessor macros define integer codes that name counter +** values associated with the [sqlite3_stmt_status()] interface. +** The meanings of the various counters are as follows: +** +**
+** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]]
SQLITE_STMTSTATUS_FULLSCAN_STEP
+**
^This is the number of times that SQLite has stepped forward in +** a table as part of a full table scan. Large numbers for this counter +** may indicate opportunities for performance improvement through +** careful use of indices.
+** +** [[SQLITE_STMTSTATUS_SORT]]
SQLITE_STMTSTATUS_SORT
+**
^This is the number of sort operations that have occurred. +** A non-zero value in this counter may indicate an opportunity to +** improvement performance through careful use of indices.
+** +** [[SQLITE_STMTSTATUS_AUTOINDEX]]
SQLITE_STMTSTATUS_AUTOINDEX
+**
^This is the number of rows inserted into transient indices that +** were created automatically in order to help joins run faster. +** A non-zero value in this counter may indicate an opportunity to +** improvement performance by adding permanent indices that do not +** need to be reinitialized each time the statement is run.
+** +** [[SQLITE_STMTSTATUS_VM_STEP]]
SQLITE_STMTSTATUS_VM_STEP
+**
^This is the number of virtual machine operations executed +** by the prepared statement if that number is less than or equal +** to 2147483647. The number of virtual machine operations can be +** used as a proxy for the total work done by the prepared statement. +** If the number of virtual machine operations exceeds 2147483647 +** then the value returned by this statement status code is undefined. +**
+**
+*/ +#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 +#define SQLITE_STMTSTATUS_SORT 2 +#define SQLITE_STMTSTATUS_AUTOINDEX 3 +#define SQLITE_STMTSTATUS_VM_STEP 4 + +/* +** CAPI3REF: Custom Page Cache Object +** +** The sqlite3_pcache type is opaque. It is implemented by +** the pluggable module. The SQLite core has no knowledge of +** its size or internal structure and never deals with the +** sqlite3_pcache object except by holding and passing pointers +** to the object. +** +** See [sqlite3_pcache_methods2] for additional information. +*/ +typedef struct sqlite3_pcache sqlite3_pcache; + +/* +** CAPI3REF: Custom Page Cache Object +** +** The sqlite3_pcache_page object represents a single page in the +** page cache. The page cache will allocate instances of this +** object. Various methods of the page cache use pointers to instances +** of this object as parameters or as their return value. +** +** See [sqlite3_pcache_methods2] for additional information. +*/ +typedef struct sqlite3_pcache_page sqlite3_pcache_page; +struct sqlite3_pcache_page +{ + void *pBuf; /* The content of the page */ + void *pExtra; /* Extra information associated with the page */ +}; + +/* +** CAPI3REF: Application Defined Page Cache. +** KEYWORDS: {page cache} +** +** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can +** register an alternative page cache implementation by passing in an +** instance of the sqlite3_pcache_methods2 structure.)^ +** In many applications, most of the heap memory allocated by +** SQLite is used for the page cache. +** By implementing a +** custom page cache using this API, an application can better control +** the amount of memory consumed by SQLite, the way in which +** that memory is allocated and released, and the policies used to +** determine exactly which parts of a database file are cached and for +** how long. +** +** The alternative page cache mechanism is an +** extreme measure that is only needed by the most demanding applications. +** The built-in page cache is recommended for most uses. +** +** ^(The contents of the sqlite3_pcache_methods2 structure are copied to an +** internal buffer by SQLite within the call to [sqlite3_config]. Hence +** the application may discard the parameter after the call to +** [sqlite3_config()] returns.)^ +** +** [[the xInit() page cache method]] +** ^(The xInit() method is called once for each effective +** call to [sqlite3_initialize()])^ +** (usually only once during the lifetime of the process). ^(The xInit() +** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^ +** The intent of the xInit() method is to set up global data structures +** required by the custom page cache implementation. +** ^(If the xInit() method is NULL, then the +** built-in default page cache is used instead of the application defined +** page cache.)^ +** +** [[the xShutdown() page cache method]] +** ^The xShutdown() method is called by [sqlite3_shutdown()]. +** It can be used to clean up +** any outstanding resources before process shutdown, if required. +** ^The xShutdown() method may be NULL. +** +** ^SQLite automatically serializes calls to the xInit method, +** so the xInit method need not be threadsafe. ^The +** xShutdown method is only called from [sqlite3_shutdown()] so it does +** not need to be threadsafe either. All other methods must be threadsafe +** in multithreaded applications. +** +** ^SQLite will never invoke xInit() more than once without an intervening +** call to xShutdown(). +** +** [[the xCreate() page cache methods]] +** ^SQLite invokes the xCreate() method to construct a new cache instance. +** SQLite will typically create one cache instance for each open database file, +** though this is not guaranteed. ^The +** first parameter, szPage, is the size in bytes of the pages that must +** be allocated by the cache. ^szPage will always a power of two. ^The +** second parameter szExtra is a number of bytes of extra storage +** associated with each page cache entry. ^The szExtra parameter will +** a number less than 250. SQLite will use the +** extra szExtra bytes on each page to store metadata about the underlying +** database page on disk. The value passed into szExtra depends +** on the SQLite version, the target platform, and how SQLite was compiled. +** ^The third argument to xCreate(), bPurgeable, is true if the cache being +** created will be used to cache database pages of a file stored on disk, or +** false if it is used for an in-memory database. The cache implementation +** does not have to do anything special based with the value of bPurgeable; +** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will +** never invoke xUnpin() except to deliberately delete a page. +** ^In other words, calls to xUnpin() on a cache with bPurgeable set to +** false will always have the "discard" flag set to true. +** ^Hence, a cache created with bPurgeable false will +** never contain any unpinned pages. +** +** [[the xCachesize() page cache method]] +** ^(The xCachesize() method may be called at any time by SQLite to set the +** suggested maximum cache-size (number of pages stored by) the cache +** instance passed as the first argument. This is the value configured using +** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable +** parameter, the implementation is not required to do anything with this +** value; it is advisory only. +** +** [[the xPagecount() page cache methods]] +** The xPagecount() method must return the number of pages currently +** stored in the cache, both pinned and unpinned. +** +** [[the xFetch() page cache methods]] +** The xFetch() method locates a page in the cache and returns a pointer to +** an sqlite3_pcache_page object associated with that page, or a NULL pointer. +** The pBuf element of the returned sqlite3_pcache_page object will be a +** pointer to a buffer of szPage bytes used to store the content of a +** single database page. The pExtra element of sqlite3_pcache_page will be +** a pointer to the szExtra bytes of extra storage that SQLite has requested +** for each entry in the page cache. +** +** The page to be fetched is determined by the key. ^The minimum key value +** is 1. After it has been retrieved using xFetch, the page is considered +** to be "pinned". +** +** If the requested page is already in the page cache, then the page cache +** implementation must return a pointer to the page buffer with its content +** intact. If the requested page is not already in the cache, then the +** cache implementation should use the value of the createFlag +** parameter to help it determined what action to take: +** +** +**
createFlag Behavior when page is not already in cache +**
0 Do not allocate a new page. Return NULL. +**
1 Allocate a new page if it easy and convenient to do so. +** Otherwise return NULL. +**
2 Make every effort to allocate a new page. Only return +** NULL if allocating a new page is effectively impossible. +**
+** +** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite +** will only use a createFlag of 2 after a prior call with a createFlag of 1 +** failed.)^ In between the to xFetch() calls, SQLite may +** attempt to unpin one or more cache pages by spilling the content of +** pinned pages to disk and synching the operating system disk cache. +** +** [[the xUnpin() page cache method]] +** ^xUnpin() is called by SQLite with a pointer to a currently pinned page +** as its second argument. If the third parameter, discard, is non-zero, +** then the page must be evicted from the cache. +** ^If the discard parameter is +** zero, then the page may be discarded or retained at the discretion of +** page cache implementation. ^The page cache implementation +** may choose to evict unpinned pages at any time. +** +** The cache must not perform any reference counting. A single +** call to xUnpin() unpins the page regardless of the number of prior calls +** to xFetch(). +** +** [[the xRekey() page cache methods]] +** The xRekey() method is used to change the key value associated with the +** page passed as the second argument. If the cache +** previously contains an entry associated with newKey, it must be +** discarded. ^Any prior cache entry associated with newKey is guaranteed not +** to be pinned. +** +** When SQLite calls the xTruncate() method, the cache must discard all +** existing cache entries with page numbers (keys) greater than or equal +** to the value of the iLimit parameter passed to xTruncate(). If any +** of these pages are pinned, they are implicitly unpinned, meaning that +** they can be safely discarded. +** +** [[the xDestroy() page cache method]] +** ^The xDestroy() method is used to delete a cache allocated by xCreate(). +** All resources associated with the specified cache should be freed. ^After +** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*] +** handle invalid, and will not use it with any other sqlite3_pcache_methods2 +** functions. +** +** [[the xShrink() page cache method]] +** ^SQLite invokes the xShrink() method when it wants the page cache to +** free up as much of heap memory as possible. The page cache implementation +** is not obligated to free any memory, but well-behaved implementations should +** do their best. +*/ +typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2; +struct sqlite3_pcache_methods2 +{ + int iVersion; + void *pArg; + int (*xInit)(void*); + void (*xShutdown)(void*); + sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable); + void (*xCachesize)(sqlite3_pcache*, int nCachesize); + int (*xPagecount)(sqlite3_pcache*); + sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); + void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard); + void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, + unsigned oldKey, unsigned newKey); + void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); + void (*xDestroy)(sqlite3_pcache*); + void (*xShrink)(sqlite3_pcache*); +}; + +/* +** This is the obsolete pcache_methods object that has now been replaced +** by sqlite3_pcache_methods2. This object is not used by SQLite. It is +** retained in the header file for backwards compatibility only. +*/ +typedef struct sqlite3_pcache_methods sqlite3_pcache_methods; +struct sqlite3_pcache_methods +{ + void *pArg; + int (*xInit)(void*); + void (*xShutdown)(void*); + sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable); + void (*xCachesize)(sqlite3_pcache*, int nCachesize); + int (*xPagecount)(sqlite3_pcache*); + void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); + void (*xUnpin)(sqlite3_pcache*, void*, int discard); + void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey); + void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); + void (*xDestroy)(sqlite3_pcache*); +}; + + +/* +** CAPI3REF: Online Backup Object +** +** The sqlite3_backup object records state information about an ongoing +** online backup operation. ^The sqlite3_backup object is created by +** a call to [sqlite3_backup_init()] and is destroyed by a call to +** [sqlite3_backup_finish()]. +** +** See Also: [Using the SQLite Online Backup API] +*/ +typedef struct sqlite3_backup sqlite3_backup; + +/* +** CAPI3REF: Online Backup API. +** +** The backup API copies the content of one database into another. +** It is useful either for creating backups of databases or +** for copying in-memory databases to or from persistent files. +** +** See Also: [Using the SQLite Online Backup API] +** +** ^SQLite holds a write transaction open on the destination database file +** for the duration of the backup operation. +** ^The source database is read-locked only while it is being read; +** it is not locked continuously for the entire backup operation. +** ^Thus, the backup may be performed on a live source database without +** preventing other database connections from +** reading or writing to the source database while the backup is underway. +** +** ^(To perform a backup operation: +**
    +**
  1. sqlite3_backup_init() is called once to initialize the +** backup, +**
  2. sqlite3_backup_step() is called one or more times to transfer +** the data between the two databases, and finally +**
  3. sqlite3_backup_finish() is called to release all resources +** associated with the backup operation. +**
)^ +** There should be exactly one call to sqlite3_backup_finish() for each +** successful call to sqlite3_backup_init(). +** +** [[sqlite3_backup_init()]] sqlite3_backup_init() +** +** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the +** [database connection] associated with the destination database +** and the database name, respectively. +** ^The database name is "main" for the main database, "temp" for the +** temporary database, or the name specified after the AS keyword in +** an [ATTACH] statement for an attached database. +** ^The S and M arguments passed to +** sqlite3_backup_init(D,N,S,M) identify the [database connection] +** and database name of the source database, respectively. +** ^The source and destination [database connections] (parameters S and D) +** must be different or else sqlite3_backup_init(D,N,S,M) will fail with +** an error. +** +** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is +** returned and an error code and error message are stored in the +** destination [database connection] D. +** ^The error code and message for the failed call to sqlite3_backup_init() +** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or +** [sqlite3_errmsg16()] functions. +** ^A successful call to sqlite3_backup_init() returns a pointer to an +** [sqlite3_backup] object. +** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and +** sqlite3_backup_finish() functions to perform the specified backup +** operation. +** +** [[sqlite3_backup_step()]] sqlite3_backup_step() +** +** ^Function sqlite3_backup_step(B,N) will copy up to N pages between +** the source and destination databases specified by [sqlite3_backup] object B. +** ^If N is negative, all remaining source pages are copied. +** ^If sqlite3_backup_step(B,N) successfully copies N pages and there +** are still more pages to be copied, then the function returns [SQLITE_OK]. +** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages +** from source to destination, then it returns [SQLITE_DONE]. +** ^If an error occurs while running sqlite3_backup_step(B,N), +** then an [error code] is returned. ^As well as [SQLITE_OK] and +** [SQLITE_DONE], a call to sqlite3_backup_step() may return [SQLITE_READONLY], +** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an +** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code. +** +** ^(The sqlite3_backup_step() might return [SQLITE_READONLY] if +**
    +**
  1. the destination database was opened read-only, or +**
  2. the destination database is using write-ahead-log journaling +** and the destination and source page sizes differ, or +**
  3. the destination database is an in-memory database and the +** destination and source page sizes differ. +**
)^ +** +** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then +** the [sqlite3_busy_handler | busy-handler function] +** is invoked (if one is specified). ^If the +** busy-handler returns non-zero before the lock is available, then +** [SQLITE_BUSY] is returned to the caller. ^In this case the call to +** sqlite3_backup_step() can be retried later. ^If the source +** [database connection] +** is being used to write to the source database when sqlite3_backup_step() +** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this +** case the call to sqlite3_backup_step() can be retried later on. ^(If +** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or +** [SQLITE_READONLY] is returned, then +** there is no point in retrying the call to sqlite3_backup_step(). These +** errors are considered fatal.)^ The application must accept +** that the backup operation has failed and pass the backup operation handle +** to the sqlite3_backup_finish() to release associated resources. +** +** ^The first call to sqlite3_backup_step() obtains an exclusive lock +** on the destination file. ^The exclusive lock is not released until either +** sqlite3_backup_finish() is called or the backup operation is complete +** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to +** sqlite3_backup_step() obtains a [shared lock] on the source database that +** lasts for the duration of the sqlite3_backup_step() call. +** ^Because the source database is not locked between calls to +** sqlite3_backup_step(), the source database may be modified mid-way +** through the backup process. ^If the source database is modified by an +** external process or via a database connection other than the one being +** used by the backup operation, then the backup will be automatically +** restarted by the next call to sqlite3_backup_step(). ^If the source +** database is modified by the using the same database connection as is used +** by the backup operation, then the backup database is automatically +** updated at the same time. +** +** [[sqlite3_backup_finish()]] sqlite3_backup_finish() +** +** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the +** application wishes to abandon the backup operation, the application +** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish(). +** ^The sqlite3_backup_finish() interfaces releases all +** resources associated with the [sqlite3_backup] object. +** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any +** active write-transaction on the destination database is rolled back. +** The [sqlite3_backup] object is invalid +** and may not be used following a call to sqlite3_backup_finish(). +** +** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no +** sqlite3_backup_step() errors occurred, regardless or whether or not +** sqlite3_backup_step() completed. +** ^If an out-of-memory condition or IO error occurred during any prior +** sqlite3_backup_step() call on the same [sqlite3_backup] object, then +** sqlite3_backup_finish() returns the corresponding [error code]. +** +** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step() +** is not a permanent error and does not affect the return value of +** sqlite3_backup_finish(). +** +** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]] +** sqlite3_backup_remaining() and sqlite3_backup_pagecount() +** +** ^Each call to sqlite3_backup_step() sets two values inside +** the [sqlite3_backup] object: the number of pages still to be backed +** up and the total number of pages in the source database file. +** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces +** retrieve these two values, respectively. +** +** ^The values returned by these functions are only updated by +** sqlite3_backup_step(). ^If the source database is modified during a backup +** operation, then the values are not updated to account for any extra +** pages that need to be updated or the size of the source database file +** changing. +** +** Concurrent Usage of Database Handles +** +** ^The source [database connection] may be used by the application for other +** purposes while a backup operation is underway or being initialized. +** ^If SQLite is compiled and configured to support threadsafe database +** connections, then the source database connection may be used concurrently +** from within other threads. +** +** However, the application must guarantee that the destination +** [database connection] is not passed to any other API (by any thread) after +** sqlite3_backup_init() is called and before the corresponding call to +** sqlite3_backup_finish(). SQLite does not currently check to see +** if the application incorrectly accesses the destination [database connection] +** and so no error code is reported, but the operations may malfunction +** nevertheless. Use of the destination database connection while a +** backup is in progress might also also cause a mutex deadlock. +** +** If running in [shared cache mode], the application must +** guarantee that the shared cache used by the destination database +** is not accessed while the backup is running. In practice this means +** that the application must guarantee that the disk file being +** backed up to is not accessed by any connection within the process, +** not just the specific connection that was passed to sqlite3_backup_init(). +** +** The [sqlite3_backup] object itself is partially threadsafe. Multiple +** threads may safely make multiple concurrent calls to sqlite3_backup_step(). +** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount() +** APIs are not strictly speaking threadsafe. If they are invoked at the +** same time as another thread is invoking sqlite3_backup_step() it is +** possible that they return invalid values. +*/ +SQLITE_API sqlite3_backup *sqlite3_backup_init( + sqlite3 *pDest, /* Destination database handle */ + const char *zDestName, /* Destination database name */ + sqlite3 *pSource, /* Source database handle */ + const char *zSourceName /* Source database name */ +); +SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); +SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); + +/* +** CAPI3REF: Unlock Notification +** +** ^When running in shared-cache mode, a database operation may fail with +** an [SQLITE_LOCKED] error if the required locks on the shared-cache or +** individual tables within the shared-cache cannot be obtained. See +** [SQLite Shared-Cache Mode] for a description of shared-cache locking. +** ^This API may be used to register a callback that SQLite will invoke +** when the connection currently holding the required lock relinquishes it. +** ^This API is only available if the library was compiled with the +** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined. +** +** See Also: [Using the SQLite Unlock Notification Feature]. +** +** ^Shared-cache locks are released when a database connection concludes +** its current transaction, either by committing it or rolling it back. +** +** ^When a connection (known as the blocked connection) fails to obtain a +** shared-cache lock and SQLITE_LOCKED is returned to the caller, the +** identity of the database connection (the blocking connection) that +** has locked the required resource is stored internally. ^After an +** application receives an SQLITE_LOCKED error, it may call the +** sqlite3_unlock_notify() method with the blocked connection handle as +** the first argument to register for a callback that will be invoked +** when the blocking connections current transaction is concluded. ^The +** callback is invoked from within the [sqlite3_step] or [sqlite3_close] +** call that concludes the blocking connections transaction. +** +** ^(If sqlite3_unlock_notify() is called in a multi-threaded application, +** there is a chance that the blocking connection will have already +** concluded its transaction by the time sqlite3_unlock_notify() is invoked. +** If this happens, then the specified callback is invoked immediately, +** from within the call to sqlite3_unlock_notify().)^ +** +** ^If the blocked connection is attempting to obtain a write-lock on a +** shared-cache table, and more than one other connection currently holds +** a read-lock on the same table, then SQLite arbitrarily selects one of +** the other connections to use as the blocking connection. +** +** ^(There may be at most one unlock-notify callback registered by a +** blocked connection. If sqlite3_unlock_notify() is called when the +** blocked connection already has a registered unlock-notify callback, +** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is +** called with a NULL pointer as its second argument, then any existing +** unlock-notify callback is canceled. ^The blocked connections +** unlock-notify callback may also be canceled by closing the blocked +** connection using [sqlite3_close()]. +** +** The unlock-notify callback is not reentrant. If an application invokes +** any sqlite3_xxx API functions from within an unlock-notify callback, a +** crash or deadlock may be the result. +** +** ^Unless deadlock is detected (see below), sqlite3_unlock_notify() always +** returns SQLITE_OK. +** +** Callback Invocation Details +** +** When an unlock-notify callback is registered, the application provides a +** single void* pointer that is passed to the callback when it is invoked. +** However, the signature of the callback function allows SQLite to pass +** it an array of void* context pointers. The first argument passed to +** an unlock-notify callback is a pointer to an array of void* pointers, +** and the second is the number of entries in the array. +** +** When a blocking connections transaction is concluded, there may be +** more than one blocked connection that has registered for an unlock-notify +** callback. ^If two or more such blocked connections have specified the +** same callback function, then instead of invoking the callback function +** multiple times, it is invoked once with the set of void* context pointers +** specified by the blocked connections bundled together into an array. +** This gives the application an opportunity to prioritize any actions +** related to the set of unblocked database connections. +** +** Deadlock Detection +** +** Assuming that after registering for an unlock-notify callback a +** database waits for the callback to be issued before taking any further +** action (a reasonable assumption), then using this API may cause the +** application to deadlock. For example, if connection X is waiting for +** connection Y's transaction to be concluded, and similarly connection +** Y is waiting on connection X's transaction, then neither connection +** will proceed and the system may remain deadlocked indefinitely. +** +** To avoid this scenario, the sqlite3_unlock_notify() performs deadlock +** detection. ^If a given call to sqlite3_unlock_notify() would put the +** system in a deadlocked state, then SQLITE_LOCKED is returned and no +** unlock-notify callback is registered. The system is said to be in +** a deadlocked state if connection A has registered for an unlock-notify +** callback on the conclusion of connection B's transaction, and connection +** B has itself registered for an unlock-notify callback when connection +** A's transaction is concluded. ^Indirect deadlock is also detected, so +** the system is also considered to be deadlocked if connection B has +** registered for an unlock-notify callback on the conclusion of connection +** C's transaction, where connection C is waiting on connection A. ^Any +** number of levels of indirection are allowed. +** +** The "DROP TABLE" Exception +** +** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost +** always appropriate to call sqlite3_unlock_notify(). There is however, +** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement, +** SQLite checks if there are any currently executing SELECT statements +** that belong to the same connection. If there are, SQLITE_LOCKED is +** returned. In this case there is no "blocking connection", so invoking +** sqlite3_unlock_notify() results in the unlock-notify callback being +** invoked immediately. If the application then re-attempts the "DROP TABLE" +** or "DROP INDEX" query, an infinite loop might be the result. +** +** One way around this problem is to check the extended error code returned +** by an sqlite3_step() call. ^(If there is a blocking connection, then the +** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in +** the special "DROP TABLE/INDEX" case, the extended error code is just +** SQLITE_LOCKED.)^ +*/ +SQLITE_API int sqlite3_unlock_notify( + sqlite3 *pBlocked, /* Waiting connection */ + void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ + void *pNotifyArg /* Argument to pass to xNotify */ +); + + +/* +** CAPI3REF: String Comparison +** +** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications +** and extensions to compare the contents of two buffers containing UTF-8 +** strings in a case-independent fashion, using the same definition of "case +** independence" that SQLite uses internally when comparing identifiers. +*/ +SQLITE_API int sqlite3_stricmp(const char *, const char *); +SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); + +/* +** CAPI3REF: String Globbing +* +** ^The [sqlite3_strglob(P,X)] interface returns zero if string X matches +** the glob pattern P, and it returns non-zero if string X does not match +** the glob pattern P. ^The definition of glob pattern matching used in +** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the +** SQL dialect used by SQLite. ^The sqlite3_strglob(P,X) function is case +** sensitive. +** +** Note that this routine returns zero on a match and non-zero if the strings +** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. +*/ +SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); + +/* +** CAPI3REF: Error Logging Interface +** +** ^The [sqlite3_log()] interface writes a message into the [error log] +** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. +** ^If logging is enabled, the zFormat string and subsequent arguments are +** used with [sqlite3_snprintf()] to generate the final output string. +** +** The sqlite3_log() interface is intended for use by extensions such as +** virtual tables, collating functions, and SQL functions. While there is +** nothing to prevent an application from calling sqlite3_log(), doing so +** is considered bad form. +** +** The zFormat string must not be NULL. +** +** To avoid deadlocks and other threading problems, the sqlite3_log() routine +** will not use dynamically allocated memory. The log message is stored in +** a fixed-length buffer on the stack. If the log message is longer than +** a few hundred characters, it will be truncated to the length of the +** buffer. +*/ +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); + +/* +** CAPI3REF: Write-Ahead Log Commit Hook +** +** ^The [sqlite3_wal_hook()] function is used to register a callback that +** will be invoked each time a database connection commits data to a +** [write-ahead log] (i.e. whenever a transaction is committed in +** [journal_mode | journal_mode=WAL mode]). +** +** ^The callback is invoked by SQLite after the commit has taken place and +** the associated write-lock on the database released, so the implementation +** may read, write or [checkpoint] the database as required. +** +** ^The first parameter passed to the callback function when it is invoked +** is a copy of the third parameter passed to sqlite3_wal_hook() when +** registering the callback. ^The second is a copy of the database handle. +** ^The third parameter is the name of the database that was written to - +** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter +** is the number of pages currently in the write-ahead log file, +** including those that were just committed. +** +** The callback function should normally return [SQLITE_OK]. ^If an error +** code is returned, that error will propagate back up through the +** SQLite code base to cause the statement that provoked the callback +** to report an error, though the commit will have still occurred. If the +** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value +** that does not correspond to any valid SQLite error code, the results +** are undefined. +** +** A single database handle may have at most a single write-ahead log callback +** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any +** previously registered write-ahead log callback. ^Note that the +** [sqlite3_wal_autocheckpoint()] interface and the +** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will +** those overwrite any prior [sqlite3_wal_hook()] settings. +*/ +SQLITE_API void *sqlite3_wal_hook( + sqlite3*, + int(*)(void *,sqlite3*,const char*,int), + void* +); + +/* +** CAPI3REF: Configure an auto-checkpoint +** +** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around +** [sqlite3_wal_hook()] that causes any database on [database connection] D +** to automatically [checkpoint] +** after committing a transaction if there are N or +** more frames in the [write-ahead log] file. ^Passing zero or +** a negative value as the nFrame parameter disables automatic +** checkpoints entirely. +** +** ^The callback registered by this function replaces any existing callback +** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback +** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism +** configured by this function. +** +** ^The [wal_autocheckpoint pragma] can be used to invoke this interface +** from SQL. +** +** ^Every new [database connection] defaults to having the auto-checkpoint +** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT] +** pages. The use of this interface +** is only necessary if the default setting is found to be suboptimal +** for a particular application. +*/ +SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); + +/* +** CAPI3REF: Checkpoint a database +** +** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X +** on [database connection] D to be [checkpointed]. ^If X is NULL or an +** empty string, then a checkpoint is run on all databases of +** connection D. ^If the database connection D is not in +** [WAL | write-ahead log mode] then this interface is a harmless no-op. +** +** ^The [wal_checkpoint pragma] can be used to invoke this interface +** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the +** [wal_autocheckpoint pragma] can be used to cause this interface to be +** run whenever the WAL reaches a certain size threshold. +** +** See also: [sqlite3_wal_checkpoint_v2()] +*/ +SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); + +/* +** CAPI3REF: Checkpoint a database +** +** Run a checkpoint operation on WAL database zDb attached to database +** handle db. The specific operation is determined by the value of the +** eMode parameter: +** +**
+**
SQLITE_CHECKPOINT_PASSIVE
+** Checkpoint as many frames as possible without waiting for any database +** readers or writers to finish. Sync the db file if all frames in the log +** are checkpointed. This mode is the same as calling +** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked. +** +**
SQLITE_CHECKPOINT_FULL
+** This mode blocks (calls the busy-handler callback) until there is no +** database writer and all readers are reading from the most recent database +** snapshot. It then checkpoints all frames in the log file and syncs the +** database file. This call blocks database writers while it is running, +** but not database readers. +** +**
SQLITE_CHECKPOINT_RESTART
+** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after +** checkpointing the log file it blocks (calls the busy-handler callback) +** until all readers are reading from the database file only. This ensures +** that the next client to write to the database file restarts the log file +** from the beginning. This call blocks database writers while it is running, +** but not database readers. +**
+** +** If pnLog is not NULL, then *pnLog is set to the total number of frames in +** the log file before returning. If pnCkpt is not NULL, then *pnCkpt is set to +** the total number of checkpointed frames (including any that were already +** checkpointed when this function is called). *pnLog and *pnCkpt may be +** populated even if sqlite3_wal_checkpoint_v2() returns other than SQLITE_OK. +** If no values are available because of an error, they are both set to -1 +** before returning to communicate this to the caller. +** +** All calls obtain an exclusive "checkpoint" lock on the database file. If +** any other process is running a checkpoint operation at the same time, the +** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a +** busy-handler configured, it will not be invoked in this case. +** +** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive +** "writer" lock on the database file. If the writer lock cannot be obtained +** immediately, and a busy-handler is configured, it is invoked and the writer +** lock retried until either the busy-handler returns 0 or the lock is +** successfully obtained. The busy-handler is also invoked while waiting for +** database readers as described above. If the busy-handler returns 0 before +** the writer lock is obtained or while waiting for database readers, the +** checkpoint operation proceeds from that point in the same way as +** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible +** without blocking any further. SQLITE_BUSY is returned in this case. +** +** If parameter zDb is NULL or points to a zero length string, then the +** specified operation is attempted on all WAL databases. In this case the +** values written to output parameters *pnLog and *pnCkpt are undefined. If +** an SQLITE_BUSY error is encountered when processing one or more of the +** attached WAL databases, the operation is still attempted on any remaining +** attached databases and SQLITE_BUSY is returned to the caller. If any other +** error occurs while processing an attached database, processing is abandoned +** and the error code returned to the caller immediately. If no error +** (SQLITE_BUSY or otherwise) is encountered while processing the attached +** databases, SQLITE_OK is returned. +** +** If database zDb is the name of an attached database that is not in WAL +** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. If +** zDb is not NULL (or a zero length string) and is not the name of any +** attached database, SQLITE_ERROR is returned to the caller. +*/ +SQLITE_API int sqlite3_wal_checkpoint_v2( + sqlite3 *db, /* Database handle */ + const char *zDb, /* Name of attached database (or NULL) */ + int eMode, /* SQLITE_CHECKPOINT_* value */ + int *pnLog, /* OUT: Size of WAL log in frames */ + int *pnCkpt /* OUT: Total number of frames checkpointed */ +); + +/* +** CAPI3REF: Checkpoint operation parameters +** +** These constants can be used as the 3rd parameter to +** [sqlite3_wal_checkpoint_v2()]. See the [sqlite3_wal_checkpoint_v2()] +** documentation for additional information about the meaning and use of +** each of these values. +*/ +#define SQLITE_CHECKPOINT_PASSIVE 0 +#define SQLITE_CHECKPOINT_FULL 1 +#define SQLITE_CHECKPOINT_RESTART 2 + +/* +** CAPI3REF: Virtual Table Interface Configuration +** +** This function may be called by either the [xConnect] or [xCreate] method +** of a [virtual table] implementation to configure +** various facets of the virtual table interface. +** +** If this interface is invoked outside the context of an xConnect or +** xCreate virtual table method then the behavior is undefined. +** +** At present, there is only one option that may be configured using +** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options +** may be added in the future. +*/ +SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); + +/* +** CAPI3REF: Virtual Table Configuration Options +** +** These macros define the various options to the +** [sqlite3_vtab_config()] interface that [virtual table] implementations +** can use to customize and optimize their behavior. +** +**
+**
SQLITE_VTAB_CONSTRAINT_SUPPORT +**
Calls of the form +** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, +** where X is an integer. If X is zero, then the [virtual table] whose +** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not +** support constraints. In this configuration (which is the default) if +** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire +** statement is rolled back as if [ON CONFLICT | OR ABORT] had been +** specified as part of the users SQL statement, regardless of the actual +** ON CONFLICT mode specified. +** +** If X is non-zero, then the virtual table implementation guarantees +** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before +** any modifications to internal or persistent data structures have been made. +** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite +** is able to roll back a statement or database transaction, and abandon +** or continue processing the current SQL statement as appropriate. +** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns +** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode +** had been ABORT. +** +** Virtual table implementations that are required to handle OR REPLACE +** must do so within the [xUpdate] method. If a call to the +** [sqlite3_vtab_on_conflict()] function indicates that the current ON +** CONFLICT policy is REPLACE, the virtual table implementation should +** silently replace the appropriate rows within the xUpdate callback and +** return SQLITE_OK. Or, if this is not possible, it may return +** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT +** constraint handling. +**
+*/ +#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1 + +/* +** CAPI3REF: Determine The Virtual Table Conflict Policy +** +** This function may only be called from within a call to the [xUpdate] method +** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The +** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL], +** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode +** of the SQL statement that triggered the call to the [xUpdate] method of the +** [virtual table]. +*/ +SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); + +/* +** CAPI3REF: Conflict resolution modes +** +** These constants are returned by [sqlite3_vtab_on_conflict()] to +** inform a [virtual table] implementation what the [ON CONFLICT] mode +** is for the SQL statement being evaluated. +** +** Note that the [SQLITE_IGNORE] constant is also used as a potential +** return value from the [sqlite3_set_authorizer()] callback and that +** [SQLITE_ABORT] is also a [result code]. +*/ +#define SQLITE_ROLLBACK 1 +/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */ +#define SQLITE_FAIL 3 +/* #define SQLITE_ABORT 4 // Also an error code */ +#define SQLITE_REPLACE 5 + + + +/* +** Undo the hack that converts floating point types to integer for +** builds on processors without floating point support. +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# undef double +#endif + +#ifdef __cplusplus +} /* End of the 'extern "C"' block */ +#endif +#endif /* _SQLITE3_H_ */ + +/* +** 2010 August 30 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +*/ + +#ifndef _SQLITE3RTREE_H_ +#define _SQLITE3RTREE_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; + +/* +** Register a geometry callback named zGeom that can be used as part of an +** R-Tree geometry query as follows: +** +** SELECT ... FROM WHERE MATCH $zGeom(... params ...) +*/ +SQLITE_API int sqlite3_rtree_geometry_callback( + sqlite3 *db, + const char *zGeom, +#ifdef SQLITE_RTREE_INT_ONLY + int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes), +#else + int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes), +#endif + void *pContext +); + + +/* +** A pointer to a structure of the following type is passed as the first +** argument to callbacks registered using rtree_geometry_callback(). +*/ +struct sqlite3_rtree_geometry +{ + void *pContext; /* Copy of pContext passed to s_r_g_c() */ + int nParam; /* Size of array aParam[] */ + double *aParam; /* Parameters passed to SQL geom function */ + void *pUser; /* Callback implementation user data */ + void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ +}; + + +#ifdef __cplusplus +} /* end of the 'extern "C"' block */ +#endif + +#endif /* ifndef _SQLITE3RTREE_H_ */ + diff --git a/x64_dbg_dbg/test/general/dll/main.cpp b/x64_dbg_dbg/test/general/dll/main.cpp new file mode 100644 index 00000000..a0294535 --- /dev/null +++ b/x64_dbg_dbg/test/general/dll/main.cpp @@ -0,0 +1,39 @@ +#include "main.h" + +char global[10]="0"; + +// a sample exported function +void DLL_EXPORT SomeFunction(const LPCSTR sometext) +{ + MessageBoxA(0, sometext, "DLL Message", MB_OK | MB_ICONINFORMATION); +} + +extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + { + GetTickCount(); + GetCurrentProcessId(); + GetCurrentProcess(); + DWORD old=0; + VirtualProtect(global, 10, PAGE_GUARD, &old); + asm("int3"); + } + break; + + case DLL_PROCESS_DETACH: + // detach from process + break; + + case DLL_THREAD_ATTACH: + // attach to thread + break; + + case DLL_THREAD_DETACH: + // detach from thread + break; + } + return TRUE; // succesful +} diff --git a/x64_dbg_dbg/test/general/dll/main.h b/x64_dbg_dbg/test/general/dll/main.h new file mode 100644 index 00000000..ee03cf33 --- /dev/null +++ b/x64_dbg_dbg/test/general/dll/main.h @@ -0,0 +1,28 @@ +#ifndef __MAIN_H__ +#define __MAIN_H__ + +#include + +/* To use this exported function of dll, include this header + * in your project. + */ + +#ifdef BUILD_DLL + #define DLL_EXPORT __declspec(dllexport) +#else + #define DLL_EXPORT __declspec(dllimport) +#endif + + +#ifdef __cplusplus +extern "C" +{ +#endif + +void DLL_EXPORT SomeFunction(const LPCSTR sometext); + +#ifdef __cplusplus +} +#endif + +#endif // __MAIN_H__ diff --git a/x64_dbg_dbg/test/general/dll/test_dll.cbp b/x64_dbg_dbg/test/general/dll/test_dll.cbp new file mode 100644 index 00000000..93335a83 --- /dev/null +++ b/x64_dbg_dbg/test/general/dll/test_dll.cbp @@ -0,0 +1,49 @@ + + + + + + diff --git a/x64_dbg_dbg/test/general/exe/main.cpp b/x64_dbg_dbg/test/general/exe/main.cpp new file mode 100644 index 00000000..773b803e --- /dev/null +++ b/x64_dbg_dbg/test/general/exe/main.cpp @@ -0,0 +1,20 @@ +#include + +char global[10]="0"; + +int main() +{ + GetTickCount(); + char* a=0; + + GetCurrentProcessId(); + GetCurrentProcess(); + DWORD old=0; + VirtualProtect(global, 0x1000, PAGE_READWRITE|PAGE_GUARD, &old); + + /*throw exceptions*/ + global[0]=0; //PAGE_GUARD + *a=0; //ACCESS_VIOLATION + asm("int3"); //BREAKPOINT + return 0; +} diff --git a/x64_dbg_dbg/test/general/exe/test_exe.cbp b/x64_dbg_dbg/test/general/exe/test_exe.cbp new file mode 100644 index 00000000..1795da07 --- /dev/null +++ b/x64_dbg_dbg/test/general/exe/test_exe.cbp @@ -0,0 +1,48 @@ + + + + + + diff --git a/x64_dbg_dbg/test/guard_page/guard_page_test.cbp b/x64_dbg_dbg/test/guard_page/guard_page_test.cbp new file mode 100644 index 00000000..2738e0d1 --- /dev/null +++ b/x64_dbg_dbg/test/guard_page/guard_page_test.cbp @@ -0,0 +1,45 @@ + + + + + + diff --git a/x64_dbg_dbg/test/guard_page/main.cpp b/x64_dbg_dbg/test/guard_page/main.cpp new file mode 100644 index 00000000..faa75832 --- /dev/null +++ b/x64_dbg_dbg/test/guard_page/main.cpp @@ -0,0 +1,37 @@ +#include +#include + +typedef bool (*CBRET)(); + +unsigned int globalvar=0; + +int main() +{ + unsigned int lol; + unsigned char* page=(unsigned char*)VirtualAlloc(0, 0x1000, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if(!page) + { + puts("error: VirtualAlloc"); + return 1; + } + page[0]=0x6A; + puts("write"); + page[1]=0x01; + puts("write"); + page[2]=0x58; + puts("write"); + page[3]=0xC3; + puts("write"); + CBRET cb=(CBRET)page; + cb(); + puts("exec"); + lol=globalvar; + puts("read"); + lol=page[1]; + puts("read"); + lol=page[3]; + puts("read"); + lol=page[2]; + puts("read"); + return 0; +} diff --git a/x64_dbg_dbg/test/highlighting/x32/highlighting.asm b/x64_dbg_dbg/test/highlighting/x32/highlighting.asm new file mode 100644 index 00000000..05be45a9 --- /dev/null +++ b/x64_dbg_dbg/test/highlighting/x32/highlighting.asm @@ -0,0 +1,20 @@ +global _start + +section .data +@real: + db 0 + +section .text + _start: + MOV EAX,DWORD [@real] + MOV EAX,DWORD [EAX*4+@real] + MOV EAX,DWORD [EAX+@real] + MOV EAX,@real + MOV EBX,DWORD [EAX] + MOV EBX,4 + XOR EDX,EDX + DIV EBX + MOV EAX,DWORD [EAX*4] + JMP SHORT @next +@next: + RET \ No newline at end of file diff --git a/x64_dbg_dbg/test/highlighting/x32/highlighting.bat b/x64_dbg_dbg/test/highlighting/x32/highlighting.bat new file mode 100644 index 00000000..a4d41cc4 --- /dev/null +++ b/x64_dbg_dbg/test/highlighting/x32/highlighting.bat @@ -0,0 +1,5 @@ +@echo off +nasm -f win32 highlighting.asm +golink highlighting.obj /entry _start +del /Q *.obj +pause \ No newline at end of file diff --git a/x64_dbg_dbg/test/highlighting/x64/highlighting.asm b/x64_dbg_dbg/test/highlighting/x64/highlighting.asm new file mode 100644 index 00000000..206c7c28 --- /dev/null +++ b/x64_dbg_dbg/test/highlighting/x64/highlighting.asm @@ -0,0 +1,20 @@ +global _start + +section .data +@real: + db 0 + +section .text + _start: + MOV RAX,QWORD [@real] + MOV RAX,QWORD [RAX*4+@real] + MOV RAX,QWORD [RAX+@real] + MOV RAX,@real + MOV RBX,QWORD [RAX] + MOV RBX,4 + XOR RDX,RDX + DIV RBX + MOV RAX,QWORD [RAX*4] + JMP SHORT @next +@next: + RET \ No newline at end of file diff --git a/x64_dbg_dbg/test/highlighting/x64/highlighting.bat b/x64_dbg_dbg/test/highlighting/x64/highlighting.bat new file mode 100644 index 00000000..ded4cb53 --- /dev/null +++ b/x64_dbg_dbg/test/highlighting/x64/highlighting.bat @@ -0,0 +1,5 @@ +@echo off +nasm -f win64 highlighting.asm +golink highlighting.obj /entry _start +del /Q *.obj +pause \ No newline at end of file diff --git a/x64_dbg_dbg/test/mmx_sse_fpu/x32/fpu/fpu.asm b/x64_dbg_dbg/test/mmx_sse_fpu/x32/fpu/fpu.asm new file mode 100644 index 00000000..5e6e0df6 --- /dev/null +++ b/x64_dbg_dbg/test/mmx_sse_fpu/x32/fpu/fpu.asm @@ -0,0 +1,23 @@ +global _start + +section .data + a: dq 1.1 + b: dq 2.2 + c: dq 3.3 + d: dq 4.4 + e: dq 5.5 + f: dq 6.6 + g: dq 7.7 + h: dq 8.8 + +section .text + _start: + fld qword [a] + fld qword [b] + fld qword [c] + fld qword [d] + fld qword [e] + fld qword [f] + fld qword [g] + fld qword [h] + ret \ No newline at end of file diff --git a/x64_dbg_dbg/test/mmx_sse_fpu/x32/fpu/fpu_build.bat b/x64_dbg_dbg/test/mmx_sse_fpu/x32/fpu/fpu_build.bat new file mode 100644 index 00000000..e39a718b --- /dev/null +++ b/x64_dbg_dbg/test/mmx_sse_fpu/x32/fpu/fpu_build.bat @@ -0,0 +1,6 @@ +@echo off +nasm -f win32 fpu.asm +golink fpu.obj /entry _start +del /Q *.obj +move fpu.exe ..\fpu.exe > nul +pause \ No newline at end of file diff --git a/x64_dbg_dbg/test/mmx_sse_fpu/x32/mmx/mmx.asm b/x64_dbg_dbg/test/mmx_sse_fpu/x32/mmx/mmx.asm new file mode 100644 index 00000000..96b9edb4 --- /dev/null +++ b/x64_dbg_dbg/test/mmx_sse_fpu/x32/mmx/mmx.asm @@ -0,0 +1,23 @@ +global _start + +section .data + a: dq 1111111122222222h + b: dq 2222222233333333h + c: dq 3333333344444444h + d: dq 4444444455555555h + e: dq 5555555566666666h + f: dq 6666666677777777h + g: dq 7777777788888888h + h: dq 8888888811111111h + +section .text + _start: + movq mm0,[a] + movq mm1,[b] + movq mm2,[c] + movq mm3,[d] + movq mm4,[e] + movq mm5,[f] + movq mm6,[g] + movq mm7,[h] + ret \ No newline at end of file diff --git a/x64_dbg_dbg/test/mmx_sse_fpu/x32/mmx/mmx_build.bat b/x64_dbg_dbg/test/mmx_sse_fpu/x32/mmx/mmx_build.bat new file mode 100644 index 00000000..9a22deb8 --- /dev/null +++ b/x64_dbg_dbg/test/mmx_sse_fpu/x32/mmx/mmx_build.bat @@ -0,0 +1,6 @@ +@echo off +nasm -fwin32 mmx.asm +golink mmx.obj /entry _start +del /Q *.obj +move mmx.exe ..\mmx.exe > nul +pause \ No newline at end of file diff --git a/x64_dbg_dbg/test/mmx_sse_fpu/x32/sse/sse.asm b/x64_dbg_dbg/test/mmx_sse_fpu/x32/sse/sse.asm new file mode 100644 index 00000000..ce15dc31 --- /dev/null +++ b/x64_dbg_dbg/test/mmx_sse_fpu/x32/sse/sse.asm @@ -0,0 +1,30 @@ +global _start + +section .data + align 16 + v1: dd 1.1, 2.2, 3.3, 4.4 + v2: dd 5.5, 6.6, 7.7, 8.8 + v3: dd 9.9, 10.10, 11.11, 12.12 + v4: dd 13.13, 14.14, 15.15, 16.16 + v5: dd 17.17, 18.18, 19.19, 20.20 + v6: dd 21.21, 22.22, 23.23, 24.24 + v7: dd 25.25, 26.26, 27.27, 28.28 + v8: dd 29.29, 30.30, 31.31, 32.32 + +section .bss + mask1: resd 1 + mask2: resd 1 + mask3: resd 1 + mask4: resd 1 + +section .text + _start: + movaps xmm0, [v1] + movaps xmm1, [v2] + movaps xmm2, [v3] + movaps xmm3, [v4] + movaps xmm4, [v5] + movaps xmm5, [v6] + movaps xmm6, [v7] + movaps xmm7, [v8] + ret \ No newline at end of file diff --git a/x64_dbg_dbg/test/mmx_sse_fpu/x32/sse/sse_build.bat b/x64_dbg_dbg/test/mmx_sse_fpu/x32/sse/sse_build.bat new file mode 100644 index 00000000..577550e3 --- /dev/null +++ b/x64_dbg_dbg/test/mmx_sse_fpu/x32/sse/sse_build.bat @@ -0,0 +1,6 @@ +@echo off +nasm -fwin32 sse.asm +golink sse.obj /entry _start +del /Q *.obj +move sse.exe ..\sse.exe > nul +pause \ No newline at end of file diff --git a/x64_dbg_dbg/test/mmx_sse_fpu/x64/fpu/fpu.asm b/x64_dbg_dbg/test/mmx_sse_fpu/x64/fpu/fpu.asm new file mode 100644 index 00000000..5e6e0df6 --- /dev/null +++ b/x64_dbg_dbg/test/mmx_sse_fpu/x64/fpu/fpu.asm @@ -0,0 +1,23 @@ +global _start + +section .data + a: dq 1.1 + b: dq 2.2 + c: dq 3.3 + d: dq 4.4 + e: dq 5.5 + f: dq 6.6 + g: dq 7.7 + h: dq 8.8 + +section .text + _start: + fld qword [a] + fld qword [b] + fld qword [c] + fld qword [d] + fld qword [e] + fld qword [f] + fld qword [g] + fld qword [h] + ret \ No newline at end of file diff --git a/x64_dbg_dbg/test/mmx_sse_fpu/x64/fpu/fpu_build.bat b/x64_dbg_dbg/test/mmx_sse_fpu/x64/fpu/fpu_build.bat new file mode 100644 index 00000000..fabae29f --- /dev/null +++ b/x64_dbg_dbg/test/mmx_sse_fpu/x64/fpu/fpu_build.bat @@ -0,0 +1,6 @@ +@echo off +nasm -f win64 fpu.asm +golink fpu.obj /entry _start +del /Q *.obj +move fpu.exe ..\fpu.exe > nul +pause \ No newline at end of file diff --git a/x64_dbg_dbg/test/mmx_sse_fpu/x64/mmx/mmx.asm b/x64_dbg_dbg/test/mmx_sse_fpu/x64/mmx/mmx.asm new file mode 100644 index 00000000..96b9edb4 --- /dev/null +++ b/x64_dbg_dbg/test/mmx_sse_fpu/x64/mmx/mmx.asm @@ -0,0 +1,23 @@ +global _start + +section .data + a: dq 1111111122222222h + b: dq 2222222233333333h + c: dq 3333333344444444h + d: dq 4444444455555555h + e: dq 5555555566666666h + f: dq 6666666677777777h + g: dq 7777777788888888h + h: dq 8888888811111111h + +section .text + _start: + movq mm0,[a] + movq mm1,[b] + movq mm2,[c] + movq mm3,[d] + movq mm4,[e] + movq mm5,[f] + movq mm6,[g] + movq mm7,[h] + ret \ No newline at end of file diff --git a/x64_dbg_dbg/test/mmx_sse_fpu/x64/mmx/mmx_build.bat b/x64_dbg_dbg/test/mmx_sse_fpu/x64/mmx/mmx_build.bat new file mode 100644 index 00000000..597ad851 --- /dev/null +++ b/x64_dbg_dbg/test/mmx_sse_fpu/x64/mmx/mmx_build.bat @@ -0,0 +1,6 @@ +@echo off +nasm -fwin64 mmx.asm +golink mmx.obj /entry _start +del /Q *.obj +move mmx.exe ..\mmx.exe > nul +pause \ No newline at end of file diff --git a/x64_dbg_dbg/test/mmx_sse_fpu/x64/sse/sse.asm b/x64_dbg_dbg/test/mmx_sse_fpu/x64/sse/sse.asm new file mode 100644 index 00000000..6abb2f02 --- /dev/null +++ b/x64_dbg_dbg/test/mmx_sse_fpu/x64/sse/sse.asm @@ -0,0 +1,46 @@ +global _start + +section .data + align 16 + v1: dd 1.1, 2.2, 3.3, 4.4 + v2: dd 5.5, 6.6, 7.7, 8.8 + v3: dd 9.9, 10.10, 11.11, 12.12 + v4: dd 13.13, 14.14, 15.15, 16.16 + v5: dd 17.17, 18.18, 19.19, 20.20 + v6: dd 21.21, 22.22, 23.23, 24.24 + v7: dd 25.25, 26.26, 27.27, 28.28 + v8: dd 29.29, 30.30, 31.31, 32.32 + v9: dd 29.29, 30.30, 31.31, 32.32 + v10: dd 33.33, 33.33, 33.33, 33.33 + v11: dd 34.34, 34.34, 34.34, 34.34 + v12: dd 35.35, 35.35, 35.35, 35.35 + v13: dd 36.36, 36.36, 36.36, 36.36 + v14: dd 37.37, 37.37, 37.37, 37.37 + v15: dd 38.38, 38.38, 38.38, 38.38 + v16: dd 39.39, 39.39, 39.39, 39.39 + +section .bss + mask1: resd 1 + mask2: resd 1 + mask3: resd 1 + mask4: resd 1 + +section .text + _start: + movaps xmm0, [v1] + movaps xmm1, [v2] + movaps xmm2, [v3] + movaps xmm3, [v4] + movaps xmm4, [v5] + movaps xmm5, [v6] + movaps xmm6, [v7] + movaps xmm7, [v8] + movaps xmm8, [v9] + movaps xmm9, [v10] + movaps xmm10, [v11] + movaps xmm11, [v12] + movaps xmm12, [v13] + movaps xmm13, [v14] + movaps xmm14, [v15] + movaps xmm15, [v16] + ret \ No newline at end of file diff --git a/x64_dbg_dbg/test/mmx_sse_fpu/x64/sse/sse_build.bat b/x64_dbg_dbg/test/mmx_sse_fpu/x64/sse/sse_build.bat new file mode 100644 index 00000000..fd206c6f --- /dev/null +++ b/x64_dbg_dbg/test/mmx_sse_fpu/x64/sse/sse_build.bat @@ -0,0 +1,6 @@ +@echo off +nasm -fwin64 sse.asm +golink sse.obj /entry _start +move sse.exe ..\sse.exe > nul +del /Q *.obj +pause \ No newline at end of file diff --git a/x64_dbg_dbg/test/pferrie/x32/pferrie.asm b/x64_dbg_dbg/test/pferrie/x32/pferrie.asm new file mode 100644 index 00000000..a84a5be9 --- /dev/null +++ b/x64_dbg_dbg/test/pferrie/x32/pferrie.asm @@ -0,0 +1,11 @@ +global _start + +section .data +@real: + mov byte [l1],0b0h + l1: mov al,1 + ret + +section .text + _start: + jmp @real \ No newline at end of file diff --git a/x64_dbg_dbg/test/pferrie/x32/pferrie.bat b/x64_dbg_dbg/test/pferrie/x32/pferrie.bat new file mode 100644 index 00000000..3423934f --- /dev/null +++ b/x64_dbg_dbg/test/pferrie/x32/pferrie.bat @@ -0,0 +1,5 @@ +@echo off +nasm -f win32 pferrie.asm +golink pferrie.obj /entry _start +del /Q *.obj +pause \ No newline at end of file diff --git a/x64_dbg_dbg/test/pferrie/x64/pferrie.asm b/x64_dbg_dbg/test/pferrie/x64/pferrie.asm new file mode 100644 index 00000000..a84a5be9 --- /dev/null +++ b/x64_dbg_dbg/test/pferrie/x64/pferrie.asm @@ -0,0 +1,11 @@ +global _start + +section .data +@real: + mov byte [l1],0b0h + l1: mov al,1 + ret + +section .text + _start: + jmp @real \ No newline at end of file diff --git a/x64_dbg_dbg/test/pferrie/x64/pferrie.bat b/x64_dbg_dbg/test/pferrie/x64/pferrie.bat new file mode 100644 index 00000000..862305e3 --- /dev/null +++ b/x64_dbg_dbg/test/pferrie/x64/pferrie.bat @@ -0,0 +1,5 @@ +@echo off +nasm -f win64 pferrie.asm +golink pferrie.obj /entry _start +del /Q *.obj +pause \ No newline at end of file diff --git a/x64_dbg_dbg/threading.cpp b/x64_dbg_dbg/threading.cpp new file mode 100644 index 00000000..f92ee718 --- /dev/null +++ b/x64_dbg_dbg/threading.cpp @@ -0,0 +1,29 @@ +#include "threading.h" + +static bool waitarray[16]; + +void waitclear() +{ + memset(waitarray, 0, sizeof(waitarray)); +} + +void wait(WAIT_ID id) +{ + while(waitarray[id]) //1=locked, 0=unlocked + Sleep(1); +} + +void lock(WAIT_ID id) +{ + waitarray[id]=true; +} + +void unlock(WAIT_ID id) +{ + waitarray[id]=false; +} + +bool waitislocked(WAIT_ID id) +{ + return waitarray[id]; +} diff --git a/x64_dbg_dbg/threading.h b/x64_dbg_dbg/threading.h new file mode 100644 index 00000000..d34d29ca --- /dev/null +++ b/x64_dbg_dbg/threading.h @@ -0,0 +1,20 @@ +#ifndef _THREADING_H +#define _THREADING_H + +#include "_global.h" + +//enums +enum WAIT_ID +{ + WAITID_SYSBREAK=0, + WAITID_RUN=1 +}; + +//functions +void waitclear(); +void wait(WAIT_ID id); +void lock(WAIT_ID id); +void unlock(WAIT_ID id); +bool waitislocked(WAIT_ID id); + +#endif // _THREADING_H diff --git a/x64_dbg_dbg/value.cpp b/x64_dbg_dbg/value.cpp new file mode 100644 index 00000000..5ea0976a --- /dev/null +++ b/x64_dbg_dbg/value.cpp @@ -0,0 +1,1308 @@ +#include "value.h" +#include "variable.h" +#include "debugger.h" +#include "console.h" +#include "math.h" +#include "memory.h" +#include + +static bool dosignedcalc=false; + +bool valuesignedcalc() +{ + return dosignedcalc; +} + +void valuesetsignedcalc(bool a) +{ + dosignedcalc=a; +} + +static bool isflag(const char* string) +{ + if(scmp(string, "cf")) + return true; + if(scmp(string, "pf")) + return true; + if(scmp(string, "af")) + return true; + if(scmp(string, "zf")) + return true; + if(scmp(string, "sf")) + return true; + if(scmp(string, "tf")) + return true; + if(scmp(string, "if")) + return true; + if(scmp(string, "df")) + return true; + if(scmp(string, "of")) + return true; + if(scmp(string, "rf")) + return true; + if(scmp(string, "vm")) + return true; + if(scmp(string, "ac")) + return true; + if(scmp(string, "vif")) + return true; + if(scmp(string, "vip")) + return true; + if(scmp(string, "id")) + return true; + return false; +} + +static bool isregister(const char* string) +{ + if(scmp(string, "eax")) + return true; + if(scmp(string, "ebx")) + return true; + if(scmp(string, "ecx")) + return true; + if(scmp(string, "edx")) + return true; + if(scmp(string, "edi")) + return true; + if(scmp(string, "esi")) + return true; + if(scmp(string, "ebp")) + return true; + if(scmp(string, "esp")) + return true; + if(scmp(string, "eip")) + return true; + if(scmp(string, "eflags")) + return true; + + if(scmp(string, "ax")) + return true; + if(scmp(string, "bx")) + return true; + if(scmp(string, "cx")) + return true; + if(scmp(string, "dx")) + return true; + if(scmp(string, "si")) + return true; + if(scmp(string, "di")) + return true; + if(scmp(string, "bp")) + return true; + if(scmp(string, "sp")) + return true; + if(scmp(string, "ip")) + return true; + + if(scmp(string, "ah")) + return true; + if(scmp(string, "al")) + return true; + if(scmp(string, "bh")) + return true; + if(scmp(string, "bl")) + return true; + if(scmp(string, "ch")) + return true; + if(scmp(string, "cl")) + return true; + if(scmp(string, "dh")) + return true; + if(scmp(string, "dl")) + return true; + if(scmp(string, "sih")) + return true; + if(scmp(string, "sil")) + return true; + if(scmp(string, "dih")) + return true; + if(scmp(string, "dil")) + return true; + if(scmp(string, "bph")) + return true; + if(scmp(string, "bpl")) + return true; + if(scmp(string, "sph")) + return true; + if(scmp(string, "spl")) + return true; + if(scmp(string, "iph")) + return true; + if(scmp(string, "ipl")) + return true; + + if(scmp(string, "dr0")) + return true; + if(scmp(string, "dr1")) + return true; + if(scmp(string, "dr2")) + return true; + if(scmp(string, "dr3")) + return true; + if(scmp(string, "dr6") or scmp(string, "dr4")) + return true; + if(scmp(string, "dr7") or scmp(string, "dr5")) + return true; + + if(scmp(string, "cip")) + return true; + if(scmp(string, "csp")) + return true; + if(scmp(string, "cflags")) + return true; + + if(scmp(string, "gs")) + return true; + if(scmp(string, "fs")) + return true; + if(scmp(string, "es")) + return true; + if(scmp(string, "ds")) + return true; + if(scmp(string, "cs")) + return true; + if(scmp(string, "ss")) + return true; + +#ifndef _WIN64 + return false; +#endif // _WIN64 + if(scmp(string, "rax")) + return true; + if(scmp(string, "rbx")) + return true; + if(scmp(string, "rcx")) + return true; + if(scmp(string, "rdx")) + return true; + if(scmp(string, "rdi")) + return true; + if(scmp(string, "rsi")) + return true; + if(scmp(string, "rbp")) + return true; + if(scmp(string, "rsp")) + return true; + if(scmp(string, "rip")) + return true; + if(scmp(string, "rflags")) + return true; + if(scmp(string, "r8")) + return true; + if(scmp(string, "r9")) + return true; + if(scmp(string, "r10")) + return true; + if(scmp(string, "r11")) + return true; + if(scmp(string, "r12")) + return true; + if(scmp(string, "r13")) + return true; + if(scmp(string, "r14")) + return true; + if(scmp(string, "r15")) + return true; + if(scmp(string, "r8d")) + return true; + if(scmp(string, "r9d")) + return true; + if(scmp(string, "r10d")) + return true; + if(scmp(string, "r11d")) + return true; + if(scmp(string, "r12d")) + return true; + if(scmp(string, "r13d")) + return true; + if(scmp(string, "r14d")) + return true; + if(scmp(string, "r15d")) + return true; + if(scmp(string, "r8w")) + return true; + if(scmp(string, "r9w")) + return true; + if(scmp(string, "r10w")) + return true; + if(scmp(string, "r11w")) + return true; + if(scmp(string, "r12w")) + return true; + if(scmp(string, "r13w")) + return true; + if(scmp(string, "r14w")) + return true; + if(scmp(string, "r15w")) + return true; + if(scmp(string, "r8b")) + return true; + if(scmp(string, "r9b")) + return true; + if(scmp(string, "r10b")) + return true; + if(scmp(string, "r11b")) + return true; + if(scmp(string, "r12b")) + return true; + if(scmp(string, "r13b")) + return true; + if(scmp(string, "r14b")) + return true; + if(scmp(string, "r15b")) + return true; + return false; +} + +bool valflagfromstring(unsigned int eflags, const char* string) +{ + if(scmp(string, "cf")) + return (bool)((int)(eflags&0x1)!=0); + if(scmp(string, "pf")) + return (bool)((int)(eflags&0x4)!=0); + if(scmp(string, "af")) + return (bool)((int)(eflags&0x10)!=0); + if(scmp(string, "zf")) + return (bool)((int)(eflags&0x40)!=0); + if(scmp(string, "sf")) + return (bool)((int)(eflags&0x80)!=0); + if(scmp(string, "tf")) + return (bool)((int)(eflags&0x100)!=0); + if(scmp(string, "if")) + return (bool)((int)(eflags&0x200)!=0); + if(scmp(string, "df")) + return (bool)((int)(eflags&0x400)!=0); + if(scmp(string, "of")) + return (bool)((int)(eflags&0x800)!=0); + if(scmp(string, "rf")) + return (bool)((int)(eflags&0x10000)!=0); + if(scmp(string, "vm")) + return (bool)((int)(eflags&0x20000)!=0); + if(scmp(string, "ac")) + return (bool)((int)(eflags&0x40000)!=0); + if(scmp(string, "vif")) + return (bool)((int)(eflags&0x80000)!=0); + if(scmp(string, "vip")) + return (bool)((int)(eflags&0x100000)!=0); + if(scmp(string, "id")) + return (bool)((int)(eflags&0x200000)!=0); + return false; +} + +static bool setflag(const char* string, bool set) +{ + uint eflags=GetContextData(UE_CFLAGS); + uint xorval=0; + uint flag=0; + if(scmp(string, "cf")) + flag=0x1; + else if(scmp(string, "pf")) + flag=0x4; + else if(scmp(string, "af")) + flag=0x10; + else if(scmp(string, "zf")) + flag=0x40; + else if(scmp(string, "sf")) + flag=0x80; + else if(scmp(string, "tf")) + flag=0x100; + else if(scmp(string, "if")) + flag=0x200; + else if(scmp(string, "df")) + flag=0x400; + else if(scmp(string, "of")) + flag=0x800; + else if(scmp(string, "rf")) + flag=0x10000; + else if(scmp(string, "vm")) + flag=0x20000; + else if(scmp(string, "ac")) + flag=0x40000; + else if(scmp(string, "vif")) + flag=0x80000; + else if(scmp(string, "vip")) + flag=0x100000; + else if(scmp(string, "id")) + flag=0x200000; + if(eflags&flag and !set) + xorval=flag; + else if(set) + xorval=flag; + return SetContextData(UE_CFLAGS, eflags^xorval); +} + +static uint getregister(int* size, const char* string) +{ + if(size) + *size=4; + if(scmp(string, "eax")) + { + return GetContextData(UE_EAX); + } + if(scmp(string, "ebx")) + { + return GetContextData(UE_EBX); + } + if(scmp(string, "ecx")) + { + return GetContextData(UE_ECX); + } + if(scmp(string, "edx")) + { + return GetContextData(UE_EDX); + } + if(scmp(string, "edi")) + { + return GetContextData(UE_EDI); + } + if(scmp(string, "esi")) + { + return GetContextData(UE_ESI); + } + if(scmp(string, "ebp")) + { + return GetContextData(UE_EBP); + } + if(scmp(string, "esp")) + { + return GetContextData(UE_ESP); + } + if(scmp(string, "eip")) + { + return GetContextData(UE_EIP); + } + if(scmp(string, "eflags")) + { + return GetContextData(UE_EFLAGS); + } + + if(scmp(string, "gs")) + { + return GetContextData(UE_SEG_GS); + } + if(scmp(string, "fs")) + { + return GetContextData(UE_SEG_FS); + } + if(scmp(string, "es")) + { + return GetContextData(UE_SEG_ES); + } + if(scmp(string, "ds")) + { + return GetContextData(UE_SEG_DS); + } + if(scmp(string, "cs")) + { + return GetContextData(UE_SEG_CS); + } + if(scmp(string, "ss")) + { + return GetContextData(UE_SEG_SS); + } + + if(size) + *size=2; + if(scmp(string, "ax")) + { + uint val=GetContextData(UE_EAX); + return val&0xFFFF; + } + if(scmp(string, "bx")) + { + uint val=GetContextData(UE_EBX); + return val&0xFFFF; + } + if(scmp(string, "cx")) + { + uint val=GetContextData(UE_ECX); + return val&0xFFFF; + } + if(scmp(string, "dx")) + { + uint val=GetContextData(UE_EDX); + return val&0xFFFF; + } + if(scmp(string, "si")) + { + uint val=GetContextData(UE_ESI); + return val&0xFFFF; + } + if(scmp(string, "di")) + { + uint val=GetContextData(UE_EDI); + return val&0xFFFF; + } + if(scmp(string, "bp")) + { + uint val=GetContextData(UE_EBP); + return val&0xFFFF; + } + if(scmp(string, "sp")) + { + uint val=GetContextData(UE_ESP); + return val&0xFFFF; + } + if(scmp(string, "ip")) + { + uint val=GetContextData(UE_EIP); + return val&0xFFFF; + } + + if(size) + *size=1; + if(scmp(string, "ah")) + { + uint val=GetContextData(UE_EAX); + return (val>>8)&0xFF; + } + if(scmp(string, "al")) + { + uint val=GetContextData(UE_EAX); + return val&0xFF; + } + if(scmp(string, "bh")) + { + uint val=GetContextData(UE_EBX); + return (val>>8)&0xFF; + } + if(scmp(string, "bl")) + { + uint val=GetContextData(UE_EBX); + return val&0xFF; + } + if(scmp(string, "ch")) + { + uint val=GetContextData(UE_ECX); + return (val>>8)&0xFF; + } + if(scmp(string, "cl")) + { + uint val=GetContextData(UE_ECX); + return val&0xFF; + } + if(scmp(string, "dh")) + { + uint val=GetContextData(UE_EDX); + return (val>>8)&0xFF; + } + if(scmp(string, "dl")) + { + uint val=GetContextData(UE_EDX); + return val&0xFF; + } + if(scmp(string, "sih")) + { + uint val=GetContextData(UE_ESI); + return (val>>8)&0xFF; + } + if(scmp(string, "sil")) + { + uint val=GetContextData(UE_ESI); + return val&0xFF; + } + if(scmp(string, "dih")) + { + uint val=GetContextData(UE_EDI); + return (val>>8)&0xFF; + } + if(scmp(string, "dil")) + { + uint val=GetContextData(UE_EDI); + return val&0xFF; + } + if(scmp(string, "bph")) + { + uint val=GetContextData(UE_EBP); + return (val>>8)&0xFF; + } + if(scmp(string, "bpl")) + { + uint val=GetContextData(UE_EBP); + return val&0xFF; + } + if(scmp(string, "sph")) + { + uint val=GetContextData(UE_ESP); + return (val>>8)&0xFF; + } + if(scmp(string, "spl")) + { + uint val=GetContextData(UE_ESP); + return val&0xFF; + } + if(scmp(string, "iph")) + { + uint val=GetContextData(UE_EIP); + return (val>>8)&0xFF; + } + if(scmp(string, "ipl")) + { + uint val=GetContextData(UE_EIP); + return val&0xFF; + } + + if(size) + *size=sizeof(uint); + if(scmp(string, "dr0")) + { + return GetContextData(UE_DR0); + } + if(scmp(string, "dr1")) + { + return GetContextData(UE_DR1); + } + if(scmp(string, "dr2")) + { + return GetContextData(UE_DR2); + } + if(scmp(string, "dr3")) + { + return GetContextData(UE_DR3); + } + if(scmp(string, "dr6") or scmp(string, "dr4")) + { + return GetContextData(UE_DR6); + } + if(scmp(string, "dr7") or scmp(string, "dr5")) + { + return GetContextData(UE_DR7); + } + + if(scmp(string, "cip")) + { + return GetContextData(UE_CIP); + } + if(scmp(string, "csp")) + { + return GetContextData(UE_CSP); + } + if(scmp(string, "cflags")) + { + return GetContextData(UE_CFLAGS); + } + +#ifdef _WIN64 + if(size) + *size=8; + if(scmp(string, "rax")) + { + return GetContextData(UE_RAX); + } + if(scmp(string, "rbx")) + { + return GetContextData(UE_RBX); + } + if(scmp(string, "rcx")) + { + return GetContextData(UE_RCX); + } + if(scmp(string, "rdx")) + { + return GetContextData(UE_RDX); + } + if(scmp(string, "rdi")) + { + return GetContextData(UE_RDI); + } + if(scmp(string, "rsi")) + { + return GetContextData(UE_RSI); + } + if(scmp(string, "rbp")) + { + return GetContextData(UE_RBP); + } + if(scmp(string, "rsp")) + { + return GetContextData(UE_RSP); + } + if(scmp(string, "rip")) + { + return GetContextData(UE_RIP); + } + if(scmp(string, "rflags")) + { + return GetContextData(UE_RFLAGS); + } + if(scmp(string, "r8")) + { + return GetContextData(UE_R8); + } + if(scmp(string, "r9")) + { + return GetContextData(UE_R9); + } + if(scmp(string, "r10")) + { + return GetContextData(UE_R10); + } + if(scmp(string, "r11")) + { + return GetContextData(UE_R11); + } + if(scmp(string, "r12")) + { + return GetContextData(UE_R12); + } + if(scmp(string, "r13")) + { + return GetContextData(UE_R13); + } + if(scmp(string, "r14")) + { + return GetContextData(UE_R14); + } + if(scmp(string, "r15")) + { + return GetContextData(UE_R15); + } + + if(size) + *size=4; + if(scmp(string, "r8d")) + { + return GetContextData(UE_R8)&0xFFFFFFFF; + } + if(scmp(string, "r9d")) + { + return GetContextData(UE_R9)&0xFFFFFFFF; + } + if(scmp(string, "r10d")) + { + return GetContextData(UE_R10)&0xFFFFFFFF; + } + if(scmp(string, "r11d")) + { + return GetContextData(UE_R11)&0xFFFFFFFF; + } + if(scmp(string, "r12d")) + { + return GetContextData(UE_R12)&0xFFFFFFFF; + } + if(scmp(string, "r13d")) + { + return GetContextData(UE_R13)&0xFFFFFFFF; + } + if(scmp(string, "r14d")) + { + return GetContextData(UE_R14)&0xFFFFFFFF; + } + if(scmp(string, "r15d")) + { + return GetContextData(UE_R15)&0xFFFFFFFF; + } + + if(size) + *size=2; + if(scmp(string, "r8w")) + { + return GetContextData(UE_R8)&0xFFFF; + } + if(scmp(string, "r9w")) + { + return GetContextData(UE_R9)&0xFFFF; + } + if(scmp(string, "r10w")) + { + return GetContextData(UE_R10)&0xFFFF; + } + if(scmp(string, "r11w")) + { + return GetContextData(UE_R11)&0xFFFF; + } + if(scmp(string, "r12w")) + { + return GetContextData(UE_R12)&0xFFFF; + } + if(scmp(string, "r13w")) + { + return GetContextData(UE_R13)&0xFFFF; + } + if(scmp(string, "r14w")) + { + return GetContextData(UE_R14)&0xFFFF; + } + if(scmp(string, "r15w")) + { + return GetContextData(UE_R15)&0xFFFF; + } + + if(size) + *size=1; + if(scmp(string, "r8b")) + { + return GetContextData(UE_R8)&0xFF; + } + if(scmp(string, "r9b")) + { + return GetContextData(UE_R9)&0xFF; + } + if(scmp(string, "r10b")) + { + return GetContextData(UE_R10)&0xFF; + } + if(scmp(string, "r11b")) + { + return GetContextData(UE_R11)&0xFF; + } + if(scmp(string, "r12b")) + { + return GetContextData(UE_R12)&0xFF; + } + if(scmp(string, "r13b")) + { + return GetContextData(UE_R13)&0xFF; + } + if(scmp(string, "r14b")) + { + return GetContextData(UE_R14)&0xFF; + } + if(scmp(string, "r15b")) + { + return GetContextData(UE_R15)&0xFF; + } +#endif //_WIN64 + + if(size) + *size=0; + return 0; +} + +static bool setregister(const char* string, uint value) +{ + if(scmp(string, "eax")) + return SetContextData(UE_EAX, value&0xFFFFFFFF); + if(scmp(string, "ebx")) + return SetContextData(UE_EBX, value&0xFFFFFFFF); + if(scmp(string, "ecx")) + return SetContextData(UE_ECX, value&0xFFFFFFFF); + if(scmp(string, "edx")) + return SetContextData(UE_EDX, value&0xFFFFFFFF); + if(scmp(string, "edi")) + return SetContextData(UE_EDI, value&0xFFFFFFFF); + if(scmp(string, "esi")) + return SetContextData(UE_ESI, value&0xFFFFFFFF); + if(scmp(string, "ebp")) + return SetContextData(UE_EBP, value&0xFFFFFFFF); + if(scmp(string, "esp")) + return SetContextData(UE_ESP, value&0xFFFFFFFF); + if(scmp(string, "eip")) + return SetContextData(UE_EIP, value&0xFFFFFFFF); + if(scmp(string, "eflags")) + return SetContextData(UE_EFLAGS, value&0xFFFFFFFF); + + if(scmp(string, "gs")) + return SetContextData(UE_SEG_GS, value&0xFFFF); + if(scmp(string, "fs")) + return SetContextData(UE_SEG_FS, value&0xFFFF); + if(scmp(string, "es")) + return SetContextData(UE_SEG_ES, value&0xFFFF); + if(scmp(string, "ds")) + return SetContextData(UE_SEG_DS, value&0xFFFF); + if(scmp(string, "cs")) + return SetContextData(UE_SEG_CS, value&0xFFFF); + if(scmp(string, "ss")) + return SetContextData(UE_SEG_SS, value&0xFFFF); + + if(scmp(string, "ax")) + return SetContextData(UE_EAX, (value&0xFFFF)|(GetContextData(UE_EAX)&0xFFFF0000)); + if(scmp(string, "bx")) + return SetContextData(UE_EBX, (value&0xFFFF)|(GetContextData(UE_EBX)&0xFFFF0000)); + if(scmp(string, "cx")) + return SetContextData(UE_ECX, (value&0xFFFF)|(GetContextData(UE_ECX)&0xFFFF0000)); + if(scmp(string, "dx")) + return SetContextData(UE_EDX, (value&0xFFFF)|(GetContextData(UE_EDX)&0xFFFF0000)); + if(scmp(string, "si")) + return SetContextData(UE_ESI, (value&0xFFFF)|(GetContextData(UE_ESI)&0xFFFF0000)); + if(scmp(string, "di")) + return SetContextData(UE_EDI, (value&0xFFFF)|(GetContextData(UE_EDI)&0xFFFF0000)); + if(scmp(string, "bp")) + return SetContextData(UE_EBP, (value&0xFFFF)|(GetContextData(UE_EBP)&0xFFFF0000)); + if(scmp(string, "sp")) + return SetContextData(UE_ESP, (value&0xFFFF)|(GetContextData(UE_ESP)&0xFFFF0000)); + if(scmp(string, "ip")) + return SetContextData(UE_EIP, (value&0xFFFF)|(GetContextData(UE_EIP)&0xFFFF0000)); + + if(scmp(string, "ah")) + return SetContextData(UE_EAX, ((value&0xFF)<<8)|(GetContextData(UE_EAX)&0xFFFF00FF)); + if(scmp(string, "al")) + return SetContextData(UE_EAX, (value&0xFF)|(GetContextData(UE_EAX)&0xFFFFFF00)); + if(scmp(string, "bh")) + return SetContextData(UE_EBX, ((value&0xFF)<<8)|(GetContextData(UE_EBX)&0xFFFF00FF)); + if(scmp(string, "bl")) + return SetContextData(UE_EBX, (value&0xFF)|(GetContextData(UE_EBX)&0xFFFFFF00)); + if(scmp(string, "ch")) + return SetContextData(UE_ECX, ((value&0xFF)<<8)|(GetContextData(UE_ECX)&0xFFFF00FF)); + if(scmp(string, "cl")) + return SetContextData(UE_ECX, (value&0xFF)|(GetContextData(UE_ECX)&0xFFFFFF00)); + if(scmp(string, "dh")) + return SetContextData(UE_EDX, ((value&0xFF)<<8)|(GetContextData(UE_EDX)&0xFFFF00FF)); + if(scmp(string, "dl")) + return SetContextData(UE_EDX, (value&0xFF)|(GetContextData(UE_EDX)&0xFFFFFF00)); + if(scmp(string, "sih")) + return SetContextData(UE_ESI, ((value&0xFF)<<8)|(GetContextData(UE_ESI)&0xFFFF00FF)); + if(scmp(string, "sil")) + return SetContextData(UE_ESI, (value&0xFF)|(GetContextData(UE_ESI)&0xFFFFFF00)); + if(scmp(string, "dih")) + return SetContextData(UE_EDI, ((value&0xFF)<<8)|(GetContextData(UE_EDI)&0xFFFF00FF)); + if(scmp(string, "dil")) + return SetContextData(UE_EDI, (value&0xFF)|(GetContextData(UE_EDI)&0xFFFFFF00)); + if(scmp(string, "bph")) + return SetContextData(UE_EBP, ((value&0xFF)<<8)|(GetContextData(UE_EBP)&0xFFFF00FF)); + if(scmp(string, "bpl")) + return SetContextData(UE_EBP, (value&0xFF)|(GetContextData(UE_EBP)&0xFFFFFF00)); + if(scmp(string, "sph")) + return SetContextData(UE_ESP, ((value&0xFF)<<8)|(GetContextData(UE_ESP)&0xFFFF00FF)); + if(scmp(string, "spl")) + return SetContextData(UE_ESP, (value&0xFF)|(GetContextData(UE_ESP)&0xFFFFFF00)); + if(scmp(string, "iph")) + return SetContextData(UE_EIP, ((value&0xFF)<<8)|(GetContextData(UE_EIP)&0xFFFF00FF)); + if(scmp(string, "ipl")) + return SetContextData(UE_EIP, (value&0xFF)|(GetContextData(UE_EIP)&0xFFFFFF00)); + + if(scmp(string, "dr0")) + return SetContextData(UE_DR0, value); + if(scmp(string, "dr1")) + return SetContextData(UE_DR1, value); + if(scmp(string, "dr2")) + return SetContextData(UE_DR2, value); + if(scmp(string, "dr3")) + return SetContextData(UE_DR3, value); + if(scmp(string, "dr6") or scmp(string, "dr4")) + return SetContextData(UE_DR6, value); + if(scmp(string, "dr7") or scmp(string, "dr5")) + return SetContextData(UE_DR7, value); + + if(scmp(string, "cip")) + return SetContextData(UE_CIP, value); + if(scmp(string, "csp")) + return SetContextData(UE_CSP, value); + if(scmp(string, "cflags")) + return SetContextData(UE_CFLAGS, value); + +#ifdef _WIN64 + if(scmp(string, "rax")) + return SetContextData(UE_RAX, value); + if(scmp(string, "rbx")) + return SetContextData(UE_RBX, value); + if(scmp(string, "rcx")) + return SetContextData(UE_RCX, value); + if(scmp(string, "rdx")) + return SetContextData(UE_RDX, value); + if(scmp(string, "rdi")) + return SetContextData(UE_RDI, value); + if(scmp(string, "rsi")) + return SetContextData(UE_RSI, value); + if(scmp(string, "rbp")) + return SetContextData(UE_RBP, value); + if(scmp(string, "rsp")) + return SetContextData(UE_RSP, value); + if(scmp(string, "rip")) + return SetContextData(UE_RIP, value); + if(scmp(string, "rflags")) + return SetContextData(UE_RFLAGS, value); + if(scmp(string, "r8")) + return SetContextData(UE_R8, value); + if(scmp(string, "r9")) + return SetContextData(UE_R9, value); + if(scmp(string, "r10")) + return SetContextData(UE_R10, value); + if(scmp(string, "r11")) + return SetContextData(UE_R11, value); + if(scmp(string, "r12")) + return SetContextData(UE_R12, value); + if(scmp(string, "r13")) + return SetContextData(UE_R13, value); + if(scmp(string, "r14")) + return SetContextData(UE_R14, value); + if(scmp(string, "r15")) + return SetContextData(UE_R15, value); + + if(scmp(string, "r8d")) + return SetContextData(UE_R8, (value&0xFFFFFFFF)|(GetContextData(UE_R8)&0xFFFFFFFF00000000)); + if(scmp(string, "r9d")) + return SetContextData(UE_R9, (value&0xFFFFFFFF)|(GetContextData(UE_R9)&0xFFFFFFFF00000000)); + if(scmp(string, "r10d")) + return SetContextData(UE_R10, (value&0xFFFFFFFF)|(GetContextData(UE_R10)&0xFFFFFFFF00000000)); + if(scmp(string, "r11d")) + return SetContextData(UE_R11, (value&0xFFFFFFFF)|(GetContextData(UE_R11)&0xFFFFFFFF00000000)); + if(scmp(string, "r12d")) + return SetContextData(UE_R12, (value&0xFFFFFFFF)|(GetContextData(UE_R12)&0xFFFFFFFF00000000)); + if(scmp(string, "r13d")) + return SetContextData(UE_R13, (value&0xFFFFFFFF)|(GetContextData(UE_R13)&0xFFFFFFFF00000000)); + if(scmp(string, "r14d")) + return SetContextData(UE_R14, (value&0xFFFFFFFF)|(GetContextData(UE_R14)&0xFFFFFFFF00000000)); + if(scmp(string, "r15d")) + return SetContextData(UE_R15, (value&0xFFFFFFFF)|(GetContextData(UE_R15)&0xFFFFFFFF00000000)); + + if(scmp(string, "r8w")) + return SetContextData(UE_R8, (value&0xFFFF)|(GetContextData(UE_R8)&0xFFFFFFFFFFFF0000)); + if(scmp(string, "r9w")) + return SetContextData(UE_R9, (value&0xFFFF)|(GetContextData(UE_R9)&0xFFFFFFFFFFFF0000)); + if(scmp(string, "r10w")) + return SetContextData(UE_R10, (value&0xFFFF)|(GetContextData(UE_R10)&0xFFFFFFFFFFFF0000)); + if(scmp(string, "r11w")) + return SetContextData(UE_R11, (value&0xFFFF)|(GetContextData(UE_R11)&0xFFFFFFFFFFFF0000)); + if(scmp(string, "r12w")) + return SetContextData(UE_R12, (value&0xFFFF)|(GetContextData(UE_R12)&0xFFFFFFFFFFFF0000)); + if(scmp(string, "r13w")) + return SetContextData(UE_R13, (value&0xFFFF)|(GetContextData(UE_R13)&0xFFFFFFFFFFFF0000)); + if(scmp(string, "r14w")) + return SetContextData(UE_R14, (value&0xFFFF)|(GetContextData(UE_R14)&0xFFFFFFFFFFFF0000)); + if(scmp(string, "r15w")) + return SetContextData(UE_R15, (value&0xFFFF)|(GetContextData(UE_R15)&0xFFFFFFFFFFFF0000)); + if(scmp(string, "r8b")) + return SetContextData(UE_R8, (value&0xFF)|(GetContextData(UE_R8)&0xFFFFFFFFFFFFFF00)); + if(scmp(string, "r9b")) + return SetContextData(UE_R9, (value&0xFF)|(GetContextData(UE_R9)&0xFFFFFFFFFFFFFF00)); + if(scmp(string, "r10b")) + return SetContextData(UE_R10, (value&0xFF)|(GetContextData(UE_R10)&0xFFFFFFFFFFFFFF00)); + if(scmp(string, "r11b")) + return SetContextData(UE_R11, (value&0xFF)|(GetContextData(UE_R11)&0xFFFFFFFFFFFFFF00)); + if(scmp(string, "r12b")) + return SetContextData(UE_R12, (value&0xFF)|(GetContextData(UE_R12)&0xFFFFFFFFFFFFFF00)); + if(scmp(string, "r13b")) + return SetContextData(UE_R13, (value&0xFF)|(GetContextData(UE_R13)&0xFFFFFFFFFFFFFF00)); + if(scmp(string, "r14b")) + return SetContextData(UE_R14, (value&0xFF)|(GetContextData(UE_R14)&0xFFFFFFFFFFFFFF00)); + if(scmp(string, "r15b")) + return SetContextData(UE_R15, (value&0xFF)|(GetContextData(UE_R15)&0xFFFFFFFFFFFFFF00)); +#endif // _WIN64 + + return false; +} + +bool valapifromstring(const char* name, uint* value, int* value_size, bool printall, bool silent, bool* hexonly) +{ + if(!value or !IsFileBeingDebugged()) + return false; + DWORD cbNeeded=1; + HMODULE hMods[256]; + uint addrfound[256]; + int found=0; + int kernelbase=-1; + if(EnumProcessModules(fdProcessInfo->hProcess, hMods, sizeof(hMods), &cbNeeded)) + { + for(unsigned int i=0; i<(cbNeeded/sizeof(HMODULE)); i++) + { + char szModName[MAX_PATH]; + if(!GetModuleFileNameEx(fdProcessInfo->hProcess, hMods[i], szModName, MAX_PATH) and !silent) + dprintf("could not get filename of module "fhex"\n", hMods[i]); + char szBaseName[256]=""; + int len=strlen(szModName); + while(szModName[len]!='\\') + len--; + strcpy(szBaseName, szModName+len+1); + HMODULE mod=LoadLibraryExA(szModName, 0, DONT_RESOLVE_DLL_REFERENCES|LOAD_LIBRARY_AS_DATAFILE); + if(!mod and !silent) + dprintf("unable to load library %s\n", szBaseName); + uint addr=(uint)GetProcAddress(mod, name); + FreeLibrary(mod); + if(addr) + { + if(!_stricmp(szBaseName, "kernelbase") or !_stricmp(szBaseName, "kernelbase.dll")) + kernelbase=found; + addrfound[found]=ImporterGetRemoteAPIAddressEx(szBaseName, (char*)name); + found++; + } + } + } + if(!found) + return false; + if(value_size) + *value_size=sizeof(uint); + if(hexonly) + *hexonly=true; + if(kernelbase!=-1) + { + *value=addrfound[kernelbase]; + if(!printall) + return true; + for(int i=0; i2) + add++; + if(!mathhandlebrackets(string_+add)) + { + efree(string_); + return false; + } + bool ret=mathfromstring(string_+add, value, value_size, isvar); + efree(string_); + return ret; + } + else if(*string=='@') //memory location + { + if(!IsFileBeingDebugged()) + { + if(!silent) + dputs("not debugging"); + *value=0; + if(value_size) + *value_size=0; + if(isvar) + *isvar=true; + return true; + } + int read_size=sizeof(uint); + int add=1; + if(string[2]==':' and isdigit((string[1]))) //@n: (number of bytes to read) + { + add+=2; + int new_size=string[1]-0x30; + if(new_sizehProcess, (void*)addr, value, read_size, 0); + if(!isrunning) + dbgenablebpx(); + if(!rpm) + { + if(!silent) + dputs("failed to read memory"); + return false; + } + if(value_size) + *value_size=read_size; + if(isvar) + *isvar=true; + return true; + } + else if(isregister(string)) //register + { + if(!IsFileBeingDebugged()) + { + if(!silent) + dputs("not debugging!"); + *value=0; + if(value_size) + *value_size=0; + if(isvar) + *isvar=true; + return true; + } + *value=getregister(value_size, string); + if(isvar) + *isvar=true; + return true; + } + else if(*string=='!' and isflag(string+1)) //flag + { + if(!IsFileBeingDebugged()) + { + if(!silent) + dputs("not debugging"); + *value=0; + if(value_size) + *value_size=0; + if(isvar) + *isvar=true; + return true; + } + uint eflags=GetContextData(UE_CFLAGS); + if(valflagfromstring(eflags, string+1)) + *value=1; + else + *value=0; + if(value_size) + *value_size=0; + if(isvar) + *isvar=true; + return true; + } + else if(isdecnumber(string)) //decimal numbers come 'first' + { + if(value_size) + *value_size=0; + if(isvar) + *isvar=false; + sscanf(string+1, "%"fext"u", value); + return true; + } + else if(ishexnumber(string)) //then hex numbers + { + if(value_size) + *value_size=0; + if(isvar) + *isvar=false; + //hexadecimal value + int inc=0; + if(*string=='x') + inc=1; + sscanf(string+inc, "%"fext"x", value); + return true; + } + else if(valapifromstring(string, value, value_size, true, silent, hexonly)) //then come APIs + return true; + else if(varget(string, value, value_size, 0)) //finally variables + { + if(isvar) + *isvar=true; + return true; + } + return false; //nothing was OK +} + +bool valtostring(const char* string, uint* value, bool silent) +{ + if(!*string or !value) + return false; + else if(*string=='@') //memory location + { + if(!IsFileBeingDebugged()) + { + if(!silent) + dputs("not debugging"); + return false; + } + int read_size=sizeof(uint); + int add=1; + if(string[2]==':' and isdigit((string[1]))) + { + add+=2; + int new_size=string[1]-0x30; + if(new_sizehProcess, (void*)temp, value, read_size, 0); + if(!isrunning) + dbgenablebpx(); + if(!wpm) + { + if(!silent) + dputs("failed to write memory"); + return false; + } + return true; + } + else if(isregister(string)) //register + { + if(!IsFileBeingDebugged()) + { + if(!silent) + dputs("not debugging!"); + return false; + } + bool ok=setregister(string, *value); + if(strstr(string, "ip")) + DebugUpdateGui(GetContextData(UE_CIP)); //update disassembly + register view + else + GuiUpdateRegisterView(); //update register view + return ok; + } + else if(*string=='!' and isflag(string+1)) //flag + { + if(!IsFileBeingDebugged()) + { + if(!silent) + dputs("not debugging"); + return false; + } + bool set=false; + if(*value) + set=true; + setflag(string+1, set); + GuiUpdateRegisterView(); //update register view + return true; + } + return varset(string, *value, false); //variable +} diff --git a/x64_dbg_dbg/value.h b/x64_dbg_dbg/value.h new file mode 100644 index 00000000..2f3f7654 --- /dev/null +++ b/x64_dbg_dbg/value.h @@ -0,0 +1,14 @@ +#ifndef _VALUE_H +#define _VALUE_H + +#include "_global.h" + +//functions +bool valuesignedcalc(); +void valuesetsignedcalc(bool a); +bool valapifromstring(const char* name, uint* value, int* value_size, bool printall, bool silent, bool* hexonly); +bool valfromstring(const char* string, uint* value, int* value_size, bool* isvar, bool silent, bool* hexonly); +bool valflagfromstring(unsigned int eflags, const char* string); +bool valtostring(const char* string, uint* value, bool silent); + +#endif // _VALUE_H diff --git a/x64_dbg_dbg/variable.cpp b/x64_dbg_dbg/variable.cpp new file mode 100644 index 00000000..3087e3aa --- /dev/null +++ b/x64_dbg_dbg/variable.cpp @@ -0,0 +1,167 @@ +#include "variable.h" + +static VAR* vars; + +static VAR* varfind(const char* name, VAR** link) +{ + VAR* cur=vars; + if(!cur) + return 0; + VAR* prev=0; + while(cur) + { + if(arraycontains(cur->name, name)) + { + if(link) + *link=prev; + return cur; + } + prev=cur; + cur=cur->next; + } + return 0; +} + +void varinit() +{ + vars=(VAR*)emalloc(sizeof(VAR)); + memset(vars, 0, sizeof(VAR)); + //General variables + varnew("$res\1$result", 0, VAR_SYSTEM); + varnew("$res1\1$result1", 0, VAR_SYSTEM); + varnew("$res2\1$result2", 0, VAR_SYSTEM); + varnew("$res3\1$result3", 0, VAR_SYSTEM); + varnew("$res4\1$result4", 0, VAR_SYSTEM); + //InitDebug variables + varnew("$hp\1$hProcess", 0, VAR_READONLY); + varnew("$pid", 0, VAR_READONLY); + //hidden variables + varnew("$ans\1$an", 0, VAR_HIDDEN); + //read-only variables + varnew("$lastalloc", 0, VAR_READONLY); +} + +VAR* vargetptr() +{ + return vars; +} + +bool varnew(const char* name_, uint value, VAR_TYPE type) +{ + if(!name_) + return false; + char* name=(char*)emalloc(strlen(name_)+2); + if(*name_!='$') + { + *name='$'; + strcpy(name+1, name_); + } + else + strcpy(name, name_); + if(!name[1]) + { + efree(name); + return false; + } + if(varfind(name, 0)) + { + efree(name); + return false; + } + VAR* var; + bool nonext=false; + if(!vars->name) + { + nonext=true; + var=vars; + } + else + var=(VAR*)emalloc(sizeof(VAR)); + memset(var, 0, sizeof(VAR)); + var->name=name; + var->type=type; + var->value.value=value; + if(!nonext) + { + VAR* cur=vars; + while(cur->next) + cur=cur->next; + cur->next=var; + } + return true; +} + +bool varget(const char* name, uint* value, int* size, VAR_TYPE* type) +{ + char newname[deflen]="$"; + int add=0; + if(*name=='$') + add=1; + strcat(newname, name+add); + VAR* found=varfind(newname, 0); + if(!found) + return false; + if(!value) + return false; + if(type) + *type=found->type; + *value=found->value.value; + return true; +} + +bool varset(const char* name, uint value, bool setreadonly) +{ + char newname[deflen]="$"; + int add=0; + if(*name=='$') + add=1; + strcat(newname, name+add); + VAR* found=varfind(newname, 0); + if(!found) + return false; + if(!setreadonly and (found->type==VAR_READONLY or found->type==VAR_HIDDEN)) + return false; + found->value.value=value; + return true; +} + +bool vardel(const char* name_, bool delsystem) +{ + char* name=(char*)emalloc(strlen(name_)+2); + if(*name_!='$') + { + *name='$'; + strcpy(name+1, name_); + } + else + strcpy(name, name_); + VAR* prev=0; + VAR* found=varfind(name, &prev); + efree(name); + if(!found) + return false; + VAR_TYPE type=found->type; + if(!delsystem and type!=VAR_USER) + return false; + if(type==VAR_HIDDEN) + return false; + efree(found->name); + if(found==vars) + { + VAR* next=vars->next; + if(next) + { + memcpy(vars, vars->next, sizeof(VAR)); + vars->next=next->next; + efree(next); + } + else + memset(vars, 0, sizeof(VAR)); + } + else + { + prev->next=found->next; + efree(found); + } + return true; +} diff --git a/x64_dbg_dbg/variable.h b/x64_dbg_dbg/variable.h new file mode 100644 index 00000000..5af03242 --- /dev/null +++ b/x64_dbg_dbg/variable.h @@ -0,0 +1,46 @@ +#ifndef _VARIABLE_H +#define _VARIABLE_H + +#include "_global.h" + +//TODO: VAR_VALUE struct usage + +//enums +enum VAR_TYPE +{ + VAR_SYSTEM=1, + VAR_USER=2, + VAR_READONLY=3, + VAR_HIDDEN=4 +}; + +enum VAR_VALUE_TYPE +{ + VAR_INT=1 +}; + +//structures +struct VAR_VALUE +{ + uint value; + VAR_VALUE_TYPE type; + int size; +}; + +struct VAR +{ + char* name; + VAR_TYPE type; + VAR_VALUE value; + VAR* next; +}; + +//functions +void varinit(); +VAR* vargetptr(); +bool varnew(const char* name, uint value, VAR_TYPE type); +bool varget(const char* name, uint* value, int* size, VAR_TYPE* type); +bool varset(const char* name, uint value, bool setreadonly); +bool vardel(const char* name_, bool delsystem); + +#endif // _VARIABLE_H diff --git a/x64_dbg_dbg/x64_dbg.cpp b/x64_dbg_dbg/x64_dbg.cpp new file mode 100644 index 00000000..326af016 --- /dev/null +++ b/x64_dbg_dbg/x64_dbg.cpp @@ -0,0 +1,134 @@ +#include "_global.h" +#include "argument.h" +#include "command.h" +#include "variable.h" +#include "instruction.h" +#include "debugger.h" +#include "data.h" +#include "simplescript.h" +#include "console.h" +#include "math.h" +#include "x64_dbg.h" +#include "msgqueue.h" + +static MESSAGE_STACK* gMsgStack; + +static CMDRESULT cbStrLen(const char* cmd) +{ + char arg1[deflen]=""; + if(argget(cmd, arg1, 0, false)) + dprintf("\"%s\"[%d]\n", arg1, strlen(arg1)); + return STATUS_CONTINUE; +} + +static CMDRESULT cbExit(const char* cmd) +{ + return STATUS_EXIT; +} + +static CMDRESULT cbCls(const char* cmd) +{ + GuiLogClear(); + return STATUS_CONTINUE; +} + +static COMMAND* command_list=0; + +static void registercommands() +{ + COMMAND* cmd=command_list=cmdinit(); + //cmdnew(cmd, "exit\1x", cbExit, false); //quit debugger + cmdnew(cmd, "strlen\1charcount\1ccount", cbStrLen, false); //get strlen, arg1:string + cmdnew(cmd, "varnew\1var", cbInstrVar, false); //make a variable arg1:name,[arg2:value] + cmdnew(cmd, "vardel", cbInstrVarDel, false); //delete a variable, arg1:variable name + cmdnew(cmd, "mov\1set", cbInstrMov, false); //mov a variable, arg1:dest,arg2:src + cmdnew(cmd, "cls", cbCls, false); //clear the screen + cmdnew(cmd, "varlist", cbInstrVarList, false); //list variables[arg1:type filter] + cmdnew(cmd, "InitDebug\1init\1initdbg", cbDebugInit, false); //init debugger arg1:exefile,[arg2:commandline] + cmdnew(cmd, "StopDebug\1stop\1dbgstop", cbStopDebug, true); //stop debugger + cmdnew(cmd, "run\1go\1r\1g", cbDebugRun, true); //unlock WAITID_RUN + cmdnew(cmd, "SetBPXOptions\1bptype", cbDebugSetBPXOptions, false); //breakpoint type + cmdnew(cmd, "SetBPX\1bp\1bpx", cbDebugSetBPX, true); //breakpoint + cmdnew(cmd, "EnableBPX\1bpe\1be", cbDebugEnableBPX, true); //breakpoint enable + cmdnew(cmd, "DisableBPX\1bpd\1bd", cbDebugDisableBPX, true); //breakpoint disable + cmdnew(cmd, "ToggleBPX\1bpt\1bt", cbDebugToggleBPX, true); //breakpoint toggle + cmdnew(cmd, "DeleteBPX\1bpc\1bc", cbDebugDeleteBPX, true); //breakpoint delete + cmdnew(cmd, "bplist", cbDebugBplist, true); //breakpoint list + cmdnew(cmd, "StepInto\1sti", cbDebugStepInto, true); //StepInto + cmdnew(cmd, "StepOver\1step\1sto\1st", cbDebugStepOver, true); //StepOver + cmdnew(cmd, "SingleStep\1sstep\1sst", cbDebugSingleStep, true); //SingleStep arg1:count + cmdnew(cmd, "HideDebugger\1dbh\1hide", cbDebugHide, true); //HideDebugger + cmdnew(cmd, "disasm\1dis\1d", cbDebugDisasm, true); //doDisasm + cmdnew(cmd, "SetMemoryBPX\1membp\1bpm", cbDebugMemoryBpx, true); //SetMemoryBPX + cmdnew(cmd, "chd", cbInstrChd, false); //Change directory + cmdnew(cmd, "rtr", cbDebugRtr, true); //rtr + cmdnew(cmd, "SetHardwareBreakpoint\1bph\1bphws", cbDebugSetHardwareBreakpoint, true); //hardware breakpoint + cmdnew(cmd, "alloc", cbDebugAlloc, true); //allocate memory + cmdnew(cmd, "free", cbDebugFree, true); //free memory + cmdnew(cmd, "Fill\1memset", cbDebugMemset, true); //memset + cmdnew(cmd, "scr\1script", cbScript, false); //script testing + cmdnew(cmd, "bench", cbBenchmark, true); //benchmark test (readmem etc) + cmdnew(cmd, "pause", cbDebugPause, true); //pause debugger + cmdnew(cmd, "memwrite", cbMemWrite, true); //memwrite test + cmdnew(cmd, "StartScylla\1scylla\1imprec", cbStartScylla, false); //start scylla +} + +static bool cbCommandProvider(char* cmd, int maxlen) +{ + MESSAGE msg; + msgwait(gMsgStack, &msg); + char* newcmd=(char*)msg.param1; + if(strlen(newcmd)>=deflen) + newcmd[deflen-1]=0; + strcpy(cmd, newcmd); + efree(newcmd); //free allocated command + return true; +} + +extern "C" DLL_EXPORT bool _dbg_dbgcmdexec(const char* cmd) +{ + int len=strlen(cmd); + char* newcmd=(char*)emalloc((len+1)*sizeof(char)); + strcpy(newcmd, cmd); + return msgsend(gMsgStack, 0, (uint)newcmd, 0); +} + +static DWORD WINAPI ConsoleReadLoopThread(void* a) +{ + char cmd[deflen]; + while(1) + { + fgets(cmd, deflen, stdin); + cmd[strlen(cmd)-1]=0; + while(!_dbg_dbgcmdexec(cmd)) //retry until the command came through + Sleep(100); + } + return 0; +} + +static DWORD WINAPI DbgCommandLoopThread(void* a) +{ + cmdloop(command_list, cbBadCmd, cbCommandProvider, cmdfindmain, false); + return 0; +} + +extern "C" DLL_EXPORT const char* _dbg_dbginit() +{ + DeleteFileA("DLLLoader.exe"); + char dir[deflen]=""; + GetModuleFileNameA(hInst, dir, deflen); + int len=strlen(dir); + while(dir[len]!='\\') + len--; + dir[len]=0; + SetCurrentDirectoryA(dir); + gMsgStack=msgallocstack(); + if(!gMsgStack) + return "Could not allocate message stack!"; + varinit(); + registercommands(); + scriptSetList(command_list); + CreateThread(0, 0, DbgCommandLoopThread, 0, 0, 0); + //CreateThread(0, 0, ConsoleReadLoopThread, 0, 0, 0); + return 0; +} diff --git a/x64_dbg_dbg/x64_dbg.h b/x64_dbg_dbg/x64_dbg.h new file mode 100644 index 00000000..fd0ef238 --- /dev/null +++ b/x64_dbg_dbg/x64_dbg.h @@ -0,0 +1,19 @@ +#ifndef _X64_DBG_H +#define _X64_DBG_H + +#include +#include "_global.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +DLL_EXPORT const char* _dbg_dbginit(); +DLL_EXPORT bool _dbg_dbgcmdexec(const char* cmd); + +#ifdef __cplusplus +} +#endif + +#endif // _X64_DBG_H diff --git a/x64_dbg_dbg/x64_dbg_dbg.cbp b/x64_dbg_dbg/x64_dbg_dbg.cbp new file mode 100644 index 00000000..3c97a046 --- /dev/null +++ b/x64_dbg_dbg/x64_dbg_dbg.cbp @@ -0,0 +1,117 @@ + + + + + + diff --git a/x64_dbg_dbg/x64_dbg_dbg.vcxproj b/x64_dbg_dbg/x64_dbg_dbg.vcxproj new file mode 100644 index 00000000..10039474 --- /dev/null +++ b/x64_dbg_dbg/x64_dbg_dbg.vcxproj @@ -0,0 +1,121 @@ + + + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Win32Proj + + + + DynamicLibrary + false + + + DynamicLibrary + false + + + + + + + + + + + + + true + $(SolutionDir)bin\x32 + $(Platform)\$(Configuration)\ + x32_dbg + + + true + $(SolutionDir)bin\x64 + x64_dbg + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + MachineX86 + true + Windows + true + true + $(SolutionDir)bin\x32\x32_bridge.lib;dbghelp\dbghelp_x86.lib;TitanEngine\TitanEngine_x86.lib;psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + true + Windows + true + true + $(SolutionDir)bin\x64\x64_bridge.lib;dbghelp\dbghelp_x64.lib;TitanEngine\TitanEngine_x64.lib;psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/x64_dbg_dbg/x64_dbg_dbg.vcxproj.filters b/x64_dbg_dbg/x64_dbg_dbg.vcxproj.filters new file mode 100644 index 00000000..e72ce3c2 --- /dev/null +++ b/x64_dbg_dbg/x64_dbg_dbg.vcxproj.filters @@ -0,0 +1,132 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/x64_dbg_dbg/x64_dbg_dbg.vcxproj.user b/x64_dbg_dbg/x64_dbg_dbg.vcxproj.user new file mode 100644 index 00000000..695b5c78 --- /dev/null +++ b/x64_dbg_dbg/x64_dbg_dbg.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/x64_dbg_exe/manifest.xml b/x64_dbg_exe/manifest.xml new file mode 100644 index 00000000..618fb8e3 --- /dev/null +++ b/x64_dbg_exe/manifest.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/x64_dbg_exe/resource.h b/x64_dbg_exe/resource.h new file mode 100644 index 00000000..c988bc7b --- /dev/null +++ b/x64_dbg_exe/resource.h @@ -0,0 +1,5 @@ +#ifndef IDC_STATIC +#define IDC_STATIC (-1) +#endif + +#define IDI_ICON1 100 diff --git a/x64_dbg_exe/resource.rc b/x64_dbg_exe/resource.rc new file mode 100644 index 00000000..1ee25103 --- /dev/null +++ b/x64_dbg_exe/resource.rc @@ -0,0 +1,25 @@ +// Generated by ResEdit 1.5.11 +// Copyright (C) 2006-2012 +// http://www.resedit.net + +#include +#include +#include +#include "resource.h" + + + + +// +// Icon resources +// +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +IDI_ICON1 ICON "..\\bug.ico" + + + +// +// Manifest resources +// +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +1 RT_MANIFEST ".\\manifest.xml" diff --git a/x64_dbg_exe/x64_dbg_exe.cbp b/x64_dbg_exe/x64_dbg_exe.cbp new file mode 100644 index 00000000..afa2e0b2 --- /dev/null +++ b/x64_dbg_exe/x64_dbg_exe.cbp @@ -0,0 +1,54 @@ + + + + + + diff --git a/x64_dbg_exe/x64_dbg_exe.cpp b/x64_dbg_exe/x64_dbg_exe.cpp new file mode 100644 index 00000000..662b2fe0 --- /dev/null +++ b/x64_dbg_exe/x64_dbg_exe.cpp @@ -0,0 +1,21 @@ +#include +#include +#include "resource.h" +#include "..\x64_dbg_bridge\bridgemain.h" + +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) +{ + const char* errormsg=BridgeInit(); + if(errormsg) + { + MessageBoxA(0, errormsg, "BridgeInit Error", MB_ICONERROR|MB_SYSTEMMODAL); + return 1; + } + errormsg=BridgeStart(); + if(errormsg) + { + MessageBoxA(0, errormsg, "BridgeStart Error", MB_ICONERROR|MB_SYSTEMMODAL); + return 1; + } + return 0; +} diff --git a/x64_dbg_exe/x64_dbg_exe.vcxproj b/x64_dbg_exe/x64_dbg_exe.vcxproj new file mode 100644 index 00000000..67812a71 --- /dev/null +++ b/x64_dbg_exe/x64_dbg_exe.vcxproj @@ -0,0 +1,89 @@ + + + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + Win32Proj + + + + Application + false + + + Application + false + + + + + + + + + + + + + true + $(SolutionDir)bin\x32 + $(Platform)\$(Configuration)\ + x32_dbg + + + true + $(SolutionDir)bin\x64 + x64_dbg + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + MachineX86 + true + Windows + true + true + $(SolutionDir)bin\x32\x32_bridge.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + true + Windows + true + true + $(SolutionDir)bin\x64\x64_bridge.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/x64_dbg_exe/x64_dbg_exe.vcxproj.filters b/x64_dbg_exe/x64_dbg_exe.vcxproj.filters new file mode 100644 index 00000000..aeb105a7 --- /dev/null +++ b/x64_dbg_exe/x64_dbg_exe.vcxproj.filters @@ -0,0 +1,32 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + + + Header Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/x64_dbg_exe/x64_dbg_exe.vcxproj.user b/x64_dbg_exe/x64_dbg_exe.vcxproj.user new file mode 100644 index 00000000..695b5c78 --- /dev/null +++ b/x64_dbg_exe/x64_dbg_exe.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/x64_dbg_gui/Disassembly.pptx b/x64_dbg_gui/Disassembly.pptx new file mode 100644 index 00000000..7ee76ed7 Binary files /dev/null and b/x64_dbg_gui/Disassembly.pptx differ diff --git a/x64_dbg_gui/Project/CopyBinaries.bat b/x64_dbg_gui/Project/CopyBinaries.bat new file mode 100644 index 00000000..fa88b168 --- /dev/null +++ b/x64_dbg_gui/Project/CopyBinaries.bat @@ -0,0 +1,25 @@ +@echo off + +:: Flag reset when a file has been found and copied +set flag=1 + +copy %1.a %2 /y + +if %ERRORLEVEL%==0 ( +set flag=0 +) + + +copy %1.exe %2 /y + +if %ERRORLEVEL%==0 ( +set flag=0 +) + +copy %1.dll %2 /y + +if %ERRORLEVEL%==0 ( +set flag=0 +) + +exit /b %flag% diff --git a/x64_dbg_gui/Project/DebuggerX64.pro b/x64_dbg_gui/Project/DebuggerX64.pro new file mode 100644 index 00000000..3617675d --- /dev/null +++ b/x64_dbg_gui/Project/DebuggerX64.pro @@ -0,0 +1,119 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2013-05-20T13:22:23 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +# Removes all debug output when defined +#DEFINES += QT_NO_DEBUG_OUTPUT + +QMAKE_CFLAGS_RELEASE += -O3 +QMAKE_CXXFLAGS_RELEASE += -O3 + + +!contains(QMAKE_HOST.arch, x86_64) { + TARGET = x32_gui +} else { + TARGET = x64_gui +} + +DEFINES += BUILD_LIB +TEMPLATE = lib +#TEMPLATE = app + +SOURCES += \ + Src/main.cpp \ + Src/Gui/MainWindow.cpp \ + Src/Gui/CPUWidget.cpp \ + Src/Gui/CommandLineEdit.cpp \ + Src/BasicView/Disassembly.cpp \ + Src/BasicView/HexDump.cpp \ + Src/BasicView/AbstractTableView.cpp \ + Src/Disassembler/QBeaEngine.cpp \ + Src/Memory/ProcessMemoryMap.cpp \ + Src/Memory/MemoryPage.cpp \ + Src/Memory/MapViewOfMem.cpp \ + Src/Bridge/Bridge.cpp \ + Src/BasicView/StdTable.cpp \ + Src/BasicView/MemoryMapView.cpp \ + Src/BasicView/LogView.cpp \ + Src/Gui/GotoDialog.cpp \ + Src/Disassembler/BeaHighlight.cpp \ + Src/BasicView/RegistersView.cpp \ + Src/Gui/StatusLabel.cpp \ + Src/BasicView/WordEditDialog.cpp + + +HEADERS += \ + Src/main.h \ + Src/Gui/MainWindow.h \ + Src/Gui/CPUWidget.h \ + Src/Gui/CommandLineEdit.h \ + Src/BasicView/Disassembly.h \ + Src/BasicView/HexDump.h \ + Src/BasicView/AbstractTableView.h \ + Src/Disassembler/QBeaEngine.h \ + Src/Memory/ProcessMemoryMap.h \ + Src/Memory/MemoryPage.h \ + Src/Memory/MapViewOfMem.h \ + Src/Bridge/Bridge.h \ + Src/Global/NewTypes.h \ + Src/Exports.h \ + Src/Imports.h \ + Src/BasicView/StdTable.h \ + Src/BasicView/MemoryMapView.h \ + Src/BasicView/LogView.h \ + Src/Gui/GotoDialog.h \ + Src/Disassembler/BeaHighlight.h \ + Src/BasicView/RegistersView.h \ + Src/Gui/StatusLabel.h \ + Src/BasicView/WordEditDialog.h + +INCLUDEPATH += \ + Src \ + Src/Gui \ + Src/BasicView \ + Src/Disassembler \ + Src/BeaEngine \ + Src/ThirdPartyLibs/BeaEngine \ + Src/Memory \ + Src/Bridge \ + Src/Global + +FORMS += \ + Src/Gui/MainWindow.ui \ + Src/Dummy.ui \ + Src/Gui/CPUWidget.ui \ + Src/Gui/GotoDialog.ui \ + Src/BasicView/WordEditDialog.ui + +INCLUDEPATH += $$PWD/Src/Bridge + +!contains(QMAKE_HOST.arch, x86_64) { + message("x86 build") + LIBS += -L"$$PWD/Src/ThirdPartyLibs/BeaEngine/" -lBeaEngine + LIBS += -L"$$PWD/Src/Bridge/" -lx32_bridge + FORMS += Src/BasicView/RegistersView32.ui + ## Windows x86 (32bit) specific build here +} else { + message("x86_64 build") + LIBS += -L"$$PWD/Src/ThirdPartyLibs/BeaEngine/" -lBeaEngine_64 + LIBS += -L"$$PWD/Src/Bridge/" -lx64_bridge + FORMS += Src/BasicView/RegistersView64.ui + ## Windows x64 (64bit) specific build here +} + +RESOURCES += \ + resource.qrc + + + + + + + + diff --git a/x64_dbg_gui/Project/Src/BasicView/AbstractTableView.cpp b/x64_dbg_gui/Project/Src/BasicView/AbstractTableView.cpp new file mode 100644 index 00000000..b6bd185c --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/AbstractTableView.cpp @@ -0,0 +1,895 @@ +#include "AbstractTableView.h" + +AbstractTableView::AbstractTableView(QWidget *parent) : QAbstractScrollArea(parent) +{ + // Class variable initialization + mTableOffset = 0; + mPrevTableOffset = mTableOffset + 1; + Header_t data; + data.isVisible=true; + data.height=20; + data.activeButtonIndex=-1; + mHeader = data; + + QFont font("Monospace", 8); + //QFont font("Terminal", 6); + //font.setBold(true); //bold + + font.setFixedPitch(true); + //font.setStyleHint(QFont::Monospace); + this->setFont(font); + + + int wRowsHeight = QFontMetrics(this->font()).height(); + wRowsHeight = (wRowsHeight * 105) / 100; + wRowsHeight = (wRowsHeight % 2) == 0 ? wRowsHeight : wRowsHeight + 1; + mRowHeight = wRowsHeight; + + mRowCount = 0; + + mHeaderButtonSytle.setStyleSheet(" QPushButton {\n background-color: rgb(192, 192, 192);\n border-style: outset;\n border-width: 2px;\n border-color: rgb(128, 128, 128);\n }\n QPushButton:pressed {\n background-color: rgb(192, 192, 192);\n border-style: inset;\n }"); + + mNbrOfLineToPrint = 0; + + mColResizeData = (ColumnResizingData_t){false, 0, 0}; + + mGuiState = AbstractTableView::NoState; + + mShouldReload = true; + + // ScrollBar Init + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + mScrollBarAttributes = (ScrollBar64_t){false, 0}; + + setMouseTracking(true); + + // Signals/Slots Connections + connect(verticalScrollBar(), SIGNAL(actionTriggered(int)), this, SLOT(vertSliderActionSlot(int))); +} + + +/************************************************************************************ + Painting Stuff +************************************************************************************/ +/** + * @brief This method has been reimplemented. It paints the whole table. + * + * @param[in] event Paint event + * + * @return Nothing. + */ +void AbstractTableView::paintEvent(QPaintEvent* event) +{ + QPainter wPainter(this->viewport()); + int wViewableRowsCount = getViewableRowsCount(); + + int x = 0; + int y = 0; + + // Reload data if needed + if(mPrevTableOffset != mTableOffset || mShouldReload == true) + { + prepareData(); + mPrevTableOffset = mTableOffset; + } + + // Paints background + wPainter.fillRect(wPainter.viewport(), QBrush(QColor(255, 251, 240))); + + // Paints header + if(mHeader.isVisible == true) + { + for(int i = 0; i < getColumnCount(); i++) + { + QStyleOptionButton wOpt; + + if((mColumnList[i].header.isPressed == true) && (mColumnList[i].header.isMouseOver == true)) + wOpt.state = QStyle::State_Sunken; + else + wOpt.state = QStyle::State_Enabled; + + wOpt.rect = QRect(x, y, getColumnWidth(i), getHeaderHeigth()); + + mHeaderButtonSytle.style()->drawControl(QStyle::CE_PushButton, &wOpt, &wPainter,&mHeaderButtonSytle); + + x += getColumnWidth(i); + } + x = 0; + y = getHeaderHeigth(); + } + + // Iterate over all columns and cells + for(int j = 0; j < getColumnCount(); j++) + { + for(int i = 0; i < wViewableRowsCount; i++) + { + // Paints cell contents + if(i < mNbrOfLineToPrint) + { + QString wStr = paintContent(&wPainter, mTableOffset, i, j, x, y, getColumnWidth(j), getRowHeight()); + wPainter.drawText(QRect(x + 4, y, getColumnWidth(j) - 4, getRowHeight()), Qt::AlignVCenter | Qt::AlignLeft, wStr); + } + + // Paints cell right borders + wPainter.save() ; + wPainter.setPen(QColor(128, 128, 128)); + wPainter.drawLine(x + getColumnWidth(j) - 1, y, x + getColumnWidth(j) - 1, y + getRowHeight() - 1); + wPainter.restore(); + + // Update y for the next iteration + y += getRowHeight(); + } + + y = getHeaderHeigth(); + x += getColumnWidth(j); + } +} + + +/************************************************************************************ + Mouse Management +************************************************************************************/ +/** + * @brief This method has been reimplemented. It manages the following actions: + * - Column resizing + * - Header button + * + * @param[in] event Mouse event + * + * @return Nothing. + */ +void AbstractTableView::mouseMoveEvent(QMouseEvent* event) +{ + // qDebug() << "mouseMoveEvent"; + + switch (mGuiState) + { + case AbstractTableView::NoState: + { + //qDebug() << "State = NoState"; + + int wColIndex = getColumnIndexFromX(event->x()); + int wStartPos = getColumnPosition(wColIndex); // Position X of the start of column + int wEndPos = getColumnPosition(wColIndex) + getColumnWidth(wColIndex); // Position X of the end of column + + if(event->buttons() == Qt::NoButton) + { + bool wHandle = true; + bool wHasCursor; + + wHasCursor = cursor().shape() == Qt::SplitHCursor ? true : false; + + if(((wColIndex != 0) && (event->x() >= wStartPos) && (event->x() <= (wStartPos + 2))) || ((wColIndex != (getColumnCount() - 1)) && (event->x() <= wEndPos) && (event->x() >= (wEndPos - 2)))) + { + wHandle = true; + } + else + { + wHandle = false; + } + + if((wHandle == true) && (wHasCursor == false)) + { + setCursor(Qt::SplitHCursor); + mColResizeData.splitHandle = true; + mGuiState = AbstractTableView::ReadyToResize; + } + if ((wHandle == false) && (wHasCursor == true)) + { + unsetCursor(); + mColResizeData.splitHandle = false; + mGuiState = AbstractTableView::NoState; + } + } + else + { + QWidget::mouseMoveEvent(event); + } + break; + } + case AbstractTableView::ReadyToResize: + { + //qDebug() << "State = ReadyToResize"; + + int wColIndex = getColumnIndexFromX(event->x()); + int wStartPos = getColumnPosition(wColIndex); // Position X of the start of column + int wEndPos = getColumnPosition(wColIndex) + getColumnWidth(wColIndex); // Position X of the end of column + + if(event->buttons() == Qt::NoButton) + { + bool wHandle = true; + + if(((wColIndex != 0) && (event->x() >= wStartPos) && (event->x() <= (wStartPos + 2))) || ((wColIndex != (getColumnCount() - 1)) && (event->x() <= wEndPos) && (event->x() >= (wEndPos - 2)))) + { + wHandle = true; + } + else + { + wHandle = false; + } + + if ((wHandle == false) && (mGuiState == AbstractTableView::ReadyToResize)) + { + unsetCursor(); + mColResizeData.splitHandle = false; + mGuiState = AbstractTableView::NoState; + } + } + break; + } + case AbstractTableView::ResizeColumnState: + { + //qDebug() << "State = ResizeColumnState"; + + int delta = event->x() - mColResizeData.lastPosX; + + int wNewSize = ((getColumnWidth(mColResizeData.index) + delta) >= 20) ? (getColumnWidth(mColResizeData.index) + delta) : (20); + + setColumnWidth(mColResizeData.index, wNewSize); + + mColResizeData.lastPosX = event->x(); + + repaint(); + + break; + } + case AbstractTableView::HeaderButtonPressed: + { + //qDebug() << "State = HeaderButtonPressed"; + + int wColIndex = getColumnIndexFromX(event->x()); + + if((wColIndex == mHeader.activeButtonIndex) && (event->y() <= getHeaderHeigth()) && (event->y() >= 0)) + { + mColumnList[mHeader.activeButtonIndex].header.isMouseOver = true; + } + else + { + mColumnList[mHeader.activeButtonIndex].header.isMouseOver = false; + } + + repaint(); + } + default: + break; + } +} + + +/** + * @brief This method has been reimplemented. It manages the following actions: + * - Column resizing + * - Header button + * + * @param[in] event Mouse event + * + * @return Nothing. + */ +void AbstractTableView::mousePressEvent(QMouseEvent* event) +{ + if(((event->buttons() & Qt::LeftButton) != 0) && ((event->buttons() & Qt::RightButton) == 0)) + { + if(mColResizeData.splitHandle == true) + { + int wColIndex = getColumnIndexFromX(event->x()); + int wStartPos = getColumnPosition(wColIndex); // Position X of the start of column + + mGuiState = AbstractTableView::ResizeColumnState; + + if(event->x() <= (wStartPos + 2)) + { + mColResizeData.index = wColIndex - 1; + } + else + { + mColResizeData.index = wColIndex; + } + + mColResizeData.lastPosX = event->x(); + } + else if((mHeader.isVisible == true) && (event->y() <= getHeaderHeigth()) && (event->y() >= 0)) + { + int wColIndex = getColumnIndexFromX(event->x()); + + qDebug() << "Button " << wColIndex << "has been pressed."; + emit headerButtonPressed(wColIndex); + + mColumnList[wColIndex].header.isPressed = true; + mColumnList[wColIndex].header.isMouseOver = true; + + mHeader.activeButtonIndex = wColIndex; + + mGuiState = AbstractTableView::HeaderButtonPressed; + + repaint(); + } + } + + //QWidget::mousePressEvent(event); +} + + +/** + * @brief This method has been reimplemented. It manages the following actions: + * - Column resizing + * - Header button + * + * @param[in] event Mouse event + * + * @return Nothing. + */ +void AbstractTableView::mouseReleaseEvent(QMouseEvent* event) +{ + if((event->buttons() & Qt::LeftButton) == 0) + { + if(mGuiState == AbstractTableView::ResizeColumnState) + { + mGuiState = AbstractTableView::NoState; + } + else if(mGuiState == AbstractTableView::HeaderButtonPressed) + { + if(mColumnList[mHeader.activeButtonIndex].header.isMouseOver == true) + { + qDebug() << "Button " << mHeader.activeButtonIndex << "has been released."; + emit headerButtonReleased(mHeader.activeButtonIndex); + } + mGuiState = AbstractTableView::NoState; + } + else + { + QWidget::mouseReleaseEvent(event); + } + + // Release all buttons + for(int i = 0; i < getColumnCount(); i++) + { + mColumnList[i].header.isPressed = false; + } + + repaint(); + } +} + + +/** + * @brief This method has been reimplemented. It manages the following actions: + * - Mouse wheel + * + * @param[in] event Wheel event + * + * @return Nothing. + */ +void AbstractTableView::wheelEvent(QWheelEvent* event) +{ + //qDebug() << "wheelEvent"; + + if(event->delta() > 0) + verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepSub); + else + verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepAdd); + + //QAbstractScrollArea::wheelEvent(event); +} + + +/** + * @brief This method has been reimplemented. It repaints the table when the height changes. + * + * @param[in] event Resize event + * + * @return Nothing. + */ +void AbstractTableView::resizeEvent(QResizeEvent* event) +{ + if(event->size().height() != event->oldSize().height()) + { + mShouldReload = true; + } + + QWidget::resizeEvent(event); +} + + +/************************************************************************************ + Keyboard Management +************************************************************************************/ +/** + * @brief This method has been reimplemented. It manages the following actions: + * - Pressed keys + * + * @param[in] event Key event + * + * @return Nothing. + */ +void AbstractTableView::keyPressEvent(QKeyEvent* event) +{ + int wKey = event->key(); + + if(wKey == Qt::Key_Up) + { + verticalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepSub); + } + else if(wKey == Qt::Key_Down) + { + verticalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepAdd); + } +} + + +/************************************************************************************ + ScrollBar Management + ***********************************************************************************/ +/** + * @brief This method is the slot connected to the actionTriggered signal of the vertical scrollbar. + * + * @param[in] action Slider action type + * + * @return Nothing. + */ +void AbstractTableView::vertSliderActionSlot(int action) +{ + int_t wDelta; + int wSliderPos = verticalScrollBar()->sliderPosition(); + int wNewScrollBarValue; + + // Bounding + wSliderPos = wSliderPos > verticalScrollBar()->maximum() ? verticalScrollBar()->maximum() : wSliderPos; + wSliderPos = wSliderPos < 0 ? 0 : wSliderPos; + + // Determine the delta + switch(action) + { + case QAbstractSlider::SliderNoAction: + break; + case QAbstractSlider::SliderSingleStepAdd: + wDelta = 1; + break; + case QAbstractSlider::SliderSingleStepSub: + wDelta = -1; + break; + case QAbstractSlider::SliderPageStepAdd: + wDelta = 3; + break; + case QAbstractSlider::SliderPageStepSub: + wDelta = -3; + break; + case QAbstractSlider::SliderToMinimum: + case QAbstractSlider::SliderToMaximum: + case QAbstractSlider::SliderMove: +#ifdef _WIN64 + wDelta = scaleFromScrollBarRangeToUint64(wSliderPos) - mTableOffset; +#else + wDelta = wSliderPos - mTableOffset; +#endif + break; + default: + break; + } + + // Call the hook (Usefull for disassembly) + mTableOffset = sliderMovedHook(action, mTableOffset, wDelta); + + // Scale the new table offset to the 32bits scrollbar range +#ifdef _WIN64 + wNewScrollBarValue = scaleFromUint64ToScrollBarRange(mTableOffset); +#else + wNewScrollBarValue = mTableOffset; +#endif + + // Update scrollbar attributes + verticalScrollBar()->setValue(wNewScrollBarValue); + verticalScrollBar()->setSliderPosition(wNewScrollBarValue); +} + + +/** + * @brief This virtual method is called at the end of the vertSliderActionSlot(...) method. + * It allows changing the table offset according to the action type, the old table offset + * and delta between the old and the new table offset. + * + * @param[in] type Type of action (Refer to the QAbstractSlider::SliderAction enum) + * @param[in] value Old table offset + * @param[in] delta Scrollbar value delta compared to the previous state + * + * @return Return the value of the new table offset. + */ +int_t AbstractTableView::sliderMovedHook(int type, int_t value, int_t delta) +{ + int_t wValue = value + delta; + int_t wMax = getRowCount() - 1; + + // Bounding + wValue = wValue > wMax ? wMax : wValue; + wValue = wValue < 0 ? 0 : wValue; + + return wValue; +} + + +/** + * @brief This method scale the given 64bits integer to the scrollbar range (32bits). + * + * @param[in] value 64bits integer to rescale + * + * @return 32bits integer. + */ +#ifdef _WIN64 +int AbstractTableView::scaleFromUint64ToScrollBarRange(int_t value) +{ + if(mScrollBarAttributes.is64 == true) + { + int_t wValue = ((int_t)value) >> mScrollBarAttributes.rightShiftCount; + int_t wValueMax = ((int_t)getRowCount() - 1) >> mScrollBarAttributes.rightShiftCount; + + if(value == ((int_t)getRowCount() - 1)) + return (int)(verticalScrollBar()->maximum()); + else + return (int)((int_t)((int_t)verticalScrollBar()->maximum() * (int_t)wValue) / (int_t)wValueMax); + } + else + { + return (int)value; + } +} +#endif + + +/** + * @brief This method scale the given 32bits integer to the table range (64bits). + * + * @param[in] value 32bits integer to rescale + * + * @return 64bits integer. + */ +#ifdef _WIN64 +int_t AbstractTableView::scaleFromScrollBarRangeToUint64(int value) +{ + if(mScrollBarAttributes.is64 == true) + { + int_t wValueMax = ((int_t)getRowCount() - 1) >> mScrollBarAttributes.rightShiftCount; + + if(value == (int)0x7FFFFFFF) + return (int_t)(getRowCount() - 1); + else + return (int_t)(((int_t)((int_t)wValueMax * (int_t)value) / (int_t)0x7FFFFFFF) << mScrollBarAttributes.rightShiftCount); + } + else + { + return (int_t)value; + } +} +#endif + + +/** + * @brief This method updates the scrollbar range and pre-computes some attributes for the 32<->64bits conversion methods. + * + * @param[in] range New table range (size) + * + * @return 32bits integer. + */ +void AbstractTableView::updateScrollBarRange(int_t range) +{ + int_t wMax = range--; + + if(wMax > 0) + { +#ifdef _WIN64 + if((uint_t)wMax < (uint_t)0x0000000080000000) + { + mScrollBarAttributes.is64 = false; + mScrollBarAttributes.rightShiftCount = 0; + verticalScrollBar()->setRange(0, wMax); + } + else + { + uint_t wMask = 0x8000000000000000; + int wLeadingZeroCount; + + // Count leading zeros + for(wLeadingZeroCount = 0; wLeadingZeroCount < 64; wLeadingZeroCount++) + { + if((uint_t)wMax < wMask) + { + wMask = wMask >> 1; + } + else + { + break; + } + } + + mScrollBarAttributes.is64 = true; + mScrollBarAttributes.rightShiftCount = 32 - wLeadingZeroCount; + verticalScrollBar()->setRange(0, 0x7FFFFFFF); + } +#else + verticalScrollBar()->setRange(0, wMax); +#endif + } +} + + +/************************************************************************************ + Coordinates Utils +************************************************************************************/ +/** + * @brief Returns the index offset (relative to the table offset) corresponding to the given y coordinate. + * + * @param[in] y Pixel offset starting from the top of the table (without the header) + * + * @return row index offset. + */ +int AbstractTableView::getIndexOffsetFromY(int y) +{ + return (y / getRowHeight()); +} + + +/** + * @brief Returns the index of the column corresponding to the given x coordinate. + * + * @param[in] x Pixel offset starting from the left of the table + * + * @return Column index. + */ +int AbstractTableView::getColumnIndexFromX(int x) +{ + int wX = 0; + int wColIndex = 0; + + while(wColIndex < getColumnCount()) + { + wX += getColumnWidth(wColIndex); + + if(x <= wX) + { + return wColIndex; + } + else if(wColIndex < getColumnCount()) + { + wColIndex++; + } + } + return getColumnCount() - 1; +} + + +/** + * @brief Returns the x coordinate of the beginning of the column at index index. + * + * @param[in] index Column index. + * + * @return X coordinate of the column index. + */ +int AbstractTableView::getColumnPosition(int index) +{ + int posX = 0; + + if((index >= 0) && (index < getColumnCount())) + { + for(int i = 0; i <= (index - 1); i++) + { + posX += getColumnWidth(i); + } + + return posX; + } + else + { + return -1; + } +} + + +/** + * @brief Substracts the header heigth from the given y. + * + * @param[in] y y coordinate + * + * @return y - getHeaderHeigth(). + */ +int AbstractTableView::transY(int y) +{ + return y - getHeaderHeigth(); +} + + +/** + * @brief Returns the number of viewable rows in the current window (Partially viewable rows are aslo counted). + * + * @return Number of viewable rows. + */ +int AbstractTableView::getViewableRowsCount() +{ + int wTableHeight = this->height() - getHeaderHeigth(); + int wCount = wTableHeight / getRowHeight(); + + wCount += (wTableHeight % getRowHeight()) > 0 ? 1 : 0; + + return wCount; +} + + +/** + * @brief This virtual method returns the number of remaining lines to print. + * + * @return Number of remaining lines to print. + */ +int AbstractTableView::getLineToPrintcount() +{ + int wViewableRowsCount = getViewableRowsCount(); + int_t wRemainingRowsCount = getRowCount() - mTableOffset; + int wCount = (int_t)wRemainingRowsCount > (int_t)wViewableRowsCount ? (int)wViewableRowsCount : (int)wRemainingRowsCount; + return wCount; +} + + +/************************************************************************************ + New Columns/New Size +************************************************************************************/ +/** + * @brief This mehtod adds a new column to the table. + * + * @param[in] width Width of the column in pixel + * @param[in] isClickable Boolean that tells whether the header is clickable or not + * + * @return Nothing. + */ +void AbstractTableView::addColumnAt(int width, bool isClickable) +{ + HeaderButton_t wHeaderButton; + Column_t wColumn; + + wHeaderButton.isPressed = false; + wHeaderButton.isClickable = isClickable; + wHeaderButton.isMouseOver = false; + + wColumn.header = wHeaderButton; + wColumn.width = width; + + mColumnList.append(wColumn); +} + + +void AbstractTableView::setRowCount(int_t count) +{ + updateScrollBarRange(count); + mRowCount = count; +} + +/************************************************************************************ + Getter & Setter +************************************************************************************/ +int_t AbstractTableView::getRowCount() +{ + return mRowCount; +} + + +int AbstractTableView::getColumnCount() +{ + return mColumnList.size(); +} + + +int AbstractTableView::getRowHeight() +{ + return mRowHeight; +} + + +int AbstractTableView::getColumnWidth(int index) +{ + if(index < 0) + { + return -1; + } + else if(index < (getColumnCount() - 1)) + { + return mColumnList.at(index).width; + } + else if(index == (getColumnCount() - 1)) + { + int wGlobWidth = 0; + + for(int i = 0; i < getColumnCount() - 1; i++) + wGlobWidth += getColumnWidth(i); + + return this->width() - wGlobWidth; + } + + return 0; +} + + +void AbstractTableView::setColumnWidth(int index, int width) +{ + mColumnList[index].width = width; +} + + +int AbstractTableView::getHeaderHeigth() +{ + if(mHeader.isVisible == true) + return mHeader.height; + else + return 0; +} + + +int AbstractTableView::getTableHeigth() +{ + return this->height() - getHeaderHeigth(); +} + + +int AbstractTableView::getGuiState() +{ + return mGuiState; +} + + +int AbstractTableView::getNbrOfLineToPrint() +{ + return mNbrOfLineToPrint; +} + + +void AbstractTableView::setNbrOfLineToPrint(int parNbrOfLineToPrint) +{ + mNbrOfLineToPrint = parNbrOfLineToPrint; +} + + +/************************************************************************************ + Table Offset Management +************************************************************************************/ +int_t AbstractTableView::getTableOffset() +{ + return mTableOffset; +} + + +void AbstractTableView::setTableOffset(int_t val) +{ + mTableOffset = val; + +#ifdef _WIN64 + int wNewValue = scaleFromUint64ToScrollBarRange(mTableOffset); + verticalScrollBar()->setValue(wNewValue); + verticalScrollBar()->setSliderPosition(wNewValue); +#else + verticalScrollBar()->setValue(val); + verticalScrollBar()->setSliderPosition(val); +#endif +} + + +/************************************************************************************ + Update/Reload/Refresh/Repaint +************************************************************************************/ +void AbstractTableView::reloadData() +{ + mShouldReload = true; + repaint(); +} + + +void AbstractTableView::repaint() +{ + this->viewport()->repaint(); +} + + +/** + * @brief This method is called when data have to be reloaded (e.g. When table offset changes). + * + * @return Nothing. + */ +void AbstractTableView::prepareData() +{ + int wViewableRowsCount = getViewableRowsCount(); + int_t wRemainingRowsCount = getRowCount() - mTableOffset; + mNbrOfLineToPrint = (int_t)wRemainingRowsCount > (int_t)wViewableRowsCount ? (int)wViewableRowsCount : (int)wRemainingRowsCount; +} diff --git a/x64_dbg_gui/Project/Src/BasicView/AbstractTableView.h b/x64_dbg_gui/Project/Src/BasicView/AbstractTableView.h new file mode 100644 index 00000000..fe5620c5 --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/AbstractTableView.h @@ -0,0 +1,141 @@ +#ifndef ABSTRACTTABLEVIEW_H +#define ABSTRACTTABLEVIEW_H + +#include +#include +#include +#include +#include +#include +#include +#include + + +class AbstractTableView : public QAbstractScrollArea +{ + Q_OBJECT +public: + enum GuiState_t {NoState, ReadyToResize, ResizeColumnState, HeaderButtonPressed}; + + // Constructor + explicit AbstractTableView(QWidget *parent = 0); + + // Pure Virtual Methods + virtual QString paintContent(QPainter* painter, int_t rowBase, int rowOffset, int col, int x, int y, int w, int h) = 0; + + // Painting Stuff + void paintEvent(QPaintEvent* event); + + // Mouse Management + void mouseMoveEvent(QMouseEvent* event); + void mousePressEvent(QMouseEvent* event); + void mouseReleaseEvent(QMouseEvent* event); + void wheelEvent(QWheelEvent* event); + void resizeEvent(QResizeEvent* event); + void keyPressEvent(QKeyEvent* event); + + // ScrollBar Management + virtual int_t sliderMovedHook(int type, int_t value, int_t delta); + int scaleFromUint64ToScrollBarRange(int_t value); + int_t scaleFromScrollBarRangeToUint64(int value); + void updateScrollBarRange(int_t range); + + // Coordinates Utils + int getIndexOffsetFromY(int y); + int getColumnIndexFromX(int x); + int getColumnPosition(int index); + int transY(int y); + int getViewableRowsCount(); + virtual int getLineToPrintcount(); + + // New Columns/New Size + virtual void addColumnAt(int width, bool isClickable); + virtual void setRowCount(int_t count); + + // Getter & Setter + int_t getRowCount(); + int getColumnCount(); + int getRowHeight(); + int getColumnWidth(int index); + void setColumnWidth(int index, int width); + int getHeaderHeigth(); + int getTableHeigth(); + int getGuiState(); + int getNbrOfLineToPrint(); + void setNbrOfLineToPrint(int parNbrOfLineToPrint); + + // Table Offset Management + int_t getTableOffset(); + void setTableOffset(int_t val); + + // Update/Reload/Refresh/Repaint + void reloadData(); + void repaint(); + virtual void prepareData(); + +signals: + void headerButtonPressed(int col); + void headerButtonReleased(int col); + +public slots: + void vertSliderActionSlot(int action); + +private: + typedef struct _ColumnResizingData_t + { + bool splitHandle; + int index; + int lastPosX; + } ColumnResizingData_t; + + typedef struct _HeaderButton_t + { + bool isClickable; + bool isPressed; + bool isMouseOver; + } HeaderButton_t; + + typedef struct _Column_t + { + int width; + HeaderButton_t header; + } Column_t; + + typedef struct _Header_t + { + bool isVisible; + int height; + int activeButtonIndex; + } Header_t; + + typedef struct _ScrollBar64_t + { + bool is64; + int rightShiftCount; + } ScrollBar64_t; + + GuiState_t mGuiState; + + ColumnResizingData_t mColResizeData; + + QPushButton mHeaderButtonSytle; + + QList mColumnList; + + int mRowHeight; + int_t mRowCount; + + + int_t mTableOffset; + Header_t mHeader; + + int mNbrOfLineToPrint; + + int_t mPrevTableOffset; + + bool mShouldReload; + + ScrollBar64_t mScrollBarAttributes; +}; + +#endif // ABSTRACTTABLEVIEW_H diff --git a/x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp b/x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp new file mode 100644 index 00000000..267518f8 --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp @@ -0,0 +1,837 @@ +#include "Disassembly.h" + +Disassembly::Disassembly(MemoryPage* parMemPage, QWidget *parent) : AbstractTableView(parent) +{ + setMemoryPage(parMemPage); + + mInstBuffer.clear(); + + SelectionData_t data; + memset(&data, 0, sizeof(SelectionData_t)); + mSelection = data; + + mCipRva = 0; + + mDisasm = new QBeaEngine(); + + mIsLastInstDisplayed = false; + + mGuiState = Disassembly::NoState; + + setRowCount(parMemPage->getSize()); + + qDebug() << "size" << parMemPage->getSize(); + + int charwidth=QFontMetrics(this->font()).width(QChar(' ')); + + addColumnAt(charwidth*2*sizeof(int_t)+8, false); //address + addColumnAt(charwidth*2*12+8, false); //bytes + addColumnAt(charwidth*40, false); //disassembly + addColumnAt(100, false); //comments + + connect(Bridge::getBridge(), SIGNAL(disassembleAt(int_t, int_t)), this, SLOT(disassambleAt(int_t, int_t))); + connect(Bridge::getBridge(), SIGNAL(dbgStateChanged(DBGSTATE)), this, SLOT(debugStateChangedSlot(DBGSTATE))); +} + +/************************************************************************************ + Private Functions +************************************************************************************/ + +void Disassembly::paintRichText(QPainter* painter, int x, int y, int w, int h, int xinc, const QList* richText) +{ + int len=richText->size(); + int charwidth=QFontMetrics(this->font()).width(QChar(' ')); + for(int i=0; iat(i); + int curRichTextLength=curRichText.text.length(); + int backgroundWidth=charwidth*curRichTextLength; + if(backgroundWidth+xinc>w) + backgroundWidth=w-xinc; + switch(curRichText.flags) + { + case FlagNone: //defaults + painter->drawText(QRect(x+xinc, y, w-xinc, h), 0, curRichText.text); + break; + case FlagColor: //color only + painter->save(); + painter->setPen(QPen(curRichText.textColor)); + painter->drawText(QRect(x+xinc, y, w-xinc, h), 0, curRichText.text); + painter->restore(); + break; + case FlagBackground: //background only + painter->save(); + if(backgroundWidth>0) + painter->fillRect(QRect(x+xinc, y, backgroundWidth, h), QBrush(curRichText.textBackground)); + painter->drawText(QRect(x+xinc, y, w-xinc, h), 0, curRichText.text); + painter->restore(); + break; + case FlagAll: //color+background + painter->save(); + if(backgroundWidth>0) + painter->fillRect(QRect(x+xinc, y, backgroundWidth, h), QBrush(curRichText.textBackground)); + painter->setPen(QPen(curRichText.textColor)); + painter->drawText(QRect(x+xinc, y, w-xinc, h), 0, curRichText.text); + painter->restore(); + break; + } + xinc+=charwidth*curRichTextLength; + } +} + + +/************************************************************************************ + Reimplemented Functions +************************************************************************************/ +/** + * @brief This method has been reimplemented. It returns the string to paint or paints it + * by its own. + * + * @param[in] painter Pointer to the painter that allows painting by its own + * @param[in] rowBase Index of the top item (Table offset) + * @param[in] rowOffset Index offset starting from rowBase + * @param[in] col Column index + * @param[in] x Rectangle x + * @param[in] y Rectangle y + * @param[in] w Rectangle width + * @param[in] h Rectangle heigth + * + * @return String to paint. + */ +QString Disassembly::paintContent(QPainter* painter, int_t rowBase, int rowOffset, int col, int x, int y, int w, int h) +{ + QString wStr = ""; + int_t wRVA = mInstBuffer.at(rowOffset).rva; + bool wIsSelected = isSelected(rowBase, rowOffset); + + // Highlight if selected + if(wIsSelected) + painter->fillRect(QRect(x, y, w, h), QBrush(QColor(192,192,192))); + + switch(col) + { + case 0: // Draw address (+ label) + { + char label[MAX_LABEL_SIZE]=""; + int_t cur_addr=mInstBuffer.at(rowOffset).rva+mMemPage->getBase(); + QString addrText=QString("%1").arg(cur_addr, sizeof(int_t)*2, 16, QChar('0')).toUpper(); + if(DbgGetLabelAt(cur_addr, SEG_DEFAULT, label)) //has label + addrText+=" <"+QString(label)+">"; + else + *label=0; + BPXTYPE bpxtype=DbgGetBpxTypeAt(cur_addr); + painter->save(); + if(mInstBuffer.at(rowOffset).rva == mCipRva) //cip + { + painter->fillRect(QRect(x, y, w, h), QBrush(QColor(0,0,0))); + switch(bpxtype) //breakpoint + { + case bpnormal: + painter->setPen(QPen(QColor("#ff0000"))); + break; + default: + painter->setPen(QPen(QColor("#fffbf0"))); + break; + } + } + else //other address + { + if(*label) //label + { + if(bpxtype==bpnone) //label only + painter->setPen(QPen(QColor("#ff0000"))); //red -> address + label text + else //label+breakpoint + { + switch(bpxtype) + { + case bpnormal: + painter->fillRect(QRect(x, y, w, h), QBrush(QColor("#ff0000"))); //fill red + break; + default: + painter->setPen(QPen(QColor("#000000"))); //black address + break; + } + } + } + else //no label + { + if(bpxtype==bpnone) //no label, no breakpoint + { + if(wIsSelected) + painter->setPen(QPen(QColor("#000000"))); //black address + else + painter->setPen(QPen(QColor("#808080"))); + } + else //breakpoint only + { + switch(bpxtype) + { + case bpnormal: + painter->fillRect(QRect(x, y, w, h), QBrush(QColor("#ff0000"))); //fill red + break; + default: + if(wIsSelected) + painter->setPen(QPen(QColor("#000000"))); //black address + else + painter->setPen(QPen(QColor("#808080"))); + break; + } + } + } + } + painter->drawText(QRect(x + 4, y , w - 4 , h), Qt::AlignVCenter | Qt::AlignLeft, addrText); + painter->restore(); + break; + } + + case 1: //draw bytes (TODO: some spaces between bytes) + { + for(int i = 0; i < mInstBuffer.at(rowOffset).dump.size(); i++) + wStr += QString("%1").arg((unsigned char)(mInstBuffer.at(rowOffset).dump.at(i)), 2, 16, QChar('0')).toUpper(); + + paintJumpsGraphic(painter, x + 5, y, wRVA); + + // Draw cell content + painter->drawText(QRect(x + 15, y, getColumnWidth(col) - 15, getRowHeight()), 0, wStr); + + wStr = ""; + + break; + } + + case 2: //draw disassembly (with colours needed) + { + QList richText; + BeaHighlight::PrintRtfInstruction(&richText, &mInstBuffer.at(rowOffset).disasm); + Disassembly::paintRichText(painter, x, y, getColumnWidth(col), getRowHeight(), 4, &richText); + break; + } + + case 3: //draw comments + { + char comment[MAX_COMMENT_SIZE]=""; + if(DbgGetCommentAt(mInstBuffer.at(rowOffset).rva+mMemPage->getBase(), comment)) + wStr=QString(comment); + else + wStr=""; + } + break; + + default: + break; + } + + return wStr; +} + + +/************************************************************************************ + Mouse Management +************************************************************************************/ +/** + * @brief This method has been reimplemented. It manages the following actions: + * - Multi-rows selection + * + * @param[in] event Mouse event + * + * @return Nothing. + */ +void Disassembly::mouseMoveEvent(QMouseEvent* event) +{ + //qDebug() << "Disassembly::mouseMoveEvent"; + + bool wAccept = true; + + if(mGuiState == Disassembly::MultiRowsSelectionState) + { + //qDebug() << "State = MultiRowsSelectionState"; + + if((transY(event->y()) >= 0) && (transY(event->y()) <= this->getTableHeigth())) + { + int wI = getIndexOffsetFromY(transY(event->y())); + + // Bound + wI = wI >= mInstBuffer.size() ? mInstBuffer.size() - 1 : wI; + wI = wI < 0 ? 0 : wI; + + int_t wRowIndex = mInstBuffer.at(wI).rva; + + if(wRowIndex < getRowCount()) + { + expandSelectionUpTo(wRowIndex); + + repaint(); + + wAccept = false; + } + } + } + + if(wAccept == true) + AbstractTableView::mouseMoveEvent(event); +} + + +/** + * @brief This method has been reimplemented. It manages the following actions: + * - Multi-rows selection + * + * @param[in] event Mouse event + * + * @return Nothing. + */ +void Disassembly::mousePressEvent(QMouseEvent* event) +{ + //qDebug() << "Disassembly::mousePressEvent"; + + bool wAccept = false; + + if(((event->buttons() & Qt::LeftButton) != 0) && ((event->buttons() & Qt::RightButton) == 0)) + { + if(getGuiState() == AbstractTableView::NoState) + { + if(event->y() > getHeaderHeigth()) + { + int_t wRowIndex = getInstructionRVA(getTableOffset(), getIndexOffsetFromY(transY(event->y()))); + + if(wRowIndex < getRowCount()) + { + setSingleSelection(wRowIndex); + + mGuiState = Disassembly::MultiRowsSelectionState; + + repaint(); + + wAccept = true; + } + } + } + } + + if(wAccept == false) + AbstractTableView::mousePressEvent(event); +} + + +/** + * @brief This method has been reimplemented. It manages the following actions: + * - Multi-rows selection + * + * @param[in] event Mouse event + * + * @return Nothing. + */ +void Disassembly::mouseReleaseEvent(QMouseEvent* event) +{ + bool wAccept = true; + + if((event->buttons() & Qt::LeftButton) == 0) + { + if(mGuiState == Disassembly::MultiRowsSelectionState) + { + mGuiState = Disassembly::NoState; + + repaint(); + + wAccept = false; + } + } + + if(wAccept == true) + AbstractTableView::mouseReleaseEvent(event); +} + + +/************************************************************************************ + Keyboard Management +************************************************************************************/ +/** + * @brief This method has been reimplemented. It processes the Up/Down key events. + * + * @param[in] event Key event + * + * @return Nothing. + */ +void Disassembly::keyPressEvent(QKeyEvent* event) +{ + int key = event->key(); + + if(key == Qt::Key_Up || key == Qt::Key_Down) + { + int_t botRVA = getTableOffset(); + int_t topRVA = getInstructionRVA(getTableOffset(), getNbrOfLineToPrint() - 1); + + if(key == Qt::Key_Up) + selectPrevious(); + else + selectNext(); + + if(getInitialSelection() < botRVA) + { + setTableOffset(getInitialSelection()); + } + else if(getInitialSelection() >= topRVA) + { + setTableOffset(getInstructionRVA(getInitialSelection(),-getNbrOfLineToPrint() + 2)); + } + + repaint(); + } + else + { + AbstractTableView::keyPressEvent(event); + } +} + + +/************************************************************************************ + ScrollBar Management + ***********************************************************************************/ +/** + * @brief This method has been reimplemented. It realigns the slider on real instructions except + * when the type is QAbstractSlider::SliderNoAction. This type (QAbstractSlider::SliderNoAction) + * is used to force the disassembling at a specific RVA. + * + * @param[in] type Type of action + * @param[in] value Old table offset + * @param[in] delta Scrollbar value delta compared to the previous state + * + * @return Return the value of the new table offset. + */ +int_t Disassembly::sliderMovedHook(int type, int_t value, int_t delta) +{ + int_t wNewValue; + + if(type == QAbstractSlider::SliderNoAction) // QAbstractSlider::SliderNoAction is used to disassembe at a specific address + { + wNewValue = value + delta; + } + else if(type == QAbstractSlider::SliderMove) // If it's a slider action, disassemble one instruction back and one instruction next in order to be aligned on a real instruction + { + if(value + delta > 0) + { + wNewValue = getInstructionRVA(value + delta, -1); + wNewValue = getInstructionRVA(wNewValue, 1); + } + else + wNewValue = 0; + } + else // For other actions, disassemble according to the delta + { + wNewValue = getInstructionRVA(value, delta); + } + + return wNewValue; +} + + +/************************************************************************************ + Jumps Graphic +************************************************************************************/ +/** + * @brief This method paints the graphic for jumps. + * + * @param[in] painter Pointer to the painter that allows painting by its own + * @param[in] x Rectangle x + * @param[in] y Rectangle y + * @param[in] addr RVA of address to process + * + * @return Nothing. + */ +void Disassembly::paintJumpsGraphic(QPainter* painter, int x, int y, int_t addr) +{ + int_t selHeadRVA = mSelection.fromIndex; + int_t rva = addr; + Instruction_t instruction = DisassembleAt(selHeadRVA); + Int32 branchType = instruction.disasm.Instruction.BranchType; + GraphicDump_t wPict = GD_Nothing; + + if( branchType == (Int32)JO || + branchType == (Int32)JC || + branchType == (Int32)JE || + branchType == (Int32)JA || + branchType == (Int32)JS || + branchType == (Int32)JP || + branchType == (Int32)JL || + branchType == (Int32)JG || + branchType == (Int32)JB || + branchType == (Int32)JECXZ || + branchType == (Int32)JmpType || + branchType == (Int32)RetType || + branchType == (Int32)JNO || + branchType == (Int32)JNC || + branchType == (Int32)JNE || + branchType == (Int32)JNA || + branchType == (Int32)JNS || + branchType == (Int32)JNP || + branchType == (Int32)JNL || + branchType == (Int32)JNG || + branchType == (Int32)JNB) + { + int_t destRVA = (int_t)instruction.disasm.Instruction.AddrValue; + + if(destRVA > (int_t)mMemPage->getBase()) + { + destRVA -= (int_t)mMemPage->getBase(); + + if(destRVA < selHeadRVA) + { + if(rva == destRVA) + wPict = GD_HeadFromBottom; + else if(rva > destRVA && rva < selHeadRVA) + wPict = GD_Vert; + else if(rva == selHeadRVA) + wPict = GD_FootToTop; + } + else if(destRVA > selHeadRVA) + { + if(rva == selHeadRVA) + wPict = GD_FootToBottom; + else if(rva > selHeadRVA && rva < destRVA) + wPict = GD_Vert; + else if(rva == destRVA) + wPict = GD_HeadFromTop; + } + } + } + + painter->save() ; + + if(DbgIsJumpGoingToExecute(instruction.rva+mMemPage->getBase())) //change pen color when jump is executed + painter->setPen(QColor(255, 0, 0)); + else + painter->setPen(QColor(128, 128, 128)); + + if(wPict == GD_Vert) + { + painter->drawLine(x, y, x, y + getRowHeight()); + } + else if(wPict == GD_FootToBottom) + { + painter->drawLine(x, y + getRowHeight() / 2, x + 5, y + getRowHeight() / 2); + painter->drawLine(x, y + getRowHeight() / 2, x, y + getRowHeight()); + } + if(wPict == GD_FootToTop) + { + painter->drawLine(x, y + getRowHeight() / 2, x + 5, y + getRowHeight() / 2); + painter->drawLine(x, y, x, y + getRowHeight() / 2); + } + else if(wPict == GD_HeadFromBottom) + { + QPoint wPoints[] = { + QPoint(x + 3, y + getRowHeight() / 2 - 2), + QPoint(x + 5, y + getRowHeight() / 2), + QPoint(x + 3, y + getRowHeight() / 2 + 2), + }; + + painter->drawLine(x, y + getRowHeight() / 2, x + 5, y + getRowHeight() / 2); + painter->drawLine(x, y + getRowHeight() / 2, x, y + getRowHeight()); + painter->drawPolyline(wPoints, 3); + } + if(wPict == GD_HeadFromTop) + { + QPoint wPoints[] = { + QPoint(x + 3, y + getRowHeight() / 2 - 2), + QPoint(x + 5, y + getRowHeight() / 2), + QPoint(x + 3, y + getRowHeight() / 2 + 2), + }; + + painter->drawLine(x, y + getRowHeight() / 2, x + 5, y + getRowHeight() / 2); + painter->drawLine(x, y, x, y + getRowHeight() / 2); + painter->drawPolyline(wPoints, 3); + } + + painter->restore(); +} + + +/************************************************************************************ + Instructions Management + ***********************************************************************************/ +/** + * @brief Returns the RVA of count-th instructions before the given instruction RVA. + * + * @param[in] rva Instruction RVA + * @param[in] count Instruction count + * + * @return RVA of count-th instructions before the given instruction RVA. + */ +int_t Disassembly::getPreviousInstructionRVA(int_t rva, uint_t count) +{ + QByteArray wBuffer; + int_t wBottomByteRealRVA; + int_t wVirtualRVA; + int_t wMaxByteCountToRead ; + + wBottomByteRealRVA = (int_t)rva - 16 * (count + 3); + wBottomByteRealRVA = wBottomByteRealRVA < 0 ? 0 : wBottomByteRealRVA; + + wVirtualRVA = (int_t)rva - wBottomByteRealRVA; + + wMaxByteCountToRead = wVirtualRVA + 1 + 16; + wBuffer.resize(wMaxByteCountToRead); + + mMemPage->readOriginalMemory(reinterpret_cast(wBuffer.data()), wBottomByteRealRVA, wMaxByteCountToRead); + + int_t addr = mDisasm->DisassembleBack(reinterpret_cast(wBuffer.data()), 0, wMaxByteCountToRead, wVirtualRVA, count); + + addr += rva - wVirtualRVA; + + return addr; +} + + +/** + * @brief Returns the RVA of count-th instructions after the given instruction RVA. + * + * @param[in] rva Instruction RVA + * @param[in] count Instruction count + * + * @return RVA of count-th instructions after the given instruction RVA. + */ +int_t Disassembly::getNextInstructionRVA(int_t rva, uint_t count) +{ + QByteArray wBuffer; + int_t wVirtualRVA = 0; + int_t wRemainingBytes; + int_t wMaxByteCountToRead; + int_t wNewRVA; + + wRemainingBytes = mMemPage->getSize() - rva; + + wMaxByteCountToRead = 16 * (count + 1); + wMaxByteCountToRead = wRemainingBytes > wMaxByteCountToRead ? wMaxByteCountToRead : wRemainingBytes; + wBuffer.resize(wMaxByteCountToRead); + + mMemPage->readOriginalMemory(reinterpret_cast(wBuffer.data()), rva, wMaxByteCountToRead); + + wNewRVA = mDisasm->DisassembleNext(reinterpret_cast(wBuffer.data()), 0, wMaxByteCountToRead, wVirtualRVA, count); + wNewRVA += rva; + + return wNewRVA; +} + + +/** + * @brief Returns the RVA of count-th instructions before/after (depending on the sign) the given instruction RVA. + * + * @param[in] rva Instruction RVA + * @param[in] count Instruction count + * + * @return RVA of count-th instructions before/after the given instruction RVA. + */ +int_t Disassembly::getInstructionRVA(int_t index, int_t count) +{ + int_t wAddr = 0; + + if(count == 0) + wAddr = index; + if(count < 0) + wAddr = getPreviousInstructionRVA(index, qAbs(count)); + else if(count > 0) + wAddr = getNextInstructionRVA(index, qAbs(count)); + + + if(wAddr < 0) + wAddr = 0; + else if(wAddr > getRowCount() - 1) + wAddr = getRowCount() - 1; + + return wAddr; +} + + +/** + * @brief Disassembles the instruction at the given RVA. + * + * @param[in] rva RVA of instruction to disassemble + * + * @return Return the disassembled instruction. + */ +Instruction_t Disassembly::DisassembleAt(int_t rva) +{ + QByteArray wBuffer; + int_t base = mMemPage->getBase(); + int_t wMaxByteCountToRead = 16 * 2; + wBuffer.resize(wMaxByteCountToRead); + + mMemPage->readOriginalMemory(reinterpret_cast(wBuffer.data()), rva, wMaxByteCountToRead); + + return mDisasm->DisassembleAt(reinterpret_cast(wBuffer.data()), wMaxByteCountToRead, 0, base, rva); +} + + +/** + * @brief Disassembles the instruction count instruction afterc the instruction at the given RVA. + * Count can be positive or negative. + * + * @param[in] rva RVA of reference instruction + * @param[in] count Number of instruction + * + * @return Return the disassembled instruction. + */ +Instruction_t Disassembly::DisassembleAt(int_t rva, int_t count) +{ + rva = getNextInstructionRVA(rva, count); + return DisassembleAt(rva); +} + + +/************************************************************************************ + Selection Management +************************************************************************************/ +void Disassembly::expandSelectionUpTo(int_t to) +{ + if(to < mSelection.firstSelectedIndex) + { + mSelection.fromIndex = to; + mSelection.toIndex = mSelection.firstSelectedIndex; + } + else if(to > mSelection.firstSelectedIndex) + { + mSelection.fromIndex = mSelection.firstSelectedIndex; + mSelection.toIndex = to; + } +} + + +void Disassembly::setSingleSelection(int_t index) +{ + mSelection.firstSelectedIndex = index; + mSelection.fromIndex = index; + mSelection.toIndex = index; +} + + +int_t Disassembly::getInitialSelection() +{ + return mSelection.firstSelectedIndex; +} + + +void Disassembly::selectNext() +{ + int_t wAddr = getInstructionRVA(getInitialSelection(), 1); + + setSingleSelection(wAddr); +} + + +void Disassembly::selectPrevious() +{ + int_t wAddr = getInstructionRVA(getInitialSelection(), -1); + + setSingleSelection(wAddr); +} + + +bool Disassembly::isSelected(int_t base, int_t offset) +{ + int_t wAddr = base; + + if(offset < 0) + wAddr = getPreviousInstructionRVA(getTableOffset(), offset); + else if(offset > 0) + wAddr = getNextInstructionRVA(getTableOffset(), offset); + + if(wAddr >= mSelection.fromIndex && wAddr <= mSelection.toIndex) + return true; + else + return false; +} + + +/************************************************************************************ + Update/Reload/Refresh/Repaint +************************************************************************************/ +void Disassembly::prepareData() +{ + int_t wViewableRowsCount = getViewableRowsCount(); + + int_t wAddrPrev = getTableOffset(); + int_t wAddr = wAddrPrev; + + int wCount = 0; + + for(int wI = 0; wI < wViewableRowsCount && getRowCount() > 0; wI++) + { + wAddrPrev = wAddr; + wAddr = getNextInstructionRVA(wAddr, 1); + + if(wAddr == wAddrPrev) + { + break; + } + + wCount++; + } + + setNbrOfLineToPrint(wCount); + + int wI = 0; + int_t wRVA = 0; + Instruction_t wInst; + + wRVA = getTableOffset(); + mInstBuffer.clear(); + + for(wI = 0; wI < wCount; wI++) + { + wInst = DisassembleAt(wRVA); + mInstBuffer.append(wInst); + wRVA += wInst.lentgh; + } +} + + +/************************************************************************************ + Public Methods +************************************************************************************/ +void Disassembly::setMemoryPage(MemoryPage* parMemPage) +{ + mMemPage = parMemPage; +} + + +void Disassembly::disassambleAt(int_t parVA, int_t parCIP) +{ + int_t wBase = Bridge::getBridge()->getBase(parVA); + int_t wSize = Bridge::getBridge()->getSize(wBase); + int_t wRVA = parVA - wBase; + int_t wCipRva = parCIP - wBase; + + setRowCount(wSize); + mMemPage->setAttributes(wBase, wSize); // Set base and size (Useful when memory page changed) + setSingleSelection(wRVA); // Selects disassembled instruction + + mCipRva = wCipRva; + + if(mInstBuffer.size() > 0 && wRVA >= (int_t)mInstBuffer.first().rva && wRVA < (int_t)mInstBuffer.last().rva) + { + repaint(); + } + else if(mInstBuffer.size() > 0 && wRVA == (int_t)mInstBuffer.last().rva) + { + setTableOffset(mInstBuffer.first().rva + mInstBuffer.first().lentgh); + } + else + { + setTableOffset(wRVA); + } + +} + + +void Disassembly::disassembleClear() +{ + //TODO: fix this (also try restarting) + setRowCount(0); + reloadData(); +} + + +void Disassembly::debugStateChangedSlot(DBGSTATE state) +{ + if(state==stopped) + disassembleClear(); +} diff --git a/x64_dbg_gui/Project/Src/BasicView/Disassembly.h b/x64_dbg_gui/Project/Src/BasicView/Disassembly.h new file mode 100644 index 00000000..5b4221ea --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/Disassembly.h @@ -0,0 +1,92 @@ +#ifndef DISASSEMBLY_H +#define DISASSEMBLY_H + +#include +#include +#include "NewTypes.h" +#include "AbstractTableView.h" +#include "QBeaEngine.h" +#include "MemoryPage.h" +#include "BeaHighlight.h" + +class Disassembly : public AbstractTableView +{ + Q_OBJECT +public: + explicit Disassembly(MemoryPage *parMemPage, QWidget *parent = 0); + + // Private Functions + void paintRichText(QPainter* painter, int x, int y, int w, int h, int xinc, const QList* richText); + + // Reimplemented Functions + QString paintContent(QPainter* painter, int_t rowBase, int rowOffset, int col, int x, int y, int w, int h); + + // Mouse Management + void mouseMoveEvent(QMouseEvent* event); + void mousePressEvent(QMouseEvent* event); + void mouseReleaseEvent(QMouseEvent* event); + + // Keyboard Management + void keyPressEvent(QKeyEvent* event); + + // ScrollBar Management + int_t sliderMovedHook(int type, int_t value, int_t delta); + + // Jumps Graphic + void paintJumpsGraphic(QPainter* painter, int x, int y, int_t addr); + + // Instructions Management + int_t getPreviousInstructionRVA(int_t rva, uint_t count); + int_t getNextInstructionRVA(int_t rva, uint_t count); + int_t getInstructionRVA(int_t index, int_t count); + Instruction_t DisassembleAt(int_t rva); + Instruction_t DisassembleAt(int_t rva, int_t count); + + // Selection Management + void expandSelectionUpTo(int_t to); + void setSingleSelection(int_t index); + int_t getInitialSelection(); + void selectNext(); + void selectPrevious(); + bool isSelected(int_t base, int_t offset); + + // Update/Reload/Refresh/Repaint + void prepareData(); + + // Public Methods + void setMemoryPage(MemoryPage* parMemPage); + void disassembleClear(); + +signals: + +public slots: + void disassambleAt(int_t parVA, int_t parCIP); + void debugStateChangedSlot(DBGSTATE state); + +private: + enum GuiState_t {NoState, MultiRowsSelectionState}; + enum GraphicDump_t {GD_Nothing, GD_FootToTop, GD_FootToBottom, GD_HeadFromTop, GD_HeadFromBottom, GD_Vert}; // GD_FootToTop = '- , GD_FootToBottom = ,- , GD_HeadFromTop = '-> , GD_HeadFromBottom = ,-> , GD_Vert = | + + typedef struct _SelectionData_t + { + int_t firstSelectedIndex; + int_t fromIndex; + int_t toIndex; + } SelectionData_t; + + QBeaEngine* mDisasm; + + SelectionData_t mSelection; + + bool mIsLastInstDisplayed; + + GuiState_t mGuiState; + + MemoryPage* mMemPage; + + int_t mCipRva; + + QList mInstBuffer; +}; + +#endif // DISASSEMBLY_H diff --git a/x64_dbg_gui/Project/Src/BasicView/HeaderButton.h b/x64_dbg_gui/Project/Src/BasicView/HeaderButton.h new file mode 100644 index 00000000..00326609 --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/HeaderButton.h @@ -0,0 +1,20 @@ +#ifndef HEADERBUTTON_H +#define HEADERBUTTON_H + +#include + +class HeaderButton : public QWidget +{ + Q_OBJECT +public: + explicit HeaderButton(QWidget *parent = 0); + void setGeometry(int x, int y, int w, int h); + +signals: + +public slots: + +}; + +#endif // HEADERBUTTON_H + diff --git a/x64_dbg_gui/Project/Src/BasicView/HexDump.cpp b/x64_dbg_gui/Project/Src/BasicView/HexDump.cpp new file mode 100644 index 00000000..7b5a2df0 --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/HexDump.cpp @@ -0,0 +1,241 @@ +#include "HexDump.h" + + + +HexDump::HexDump(QWidget *parent) :AbstractTableView(parent) +{ + SelectionData_t data; + memset(&data, 0, sizeof(SelectionData_t)); + mSelection = data; + + mGuiState = HexDump::NoState; + + + mByteWidth = QFontMetrics(this->font()).width(QChar('L')) + 4; + mDumpByteWidth = 16; + + setRowCount(0); + + mMemPage = new MemoryPage(0, 0); + + addColumnAt(100, false); + addColumnAt(100, false); + addColumnAt(100, false); + + connect(Bridge::getBridge(), SIGNAL(disassembleAt(int_t, int_t)), this, SLOT(printDumpAt(int_t))); +} + + +void HexDump::printDumpAt(int_t parVA) +{ + int_t wBase = Bridge::getBridge()->getBase(parVA); + int_t wSize = Bridge::getBridge()->getSize(wBase); + int_t wRVA = parVA - wBase; + + setRowCount(wSize/mDumpByteWidth); + mMemPage->setAttributes(wBase, wSize); // Set base and size (Useful when memory page changed) + setTableOffset(wRVA/mDumpByteWidth); +} + +void HexDump::mouseMoveEvent(QMouseEvent* event) +{ + qDebug() << "HexDump::mouseMoveEvent"; + + bool wAccept = true; + + if(mGuiState == HexDump::MultiRowsSelectionState) + { + qDebug() << "State = MultiRowsSelectionState"; + + if((transY(event->y()) >= 0) && (transY(event->y()) <= this->getTableHeigth())) + { + int wRowIndex = getTableOffset() +getIndexOffsetFromY(transY(event->y())); + + if(wRowIndex < getRowCount()) + { + expandSelectionUpTo(wRowIndex); + + this->viewport()->repaint(); + + wAccept = false; + } + } + } + + if(wAccept == true) + AbstractTableView::mouseMoveEvent(event); +} + + + +void HexDump::mousePressEvent(QMouseEvent* event) +{ + qDebug() << "HexDump::mousePressEvent"; + + bool wAccept = false; + + if(((event->buttons() & Qt::LeftButton) != 0) && ((event->buttons() & Qt::RightButton) == 0)) + { + if(getGuiState() == AbstractTableView::NoState) + { + if(event->y() > getHeaderHeigth()) + { + int wRowIndex = getTableOffset()+ getIndexOffsetFromY(transY(event->y())); + int wColIndex = getColumnIndexFromX(event->x()); + int wByteIndex; + + if(wRowIndex < getRowCount()) + { + if(wColIndex == 1) + { + int wX = event->x() - getColumnPosition(wColIndex); + + } + else if(wColIndex == 2) + { + int wColBegin = getColumnPosition(wColIndex); + + } + + setSingleSelection(wRowIndex); + + mGuiState = HexDump::MultiRowsSelectionState; + + viewport()->repaint(); + + wAccept = true; + } + } + } + } + + if(wAccept == false) + AbstractTableView::mousePressEvent(event); +} + + + +void HexDump::mouseReleaseEvent(QMouseEvent* event) +{ + bool wAccept = true; + + if((event->buttons() & Qt::LeftButton) == 0) + { + if(mGuiState == HexDump::MultiRowsSelectionState) + { + mGuiState = HexDump::NoState; + + this->viewport()->repaint(); + + wAccept = false; + } + } + + if(wAccept == true) + AbstractTableView::mouseReleaseEvent(event); +} + + + + + +QString HexDump::paintContent(QPainter* painter, int_t rowBase, int rowOffset, int col, int x, int y, int w, int h) +{ + //return QString("HexDump: Col:") + QString::number(col) + "Row:" + QString::number(rowBase + rowOffset); + + QString wStr = ""; + int_t wRva = (rowBase + rowOffset) * mDumpByteWidth; + + + //if(isSelected(rowBase, rowOffset) == true) + // painter->fillRect(QRect(x, y, w, h), QBrush(QColor(192,192,192))); + + switch(col) + { + case 0: + { + //uint_t wAddr = (uint_t)instruction.rva + (uint_t)mMemoryView->getBase(); + //wStr = QString("%1").arg(wAddr, 8, 16, QChar('0')).toUpper(); + wStr += QString::number(wRva); + break; + } + + case 1: + { + QByteArray wBuffer; + wBuffer.resize(mDumpByteWidth); + mMemPage->readOriginalMemory(reinterpret_cast(wBuffer.data()), wRva, mDumpByteWidth); + + for(int i = 0; i < mDumpByteWidth; i++) + wStr += QString("%1").arg((unsigned char)wBuffer.at(i), 2, 16, QChar('0')).toUpper() + " "; + + break; + } + + case 2: + { + wStr = "ToDo"; + break; + } + + default: + break; + } + + return wStr; +} + + + + +/************************************************************************************ + Selection Management +************************************************************************************/ +void HexDump::expandSelectionUpTo(int to) +{ + if(to < mSelection.firstSelectedIndex) + { + mSelection.fromIndex = to; + mSelection.toIndex = mSelection.firstSelectedIndex; + } + else if(to > mSelection.firstSelectedIndex) + { + mSelection.fromIndex = mSelection.firstSelectedIndex; + mSelection.toIndex = to; + } +} + + +void HexDump::setSingleSelection(int index) +{ + mSelection.firstSelectedIndex = index; + mSelection.fromIndex = index; + mSelection.toIndex = index; +} + + +int HexDump::getInitialSelection() +{ + return mSelection.firstSelectedIndex; +} + + +bool HexDump::isSelected(int base, int offset) +{ + /* + int wAddr = base; + + if(offset < 0) + wAddr = getPreviousInstructionRVA(getTableOffset(), offset); + else if(offset > 0) + wAddr = getNextInstructionRVA(getTableOffset(), offset); + + if(wAddr >= mSelection.fromIndex && wAddr <= mSelection.toIndex) + return true; + else + return false; + */ + return false; +} + + diff --git a/x64_dbg_gui/Project/Src/BasicView/HexDump.h b/x64_dbg_gui/Project/Src/BasicView/HexDump.h new file mode 100644 index 00000000..77828894 --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/HexDump.h @@ -0,0 +1,59 @@ +#ifndef DUMP_H +#define DUMP_H + +#include +#include +#include "NewTypes.h" +#include "AbstractTableView.h" +#include "MemoryPage.h" +#include "QBeaEngine.h" +#include "Bridge.h" + +class HexDump : public AbstractTableView +{ + Q_OBJECT +public: + explicit HexDump(QWidget *parent = 0); + + //QString getStringToPrint(int rowBase, int rowOffset, int col); + void mouseMoveEvent(QMouseEvent* event); + void mousePressEvent(QMouseEvent* event); + void mouseReleaseEvent(QMouseEvent* event); + + QString paintContent(QPainter* painter, int_t rowBase, int rowOffset, int col, int x, int y, int w, int h); + void paintGraphicDump(QPainter* painter, int x, int y, int addr); + + // Selection Management + void expandSelectionUpTo(int to); + void setSingleSelection(int index); + int getInitialSelection(); + bool isSelected(int base, int offset); + + +signals: + +public slots: + void printDumpAt(int_t parVA); + +private: + enum GuiState_t {NoState, MultiRowsSelectionState}; + + typedef struct _SelectionData_t + { + int firstSelectedIndex; + int fromIndex; + int toIndex; + } SelectionData_t; + + SelectionData_t mSelection; + + GuiState_t mGuiState; + + int mByteWidth; + + int mDumpByteWidth; + + MemoryPage* mMemPage; +}; + +#endif // DUMP_H diff --git a/x64_dbg_gui/Project/Src/BasicView/LogView.cpp b/x64_dbg_gui/Project/Src/BasicView/LogView.cpp new file mode 100644 index 00000000..777eebbf --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/LogView.cpp @@ -0,0 +1,30 @@ +#include "LogView.h" + +LogView::LogView(QWidget *parent) : QTextEdit(parent) +{ + QFont wFont("Monospace", 8); + wFont.setStyleHint(QFont::Monospace); + wFont.setFixedPitch(true); + + this->setFont(wFont); + + this->setStyleSheet("QTextEdit { background-color: rgb(255, 251, 240) }"); + this->setUndoRedoEnabled(false); + this->setReadOnly(true); + + connect(Bridge::getBridge(), SIGNAL(addMsgToLog(QString)), this, SLOT(addMsgToLogSlot(QString))); + connect(Bridge::getBridge(), SIGNAL(clearLog()), this, SLOT(clearLogSlot())); +} + + +void LogView::addMsgToLogSlot(QString msg) +{ + this->moveCursor(QTextCursor::End); + this->insertPlainText(msg); +} + + +void LogView::clearLogSlot() +{ + this->clear(); +} diff --git a/x64_dbg_gui/Project/Src/BasicView/LogView.h b/x64_dbg_gui/Project/Src/BasicView/LogView.h new file mode 100644 index 00000000..cb9a2e6e --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/LogView.h @@ -0,0 +1,26 @@ +#ifndef LOGVIEW_H +#define LOGVIEW_H + +#include +#include +#include "Bridge.h" + +class LogView : public QTextEdit +{ + Q_OBJECT +public: + explicit LogView(QWidget *parent = 0); + +signals: + +public slots: + void addMsgToLogSlot(QString msg); + void clearLogSlot(); + +private: + + + +}; + +#endif // LOGVIEW_H diff --git a/x64_dbg_gui/Project/Src/BasicView/MemoryMapView.cpp b/x64_dbg_gui/Project/Src/BasicView/MemoryMapView.cpp new file mode 100644 index 00000000..0901007e --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/MemoryMapView.cpp @@ -0,0 +1,147 @@ +#include "MemoryMapView.h" + +MemoryMapView::MemoryMapView(StdTable *parent) : StdTable(parent) +{ + enableMultiSelection(false); + + int charwidth=QFontMetrics(this->font()).width(QChar(' ')); + + addColumnAt(8+charwidth*2*sizeof(uint_t), false); //addr + addColumnAt(8+charwidth*2*sizeof(uint_t), false); //size + addColumnAt(8+charwidth*32, false); //module + addColumnAt(8+charwidth*3, false); + addColumnAt(8+charwidth*5, false); + addColumnAt(8+charwidth*5, false); + addColumnAt(100, false); + + + //setRowCount(100); + + + connect(Bridge::getBridge(), SIGNAL(dbgStateChanged(DBGSTATE)), this, SLOT(stateChangedSlot(DBGSTATE))); +} + +QString MemoryMapView::getProtectionString(DWORD Protect) +{ + QString wS; + switch(Protect & 0xFF) + { + case PAGE_EXECUTE: + wS = QString("E---"); + break; + case PAGE_EXECUTE_READ: + wS = QString("ER--"); + break; + case PAGE_EXECUTE_READWRITE: + wS = QString("ERW-"); + break; + case PAGE_EXECUTE_WRITECOPY: + wS = QString("ERWC"); + break; + case PAGE_NOACCESS: + wS = QString("----"); + break; + case PAGE_READONLY: + wS = QString("-R--"); + break; + case PAGE_READWRITE: + wS = QString("-RW-"); + break; + case PAGE_WRITECOPY: + wS = QString("-RWC"); + break; + } + if(Protect&PAGE_GUARD) + wS+=QString("G"); + else + wS+=QString("-"); + return wS; +} + +void MemoryMapView::stateChangedSlot(DBGSTATE state) +{ + if(state == paused) + { + MEMMAP wMemMapStruct; + int wI; + + memset(&wMemMapStruct, 0, sizeof(MEMMAP)); + + + Bridge::getBridge()->getMemMapFromDbg(&wMemMapStruct); + + //qDebug() << "count " << wMemMapStruct.count; + + setRowCount(wMemMapStruct.count); + + for(wI = 0; wI < wMemMapStruct.count; wI++) + { + QString wS; + MEMORY_BASIC_INFORMATION wMbi = (wMemMapStruct.page)[wI].mbi; + + // Base address + wS = QString("%1").arg((uint_t)wMbi.BaseAddress, sizeof(uint_t)*2, 16, QChar('0')).toUpper(); + setCellContent(wI, 0, wS); + + // Size + wS = QString("%1").arg((uint_t)wMbi.RegionSize, sizeof(uint_t)*2, 16, QChar('0')).toUpper(); + setCellContent(wI, 1, wS); + + // Module Name + char newMod[17]=""; + memcpy(newMod, (wMemMapStruct.page)[wI].mod, 16); + wS = QString(newMod); + setCellContent(wI, 2, wS); + + // State + switch(wMbi.State) + { + case MEM_FREE: + wS = QString("FREE"); + break; + case MEM_COMMIT: + wS = QString("COMM"); + break; + case MEM_RESERVE: + wS = QString("RESV"); + break; + default: + wS = QString("????"); + } + setCellContent(wI, 3, wS); + + // Type + switch(wMbi.Type) + { + case MEM_IMAGE: + wS = QString("IMG"); + break; + case MEM_MAPPED: + wS = QString("MAP"); + break; + case MEM_PRIVATE: + wS = QString("PRV"); + break; + default: + wS = QString("N/A"); + break; + } + setCellContent(wI, 3, wS); + + // current access protection + wS=getProtectionString(wMbi.Protect); + setCellContent(wI, 4, wS); + + // allocation protection + wS=getProtectionString(wMbi.AllocationProtect); + setCellContent(wI, 5, wS); + + } + + if(wMemMapStruct.page != 0) + { + Bridge::getBridge()->Free(wMemMapStruct.page); + } + } + +} diff --git a/x64_dbg_gui/Project/Src/BasicView/MemoryMapView.h b/x64_dbg_gui/Project/Src/BasicView/MemoryMapView.h new file mode 100644 index 00000000..e883d630 --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/MemoryMapView.h @@ -0,0 +1,24 @@ +#ifndef MEMORYMAPVIEW_H +#define MEMORYMAPVIEW_H + +#include +#include "StdTable.h" +#include "Bridge.h" + +class MemoryMapView : public StdTable +{ + Q_OBJECT +public: + explicit MemoryMapView(StdTable *parent = 0); + +signals: + +public slots: + void stateChangedSlot(DBGSTATE state); + +private: + QString getProtectionString(DWORD Protect); + +}; + +#endif // MEMORYMAPVIEW_H diff --git a/x64_dbg_gui/Project/Src/BasicView/RegistersView.cpp b/x64_dbg_gui/Project/Src/BasicView/RegistersView.cpp new file mode 100644 index 00000000..1c2f1436 --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/RegistersView.cpp @@ -0,0 +1,529 @@ +#include "RegistersView.h" +#ifdef _WIN64 +#include "ui_RegistersView64.h" +#else +#include "ui_RegistersView32.h" +#endif + + +RegistersView::RegistersView(QWidget *parent) : QWidget(parent), ui(new Ui::RegistersView) +{ + int wI = 0; + ui->setupUi(this); + + // Set background color + QPalette wPalette; + wPalette.setColor(QPalette::Window, QColor(255, 251, 240)); + this->setAutoFillBackground(true); + this->setPalette(wPalette); + + // Context Menu + this->setContextMenuPolicy(Qt::CustomContextMenu); + + + + mSelected = -1; + + mRegList = new QList(); + mRegNamesList = new QList(); + + mRegList->append(ui->AXRegLabel); + mRegNamesList->append(CAX); + mRegList->append(ui->CXRegLabel); + mRegNamesList->append(CCX); + mRegList->append(ui->DXRegLabel); + mRegNamesList->append(CDX); + mRegList->append(ui->BXRegLabel); + mRegNamesList->append(CBX); + mRegList->append(ui->DIRegLabel); + mRegNamesList->append(CDI); + mRegList->append(ui->BPRegLabel); + mRegNamesList->append(CBP); + mRegList->append(ui->SIRegLabel); + mRegNamesList->append(CSI); + mRegList->append(ui->SPRegLabel); + mRegNamesList->append(CSP); + +#ifdef _WIN64 + mRegList->append(ui->R8RegLabel); + mRegNamesList->append(R8); + mRegList->append(ui->R9RegLabel); + mRegNamesList->append(R9); + mRegList->append(ui->R10RegLabel); + mRegNamesList->append(R10); + mRegList->append(ui->R11RegLabel); + mRegNamesList->append(R11); + mRegList->append(ui->R12RegLabel); + mRegNamesList->append(R12); + mRegList->append(ui->R13RegLabel); + mRegNamesList->append(R13); + mRegList->append(ui->R14RegLabel); + mRegNamesList->append(R14); + mRegList->append(ui->R15RegLabel); + mRegNamesList->append(R15); +#endif + + mRegList->append(ui->IPRegLabel); + mRegNamesList->append(CIP); + + mRegList->append(ui->FLAGSRegLabel); + mRegNamesList->append(EFLAGS); + + mRegList->append(ui->CFRegLabel); + mRegNamesList->append(CF); + mRegList->append(ui->PFRegLabel); + mRegNamesList->append(PF); + mRegList->append(ui->AFRegLabel); + mRegNamesList->append(AF); + mRegList->append(ui->ZFRegLabel); + mRegNamesList->append(ZF); + mRegList->append(ui->SFRegLabel); + mRegNamesList->append(SF); + mRegList->append(ui->TFRegLabel); + mRegNamesList->append(TF); + mRegList->append(ui->IFRegLabel); + mRegNamesList->append(IF); + mRegList->append(ui->DFRegLabel); + mRegNamesList->append(DF); + mRegList->append(ui->OFRegLabel); + mRegNamesList->append(OF); + + mRegList->append(ui->GSRegLabel); + mRegNamesList->append(GS); + mRegList->append(ui->FSRegLabel); + mRegNamesList->append(FS); + mRegList->append(ui->ESRegLabel); + mRegNamesList->append(ES); + mRegList->append(ui->DSRegLabel); + mRegNamesList->append(DS); + mRegList->append(ui->CSRegLabel); + mRegNamesList->append(CS); + mRegList->append(ui->SSRegLabel); + mRegNamesList->append(SS); + + mRegList->append(ui->DR0RegLabel); + mRegNamesList->append(DR0); + mRegList->append(ui->DR1RegLabel); + mRegNamesList->append(DR1); + mRegList->append(ui->DR2RegLabel); + mRegNamesList->append(DR2); + mRegList->append(ui->DR3RegLabel); + mRegNamesList->append(DR3); + mRegList->append(ui->DR6RegLabel); + mRegNamesList->append(DR6); + mRegList->append(ui->DR7RegLabel); + mRegNamesList->append(DR7); + + for(wI = 0; wI < mRegList->size(); wI++) + { + QLabel* curLabel=mRegList->at(wI); + QFont wFont(curLabel->font()); + wFont.setFamily("Monospace"); + wFont.setStyleHint(QFont::Monospace); + wFont.setFixedPitch(true); + curLabel->setAutoFillBackground(true); + curLabel->setFont(wFont); + curLabel->setFixedWidth(QFontMetrics(wFont).width(curLabel->text())+1); + } + + connect(Bridge::getBridge(), SIGNAL(updateRegisters()), this, SLOT(updateRegistersSlot())); + connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(displayCustomContextMenuSlot(QPoint))); +} + +RegistersView::~RegistersView() +{ + delete ui; +} + +void RegistersView::mousePressEvent(QMouseEvent* event) +{ + int wI = 0; + int wSelected = -1; + QPalette wPalette; + + if(!DbgIsDebugging()) //disable register editing when not debugging + { + wSelected = -1; + return; + } + + for(wI = 0; wI < mRegList->size(); wI++) + { + if(mRegList->at(wI)->underMouse() == true) + { + wSelected = wI; + } + } + + if(wSelected != mSelected) + { + // Unselect previous register + if(mSelected != -1) + { + wPalette.setColor(QPalette::Window, QColor(192,192,192,0)); + mRegList->at(mSelected)->setPalette(wPalette); + } + + // Select new register + mSelected = wSelected; + if(mSelected != -1) + { + wPalette.setColor(QPalette::Window, QColor(192,192,192,255)); + mRegList->at(mSelected)->setPalette(wPalette); + } + } +} + + + +void RegistersView::mouseDoubleClickEvent(QMouseEvent* event) +{ + if(mSelected==-1) //no selection + return; + + if( mRegNamesList->at(mSelected) == CAX || + mRegNamesList->at(mSelected) == CCX || + mRegNamesList->at(mSelected) == CDX || + mRegNamesList->at(mSelected) == CBX || + mRegNamesList->at(mSelected) == CDI || + mRegNamesList->at(mSelected) == CBP || + mRegNamesList->at(mSelected) == CSI || + mRegNamesList->at(mSelected) == CSP || + + mRegNamesList->at(mSelected) == R8 || + mRegNamesList->at(mSelected) == R9 || + mRegNamesList->at(mSelected) == R10 || + mRegNamesList->at(mSelected) == R11 || + mRegNamesList->at(mSelected) == R12 || + mRegNamesList->at(mSelected) == R13 || + mRegNamesList->at(mSelected) == R14 || + mRegNamesList->at(mSelected) == R15 || + + mRegNamesList->at(mSelected) == CIP || + + mRegNamesList->at(mSelected) == EFLAGS) + { //double clicked general register + displayEditDialog(); + } + else if(mRegNamesList->at(mSelected) == CF || + mRegNamesList->at(mSelected) == PF || + mRegNamesList->at(mSelected) == AF || + mRegNamesList->at(mSelected) == ZF || + mRegNamesList->at(mSelected) == SF || + mRegNamesList->at(mSelected) == TF || + mRegNamesList->at(mSelected) == IF || + mRegNamesList->at(mSelected) == DF || + mRegNamesList->at(mSelected) == OF) + { //double clicked a flag + setRegister(mRegNamesList->at(mSelected), mRegList->at(mSelected)->text().toInt()^1); //toggle flag (stupid way in fact) + } +} + + +void RegistersView::updateRegistersSlot() +{ + REGDUMP wRegDumpStruct; + memset(&wRegDumpStruct, 0, sizeof(REGDUMP)); + + Bridge::getBridge()->getRegDumpFromDbg(&wRegDumpStruct); + + ui->AXRegLabel->setText(QString("%1").arg(wRegDumpStruct.cax, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->CXRegLabel->setText(QString("%1").arg(wRegDumpStruct.ccx, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->DXRegLabel->setText(QString("%1").arg(wRegDumpStruct.cdx, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->BXRegLabel->setText(QString("%1").arg(wRegDumpStruct.cbx, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->DIRegLabel->setText(QString("%1").arg(wRegDumpStruct.cdi, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->BPRegLabel->setText(QString("%1").arg(wRegDumpStruct.cbp, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->SIRegLabel->setText(QString("%1").arg(wRegDumpStruct.csi, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->SPRegLabel->setText(QString("%1").arg(wRegDumpStruct.csp, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + +#ifdef _WIN64 + ui->R8RegLabel->setText(QString("%1").arg(wRegDumpStruct.r8, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->R9RegLabel->setText(QString("%1").arg(wRegDumpStruct.r9, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->R10RegLabel->setText(QString("%1").arg(wRegDumpStruct.r10, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->R11RegLabel->setText(QString("%1").arg(wRegDumpStruct.r11, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->R12RegLabel->setText(QString("%1").arg(wRegDumpStruct.r12, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->R13RegLabel->setText(QString("%1").arg(wRegDumpStruct.r13, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->R14RegLabel->setText(QString("%1").arg(wRegDumpStruct.r14, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->R15RegLabel->setText(QString("%1").arg(wRegDumpStruct.r15, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); +#endif + + ui->IPRegLabel->setText(QString("%1").arg(wRegDumpStruct.cip, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + + ui->FLAGSRegLabel->setText(QString("%1").arg(wRegDumpStruct.eflags, sizeof(unsigned int) * 2, 16, QChar('0')).toUpper()); + ui->CFRegLabel->setText(QString("%1").arg(wRegDumpStruct.flags.c, 1, 16, QChar('0')).toUpper()); + ui->PFRegLabel->setText(QString("%1").arg(wRegDumpStruct.flags.p, 1, 16, QChar('0')).toUpper()); + ui->AFRegLabel->setText(QString("%1").arg(wRegDumpStruct.flags.a, 1, 16, QChar('0')).toUpper()); + ui->ZFRegLabel->setText(QString("%1").arg(wRegDumpStruct.flags.z, 1, 16, QChar('0')).toUpper()); + ui->SFRegLabel->setText(QString("%1").arg(wRegDumpStruct.flags.s, 1, 16, QChar('0')).toUpper()); + ui->TFRegLabel->setText(QString("%1").arg(wRegDumpStruct.flags.t, 1, 16, QChar('0')).toUpper()); + ui->IFRegLabel->setText(QString("%1").arg(wRegDumpStruct.flags.i, 1, 16, QChar('0')).toUpper()); + ui->DFRegLabel->setText(QString("%1").arg(wRegDumpStruct.flags.d, 1, 16, QChar('0')).toUpper()); + ui->OFRegLabel->setText(QString("%1").arg(wRegDumpStruct.flags.o, 1, 16, QChar('0')).toUpper()); + + ui->GSRegLabel->setText(QString("%1").arg(wRegDumpStruct.gs, 4, 16, QChar('0')).toUpper()); + ui->FSRegLabel->setText(QString("%1").arg(wRegDumpStruct.fs, 4, 16, QChar('0')).toUpper()); + ui->ESRegLabel->setText(QString("%1").arg(wRegDumpStruct.es, 4, 16, QChar('0')).toUpper()); + ui->DSRegLabel->setText(QString("%1").arg(wRegDumpStruct.ds, 4, 16, QChar('0')).toUpper()); + ui->CSRegLabel->setText(QString("%1").arg(wRegDumpStruct.cs, 4, 16, QChar('0')).toUpper()); + ui->SSRegLabel->setText(QString("%1").arg(wRegDumpStruct.ss, 4, 16, QChar('0')).toUpper()); + + ui->DR0RegLabel->setText(QString("%1").arg(wRegDumpStruct.dr0, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->DR1RegLabel->setText(QString("%1").arg(wRegDumpStruct.dr1, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->DR2RegLabel->setText(QString("%1").arg(wRegDumpStruct.dr2, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->DR3RegLabel->setText(QString("%1").arg(wRegDumpStruct.dr3, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->DR6RegLabel->setText(QString("%1").arg(wRegDumpStruct.dr6, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->DR7RegLabel->setText(QString("%1").arg(wRegDumpStruct.dr7, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); +} + + +void RegistersView::displayEditDialog() +{ + WordEditDialog wEditDial; + QString wReg = mRegList->at(mSelected)->text(); + +#ifdef _WIN64 + wEditDial.setup(QString("Edit"), wReg.toULongLong(0, 16), 8); +#else + wEditDial.setup(QString("Edit"), wReg.toULong(0, 16), 4); +#endif + + if(wEditDial.exec() == QDialog::Accepted) //OK button clicked + setRegister(mRegNamesList->at(mSelected), wEditDial.getVal()); +} + +void RegistersView::displayCustomContextMenuSlot(QPoint pos) +{ + QMenu wMenu(this); + + if(mSelected != -1) + { + if( mRegNamesList->at(mSelected) == CAX || + mRegNamesList->at(mSelected) == CCX || + mRegNamesList->at(mSelected) == CDX || + mRegNamesList->at(mSelected) == CBX || + mRegNamesList->at(mSelected) == CDI || + mRegNamesList->at(mSelected) == CBP || + mRegNamesList->at(mSelected) == CSI || + mRegNamesList->at(mSelected) == CSP || + + mRegNamesList->at(mSelected) == R8 || + mRegNamesList->at(mSelected) == R9 || + mRegNamesList->at(mSelected) == R10 || + mRegNamesList->at(mSelected) == R11 || + mRegNamesList->at(mSelected) == R12 || + mRegNamesList->at(mSelected) == R13 || + mRegNamesList->at(mSelected) == R14 || + mRegNamesList->at(mSelected) == R15 || + + mRegNamesList->at(mSelected) == CIP || + + mRegNamesList->at(mSelected) == EFLAGS) + { + QAction* wEdit = wMenu.addAction("Edit"); + QAction* wSetTo0 = wMenu.addAction("Set to 0"); + QAction* wSetTo1 = wMenu.addAction("Set to 1"); + QAction* wAction = wMenu.exec(this->mapToGlobal(pos)); + + if(wAction == wEdit) + { + displayEditDialog(); + } + else if(wAction == wSetTo0) + { + setRegister(mRegNamesList->at(mSelected), 0); + } + else if(wAction == wSetTo1) + { + setRegister(mRegNamesList->at(mSelected), 1); + } + } + else if(mRegNamesList->at(mSelected) == CF || + mRegNamesList->at(mSelected) == PF || + mRegNamesList->at(mSelected) == AF || + mRegNamesList->at(mSelected) == ZF || + mRegNamesList->at(mSelected) == SF || + mRegNamesList->at(mSelected) == TF || + mRegNamesList->at(mSelected) == IF || + mRegNamesList->at(mSelected) == DF || + mRegNamesList->at(mSelected) == OF) + { + QAction* wSetTo0 = wMenu.addAction("Set to 0"); + QAction* wSetTo1 = wMenu.addAction("Set to 1"); + QAction* wAction = wMenu.exec(this->mapToGlobal(pos)); + + if(wAction == wSetTo0) + { + setRegister(mRegNamesList->at(mSelected), 0); + } + else if(wAction == wSetTo1) + { + setRegister(mRegNamesList->at(mSelected), 1); + } + } + } +} + +void RegistersView::setRegister(REGISTER_NAME reg, uint_t value) +{ + QString wRegName = ""; + + // Basic registers + if(reg == CAX) + { +#ifdef _WIN64 + wRegName = "rax"; +#else + wRegName = "eax"; +#endif + } + else if(reg == CCX) + { +#ifdef _WIN64 + wRegName = "rcx"; +#else + wRegName = "ecx"; +#endif + } + else if(reg == CDX) + { +#ifdef _WIN64 + wRegName = "rdx"; +#else + wRegName = "edx"; +#endif + } + else if(reg == CBX) + { +#ifdef _WIN64 + wRegName = "rbx"; +#else + wRegName = "ebx"; +#endif + } + else if(reg == CDI) + { +#ifdef _WIN64 + wRegName = "rdi"; +#else + wRegName = "edi"; +#endif + } + else if(reg == CBP) + { +#ifdef _WIN64 + wRegName = "rbp"; +#else + wRegName = "ebp"; +#endif + } + else if(reg == CSI) + { +#ifdef _WIN64 + wRegName = "rsi"; +#else + wRegName = "esi"; +#endif + } + else if(reg == CSP) + { +#ifdef _WIN64 + wRegName = "rsp"; +#else + wRegName = "esp"; +#endif + } + + // General purpose register + else if(reg == R8) + { + wRegName = "r8"; + } + else if(reg == R9) + { + wRegName = "r9"; + } + else if(reg == R10) + { + wRegName = "r10"; + } + else if(reg == R11) + { + wRegName = "r11"; + } + else if(reg == R12) + { + wRegName = "r12"; + } + else if(reg == R13) + { + wRegName = "r13"; + } + else if(reg == R14) + { + wRegName = "r14"; + } + else if(reg == R15) + { + wRegName = "r15"; + } + + // Instruction pointer register + else if(reg == CIP) + { +#ifdef _WIN64 + wRegName = "rip"; +#else + wRegName = "eip"; +#endif + } + + // Flags + else if(reg == EFLAGS) + { +#ifdef _WIN64 + wRegName = "rflags"; +#else + wRegName = "eflags"; +#endif + } + else if(reg == CF) + { + wRegName = "!cf"; + } + else if(reg == PF) + { + wRegName = "!pf"; + } + else if(reg == AF) + { + wRegName = "!af"; + } + else if(reg == ZF) + { + wRegName = "!zf"; + } + else if(reg == SF) + { + wRegName = "!sf"; + } + else if(reg == TF) + { + wRegName = "!tf"; + } + else if(reg == IF) + { + wRegName = "!if"; + } + else if(reg == DF) + { + wRegName = "!df"; + } + else if(reg == OF) + { + wRegName = "!of"; + } + else + return; + + Bridge::getBridge()->valToString(wRegName.toUtf8().constData(), value); +} diff --git a/x64_dbg_gui/Project/Src/BasicView/RegistersView.h b/x64_dbg_gui/Project/Src/BasicView/RegistersView.h new file mode 100644 index 00000000..29257c91 --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/RegistersView.h @@ -0,0 +1,84 @@ +#ifndef REGISTERSVIEW_H +#define REGISTERSVIEW_H + +#include +#include +#include +#include "Bridge.h" +#include "WordEditDialog.h" + +namespace Ui { +class RegistersView; +} + +class RegistersView : public QWidget +{ + Q_OBJECT + +public: + enum REGISTER_NAME { + CAX, + CCX, + CDX, + CBX, + CDI, + CBP, + CSI, + CSP, + + R8, + R9, + R10, + R11, + R12, + R13, + R14, + R15, + + CIP, + + EFLAGS, + CF, + PF, + AF, + ZF, + SF, + TF, + IF, + DF, + OF, + + GS, + FS, + ES, + DS, + CS, + SS, + + DR0, + DR1, + DR2, + DR3, + DR6, + DR7 + }; + + explicit RegistersView(QWidget *parent = 0); + ~RegistersView(); + void mousePressEvent(QMouseEvent* event); + void mouseDoubleClickEvent(QMouseEvent* event); + +public slots: + void updateRegistersSlot(); + void displayCustomContextMenuSlot(QPoint pos); + void setRegister(REGISTER_NAME reg, uint_t value); + +private: + void displayEditDialog(); + Ui::RegistersView *ui; + QList* mRegList; + QList* mRegNamesList; + int mSelected; +}; + +#endif // REGISTERSVIEW_H diff --git a/x64_dbg_gui/Project/Src/BasicView/RegistersView32.ui b/x64_dbg_gui/Project/Src/BasicView/RegistersView32.ui new file mode 100644 index 00000000..3bfd07fd --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/RegistersView32.ui @@ -0,0 +1,871 @@ + + + RegistersView + + + + 0 + 0 + 150 + 480 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + + + 0 + 0 + 148 + 460 + + + + + 148 + 460 + + + + + 148 + 460 + + + + + + 10 + 405 + 50 + 13 + + + + DR3 + + + + + + 10 + 435 + 50 + 13 + + + + DR7 + + + + + + 85 + 205 + 30 + 13 + + + + DF + + + + + + 60 + 80 + 55 + 13 + + + + 00000000 + + + + + + 40 + 235 + 15 + 13 + + + + 0 + + + + + + 10 + 175 + 30 + 13 + + + + CF + + + + + + 60 + 420 + 55 + 13 + + + + 00000000 + + + + + + 60 + 390 + 55 + 13 + + + + 00000000 + + + + + + 60 + 135 + 55 + 13 + + + + 00000000 + + + + + + 10 + 375 + 50 + 13 + + + + DR1 + + + + + + 10 + 95 + 50 + 13 + + + + ESI + + + + + + 10 + 360 + 50 + 13 + + + + DR0 + + + + + + 60 + 320 + 40 + 13 + + + + 0000 + + + + + + 60 + 275 + 40 + 13 + + + + 0000 + + + + + + 10 + 135 + 50 + 13 + + + + EIP + + + + + + 10 + 20 + 50 + 13 + + + + ECX + + + + + + 60 + 35 + 55 + 13 + + + + 00000000 + + + + + + 60 + 65 + 55 + 13 + + + + 00000000 + + + + + + 10 + 5 + 50 + 13 + + + + EAX + + + + + + 60 + 260 + 40 + 13 + + + + 0000 + + + + + + 60 + 95 + 55 + 13 + + + + 00000000 + + + + + + 40 + 220 + 15 + 13 + + + + 0 + + + + + + 60 + 110 + 55 + 13 + + + + 00000000 + + + + + + 10 + 305 + 50 + 13 + + + + DS + + + + + + 85 + 220 + 30 + 13 + + + + OF + + + + + + 60 + 5 + 55 + 13 + + + + 00000000 + + + + + + 60 + 305 + 40 + 13 + + + + 0000 + + + + + + 40 + 205 + 15 + 13 + + + + 0 + + + + + + 60 + 20 + 55 + 13 + + + + 00000000 + + + + + + 10 + 390 + 50 + 13 + + + + DR2 + + + + + + 10 + 320 + 50 + 13 + + + + CS + + + + + + 10 + 275 + 50 + 13 + + + + FS + + + + + + 85 + 175 + 30 + 13 + + + + TF + + + + + + 10 + 290 + 50 + 13 + + + + ES + + + + + + 85 + 190 + 30 + 13 + + + + IF + + + + + + 60 + 290 + 40 + 13 + + + + 0000 + + + + + + 60 + 360 + 55 + 13 + + + + 00000000 + + + + + + 40 + 190 + 15 + 13 + + + + 0 + + + + + + 10 + 50 + 50 + 13 + + + + EBX + + + + + + 115 + 190 + 15 + 13 + + + + 0 + + + + + + 10 + 205 + 30 + 13 + + + + AF + + + + + + 115 + 220 + 15 + 13 + + + + 0 + + + + + + 60 + 160 + 55 + 13 + + + + 00000000 + + + + + + 115 + 205 + 15 + 13 + + + + 0 + + + + + + 40 + 175 + 15 + 13 + + + + 0 + + + + + + 10 + 160 + 50 + 13 + + + + EFLAGS + + + + + + 60 + 405 + 55 + 13 + + + + 00000000 + + + + + + 60 + 50 + 55 + 13 + + + + 00000000 + + + + + + 10 + 220 + 30 + 13 + + + + ZF + + + + + + 10 + 260 + 50 + 13 + + + + GS + + + + + + 60 + 375 + 55 + 13 + + + + 00000000 + + + + + + 10 + 335 + 50 + 13 + + + + SS + + + + + + 10 + 190 + 30 + 13 + + + + PF + + + + + + 10 + 65 + 50 + 13 + + + + ESP + + + + + + 115 + 175 + 15 + 13 + + + + 0 + + + + + + 60 + 435 + 55 + 13 + + + + 00000000 + + + + + + 10 + 420 + 50 + 13 + + + + DR6 + + + + + + 10 + 235 + 30 + 13 + + + + SF + + + + + + 10 + 35 + 50 + 13 + + + + EDX + + + + + + 10 + 110 + 50 + 13 + + + + EDI + + + + + + 60 + 335 + 40 + 13 + + + + 0000 + + + + + + 10 + 80 + 50 + 13 + + + + EBP + + + + + + + + + + diff --git a/x64_dbg_gui/Project/Src/BasicView/RegistersView64.ui b/x64_dbg_gui/Project/Src/BasicView/RegistersView64.ui new file mode 100644 index 00000000..2c0053ba --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/RegistersView64.ui @@ -0,0 +1,1079 @@ + + + RegistersView + + + + 0 + 0 + 180 + 600 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + + + 0 + 0 + 178 + 590 + + + + + 178 + 590 + + + + + 178 + 590 + + + + + + 60 + 565 + 110 + 13 + + + + 0000000000000000 + + + + + + 40 + 335 + 15 + 13 + + + + 0 + + + + + + 85 + 350 + 30 + 13 + + + + OF + + + + + + 60 + 210 + 110 + 13 + + + + 0000000000000000 + + + + + + 10 + 520 + 50 + 13 + + + + DR2 + + + + + + 10 + 180 + 50 + 13 + + + + R11 + + + + + + 10 + 505 + 50 + 13 + + + + DR1 + + + + + + 10 + 465 + 50 + 13 + + + + SS + + + + + + 60 + 535 + 110 + 13 + + + + 0000000000000000 + + + + + + 60 + 135 + 110 + 13 + + + + 0000000000000000 + + + + + + 60 + 225 + 110 + 13 + + + + 0000000000000000 + + + + + + 85 + 335 + 30 + 13 + + + + DF + + + + + + 60 + 180 + 110 + 13 + + + + 0000000000000000 + + + + + + 10 + 390 + 50 + 13 + + + + GS + + + + + + 40 + 365 + 15 + 13 + + + + 0 + + + + + + 115 + 305 + 15 + 13 + + + + 0 + + + + + + 60 + 50 + 110 + 13 + + + + 0000000000000000 + + + + + + 10 + 165 + 50 + 13 + + + + R10 + + + + + + 10 + 435 + 50 + 13 + + + + DS + + + + + + 10 + 420 + 50 + 13 + + + + ES + + + + + + 10 + 490 + 50 + 13 + + + + DR0 + + + + + + 60 + 520 + 110 + 13 + + + + 0000000000000000 + + + + + + 60 + 405 + 40 + 13 + + + + 0000 + + + + + + 40 + 305 + 15 + 13 + + + + 0 + + + + + + 60 + 65 + 110 + 13 + + + + 0000000000000000 + + + + + + 60 + 390 + 40 + 13 + + + + 0000 + + + + + + 10 + 195 + 50 + 13 + + + + R12 + + + + + + 60 + 465 + 40 + 13 + + + + 0000 + + + + + + 10 + 535 + 50 + 13 + + + + DR3 + + + + + + 60 + 435 + 40 + 13 + + + + 0000 + + + + + + 10 + 225 + 50 + 13 + + + + R14 + + + + + + 60 + 420 + 40 + 13 + + + + 0000 + + + + + + 60 + 110 + 110 + 13 + + + + 0000000000000000 + + + + + + 85 + 305 + 30 + 13 + + + + TF + + + + + + 10 + 335 + 30 + 13 + + + + AF + + + + + + 10 + 350 + 30 + 13 + + + + ZF + + + + + + 60 + 450 + 40 + 13 + + + + 0000 + + + + + + 10 + 150 + 50 + 13 + + + + R9 + + + + + + 10 + 135 + 50 + 13 + + + + R8 + + + + + + 10 + 210 + 50 + 13 + + + + R13 + + + + + + 115 + 320 + 15 + 13 + + + + 0 + + + + + + 10 + 35 + 50 + 13 + + + + RDX + + + + + + 10 + 265 + 50 + 13 + + + + RIP + + + + + + 10 + 405 + 50 + 13 + + + + FS + + + + + + 10 + 565 + 50 + 13 + + + + DR7 + + + + + + 10 + 320 + 30 + 13 + + + + PF + + + + + + 60 + 5 + 110 + 13 + + + + 0000000000000000 + + + + + + 10 + 80 + 50 + 13 + + + + RBP + + + + + + 60 + 290 + 60 + 13 + + + + 00000000 + + + + + + 60 + 35 + 110 + 13 + + + + 0000000000000000 + + + + + + 60 + 150 + 110 + 13 + + + + 0000000000000000 + + + + + + 10 + 450 + 50 + 13 + + + + CS + + + + + + 60 + 20 + 110 + 13 + + + + 0000000000000000 + + + + + + 10 + 95 + 50 + 13 + + + + RSI + + + + + + 10 + 240 + 50 + 13 + + + + R15 + + + + + + 40 + 320 + 15 + 13 + + + + 0 + + + + + + 60 + 505 + 110 + 13 + + + + 0000000000000000 + + + + + + 60 + 550 + 110 + 13 + + + + 0000000000000000 + + + + + + 10 + 50 + 50 + 13 + + + + RBX + + + + + + 10 + 110 + 50 + 13 + + + + RDI + + + + + + 60 + 490 + 110 + 13 + + + + 0000000000000000 + + + + + + 40 + 350 + 15 + 13 + + + + 0 + + + + + + 85 + 320 + 30 + 13 + + + + IF + + + + + + 10 + 65 + 50 + 13 + + + + RSP + + + + + + 115 + 350 + 15 + 13 + + + + 0 + + + + + + 60 + 95 + 110 + 13 + + + + 0000000000000000 + + + + + + 60 + 265 + 110 + 13 + + + + 0000000000000000 + + + + + + 10 + 20 + 50 + 13 + + + + RCX + + + + + + 60 + 195 + 110 + 13 + + + + 0000000000000000 + + + + + + 60 + 165 + 110 + 13 + + + + 0000000000000000 + + + + + + 10 + 365 + 30 + 13 + + + + SF + + + + + + 10 + 305 + 30 + 13 + + + + CF + + + + + + 10 + 290 + 50 + 13 + + + + EFLAGS + + + + + + 60 + 80 + 110 + 13 + + + + 0000000000000000 + + + + + + 60 + 240 + 110 + 13 + + + + 0000000000000000 + + + + + + 10 + 5 + 50 + 13 + + + + RAX + + + + + + 115 + 335 + 15 + 13 + + + + 0 + + + + + + 10 + 550 + 50 + 13 + + + + DR6 + + + + + + + + + + diff --git a/x64_dbg_gui/Project/Src/BasicView/StdTable.cpp b/x64_dbg_gui/Project/Src/BasicView/StdTable.cpp new file mode 100644 index 00000000..ab46d174 --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/StdTable.cpp @@ -0,0 +1,262 @@ +#include "StdTable.h" + + +/* + * TODO + * Pass all variables in 32/64bits + * + */ + + +StdTable::StdTable(QWidget *parent) : AbstractTableView(parent) +{ + SelectionData_t data; + memset(&data, 0, sizeof(SelectionData_t)); + mSelection = data; + + mIsMultiSelctionAllowed = false; + + mData = new QList< QList* >(); +/* + setRowCount(100); + + addColumnAt(getColumnCount(), 100, false); + addColumnAt(getColumnCount(), 100, false); + addColumnAt(getColumnCount(), 100, false); + */ +} + + +QString StdTable::paintContent(QPainter* painter, int_t rowBase, int rowOffset, int col, int x, int y, int w, int h) +{ + if(isSelected(rowBase, rowOffset) == true) + painter->fillRect(QRect(x, y, w, h), QBrush(QColor(192,192,192))); + + //return "c " + QString::number(col) + " r " + QString::number(rowBase + rowOffset); + return mData->at(col)->at(rowBase + rowOffset); +} + + +void StdTable::mouseMoveEvent(QMouseEvent* event) +{ + bool wAccept = true; + + if(mGuiState == StdTable::MultiRowsSelectionState) + { + //qDebug() << "State = MultiRowsSelectionState"; + + if((transY(event->y()) >= 0) && (transY(event->y()) <= this->getTableHeigth())) + { + int wRowIndex = getTableOffset() + getIndexOffsetFromY(transY(event->y())); + + if(wRowIndex < getRowCount()) + { + if(mIsMultiSelctionAllowed == true) + expandSelectionUpTo(wRowIndex); + else + setSingleSelection(wRowIndex); + + this->viewport()->repaint(); + + wAccept = false; + } + } + } + + if(wAccept == true) + AbstractTableView::mouseMoveEvent(event); +} + + +void StdTable::mousePressEvent(QMouseEvent* event) +{ + bool wAccept = false; + + if(((event->buttons() & Qt::LeftButton) != 0) && ((event->buttons() & Qt::RightButton) == 0)) + { + if(getGuiState() == AbstractTableView::NoState) + { + if(event->y() > getHeaderHeigth()) + { + int wRowIndex = getTableOffset() + getIndexOffsetFromY(transY(event->y())); + + if(wRowIndex < getRowCount()) + { + setSingleSelection(wRowIndex); + + mGuiState = StdTable::MultiRowsSelectionState; + + viewport()->repaint(); + + wAccept = true; + } + } + } + } + + if(wAccept == false) + AbstractTableView::mousePressEvent(event); +} + + +void StdTable::mouseReleaseEvent(QMouseEvent* event) +{ + bool wAccept = true; + + if((event->buttons() & Qt::LeftButton) == 0) + { + if(mGuiState == StdTable::MultiRowsSelectionState) + { + mGuiState = StdTable::NoState; + + this->viewport()->repaint(); + + wAccept = false; + } + } + + if(wAccept == true) + AbstractTableView::mouseReleaseEvent(event); +} + + +void StdTable::enableMultiSelection(bool enabled) +{ + mIsMultiSelctionAllowed = enabled; +} + + + + +/************************************************************************************ + Selection Management +************************************************************************************/ +void StdTable::expandSelectionUpTo(int to) +{ + if(to < mSelection.firstSelectedIndex) + { + mSelection.fromIndex = to; + mSelection.toIndex = mSelection.firstSelectedIndex; + } + else if(to > mSelection.firstSelectedIndex) + { + mSelection.fromIndex = mSelection.firstSelectedIndex; + mSelection.toIndex = to; + } +} + + +void StdTable::setSingleSelection(int index) +{ + mSelection.firstSelectedIndex = index; + mSelection.fromIndex = index; + mSelection.toIndex = index; +} + + +int StdTable::getInitialSelection() +{ + return mSelection.firstSelectedIndex; +} + + +void StdTable::selectNext() +{ + uint_t wNext = getInitialSelection() + 1; + + wNext = wNext > getRowCount() - 1 ? getRowCount() - 1 : wNext; + + setSingleSelection(wNext); +} + + +void StdTable::selectPrevious() +{ + uint_t wNext = getInitialSelection() - 1; + + wNext = wNext > getRowCount() - 1 ? getRowCount() - 1 : wNext; + + setSingleSelection(wNext); +} + + +bool StdTable::isSelected(int base, int offset) +{ + int wIndex = base + offset; + + if(wIndex >= mSelection.fromIndex && wIndex <= mSelection.toIndex) + return true; + else + return false; +} + + + +/************************************************************************************ + Data Management +************************************************************************************/ +void StdTable::addColumnAt(int width, bool isClickable) +{ + AbstractTableView::addColumnAt(width, isClickable); + + mData->append(new QList()); + + for(int wI = 0; wI < (getRowCount() - mData->last()->size()); wI++) + { + mData->last()->append(QString("")); + } +} + + + +void StdTable::setRowCount(int count) +{ + int wI, wJ; + + for(wJ = 0; wJ < getColumnCount(); wJ++) + { + int wRowToAddOrRemove = count - mData->at(wJ)->size(); + + for(wI = 0; wI < qAbs(wRowToAddOrRemove); wI++) + { + if(wRowToAddOrRemove > 0) + mData->at(wJ)->append(QString("")); + else + mData->at(wJ)->removeLast(); + } + } + + + + AbstractTableView::setRowCount(count); +} + + + + +void StdTable::setCellContent(int r, int c, QString s) +{ + mData->at(c)->replace(r, s); +} + + + + + + + + + + + + + + + + + + + + + + diff --git a/x64_dbg_gui/Project/Src/BasicView/StdTable.h b/x64_dbg_gui/Project/Src/BasicView/StdTable.h new file mode 100644 index 00000000..e72c798e --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/StdTable.h @@ -0,0 +1,59 @@ +#ifndef STDTABLE_H +#define STDTABLE_H + +#include +#include "NewTypes.h" +#include "AbstractTableView.h" + +class StdTable : public AbstractTableView +{ + Q_OBJECT +public: + explicit StdTable(QWidget *parent = 0); + QString paintContent(QPainter* painter, int_t rowBase, int rowOffset, int col, int x, int y, int w, int h); + + void mouseMoveEvent(QMouseEvent* event); + void mousePressEvent(QMouseEvent* event); + void mouseReleaseEvent(QMouseEvent* event); + + void enableMultiSelection(bool enabled); + + // Selection Management + void expandSelectionUpTo(int to); + void setSingleSelection(int index); + int getInitialSelection(); + void selectNext(); + void selectPrevious(); + bool isSelected(int base, int offset); + + // Data Management + void addColumnAt(int width, bool isClickable); + void setRowCount(int count); + void setCellContent(int r, int c, QString s); + +signals: + +public slots: + +private: + enum GuiState_t {NoState, MultiRowsSelectionState}; + + typedef struct _SelectionData_t + { + int firstSelectedIndex; + int fromIndex; + int toIndex; + } SelectionData_t; + + GuiState_t mGuiState; + + SelectionData_t mSelection; + + bool mIsMultiSelctionAllowed; + + + + QList< QList* >* mData; +}; + +#endif // STDTABLE_H diff --git a/x64_dbg_gui/Project/Src/BasicView/WordEditDialog.cpp b/x64_dbg_gui/Project/Src/BasicView/WordEditDialog.cpp new file mode 100644 index 00000000..f73b0207 --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/WordEditDialog.cpp @@ -0,0 +1,60 @@ +#include "WordEditDialog.h" +#include "ui_WordEditDialog.h" + +WordEditDialog::WordEditDialog(QWidget *parent) : QDialog(parent), ui(new Ui::WordEditDialog) +{ + ui->setupUi(this); + + setModal(true); + setWindowFlags(Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::MSWindowsFixedSizeDialogHint); + + + mWord = 0; + + connect(ui->expressionLineEdit, SIGNAL(textChanged(const QString)), this, SLOT(expressionChanged(QString))); +} + +WordEditDialog::~WordEditDialog() +{ + delete ui; +} + +void WordEditDialog::expressionChanged(QString s) +{ + bool wIsValid = Bridge::getBridge()->isValidExpression(s.toUtf8().constData()); + + if(wIsValid == true) + { + ui->expressionLineEdit->setStyleSheet(""); + ui->buttons->button(QDialogButtonBox::Ok)->setEnabled(true); + mWord = Bridge::getBridge()->getValFromString(reinterpret_cast(s.toUtf8().constData())); + ui->hexLineEdit->setText(QString("%1").arg(mWord, sizeof(uint_t) * 2, 16, QChar('0')).toUpper()); + ui->signedLineEdit->setText(QString::number((int_t)mWord)); + ui->unsignedLineEdit->setText(QString::number((uint_t)mWord)); + } + else + { + ui->expressionLineEdit->setStyleSheet("border: 1px solid red"); + ui->buttons->button(QDialogButtonBox::Ok)->setEnabled(false); + } +} + + + +void WordEditDialog::setup(QString title, uint_t defVal, int byteCount) +{ + this->setWindowTitle(title); + ui->expressionLineEdit->setText(QString("%1").arg(defVal, byteCount * 2, 16, QChar('0')).toUpper()); + ui->hexLineEdit->setText(QString("%1").arg(defVal, byteCount * 2, 16, QChar('0')).toUpper()); + ui->signedLineEdit->setText(QString::number((int_t)defVal)); + ui->unsignedLineEdit->setText(QString::number((uint_t)defVal)); + ui->hexLineEdit->setInputMask(QString("hh ").repeated(byteCount)); + ui->expressionLineEdit->selectAll(); + ui->expressionLineEdit->setFocus(); +} + + +uint_t WordEditDialog::getVal() +{ + return mWord; +} diff --git a/x64_dbg_gui/Project/Src/BasicView/WordEditDialog.h b/x64_dbg_gui/Project/Src/BasicView/WordEditDialog.h new file mode 100644 index 00000000..fe2dac05 --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/WordEditDialog.h @@ -0,0 +1,31 @@ +#ifndef WORDEDITDIALOG_H +#define WORDEDITDIALOG_H + +#include +#include +#include +#include "Bridge.h" + +namespace Ui { +class WordEditDialog; +} + +class WordEditDialog : public QDialog +{ + Q_OBJECT + +public: + explicit WordEditDialog(QWidget *parent = 0); + ~WordEditDialog(); + void setup(QString title, uint_t defVal, int byteCount); + uint_t getVal(); + +public slots: + void expressionChanged(QString s); + +private: + Ui::WordEditDialog *ui; + uint_t mWord; +}; + +#endif // WORDEDITDIALOG_H diff --git a/x64_dbg_gui/Project/Src/BasicView/WordEditDialog.ui b/x64_dbg_gui/Project/Src/BasicView/WordEditDialog.ui new file mode 100644 index 00000000..8fd1d6f4 --- /dev/null +++ b/x64_dbg_gui/Project/Src/BasicView/WordEditDialog.ui @@ -0,0 +1,320 @@ + + + WordEditDialog + + + + 0 + 0 + 250 + 150 + + + + + 0 + 0 + + + + + 250 + 150 + + + + + 250 + 150 + + + + Edit + + + + :/icons/images/ui-combo-box-edit.png:/icons/images/ui-combo-box-edit.png + + + + + 20 + 120 + 161 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 10 + 0 + 231 + 31 + + + + + + + Expression + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 140 + 0 + + + + + 140 + 16777215 + + + + + + + + + + 10 + 60 + 231 + 31 + + + + + + + Signed + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + + 0 + 0 + + + + + 140 + 0 + + + + + 140 + 16777215 + + + + true + + + + + + + + + 10 + 90 + 231 + 31 + + + + + + + Unsigned + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + + 140 + 0 + + + + + 140 + 16777215 + + + + true + + + + + + + + + 10 + 30 + 231 + 31 + + + + + + + Hexadecimal + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + + 0 + 0 + + + + + 140 + 0 + + + + + 140 + 16777215 + + + + true + + + + + + + + + + + + buttons + accepted() + WordEditDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttons + rejected() + WordEditDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/x64_dbg_gui/Project/Src/Bridge/Bridge.cpp b/x64_dbg_gui/Project/Src/Bridge/Bridge.cpp new file mode 100644 index 00000000..54a4fb25 --- /dev/null +++ b/x64_dbg_gui/Project/Src/Bridge/Bridge.cpp @@ -0,0 +1,233 @@ +#include "Bridge.h" + +/************************************************************************************ + Global Variables +************************************************************************************/ +Bridge* mBridge; + + + +/************************************************************************************ + Class Members +************************************************************************************/ +Bridge::Bridge(QObject *parent) : QObject(parent) +{ + mData = new QByteArray(); + + QFile wFile("AsmCode.bin"); + + if(wFile.open(QIODevice::ReadOnly) == false) + //qDebug() << "File has not been opened."; + + *mData = wFile.readAll(); + //qDebug() << "Size: " << mData->size(); + + if(mData->size() == 0) + { + //qDebug() << "No Data"; + } +} + + + +void Bridge::readProcessMemory(byte_t* dest, uint_t va, uint_t size) +{ +#ifdef BUILD_LIB + DbgMemRead(va, dest, size); +#else + stubReadProcessMemory(dest, va, size); +#endif +} + +void Bridge::emitDisassembleAtSignal(int_t va, int_t eip) +{ +#ifdef BUILD_LIB + emit disassembleAt(va, eip); +#endif +} + +uint_t Bridge::getSize(uint_t va) +{ +#ifdef BUILD_LIB + return DbgMemGetPageSize(va); +#else + return mData->size(); +#endif +} + +uint_t Bridge::getBase(uint_t addr) +{ +#ifdef BUILD_LIB + return DbgMemFindBaseAddr(addr,0); +#else + return 0x00401000; +#endif +} + + +void Bridge::emitDbgStateChanged(DBGSTATE state) +{ +#ifdef BUILD_LIB + emit dbgStateChanged(state); +#endif +} + + +void Bridge::emitAddMsgToLog(QString msg) +{ + emit addMsgToLog(msg); +} + + +void Bridge::emitClearLog() +{ + emit clearLog(); +} + +void Bridge::emitUpdateRegisters() +{ + emit updateRegisters(); +} + + +bool Bridge::execCmd(const char* cmd) +{ + return DbgCmdExec(cmd); +} + +bool Bridge::getMemMapFromDbg(MEMMAP* parMemMap) +{ + return DbgMemMap(parMemMap); +} + +bool Bridge::isValidExpression(const char* expression) +{ + return DbgIsValidExpression(expression); +} + +bool Bridge::valToString(const char* name, uint_t value) +{ + return DbgValToString(name, value); +} + +void Bridge::Free(void* ptr) +{ + BridgeFree(ptr); +} + + +bool Bridge::getRegDumpFromDbg(REGDUMP* parRegDump) +{ + return DbgGetRegDump(parRegDump); +} + +uint_t Bridge::getValFromString(const char* string) +{ + return DbgValFromString(string); +} + + +/************************************************************************************ + Static Functions +************************************************************************************/ +Bridge* Bridge::getBridge() +{ + return mBridge; +} + + +void Bridge::initBridge() +{ + mBridge = new Bridge(); +} + + + + + +/************************************************************************************ + Exported Functions +************************************************************************************/ + +#ifdef BUILD_LIB + + __declspec(dllexport) int _gui_guiinit(int argc, char *argv[]) + { + return main(argc, argv); + } + + + __declspec(dllexport) void _gui_disassembleat(duint va, duint eip) + { + Bridge::getBridge()->emitDisassembleAtSignal((int_t)va, (int_t)eip); + } + + + __declspec(dllexport) void _gui_setdebugstate(DBGSTATE state) + { + Bridge::getBridge()->emitDbgStateChanged(state); + } + + + __declspec(dllexport) void _gui_addlogmessage(const char* msg) + { + Bridge::getBridge()->emitAddMsgToLog(QString(msg)); + } + + + __declspec(dllexport) void _gui_logclear() + { + Bridge::getBridge()->emitClearLog(); + } + + __declspec(dllexport) void _gui_updateregisterview() + { + Bridge::getBridge()->emitUpdateRegisters(); + } +#endif + + +/************************************************************************************ + Imported Functions (Stub) +************************************************************************************/ +#ifndef BUILD_LIB + void stubReadProcessMemory(byte_t* dest, uint_t va, uint_t size) + { + uint_t wI; + + for(wI = 0; wI < size; wI++) + { + dest[wI] = Bridge::getBridge()->mData->data()[(va - Bridge::getBridge()->getBase(0)) + wI]; + } + } +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/x64_dbg_gui/Project/Src/Bridge/Bridge.h b/x64_dbg_gui/Project/Src/Bridge/Bridge.h new file mode 100644 index 00000000..7e88ce5d --- /dev/null +++ b/x64_dbg_gui/Project/Src/Bridge/Bridge.h @@ -0,0 +1,55 @@ +#ifndef BRIDGE_H +#define BRIDGE_H + +#include +#include +#include +#include "NewTypes.h" + +#ifdef BUILD_LIB + #include "Exports.h" + #include "main.h" +#endif + +#include "Imports.h" + + +class Bridge : public QObject +{ + Q_OBJECT +public: + explicit Bridge(QObject *parent = 0); + void readProcessMemory(byte_t* dest, uint_t va, uint_t size); + uint_t getSize(uint_t va); + void emitDisassembleAtSignal(int_t va, int_t eip); + void emitDbgStateChanged(DBGSTATE state); + uint_t getBase(uint_t addr); + static Bridge* getBridge(); + static void initBridge(); + bool execCmd(const char* cmd); + bool getMemMapFromDbg(MEMMAP* parMemMap); + bool isValidExpression(const char* expression); + void Free(void* ptr); + bool getRegDumpFromDbg(REGDUMP* parRegDump); + uint_t getValFromString(const char* string); + bool valToString(const char* name, uint_t value); + void emitAddMsgToLog(QString msg); + void emitClearLog(); + void emitUpdateRegisters(); + +signals: + void disassembleAt(int_t va, int_t eip); + void dbgStateChanged(DBGSTATE state); + void addMsgToLog(QString msg); + void clearLog(); + void updateRegisters(); + +public slots: + +private: + +public: + QByteArray* mData; +}; + +#endif // BRIDGE_H diff --git a/x64_dbg_gui/Project/Src/Bridge/x32_bridge.lib b/x64_dbg_gui/Project/Src/Bridge/x32_bridge.lib new file mode 100644 index 00000000..e64978b7 Binary files /dev/null and b/x64_dbg_gui/Project/Src/Bridge/x32_bridge.lib differ diff --git a/x64_dbg_gui/Project/Src/Bridge/x64_bridge.lib b/x64_dbg_gui/Project/Src/Bridge/x64_bridge.lib new file mode 100644 index 00000000..e1b9aac9 Binary files /dev/null and b/x64_dbg_gui/Project/Src/Bridge/x64_bridge.lib differ diff --git a/x64_dbg_gui/Project/Src/Disassembler/BeaHighlight.cpp b/x64_dbg_gui/Project/Src/Disassembler/BeaHighlight.cpp new file mode 100644 index 00000000..347dc2de --- /dev/null +++ b/x64_dbg_gui/Project/Src/Disassembler/BeaHighlight.cpp @@ -0,0 +1,265 @@ +#include "BeaHighlight.h" + +BeaHighlight::BeaHighlight() +{ +} + +SEGMENTREG BeaHighlight::ConvertBeaSeg(int beaSeg) +{ + switch(beaSeg) + { + case ESReg: + return SEG_ES; + break; + case DSReg: + return SEG_DS; + break; + case FSReg: + return SEG_FS; + break; + case GSReg: + return SEG_GS; + break; + case CSReg: + return SEG_CS; + break; + case SSReg: + return SEG_SS; + break; + } + return SEG_DEFAULT; +} + +bool BeaHighlight::PrintArgument(QList* richText, const ARGTYPE* Argument, const INSTRTYPE* Instruction, bool* had_arg) +{ + CustomRichText_t argument; + argument.flags=FlagNone; + int argtype=Argument->ArgType; + int brtype=Instruction->BranchType; + QString argmnemonic=QString(Argument->ArgMnemonic); + if(argtype!=NO_ARGUMENT && *Argument->ArgMnemonic) + { + if(*had_arg) //add a comma + { + CustomRichText_t comma; + comma.text=","; + comma.flags=FlagNone; + richText->push_back(comma); + } + + if(argtype&MEMORY_TYPE) //mov [],a || mov a,[] + { + char segment[3]=""; + int segmentReg=Argument->SegmentReg; + switch(segmentReg) + { + case ESReg: + strcpy(segment, "es"); + break; + case DSReg: + strcpy(segment, "ds"); + break; + case FSReg: + strcpy(segment, "fs"); + break; + case GSReg: + strcpy(segment, "gs"); + break; + case CSReg: + strcpy(segment, "cs"); + break; + case SSReg: + strcpy(segment, "ss"); + break; + } + int basereg=Argument->Memory.BaseRegister; + if(basereg®4 || basereg®5) //esp || ebp + { + argument.textBackground=QColor(0,255,255); + argument.flags=FlagBackground; + //Highlight ESP || EBP memory move + } + else + { + argument.textColor=QColor(0,0,128); + argument.flags=FlagColor; + } + + //labels + uint_t label_addr=Argument->Memory.Displacement; + char label_text[MAX_LABEL_SIZE]=""; + if(DbgGetLabelAt(label_addr, ConvertBeaSeg(segmentReg), label_text)) + { + QString label_addr_text=QString("%1").arg(label_addr, 0, 16, QChar('0')).toUpper(); + if(argmnemonic.indexOf(label_addr_text)!=-1) + { + argmnemonic.replace(label_addr_text, "<"+QString(label_text)+">"); + } + } + + switch(Argument->ArgSize) + { + case 8: + argument.text.sprintf("byte ptr %s:[%s]", segment, argmnemonic.toUtf8().constData()); + break; + case 16: + argument.text.sprintf("word ptr %s:[%s]", segment, argmnemonic.toUtf8().constData()); + break; + case 32: + argument.text.sprintf("dword ptr %s:[%s]", segment, argmnemonic.toUtf8().constData()); + break; + case 64: + argument.text.sprintf("qword ptr %s:[%s]", segment, argmnemonic.toUtf8().constData()); + break; + } + } + else + { + //labels + uint_t label_addr=Instruction->Immediat; + if(!label_addr) + label_addr=Instruction->AddrValue; + char label_text[MAX_LABEL_SIZE]=""; + char module_text[33]=""; + bool hasLabel=DbgGetLabelAt(label_addr, SEG_DEFAULT, label_text); + bool hasModule=DbgGetModuleAt(label_addr, module_text); + QString label_addr_text=QString("%1").arg(label_addr, 0, 16, QChar('0')).toUpper();; + QString newText; + if(hasLabel && hasModule) // + { + newText="<"+QString(module_text)+"."+QString(label_text)+">"; + if(argmnemonic.indexOf(label_addr_text)!=-1) + { + argument.flags=FlagBackground; + argument.textBackground=QColor(255,255,0); + argmnemonic.replace(label_addr_text, newText); + } + } + else if(hasModule) //module.%llX + { + newText=QString(module_text)+"."+QString(label_addr_text); + if(argmnemonic.indexOf(label_addr_text)!=-1) + { + argument.flags=FlagBackground; + argument.textBackground=QColor(255,255,0); + argmnemonic.replace(label_addr_text, newText); + } + } + else if(hasLabel) //