我试图移植下面的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,0,NULL,REG_OPTION_NON_VOLATILE,KEY_QUERY_VALUE,NULL,&hKey,&dwDisposition);

if(ret!=ERROR_SUCCESS)
    return FALSE;
else if(dwDisposition!=REG_OPENED_EXISTING_KEY) {
    RegCloseKey(hKey);
    return FALSE;
}
else {
    if(RegOpenKeyEx(hKey,valueName,0,KEY_READ,&hSubKey)==ERROR_SUCCESS) {
        classSize = 8+1;
        ret = RegQueryInfoKey(hSubKey,(LPTSTR)classStr,&classSize,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,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个小时试图找出我的问题,但没有成功。我知道我正确地调用了这个方法。我的密码是
 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, keyName, 0, 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, valueName, 0, (int)RegSAM.Read, out hSubKey);
            if (res == 0)
            {
                classSize = 8 + 1;
                ret = RegQueryInfoKey(hSubKey, out classStr, ref classSize, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 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, out classStr, ref classSize, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);

我知道这不是权限问题,因为这个c程序是以管理员权限和本地系统帐户运行的。我需要.NETAPI不提供的方法是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,
    ref uint lpcbClass,
    IntPtr lpReserved,
    IntPtr lpcSubKeys,
    IntPtr lpcbMaxSubKeyLen,
    IntPtr lpcbMaxClassLen,
    IntPtr lpcValues,
    IntPtr lpcbMaxValueNameLen,
    IntPtr lpcbMaxValueLen,
    IntPtr lpcbSecurityDescriptor,
    IntPtr lpftLastWriteTime
);

您还需要分配StringBuilder实例以获得所需的容量。所以,像这样分配StringBuilder
StringBuilder classStr = new StringBuilder(255);//or whatever length you like

然后按如下方式设置classSize
classSize = classStr.Capacity+1;

我删除了DllImport的参数。大多数是不必要的,SetLastError是不正确的。
您的代码可能存在其他问题,但随着这些更改,至少对RegQueryInfoKey的调用将与C++代码匹配。

08-28 02:27