Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Subtitute _ENV in CE Lua (Lua 5.3)

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
Corroder
Grandmaster Cheater Supreme
Reputation: 75

Joined: 10 Apr 2015
Posts: 1668

PostPosted: Wed Jan 15, 2020 9:17 pm    Post subject: Subtitute _ENV in CE Lua (Lua 5.3) Reply with quote

I try to use winapi module on my script but have some problems when loading winapi.lua to initiation. In namespace.lua there are 'setfenv' statement. I knew this setfenv doesn't work since Lua 5.2. I try substituting the setfenv statement with:

Code:
local function setfenv(fn, env)
  local i = 1
  while true do
    local name = debug.getupvalue(fn, i)
    if name == "_ENV" then
      debug.upvaluejoin(fn, i, (function()
        return env
      end), 1)
      break
    elseif not name then
      break
    end

    i = i + 1
  end

  return fn
end

local function getfenv(fn)
  local i = 1
  while true do
    local name, val = debug.getupvalue(fn, i)
    if name == "_ENV" then
      return val
    elseif not name then
      break
    end
    i = i + 1
  end
end


and namespace.lua :

Code:
--binding/namespace: namespace module and utils
--additional sub-namespaces are published here too.

local _M = {__index = _G}
setmetatable(_M, _M)
_M._M = _M

setfenv(1, _M) --all sub-modules use this pattern to publish their stuff.

--utility to import the contents of a table into the global winapi namespace
--because when strict mode is enabled we can't do glue.update(_M, t)
function import(globals)
   for k,v in pairs(globals) do
      rawset(_M, k, v)
   end
   return globals
end

--import a table as module globals and return the reverse lookup table of it.
function constants(t)
   import(t)
   return index(t)
end

--WM is a namespace for registering window message decoders.
WM = {} --{WM_* = function(wParam, lParam) return decoded values ... end}

--NM is a namespace for registering WM_NOTIFY message decoders.
NM = {} --{NM_* = function(hdr, wParam) return decoded values ... end}

return _M



And trying a script:

Code:
local winapi = require'winapi'
require'winapi.windowclass'

local win = winapi.Window{
   w = 500,                --all these are "initial fields"
   h = 300,
   title = 'Lua rulez',
   autoquit = true,        --this is to quit app when the window is closed
   visible = false,        --this field is from BaseWindow
}

function win:on_close()    --this is an event handler
   print'Bye'
end

print(win.title)           --this is how to read the value of a property
win.title = 'Lua rulez!'   --this is how to set the value of a property
win:show()                 --this is a method call

os.exit(winapi.MessageLoop()) --start the message loop


Got error: "Error:.\winapi\namespace.lua:4: bad argument #1 to 'getupvalue' (function expected, got number)"

Any help to fix the error?

_________________
Stealing Code From Stolen Code...
And Admit It.. Hmmm....Typically LOL
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 205

Joined: 25 Jan 2006
Posts: 8587
Location: 127.0.0.1

PostPosted: Thu Jan 16, 2020 12:08 am    Post subject: Reply with quote

debug.getupvalue expects the first argument to be a function.
Your line here:
Code:

setfenv(1, _M) --all sub-modules use this pattern to publish their stuff.


Is passing 1 as the first param, which gets passed to debug.getupvalue as the first param and is invalid.

Your code is similar to the ones found on this site, so I'd suggest taking a look at how they are making use of it to reimplement the set/getfenv stuff:
https://leafo.net/guides/setfenv-in-lua52-and-above.html

Another example of reimplementation is:
https://github.com/pkulchenko/MobDebug/blob/master/src/mobdebug.lua#L68

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
panraven
Grandmaster Cheater
Reputation: 62

Joined: 01 Oct 2008
Posts: 959

PostPosted: Thu Jan 16, 2020 12:42 am    Post subject: Reply with quote

I guess your winapi is from luapower? https://github.com/luapower/winapi/blob/master/winapi/namespace.lua
then it is for luajit, which is not compatible with lua 5.1, then that may be why leafo.net's setenvf not work, ie. luajit is not upward compatible to lua 5.1, and more so is CE's lua 5.3.
Moreover, if I'm not wrong, luajit still no 64bit version, which mean even DB release a ce come with luajit, that ce can only be 32bit version, and it won't attach 64bit process.

