RegGetValue 使用 luajit ffi 的硬崩溃应用程序

问题描述

我正在尝试使用 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)

解决方法

当你使用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))
,

我收到“找不到文件”错误

这意味着“未找到注册表项”。
64 位 Windows 中有两个不同的注册表,您应该尝试阅读它们:

local ffi = require'ffi'
ffi.cdef"int RegGetValueA(uintptr_t,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",0x0000ffff + WOW64_flag,pvData,pcbData
   )
   if errcode == 0 then
      break
   end
end
print(ffi.string(pvData))