函数调用CRegKey::QueryStringValue时出错
Error with function call CRegKey::QueryStringValue
今天我在查询时区信息时发现了这个奇怪的错误。读取时区显示名称的代码看起来像这个
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时,返回始终error_invalid_data。
为了确认这一点,我已经将regkeyapi调用更改为
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);
}
或者,您需要提供足够大的缓冲区,您认为这是足够的。
reg中的字符串不能以null结尾。因此,以下验证失败:
if ((nBytes % sizeof(TCHAR) != 0) || (pszValue[nBytes / sizeof(TCHAR) -1] != 0))
{
return ERROR_INVALID_DATA;
}
请注意,这似乎是CRegKey::QueryStringValue
中的一个错误,RegQueryValueEx
允许读取非null终止的字符串,并且由调用方负责处理这种情况。我在代码中遇到了这个问题,不得不用自己的函数替换对CRegKey::QueryStringValue
的调用。
相关文章:
- 访问者访问变体并返回不同类型时出错
- 在Linux for Windows上编译C++代码时出错
- 读取文件的最后一行并输入到链接列表时出错
- 重载操作程序时出错>>用于类中的字符串 memebr
- 调用专用模板时出错"no matching function for call to [...]"
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错
- LINK 尝试使用 OpenSSL evp aes 256 c++ 时出错
- 在Google Kick start中提交时出错
- 在c++中访问int到类对象的映射时出错
- 分段错误当我试图运行程序时出错
- 使用dynamic_cast和构造函数时出错
- CHECK(调用)函数在Google Colab中出错
- 用pybind11包装C++抽象类时出错
- 为x86而非x64编译时出错
- 从R调用C++函数并对其进行集成时出错
- 这个函数哪里出错了
- C++ 创建包含链表和字符串的对象的链接列表时出错
- 为重写std::exception的库生成swig接口时出错
- 导入/导出变量时出错
- PrintWindow函数在notepad.exe中出错