2013-02-21 54 views
0

你好,并提前感谢。 我今天的问题是我回到“垃圾”字符串的注册表键值名称和值数据。这似乎是一个键/文件夹内的所有注册表值的问题,除了最后一个值,但有时我能够读取第一个值的名称(但仍然不是数据)注册表失败的字符串/值枚举调用

我在试图要做的是能够显示在一个单一的,可能是变量,注册表项中的值名称和值数据(我不在乎子项在这一点) 我试图用windows unicode字符串,WCHAR *和LPWSTR类型。 我在问题字符串中看到的“垃圾”是重复的一系列非英文字符,它们混淆了随后的wcout显示。 在注册表编辑器显示中,我试图读取的值有REG_SZ类型的数据,我知道它是一个字符串。

可能是我最大的问题是我无法找到一个简单的指南,简单地说明如何完成我想要做的事情,查看注册表项中的内容,并列出值名称和值数据。任何帮助将不胜感激。我是新来的unicode字符串和Windows API。我的环境是windows xp 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; 
    } 

这个版本部分基于评论者的帮助似乎工作如何我想要的,我发布这个供他人参考。对我来说很明显的是,当为角色获取角色数量时,不会包含空终止字符(当然),而且您传递给它的缓冲区的大小需要包含该字符,因此如果您返回16你输入16,这就是为什么它会返回234,(不公平的是,输入如下比输出diferent约束,但是生活是不公平的),然后需要输入17字符串大小

 /* 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; 
} 

回答

0

有几个明显问题:

  • 当您调用RegEnumValue时,valuename_size和data_size应该包含缓冲区的大小,但它们只对第一个值有效。对于第二个值及其以后的值,它们包含之前调用的结果。
  • 注册表中的字符串值不保证以NULL结尾。您需要在使用它们之前明确终止字符串(使用返回的长度)。请注意,由于您使用的是unicode,因此您需要将字节长度除以2以获得代码单位的长度。这些评论仅适用于值,而不适用于名称。
  • 您认为任何不是DWORD的值都是一个字符串。二元值呢?
+0

1&2.根据您的评论和一些研究,我已添加valuename [0] = L'\ 0';和数据[0] = L'\ 0';在do-while循环的顶部,并且valuename [valuename_size] = L'\ 0';和data [data_size] = L'\ 0';然后将它们用作字符串。 3.我保持我的测试限于REG_SZ和REG_DWORD类型,直到我纠正了当前的问题。 虽然我有一个新的问题,我似乎无法得到一个DWORD的数据(RegEnumValue返回ERROR_MORE_DATA(234),即使我的缓冲区的大小应该至少是正确的) – Venevus 2013-02-22 19:38:56

+0

在调用之前终止数组RegEnumValue将不会实现任何操作,每次调用之前需要重新初始化valuename_size和data_size,否则将解释ERROR_MORE_DATA。正如我在第2点所述,您需要将字节长度除以2,即数据[ data_size/2] = 0,当你声明数组的时候,你也应该这样做;如果data_size是102字节,那么它只有51个WCHARs,更可读的是,在BYTE中声明缓冲区,并且只有在数据是字符串时才转换为WCHARs 。 – arx 2013-02-22 20:40:53

+0

我没有提及我在do-while循环“data_size = maxValueData; valuename_size = maxValue;”的末尾重新初始化data_size和valuename_size。我也发现我在某些按键中仍然存在字符串问题,所以当我有时间的时候,我会在此处发布我的代码的完整更新 – Venevus 2013-02-22 21:17:38