2013-02-21 56 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