_________________
- Retarded.
Back to top
View user's profile Send private message
Corroder
Grandmaster Cheater Supreme
Reputation: 75

Joined: 10 Apr 2015
Posts: 1668

PostPosted: Thu Jan 16, 2020 1:23 am    Post subject: Reply with quote

atom0s wrote:
debug.getupvalue expects the first argument to be a function.
Your line here:
Code:

setfenv(1, _M) --all sub-modules use this pattern to publish their stuff.


Is passing 1 as the first param, which gets passed to debug.getupvalue as the first param and is invalid.

Your code is similar to the ones found on this site, so I'd suggest taking a look at how they are making use of it to reimplement the set/getfenv stuff:
https://leafo.net/guides/setfenv-in-lua52-and-above.html

Another example of reimplementation is:
https://github.com/pkulchenko/MobDebug/blob/master/src/mobdebug.lua#L68


Thanks for detail info, I'll taking a look at how they are making use of it to reimplement the set/getfenv stuff.


Quote:
@Panraven : guess your winapi is from luapower? https://github.com/luapower/winapi/blob/master/winapi/namespace.lua
then it is for luajit, which is not compatible with lua 5.1, then that may be why leafo.net's setenvf not work, ie. luajit is not upward compatible to lua 5.1, and more so is CE's lua 5.3.
Moreover, if I'm not wrong, luajit still no 64bit version, which mean even DB release a ce come with luajit, that ce can only be 32bit version, and it won't attach 64bit process.


Yes, you are right. The winapi module is from luapower, I am still check what is it comptible to Lua version including luajit.

However, the main purpose that I am trying to do is to take a look and learn how the structure they use when to call a function from a windows apps lib, eq: win32.dll.

For example regarding to this topic: https://forum.cheatengine.org/viewtopic.php?t=613222
I imagine we able to create balloon tooltips using something like :


Code:
--proc/controls/tooltip: standard tooltip control
--Written by Cosmin Apreutesei. Public Domain.

setfenv(1, require'winapi')
require'winapi.window'
require'winapi.comctl'

InitCommonControlsEx(ICC_TAB_CLASSES)

TOOLTIPS_CLASS = 'tooltips_class32'

-- ToolTip Icons (Set with TTM_SETTITLE)
TTI_NONE                = 0
TTI_INFO                = 1
TTI_WARNING             = 2
TTI_ERROR               = 3
TTI_INFO_LARGE          = 4
TTI_WARNING_LARGE       = 5
TTI_ERROR_LARGE         = 6

ffi.cdef[[
typedef struct tagTOOLINFOW {
    UINT cbSize;
    UINT uFlags;      // TTF_*
    HWND hwnd;
    UINT_PTR uId;
    RECT rect;
    HINSTANCE hinst;
    LPWSTR lpszText;  // V1 ends here
    LPARAM lParam;    // V2 ends here
} TTTOOLINFOW, *PTOOLINFOW, *LPTTTOOLINFOW;
]]

TTS_ALWAYSTIP           = 0x01
TTS_NOPREFIX            = 0x02
TTS_NOANIMATE           = 0x10
TTS_NOFADE              = 0x20
TTS_BALLOON             = 0x40
TTS_CLOSE               = 0x80
TTS_USEVISUALSTYLE      = 0x100  -- Use themed hyperlinks

TTF_IDISHWND            = 0x0001

-- Use this to center around trackpoint in trackmode
-- -OR- to center around tool in normal mode.
-- Use TTF_ABSOLUTE to place the tip exactly at the track coords when
-- in tracking mode.  TTF_ABSOLUTE can be used in conjunction with TTF_CENTERTIP
-- to center the tip absolutely about the track point.

TTF_CENTERTIP           = 0x0002
TTF_RTLREADING          = 0x0004
TTF_SUBCLASS            = 0x0010
TTF_TRACK               = 0x0020
TTF_ABSOLUTE            = 0x0080
TTF_TRANSPARENT         = 0x0100
TTF_PARSELINKS          = 0x1000

