使用LuaJIT FFI引起了严重崩溃的应用程序RegGetValueA

我正在尝试使用Windows API中的RegGetValueA(),但迄今为止我无法从中获得任何结果。最好的情况下,我会得到一个“文件未找到”错误,最糟糕的情况下,它会在没有任何错误消息的情况下严重崩溃。

以下是我目前的代码;我不确定什么是重要的和不重要的,以及可能引起问题或不引起问题的原因。我只有一点C知识,请尽量简单明了。

ffi.cdef([[
        typedef void *  HKEY;
        typedef HKEY *  PHKEY;
        typedef unsigned long DWORD;
        int RegGetValueA(HKEY handle, const char* path, const char* value, int filter_flags, void* unused, char *result, DWORD* size);
]])

    local size = ffi.new('DWORD[1]')
    size = 1024
    local data = ffi.new('char['..size..']')
    local dptr = ffi.cast('char*', data)
    local lenptr = ffi.cast('DWORD*', size)
    test = reg.RegGetValueA(ffi.cast("HKEY", ffi.cast("uintptr_t",0x80000002)), "SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\CereVoice Heather 5.0.1", "CLSID", 0x0000ffff, nil, dptr, lenptr)
点赞
用户1847592
用户1847592

我收到了一个 "文件未找到" 的错误

这意味着 "注册表键未找到"。

64位 Windows 系统中有两个不同的注册表,您应该尝试从两个注册表中读取:

local ffi = require'ffi'
ffi.cdef"int RegGetValueA(uintptr_t, const char*, const char*, uint32_t, void*, char*, uint32_t*);"

local size = 1024
local pcbData = ffi.new'uint32_t[1]'
local pvData = ffi.new('char[?]', size)

local RRF_SUBKEY_WOW6464KEY = 0x00010000
local RRF_SUBKEY_WOW6432KEY = 0x00020000
for _, WOW64_flag in ipairs{RRF_SUBKEY_WOW6464KEY, RRF_SUBKEY_WOW6432KEY} do
   pcbData[0] = size
   local errcode = ffi.C.RegGetValueA(
      0x80000002,   -- HKLM
      "SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\MS-Anna-1033-20-DSK",
      "CLSID",
      0x0000ffff + WOW64_flag,
      nil,
      pvData,
      pcbData
   )
   if errcode == 0 then
      break
   end
end
print(ffi.string(pvData))
2021-02-16 02:33:17
用户13566062
用户13566062

当你使用ffi.new时,你得到的是一个指针变量,你将指针分配给1024,然后使用ffi.cast将其转换为DWORD *,这会在调用RegGetValueA时导致访问地址冲突,从而导致程序崩溃。 你只需要修改代码如下:

local ffi = require("ffi")
ffi.cdef([[
    typedef void *  HKEY;
    typedef HKEY *  PHKEY;
    typedef unsigned long DWORD;
    int RegGetValueA(HKEY handle, const char* path, const char* value, int
filter_flags, void* unused, char *result, DWORD* size);
]])
local size = 1024
local data = ffi.new('char['..size..']')
local dptr = ffi.cast('char*', data)
local lenptr = ffi.new('DWORD[1]', size)

local test = ffi.C.RegGetValueA(ffi.cast("HKEY", ffi.cast("uintptr_t",0x80000002)), "SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\CereVoice Heather 5.0.1", "CLSID", 0x0000ffff, nil, dptr, lenptr)
print(test)
print(ffi.string(dptr))
2021-02-16 08:09:52