2015-09-08 2 views
0

Я пишу программу VC++, которая должна возвращать версии Java вместе с Java Home из реестра. Цель кода - показать все версии JRE, установленные в одной системе, а также отобразить самую высокую версию. У меня есть JRE 1.5, 1.6, 1.7 и 1.8, установленные в моей системе. У меня нет проблем с отображением информации о версиях. Но при отображении JavaHome из реестра путь подходит только для версий Java 1.5.1.6 и 1.7. Для версии 1.8 он показывает путь JRE 7. Я попытался отобразить путь, используя INSTALLDIR из каталога MSI, присутствующего в каждой установленной JRE. Тогда также есть проблема с JRE 8. Первоначально я думал, что это ошибка в цикле, которая использовалась при отображении всех версий JRE. Поэтому я удалил JRE 1.8 и проверял, теперь, JRE 1.7 показывает путь JRE 1.6. Но нет. JRE 1.7 показывает правильный путь. Только когда дело доходит до JRE 1.8, он отображает путь 1.7 вместо 1.8. Пожалуйста, помогите мне. Я прилагаю код ниже. И да, проверил путь, присутствующий в реестре для JRE 1.8. У этого есть отдельный путь. Не путь JRE 1.7. Кроме того, когда я пытался отобразить длину пути Java 1.8, он показывает правильную длину 36 (как это должно быть, так как это длина пути JAVA 1.8), даже если на выходе показан путь 1.7 для версии 1.8. Это что-то не так со сравнением строк? Помогите мне в этом, пожалуйста.RegGetValue() возвращает неверную информацию

#include "StdAfx.h" 
#include "targetver.h" 
#include "windows.h" 
#include"stdio.h" 
#include "sstream" 
#include"string.h" 
#include"tchar.h" 
#define MAX_KEY_LENGTH 255 
#define MAX_VALUE_NAME 16383 
#define BUFFER 8192 
char value[BUFFER]; 
TCHAR** versions = new TCHAR*[]; 
DWORD BufferSize = BUFFER; 
char str1[20]; 
char *javapath; 
void QueryKey(HKEY hKey) 
{ 
TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name 
DWORD cbName;     // size of name string 
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name 
DWORD cchClassName = MAX_PATH; // size of class string 
DWORD cSubKeys=0;    // number of subkeys 
DWORD cbMaxSubKey;    // longest subkey size 
DWORD cchMaxClass;    // longest class string 
DWORD cValues;    // number of values for key 
DWORD cchMaxValue;   // longest value name 
DWORD cbMaxValueData;  // longest value data 
DWORD cbSecurityDescriptor; // size of security descriptor 
FILETIME ftLastWriteTime;  // last write time 
DWORD i, retCode; 
// Get the class name and the value count. 
retCode = RegQueryInfoKey(
hKey,     // key handle 
achClass,    // buffer for class name 
&cchClassName,   // size of class string 
NULL,     // reserved 
&cSubKeys,    // number of subkeys 
&cbMaxSubKey,   // longest subkey size 
&cchMaxClass,   // longest class string 
&cValues,    // number of values for this key 
&cchMaxValue,   // longest value name 
&cbMaxValueData,   // longest value data 
&cbSecurityDescriptor, // security descriptor 
&ftLastWriteTime);  // last write time 

// Enumerate the subkeys, until RegEnumKeyEx fails. 
TCHAR** versions = new TCHAR*[]; 
for(int i = 0; i < cSubKeys; i++) 
versions[i] = new TCHAR[MAX_KEY_LENGTH]; 
if (cSubKeys) 
{ 
for (i=0; i<cSubKeys; i++) 
    { 
     cbName = MAX_KEY_LENGTH; 
     retCode = RegEnumKeyEx(hKey, i, 
           achKey, 
           &cbName, 
           NULL, 
           NULL, 
           NULL, 
           &ftLastWriteTime); 
      if (retCode == ERROR_SUCCESS) 
      { 
       if(strlen(achKey)==8) 
       { 
        printf("\nJava Version:"); 
        _tprintf(TEXT("%s"),achKey);  
        printf("\nJava Home:"); 
        strcpy(str1,"SOFTWARE\\\\JavaSoft\\\\Java Runtime Environment\\\\"); 
        strcat(str1,achKey); 
        strcat(str1,"\\\\"); 
        RegGetValue(HKEY_LOCAL_MACHINE,str1, "JavaHome", RRF_RT_ANY, NULL, (PVOID)&value, &BufferSize); 
        printf("%s",value); 
        printf("\n"); 
        strcpy(versions[i],achKey); 

      } 
      else 
       continue; 
     } 
    } 
} 
      TCHAR* big=0; 
     for(i=0;i<cSubKeys;i++) 
     { 

      if(strlen(versions[i])==8) 
      { 
       _tprintf(TEXT(" versions are %s:\n"),versions[i]); 
       if(versions[i]>big) 
        big=versions[i]; 
      } 
       else 
        continue; 
     } 
      _tprintf(" \nLatest version in the system is %s\n",big); 
} 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
    HKEY hKey; 
LONG dwRegOPenKey = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\JavaSoft\\Java Runtime Environment\\"), 0, KEY_READ, &hKey); 
if(dwRegOPenKey == ERROR_SUCCESS) 
{ 
    printf("RegOpenKeyEx succeeded, error code %d\n", GetLastError()); 
    QueryKey(hKey); 

} 
else 
{ 
    printf("RegOpenKeyEx failed, error code %d\n", dwRegOPenKey); 
} 
    RegCloseKey(hKey); 
    return 0; 
} 
+1

Вы не проверяете возвращаемое значение 'RegGetValue'. Он не работает из-за недостаточного буфера, потому что вы пропускаете неправильный размер буфера в последнем параметре. Пройдите через свой код, чтобы узнать, что происходит. –

+0

Сколько указателей TCHAR вы выделяете. Ваша переменная 'version' изменяет глобальную переменную. 'javapath' никогда не назначается. Почему «BufferSize» глобальный? Можете ли вы избежать глобальных переменных, передав вместо этого ссылку на структуру? Кто контролирует время жизни указателей в «версиях»? – user877329

+0

Если это проблема с Bufferoverflow, то почему, даже если я устанавливаю другие обновления java 1.5 или 1.6 или 1.7, все они показывают правильный путь? Независимо от того, сколько версий установлено, только когда дело доходит до версии 1.8, он показывает путь к предыдущей версии, установленной в системе. @RaymondChen – TheEvilGuardian

ответ

3

Вы не проверять возвращаемое значение RegGetValue, который будет говорить вам ERROR_INSUFFICIENT_BUFFER. Некоторая отладка показала бы, что переменная BufferSize становится все меньше и меньше. Это связано с тем, что вы не сбрасываете переменную BufferSize до sizeof(value) перед каждым вызовом до RegGetValue, поэтому каждый вызов повторно использует значение, оставшееся от предыдущего вызова, размер которого получен. Звонок успешно выполняется для Java 1.5, потому что это первый вызов. Он преуспевает для Java 1.6 и 1.7, потому что эти значения имеют ту же длину, что и значение Java 1.5. И, наконец, он не работает для Java 1.8, потому что это значение больше, чем другие.

TL; DR: Установить BufferSize = sizeof(value); перед тем, как позвонить RegGetValue.

Смежные вопросы