String 注册表枚举调用中的字符串/值失败

String 注册表枚举调用中的字符串/值失败,string,winapi,visual-c++,unicode,registry,String,Winapi,Visual C++,Unicode,Registry,您好,提前谢谢。 我今天的问题是,我要返回注册表项值名称和值数据字符串的“垃圾”。这似乎是一个问题,除了最后一个值外,一个键/文件夹中的所有注册表值都有问题,尽管有时我能够读取第一个值的名称(但仍然不能读取数据) 我试图做的是能够显示单个注册表项(可能是变量)中的值名称和值数据(此时我不关心子项) 我正在尝试使用windows unicode字符串、WCHAR*和LPWSTR类型来实现这一点。 我看到的问题字符串的“垃圾”是一系列重复的非英语字符,这会弄乱后续的wcout显示。 在注册表编辑器显

您好,提前谢谢。 我今天的问题是,我要返回注册表项值名称和值数据字符串的“垃圾”。这似乎是一个问题,除了最后一个值外,一个键/文件夹中的所有注册表值都有问题,尽管有时我能够读取第一个值的名称(但仍然不能读取数据)

我试图做的是能够显示单个注册表项(可能是变量)中的值名称和值数据(此时我不关心子项) 我正在尝试使用windows unicode字符串、WCHAR*和LPWSTR类型来实现这一点。 我看到的问题字符串的“垃圾”是一系列重复的非英语字符,这会弄乱后续的wcout显示。 在注册表编辑器显示中,我试图读取的值具有REG_SZ类型的数据,我理解为字符串

可能我最大的问题是,我找不到一个明确的指南,简单地说明如何准确地执行我正在尝试执行的操作,查看注册表项内部,并列出值名称和值数据。任何帮助都将不胜感激。我不熟悉unicode字符串和windows api。我的环境是WindowsXP SP3,Visual C++ 2010 Express。
#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;
}