今天我在查询时区信息时发现了这个奇怪的错误。 读取时区显示名称的代码如下所示
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++;
}
但对于某些时区,例如:argentina,返回值不是error_success。 在进一步调试QueryStringValue时,我发现了这个
if ((nBytes % sizeof(TCHAR) != 0) || (pszValue[nBytes / sizeof(TCHAR) - 1] != 0)) {
return ERROR_INVALID_DATA;
}
如果任何时区显示值的nBytes大小 48 ,则返回始终 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:在某些机器中,一切都能正常运行上面提到的代码(即第一个),而在其他一些机器中,它不是真正奇怪的东西,而且在第二个代码到处都可以看到代码工作正常。答案 0 :(得分:0)
代码
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);
}
或者,您需要提供足够大的缓冲区,您认为这足够了。
答案 1 :(得分:0)
reg中的字符串可能不会以空值终止。因此,以下验证失败:
if ((nBytes % sizeof(TCHAR) != 0) || (pszValue[nBytes / sizeof(TCHAR) -1] != 0))
{
return ERROR_INVALID_DATA;
}
请注意,它似乎是CRegKey::QueryStringValue
中的错误,RegQueryValueEx
允许读取非空终止字符串,并且调用者负责处理此情况。我在代码中遇到了这个问题,不得不用我自己的函数替换对CRegKey::QueryStringValue
的调用。