加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C#P / Invoke Win32函数RegQueryInfoKey

发布时间:2020-12-16 05:03:59 所属栏目:百科 来源:网络整理
导读:我想尝试移植以下C代码: BOOL SyskeyGetClassBytes(HKEY hKeyReg,LPSTR keyName,LPSTR valueName,LPBYTE classBytes) {HKEY hKey,hSubKey;DWORD dwDisposition=0,classSize;BYTE classStr[16];LONG ret;BOOL isSuccess = FALSE;ret = RegCreateKeyEx(hKeyRe
我想尝试移植以下C代码:
BOOL SyskeyGetClassBytes(HKEY hKeyReg,LPSTR keyName,LPSTR valueName,LPBYTE classBytes) {
HKEY hKey,hSubKey;
DWORD dwDisposition=0,classSize;
BYTE classStr[16];
LONG ret;
BOOL isSuccess = FALSE;

ret = RegCreateKeyEx(hKeyReg,keyName,NULL,REG_OPTION_NON_VOLATILE,KEY_QUERY_VALUE,&hKey,&dwDisposition);

if(ret!=ERROR_SUCCESS) 
    return FALSE;
else if(dwDisposition!=REG_OPENED_EXISTING_KEY) {
    RegCloseKey(hKey);
    return FALSE;
}
else {
    if(RegOpenKeyEx(hKey,valueName,KEY_READ,&hSubKey)==ERROR_SUCCESS) {
        classSize = 8+1;
        ret = RegQueryInfoKey(hSubKey,(LPTSTR)classStr,&classSize,NULL);
        if((ret==ERROR_SUCCESS)&&(classSize==8)) {
            classBytes[0]= (HexDigitToByte(classStr[0]) << 4) | HexDigitToByte(classStr[1]);
            classBytes[1]= (HexDigitToByte(classStr[2]) << 4) | HexDigitToByte(classStr[3]);
            classBytes[2]= (HexDigitToByte(classStr[4]) << 4) | HexDigitToByte(classStr[5]);
            classBytes[3]= (HexDigitToByte(classStr[6]) << 4) | HexDigitToByte(classStr[7]);
            isSuccess = TRUE;
        }
        RegCloseKey(hSubKey);
    }
    RegCloseKey(hKey);
}

return isSuccess;

}

我花了5个小时试图弄清楚我的问题,没有成功.我知道我正在调用这种方法.我的C#代码是

unsafe static bool SyskeyGetClassBytes(RegistryHive hKeyReg,string keyName,string valueName,byte* classBytes)
    {
        UIntPtr hSubKey;
        UIntPtr hKey;
        RegResult tmp; ;
        uint classSize;
        StringBuilder classStr = new StringBuilder();
        int ret;
        bool isSuccess = false;
        ret = RegCreateKeyEx(hKeyReg,null,RegOption.NonVolatile,RegSAM.QueryValue,UIntPtr.Zero,out hKey,out tmp);

        if (ret != 0)
        {
            return false;

        }
        else if (tmp != RegResult.OpenedExistingKey)
        {
            return false;
        }
        else
        {
            int res = RegOpenKeyEx(hKey,(int)RegSAM.Read,out hSubKey);
            if (res == 0)
            {
                classSize = 8 + 1;
                ret = RegQueryInfoKey(hSubKey,out classStr,ref classSize,IntPtr.Zero,IntPtr.Zero);

                if ((classSize == 8))
                {
                    classBytes[0] = (byte)((byte)(HexDigitToByte(classStr[0]) << (byte)4) | HexDigitToByte(classStr[1]));
                    classBytes[1] = (byte)((byte)(HexDigitToByte(classStr[2]) << (byte)4) | HexDigitToByte(classStr[3]));
                    classBytes[2] = (byte)((byte)(HexDigitToByte(classStr[4]) << (byte)4) | HexDigitToByte(classStr[5]));
                    classBytes[3] = (byte)((byte)(HexDigitToByte(classStr[6]) << (byte)4) | HexDigitToByte(classStr[7]));
                    isSuccess = true;
                }
                RegCloseKey(hSubKey);
            }
            else
            {
                return false;
            }
            RegCloseKey(hKey);
        }
        return isSuccess;
    }

它对我来说有点难以调试,但最终我确定问题是在这一行发生的.之后执行似乎停止了.

ret = RegQueryInfoKey(hSubKey,IntPtr.Zero);

我知道这不是权限问题,因为这个C#程序使用admin perms AND作为本地系统帐户运行.我需要的.Net API不提供的方法是RegQueryInfoKey.我的P / Invoke签名和使用的类型是:

[StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        public int nLength;
        public unsafe byte* lpSecurityDescriptor;
        public int bInheritHandle;
    }
    [Flags]
    public enum RegOption
    {
        NonVolatile = 0x0,Volatile = 0x1,CreateLink = 0x2,BackupRestore = 0x4,OpenLink = 0x8
    }

    [Flags]
    public enum RegSAM
    {
        QueryValue = 0x0001,SetValue = 0x0002,CreateSubKey = 0x0004,EnumerateSubKeys = 0x0008,Notify = 0x0010,CreateLink = 0x0020,WOW64_32Key = 0x0200,WOW64_64Key = 0x0100,WOW64_Res = 0x0300,Read = 0x00020019,Write = 0x00020006,Execute = 0x00020019,AllAccess = 0x000f003f
    }

    public enum RegResult
    {
        CreatedNewKey = 0x00000001,OpenedExistingKey = 0x00000002
    }
    [DllImport("advapi32.dll",CharSet = CharSet.Auto)]
    public static extern int RegOpenKeyEx(
      UIntPtr hKey,string subKey,int ulOptions,int samDesired,out UIntPtr hkResult);
    [DllImport("advapi32.dll",SetLastError = true)]
    public static extern int RegCloseKey(
        UIntPtr hKey);
    [DllImport("advapi32.dll",SetLastError = true)]
    static extern int RegCreateKeyEx(
                RegistryHive hKey,string lpSubKey,int Reserved,string lpClass,RegOption dwOptions,RegSAM samDesired,UIntPtr lpSecurityAttributes,out UIntPtr phkResult,out RegResult lpdwDisposition);
    [DllImport("advapi32.dll",EntryPoint = "RegQueryInfoKey",CallingConvention = CallingConvention.Winapi,SetLastError = true)]
    extern private static int RegQueryInfoKey(
        UIntPtr hkey,out StringBuilder lpClass,ref uint lpcbClass,IntPtr lpReserved,IntPtr lpcSubKeys,IntPtr lpcbMaxSubKeyLen,IntPtr lpcbMaxClassLen,IntPtr lpcValues,IntPtr lpcbMaxValueNameLen,IntPtr lpcbMaxValueLen,IntPtr lpcbSecurityDescriptor,IntPtr lpftLastWriteTime);

解决方法

lpClass参数声明不正确.按值传递StringBuilder.
[DllImport("advapi32.dll")]
extern private static int RegQueryInfoKey(
    UIntPtr hkey,StringBuilder lpClass,IntPtr lpftLastWriteTime
);

您还需要分配StringBuilder实例以获得所需的容量.所以,像这样分配StringBuilder:

StringBuilder classStr = new StringBuilder(255);//or whatever length you like

然后像这样设置classSize:

classSize = classStr.Capacity+1;

我删除了DllImport的参数.大多数都不是必需的,并且SetLastError不正确.

您的代码可能存在其他问题,但是通过这些更改,至少对RegQueryInfoKey的调用将与您的C代码匹配.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读