TTF_DI_SETITEM          = 0x8000 -- valid only on the TTN_NEEDTEXT callback

local tt_bitmask = bitmask{
   center_tip = TTF_CENTERTIP,
   rtl_reading = TTF_RTLREADING,
   subclass = TTF_SUBCLASS,
   track = TTF_TRACK,
   absolute = TTF_ABSOLUTE,
   transparent = TTF_TRANSPARENT,
   parse_links = TTF_PARSELINKS,
   id_is_hwnd = TTF_IDISHWND,
}

local function set_tt_flags(t, cdata)
   return tt_bitmask:set(cdata.uFlags, t)
end

local function get_tt_flags(uFlags)
   return tt_bitmask:get(uFlags)
end

TOOLINFO = struct{
   ctype = 'TTTOOLINFOW', size = 'cbSize',
   fields = sfields{
      'flags', 'uFlags', flags, pass,
      'flagbits', 'uFlags', set_tt_flags, get_tt_flags,
      'text', 'lpszText', wcs, mbs,
   },
}

TTDT_AUTOMATIC          = 0
TTDT_RESHOW             = 1
TTDT_AUTOPOP            = 2
TTDT_INITIAL            = 3

-- ToolTip Icons (Set with TTM_SETTITLE)
TTI_NONE                = 0
TTI_INFO                = 1
TTI_WARNING             = 2
TTI_ERROR               = 3
TTI_INFO_LARGE          = 4
TTI_WARNING_LARGE       = 5
TTI_ERROR_LARGE         = 6

-- Tool Tip Messages
update(WM_NAMES, constants{
   TTM_ACTIVATE            = (WM_USER +  1),
   TTM_SETDELAYTIME        = (WM_USER +  3),
   TTM_ADDTOOL             = (WM_USER + 50),
   TTM_DELTOOL             = (WM_USER + 51),
   TTM_NEWTOOLRECT         = (WM_USER + 52),
   TTM_RELAYEVENT          = (WM_USER +  7), -- Win7: wParam = GetMessageExtraInfo() when relaying WM_MOUSEMOVE
   TTM_GETTOOLINFO         = (WM_USER + 53),
   TTM_SETTOOLINFO         = (WM_USER + 54),
   TTM_HITTEST             = (WM_USER + 55),
   TTM_GETTEXT             = (WM_USER + 56),
   TTM_UPDATETIPTEXT       = (WM_USER + 57),
   TTM_GETTOOLCOUNT        = (WM_USER + 13),
   TTM_ENUMTOOLS           = (WM_USER + 58),
   TTM_GETCURRENTTOOL      = (WM_USER + 59),
   TTM_WINDOWFROMPOINT     = (WM_USER + 16),
   TTM_TRACKACTIVATE       = (WM_USER + 17), -- wParam = TRUE/FALSE start end  lparam = LPTOOLINFO
   TTM_TRACKPOSITION       = (WM_USER + 18), -- lParam = dwPos
   TTM_SETTIPBKCOLOR       = (WM_USER + 19),
   TTM_SETTIPTEXTCOLOR     = (WM_USER + 20),
   TTM_GETDELAYTIME        = (WM_USER + 21),
   TTM_GETTIPBKCOLOR       = (WM_USER + 22),
   TTM_GETTIPTEXTCOLOR     = (WM_USER + 23),
   TTM_SETMAXTIPWIDTH      = (WM_USER + 24),
   TTM_GETMAXTIPWIDTH      = (WM_USER + 25),
   TTM_SETMARGIN           = (WM_USER + 26), -- lParam = lprc
   TTM_GETMARGIN           = (WM_USER + 27), -- lParam = lprc
   TTM_POP                 = (WM_USER + 28),
   TTM_UPDATE              = (WM_USER + 29),
   TTM_GETBUBBLESIZE       = (WM_USER + 30),
   TTM_ADJUSTRECT          = (WM_USER + 31),
   TTM_SETTITLE            = (WM_USER + 33), -- wParam = TTI_*, lParam = wchar* szTitle
   TTM_POPUP               = (WM_USER + 34),
   TTM_GETTITLE            = (WM_USER + 35), -- wParam = 0, lParam = TTGETTITLE*
})

