Reputation: 95
I am writing a VC++ program that is supposed to return the Java versions along with the Java Home from the registry. The purpose of the code is to display all the versions of JRE installed within a single system and also display the highest version. I have JRE 1.5, 1.6, 1.7 and 1.8 installed in my system. I have no problems in displaying the information about the versions. But when displaying the JavaHome from the registry, the path is coming right for Java versions 1.5,1.6 and 1.7 only. For version 1.8, it is displaying the path of JRE 7. I tried displaying path using INSTALLDIR from the MSI directory present within each JRE installed. Then also, there is problem with JRE 8. Initially I thought it was the error in the loop which was used in displaying all the JRE versions. So I uninstalled JRE 1.8 and checked if now, JRE 1.7 is showing the path of JRE 1.6. But nope. JRE 1.7 shows the correct path. Only when it comes to JRE 1.8, it is displaying the path of 1.7 instead of 1.8. Please help me out. I'm attaching the code below. And yeah, Checked the path present in Registry for JRE 1.8. It does have a seperate path of its own. Not the path of JRE 1.7. Also, when I tried to display the length of the Java 1.8 path, it is showing correct length 36 (as it should since that is the length of the path of JAVA 1.8) even though the output shows path of 1.7 for version 1.8. Is it something wrong with the string comparison? Help me out in this one please.
#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;
}
Upvotes: 0
Views: 556
Reputation: 45172
You are not checking the return value of RegGetValue
, which would be telling you ERROR_INSUFFICIENT_BUFFER
. Some debugging would reveal that the BufferSize
variable keeps getting smaller and smaller. That's because you are not resetting the BufferSize
variable to sizeof(value)
prior to each call to RegGetValue
, so each call reuses the value left over from the previous call, which is the size of the value retrieved. The call succeeds for Java 1.5 because it is the first call. It succeeds for Java 1.6 and 1.7 because those values happen to be the same length as Java 1.5's value. And finally, it fails for Java 1.8 because that value is longer than the others.
TL;DR: Set BufferSize = sizeof(value);
before calling RegGetValue
.
Upvotes: 3