String 注册表枚举调用中的字符串/值失败
您好,提前谢谢。 我今天的问题是,我要返回注册表项值名称和值数据字符串的“垃圾”。这似乎是一个问题,除了最后一个值外,一个键/文件夹中的所有注册表值都有问题,尽管有时我能够读取第一个值的名称(但仍然不能读取数据) 我试图做的是能够显示单个注册表项(可能是变量)中的值名称和值数据(此时我不关心子项) 我正在尝试使用windows unicode字符串、WCHAR*和LPWSTR类型来实现这一点。 我看到的问题字符串的“垃圾”是一系列重复的非英语字符,这会弄乱后续的wcout显示。 在注册表编辑器显示中,我试图读取的值具有REG_SZ类型的数据,我理解为字符串 可能我最大的问题是,我找不到一个明确的指南,简单地说明如何准确地执行我正在尝试执行的操作,查看注册表项内部,并列出值名称和值数据。任何帮助都将不胜感激。我不熟悉unicode字符串和windows api。我的环境是WindowsXP SP3,Visual C++ 2010 Express。String 注册表枚举调用中的字符串/值失败,string,winapi,visual-c++,unicode,registry,String,Winapi,Visual C++,Unicode,Registry,您好,提前谢谢。 我今天的问题是,我要返回注册表项值名称和值数据字符串的“垃圾”。这似乎是一个问题,除了最后一个值外,一个键/文件夹中的所有注册表值都有问题,尽管有时我能够读取第一个值的名称(但仍然不能读取数据) 我试图做的是能够显示单个注册表项(可能是变量)中的值名称和值数据(此时我不关心子项) 我正在尝试使用windows unicode字符串、WCHAR*和LPWSTR类型来实现这一点。 我看到的问题字符串的“垃圾”是一系列重复的非英语字符,这会弄乱后续的wcout显示。 在注册表编辑器显
#include <stdio.h>
#include <iostream> /* for std::wcin and wcout */
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <process.h>
#include "conio.h"
#
include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
int return_val;
DWORD error;
HKEY hkey;
BYTE iterations = 0;
/* 1. first, open key (folder) */
return_val = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\VIDEO", 0, KEY_READ, &hkey);
/* check how the open went */
if(return_val != ERROR_SUCCESS)
{
std::wcout << L"error opening the key: " << return_val << std::endl;
}
else
{
std::wcout << L"it's cool" << std::endl;
/* 1.a. query the key (optional) */
LPTSTR className = new WCHAR[255];
DWORD classNameSize = MAX_PATH;
DWORD subKey = 0;
DWORD maxSubKey;
DWORD maxClass;
DWORD value;
DWORD maxValue;
DWORD maxValueData;
DWORD securityDescriptor;
FILETIME ftLastWriteTime;
DWORD sectionNameSize;
return_val = RegQueryInfoKey(hkey, className, &classNameSize, NULL,
&subKey, &maxSubKey, &maxClass, &value, &maxValue,
&maxValueData, &securityDescriptor, &ftLastWriteTime);
std::wcout << L"query return: " << return_val << std::endl;
std::wcout << L"class name: " << className << L", (size): " << classNameSize << std::endl;
std::wcout << L"subkey: " << subKey << L", max: " << maxSubKey << L", maxClass: " << maxClass << std::endl;
std::wcout << L"Value: " << value << L", maxval: " << maxValue << L", maxvaldata: " << maxValueData << std::endl;
std::wcout << L"Sec descrpt: " << securityDescriptor << std::endl << std::endl;
/* now enumerate the strings in the key */
int count = 0;
DWORD valuename_size = 16, type_return = 0, data_size = 102;
LPWSTR valuename = new WCHAR[valuename_size];//maxValue
LPWSTR data = new WCHAR[data_size];//maxValueData>>1
/* 2. the outer loop grabs the values one at a time (the data within the key/folder) */
do {
iterations++; /* just for debugging */
return_val = RegEnumValue(hkey, count, valuename, &valuename_size, 0, &type_return, (LPBYTE)data, &data_size);
/* return of RegEnumValue */
std::wcout << L"RegEnumValue return val: " << return_val << std::endl;
/* double check sizes */
std::wcout << L"size: valname_size: " << valuename_size << L", data_size: " << data_size << std::endl;
if(return_val == ERROR_SUCCESS || return_val == ERROR_MORE_DATA)
{
/* to try and avoid bad strings */
if(type_return == REG_DWORD || count == 0)
std::wcout << L"Value - " << valuename << L", Type: " << type_return << L" Data - " << (BYTE)(*data) << std::endl;
else
std::wcout << L"Value - " << valuename << L", Type: " << type_return << L" Data - " << data << std::endl;
}
//data = REG_SZ;
count++;
} while (return_val != ERROR_NO_MORE_ITEMS && count < value);
}
/* just to check my code */
std::wcout << L"iterations: " << iterations << std::endl;
/* to "pause" during debugging */
std::wcin >> input;
return 0;
}
#包括
#包含/*用于标准::wcin和wcout*/
#包括
#包括
#包括
#包括
#包括“conio.h”
#
包括“stdafx.h”
int _tmain(int argc,_TCHAR*argv[]
{
返回值;
德沃德误差;
HKEY HKEY;
字节迭代次数=0;
/*1.首先,打开密钥(文件夹)*/
return_val=RegOpenKeyExW(HKEY_LOCAL_MACHINE,L“HARDWARE\\DEVICEMAP\\VIDEO”,0,KEY_READ,&HKEY);
/*看看公开赛进展如何*/
如果(返回值!=错误\u成功)
{
std::wcout几个明显的问题:
- 调用RegEnumValue时,valuename_size和data_size应包含缓冲区的大小,但它们仅对第一个值这样做。对于第二个值及其后的值,它们包含上一次调用的结果
- 注册表中的字符串值不保证以NULL结尾。在使用字符串之前,您需要显式终止字符串(使用返回的长度)。请注意,由于您使用的是unicode,因此需要将字节长度除以2以获得代码单位的长度。这些注释仅适用于值,而不适用于名称
- 假设任何不是DWORD的值都是字符串。那么二进制值呢
1&2.根据您的评论和一些研究,我在do-while循环的顶部添加了valuename[0]=L'\0';data[0]=L'\0';valuename[valuename\u size]=L'\0';data[data\u size]=L'\0';在将它们用作字符串之前。3.在更正当前问题之前,我一直将测试限制在REG_SZ和REG_DWORD类型。不过,我遇到了一个新问题,我似乎根本无法获取DWORD的数据(RegEnumValuereturns ERROR_MORE_data(234)即使我的缓冲区的大小至少应该是正确的。在调用RegEnumValue之前终止数组不会有任何效果。每次调用之前都需要重新初始化valuename\u size和data\u size。如果不这样做,将解释错误。\u更多数据。正如我在第2点中所说,需要将字节长度除以2,即data[data_size/2]=0。您在声明数组时也应该这样做;如果data_size为102字节,则仅为51 WCHARs。更容易理解的是,以字节为单位声明缓冲区,并且仅当数据为字符串时才强制转换为WCHARs。我没有提到我在do while循环结束时重新初始化data_size和valuename_size“data\u size=maxValueData;valuename\u size=maxValue;”。我还发现我的一些键仍然存在字符串问题,所以当我有时间的时候,我会在这里发布我的代码的完整更新,“”null的示例终止了valuename,我发现即使我没有得到正确的结果,它也不会阻止我的wcout工作(我的控制台在坏字符串试图显示的地方停止输出)您没有正确终止数据的空值。数据是一个字节数组,因此data[data_size]=0
只设置半个unicode字符,不一定终止字符串。类似的操作将起作用:((LPWSTR)data)[data_size/2]=0
/* now enumerate the strings in the key */
int count = 0;
DWORD valuename_size, type_return = 0, data_size;
LPWSTR valuename;
BYTE *data;
/* 2. the outer loop grabs the values one at a time (the data within the key/folder) */
do {
valuename_size = maxValue;
data_size = maxValueData;
iterations++; /* just for debugging */
return_val = RegEnumValue(hkey, count, NULL, &valuename_size, 0, &type_return, NULL, &data_size); /* value name */
//return_val = RegEnumValue(hkey, count, NULL, NULL, 0, &type_return, NULL, &data_size); /* value data */
valuename = new WCHAR[valuename_size+1];
data = new BYTE[data_size]; /* data_size is in BYTES, of any type */
valuename[0] = L'\0'; /* if the string returned is still invalid, this will help make sure wcout doesnt mess up */
return_val = RegEnumValue(hkey, count, valuename, &valuename_size, 0, &type_return, (LPBYTE)data, &data_size); /* value name */
//return_val = RegEnumValue(hkey, count, NULL, NULL, 0, &type_return, (LPBYTE)data, &data_size); /* value data */
/* return of RegEnumValue */
std::wcout << L"RegEnumValue return val: " << return_val << std::endl;
/* double check sizes */
std::wcout << L"size: valname_size: " << valuename_size << L", data_size: " << data_size << L", Type: " << type_return << std::endl;
if(return_val == ERROR_MORE_DATA /*&& type_return == REG_DWORD*/)
{
/* try again? */
delete valuename;//free(valuename);
delete data;
/* double the "global" max number of WORDs for the string (including null termination) */
maxValue <<= 1;
valuename_size = maxValue;
maxValueData <<= 1;
data_size = maxValueData;
/* doublecheck */
std::wcout << L"new val size before enum: " << valuename_size << L", new data size before enum: " << data_size << std::endl;
return_val = RegEnumValue(hkey, count, NULL, &valuename_size, 0, &type_return, NULL, &data_size); /* value name */
/* the return version of valuename_size is the number of characters, not including the null terminating character */
valuename = new WCHAR[valuename_size+1];
data = new BYTE[data_size];
valuename[0] = L'\0'; /* if the string returned is still invalid, this will help make sure wcout doesnt mess up */
return_val = RegEnumValue(hkey, count, valuename, &valuename_size, 0, &type_return, (LPBYTE)data, &data_size); /* value name */
std::wcout << std::endl << L"return: " << return_val << L", Val size: " << valuename_size << L", data_size: " << data_size << std::endl << std::endl;
}
if(return_val == ERROR_SUCCESS)
{
valuename[valuename_size] = L'\0'; /* null terminate the string before printing */
/* I only care about string data */
if (type_return == REG_SZ)
{
data[data_size] = 0; /* null terminate the string before printing */
std::wcout << L"Value - " << valuename << L", Type: " << type_return << L" Data - " << (LPWSTR)data << std::endl;
}
}
count++;
} while (return_val != ERROR_NO_MORE_ITEMS && count < value);
}
/* just to check my code */
std::wcout << L"iterations: " << iterations << std::endl;
/* to "pause" during debugging */
std::wcin >> input;
return 0;
}