ffi.cdef[[
typedef struct _TTGETTITLE
{
    DWORD dwSize;
    UINT uTitleBitmap;
    UINT cch;
    WCHAR* pszTitle;
} TTGETTITLE, *PTTGETTITLE;
]]

ffi.cdef[[
typedef struct _TT_HITTESTINFOW {
    HWND hwnd;
    POINT pt;
    TTTOOLINFOW ti;
} TTHITTESTINFOW, *LPTTHITTESTINFOW;
]]

local TTN_FIRST = tonumber(ffi.cast('uint32_t', -520))

update(WM_NOTIFY_NAMES, constants{
   TTN_GETDISPINFO         = (TTN_FIRST - 10),
   TTN_SHOW                = (TTN_FIRST - 1),
   TTN_POP                 = (TTN_FIRST - 2),
   TTN_LINKCLICK           = (TTN_FIRST - 3),
})

ffi.cdef[[
typedef struct tagNMTTDISPINFOW {
    NMHDR hdr;
    LPWSTR lpszText;
    WCHAR szText[80];
    HINSTANCE hinst;
    UINT uFlags;
    LPARAM lParam;
} NMTTDISPINFOW, *LPNMTTDISPINFOW;
]]

local nmt_bitmask = bitmask{
   rtl_reading = TTF_RTLREADING,
   id_is_hwnd = TTF_IDISHWND,
   setitem = TTF_DI_SETITEM,
}
local function set_nmt_flags(t, nmt) return tt_bitmask:set(nmt.uFlags, t) end
local function get_nmt_flags(uFlags) return tt_bitmask:get(uFlags) end

NMTTDISPINFO = struct{
   ctype = 'NMTTDISPINFOW',
   fields = sfields{
      'text', 'lpszText', wcs, mbs,
      'flags', 'uFlags', flags, pass,
      'flagbits', 'uFlags', set_nmt_flags, get_nmt_flags,
   },
}

function NM.TTN_GETDISPINFO(hdr, wParam)
   return ffi.cast('NMTTDISPINFOW*', hdr)
end


of course, the code above belongs of winapi module. Ignoring the 'require' and 'ffi' section just to know-how the structures when calling tooltips function from windows apps lib.

Or in short, how to use below code using CE Lua : 'executeCodeLocalEx()'

Code:
HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
                            WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                            hwndParent, NULL, hinstMyDll,
                            NULL);

SetWindowPos(hwndTip, HWND_TOPMOST,0, 0, 0, 0,
             SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);


If there are work example then I think we able to learn how to implementation CE Lua executeCodeLocalEx() statement for other windows apps lib functions.
For note: There are no example in CE Lua script explanation for executeCodeLocalEx() '(in wikipedia, github or other sites)

Regards,

_________________
Stealing Code From Stolen Code...
And Admit It.. Hmmm....Typically LOL
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 205

Joined: 25 Jan 2006
Posts: 8587
Location: 127.0.0.1

PostPosted: Fri Jan 17, 2020 4:03 am    Post subject: Reply with quote

If Luajit is being used, then you would be interested in looking into Luajit's FFI library.
http://luajit.org/ext_ffi.html

(Also check the other side links on the site for the FFI lib.)

The FFI library in Luajit is what exposes the C interfaces inside of Lua to be able to define structures, pointers, etc. and call Win32 API from modules directly.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Corroder
Grandmaster Cheater Supreme
Reputation: 75

Joined: 10 Apr 2015
Posts: 1668

PostPosted: Fri Jan 17, 2020 4:50 am    Post subject: Reply with quote

atom0s, thank you for pointing me the way.
I need to try to use ff lib though no stand-alone ffi module incases the ffi lib is built by LuaJIT. Anyhow, I have appreciated your suggestion and still learn about these.

Regards


EDIT :
I have luaffi master from https://github.com/jmckaskill/luaffi
but unfortunately, I can't compile the module using msvcbuild.bat though I have changed several command lines on msvcbuild.bat (change lua 5.1 to lua 5.3.0.

Is there compiled luaffi module (luaffi.dll) somewhere?

_________________
Stealing Code From Stolen Code...
And Admit It.. Hmmm....Typically LOL
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites