c++ - 函数调用 CRegKey::QueryStringValue 出错

标签 c++ visual-c++ registry atl

今天在查询时区信息时发现了这个奇怪的错误。 读取时区显示名称的代码如下所示

typedef struct {
    LONG Bias;
    LONG StandardBias;
    LONG DaylightBias;
    SYSTEMTIME StandardDate;
    SYSTEMTIME DaylightDate;
} TZI, * PTZI;

CRegKey RegKey;
CString regKey = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones");
int idx = 0;
bool bMoreKeys = true;
bool bSuccess = true;
while (bMoreKeys && bSuccess) {
    CString sSubkeyName;
    DWORD nLength = 200;
    LPTSTR sBuffer = sSubkeyName.GetBufferSetLength(nLength);
    FILETIME ftLastWriteTime;
    bMoreKeys = (RegKey.EnumKey(idx, sBuffer, & nLength, & ftLastWriteTime) == ERROR_SUCCESS);
    sSubkeyName.ReleaseBuffer();
    if (!bMoreKeys) {
        bMoreKeys = false;
        break;
    }
    CString sSubKeyPath = regKey + _T("\\") + sSubkeyName;
    CRegKey subKey;
    if (subKey.Open(HKEY_LOCAL_MACHINE, sSubKeyPath, KEY_READ) != ERROR_SUCCESS) {
        //LOG_ERROR
        bSuccess = false;
        break;
    }
    // Get the display name
    CString sDispName;
    DWORD nDispBufferLength = 1000;
    LPTSTR sDispBuffer = sDispName.GetBufferSetLength(nDispBufferLength);
    if (subKey.QueryStringValue(_T("Display"), sDispBuffer, & nDispBufferLength) != ERROR_SUCCESS) {
        //LOG_ERROR
        bSuccess = false;
        break;
    }
    sDispName.ReleaseBuffer();
    // Get the Bias (for later sorting);
    TZI tzi;
    nLength = sizeof(tzi);
    if (subKey.QueryBinaryValue(_T("TZI"), & tzi, & nLength) != ERROR_SUCCESS && nLength != sizeof(tzi)) {
        //LOG_ERROR
        bSuccess = false;
    }
    (void) subKey.Close();
    idx++;
}

但对于某些时区,例如:阿根廷,返回值不是 error_success。 在进一步调试 QueryStringValue 时,我发现了这个

if ((nBytes % sizeof(TCHAR) != 0) || (pszValue[nBytes / sizeof(TCHAR) - 1] != 0)) {
    return ERROR_INVALID_DATA;
}

并且当任何时区显示值的 nBytes 大小为 48 时,返回 always error_invalid_data 。

为了确认这一点,我已将 regkey api 调用更改为

DWORD dwType = 0;
ULONG nBytes = 256 * sizeof(TCHAR);
TCHAR displayValue[256];
if (subKey.QueryValue(
    _T("Display"), & dwType, (LPBYTE) displayValue, & nBytes) == 0 && dwType == REG_SZ) {}

我不再收到错误,一切正常。 无法找出它发生的任何有效原因。任何人都可以更好地解释为什么对于大小为 48 的所有时区我们都会收到无效数据错误。 提前致谢。

编辑:

PS:在某些机器上,上面提到的代码(即第一个)一切正常,而在其他一些机器上,这并不是真正奇怪的地方,第二个代码无处不在,我可以看到代码工作正常。

最佳答案

代码

CRegKey Key;
LONG nA = Key.Open(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\Argentina Standard Time"), KEY_READ);
TCHAR pszValue[24];
ULONG nValueLength = _countof(pszValue);
LONG nB = Key.QueryStringValue(_T("Display"), pszValue, &nValueLength);

给你一个不同的错误,234,它是 ERROR_MORE_DATA“更多数据可用。”

发生这种情况是因为值本身不完全适合提供的缓冲区。

这就是你想要的:

CRegKey Key;
LONG nA = Key.Open(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\Argentina Standard Time"), KEY_READ);
ULONG nValueLength = 0;
LONG nB = Key.QueryStringValue(_T("Display"), NULL, &nValueLength);
CString sValue;
if(nValueLength > 0)
{
    LONG nC = Key.QueryStringValue(_T("Display"), sValue.GetBufferSetLength(nValueLength - 1), &nValueLength);
}

或者,您需要提供足够大的缓冲区,您认为这是足够的。

关于c++ - 函数调用 CRegKey::QueryStringValue 出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20553155/

相关文章:

c++ - 非递归访问自定义变量-如何优雅地返回值?

windows - 编辑Windows注册表时(如果需要)可使用哪个注册表编辑器版本来启动reg文件?

registry - 系统注册表的意义何在?

c++ - 如何使用常规构造函数模式初始化 C++ 11 标准容器?

c++ - 如何读取二进制文件的全部 64 个字节?

c++ - abs vs std::abs,引用说明了什么?

c++ - 结构静态成员含义/定义

c++ - 组织外部库的编译器依赖路径

c++ - VC++中的第一次机会异常

docker - 行动 : push: unauthorized to access repository docker harbor registry